编辑
2023-06-09
K8S
00
请注意,本文编写于 593 天前,最后修改于 592 天前,其中某些信息可能已经过时。

目录

1.什么是 StatefulSet
2. StatefulSet 特点
3. 限制
4.使用 StatefulSet
4.1 搭建 NFS 服务
4.2客户端服务器测试
5.使用 statefulset
5.1
5.2
5.3

1.什么是 StatefulSet

官方地址: https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/

StatefulSet 是用来管理有状态应用的工作负载 API 对象。

无状态应用: 应用本身不存储任何数据的应用称之为无状态应用。

有状态应用: 应用本身需要存储相关数据应用称之为有状态应用。

博客: 前端vue 后端 java mysql redis es ....

数据采集: 采集程序 有状态应用

StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。

和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。 尽管 StatefulSet 中的单个 Pod 仍可能出现故障, 但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。

2. StatefulSet 特点

StatefulSet 对于需要满足以下一个或多个需求的应用程序很有价值:

  • 稳定的、唯一的网络标识符。
  • 稳定的、持久的存储。
  • 有序的、优雅的部署和扩缩。
  • 有序的、自动的滚动更新。

在上面描述中,“稳定的”意味着 Pod 调度或重调度的整个过程是有持久性的。 如果应用程序不需要任何稳定的标识符或有序的部署、删除或扩缩, 则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如 Deployment或者 ReplicaSet 可能更适用于你的无状态应用部署需要。

3. 限制

  • 给定 Pod 的存储必须由 PersistentVolume Provisioner 基于所请求的 storage class 来制备,或者由管理员预先制备。
  • 删除或者扩缩 StatefulSet 并不会删除它关联的存储卷。 这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。
  • StatefulSet 当前需要无头服务来负责 Pod 的网络标识。你需要负责创建此服务。
  • 当删除一个 StatefulSet 时,该 StatefulSet 不提供任何终止 Pod 的保证。 为了实现 StatefulSet 中的 Pod 可以有序且体面地终止,可以在删除之前将 StatefulSet 缩容到 0。
  • 在默认 Pod 管理策略(OrderedReady) 时使用滚动更新, 可能进入需要人工干预才能修复的损坏状态。

4.使用 StatefulSet

4.1 搭建 NFS 服务

找一台服务器进行搭建NFS服务器

sh
#安装nfs-utils yum install -y rpcbind nfs-utils #创建nfs目录 mkdir -p /root/nfs/data #编辑/etc/exports输入如下内容 # insecure:通过 1024 以上端口发送 rw: 读写 sync:请求时写入共享 no_root_squash:root用户有完全根目录访问权限 echo "/root/nfs/data *(insecure,rw,sync,no_root_squash)" >> /etc/exports #启动相关服务并配置开机自启动 systemctl start rpcbind systemctl start nfs-server systemctl enable rpcbind systemctl enable nfs-server #重新挂载 使 /etc/exports生效 exportfs -r #查看共享情况 exportfs

4.2客户端服务器测试

sh
# 1.安装客户端 所有节点安装 yum install -y nfs-utils # 2.创建本地目录 mkdir -p /root/nfs # 3.挂载远程nfs目录到本地 #前面是nfs服务器挂载的目录 后面是本机挂载的目录 mount -t nfs 10.15.0.9:/root/nfs /root/nfs # 4.写入一个测试文件 echo "hello nfs server" > /root/nfs/test.txt # 5.去远程 nfs 目录查看 cat /root/nfs/test.txt # 挂取消载 umount -f -l nfs目录

5.使用 statefulset

5.1

js
vi nfs-client-provider.yml
yml
apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner labels: app: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: kube-system spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: chronolaw/nfs-subdir-external-provisioner:v4.0.2 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: k8s-sigs.io/nfs-subdir-external-provisioner - name: NFS_SERVER value: 192.168.24.131 #nfs服务器ip地址 - name: NFS_PATH value: /root/nfs/data #nfs服务器共享数据目录 volumes: - name: nfs-client-root nfs: server: 192.168.24.131 #nfs服务器ip地址 path: /root/nfs/data #nfs服务器共享数据目录

5.2

js
vi rbac.yml
yml
apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: kube-system --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: nfs-client-provisioner-runner rules: - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["create", "update", "patch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-client-provisioner subjects: - kind: ServiceAccount name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: kube-system roleRef: kind: ClusterRole name: nfs-client-provisioner-runner apiGroup: rbac.authorization.k8s.io --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: kube-system rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: leader-locking-nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: kube-system subjects: - kind: ServiceAccount name: nfs-client-provisioner # replace with namespace where provisioner is deployed namespace: kube-system roleRef: kind: Role name: leader-locking-nfs-client-provisioner apiGroup: rbac.authorization.k8s.io

5.3

mysql.yml

yml
apiVersion: v1 kind: Namespace metadata: name: ems --- apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: mysql-nfs-sc namespace: ems provisioner: k8s-sigs.io/nfs-subdir-external-provisioner parameters: onDelete: "remain" --- apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql labels: app: mysql namespace: ems spec: serviceName: mysql #headless 无头服务 保证网络标识符唯一 必须存在 replicas: 1 template: metadata: name: mysql labels: app: mysql spec: containers: - name: mysql image: mysql/mysql-server:8.0 imagePullPolicy: IfNotPresent env: - name: MYSQL_ROOT_PASSWORD value: root volumeMounts: - mountPath: /var/lib/mysql #自己容器写入数据目录 name: data #保存到指定一个变量中 变量名字就是 data ports: - containerPort: 3306 #容器内的端口 restartPolicy: Always volumeClaimTemplates: #声明动态创建数据卷模板 - metadata: name: data # 数据卷变量名称 namespace: ems # 在哪个命名空间创建数据卷 spec: accessModes: # 访问数据卷模式是什么 - ReadWriteMany storageClassName: mysql-nfs-sc # 使用哪个 storage class 模板存储数据 resources: requests: storage: 2G selector: matchLabels: app: mysql ---

本文作者:松轩(^U^)

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

Document