Statefulset+storageclass+ceph
一、简介
1、StatefulSet
StatefulSet 是用来管理有状态应用的工作负载 API 对象。
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、官网示例演示
apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels: app: nginx # 必须匹配 .spec.template.metadata.labels serviceName: "nginx" replicas: 3 # 默认值是 1 minReadySeconds: 10 # 默认值是 0 template: metadata: labels: app: nginx # 必须匹配 .spec.selector.matchLabels spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: registry.k8s.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "my-storage-class" resources: requests: storage: 1Gi
上述例子中:
- 名为
nginx
的 Headless Service 用来控制网络域名。 - 名为
web
的 StatefulSet 有一个 Spec,它表明将在独立的 3 个 Pod 副本中启动 nginx 容器。 volumeClaimTemplates
将通过 PersistentVolume 制备程序所准备的 PersistentVolumes 来提供稳定的存储。
StatefulSet 的命名需要遵循 DNS 标签规范
二、案例
1、创建kubernetes对接ceph需要的外部客户端rbd-provisioner
注:假如你的kubernetes集群是由kubeadm初始化时,那么kube-controller-manager本身是没有rbd的命令,所以需要添加一个外部插件
quay.io/external_storage/rbd-provisioner:latest,添加方法如下
cat rbd-provisioner.yaml
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: rbd-provisioner rules: - 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"] - apiGroups: [""] resources: ["services"] resourceNames: ["kube-dns","coredns"] verbs: ["list", "get"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: rbd-provisioner subjects: - kind: ServiceAccount name: rbd-provisioner namespace: default roleRef: kind: ClusterRole name: rbd-provisioner apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: rbd-provisioner rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get"] - apiGroups: [""] resources: ["endpoints"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: rbd-provisioner roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: rbd-provisioner subjects: - kind: ServiceAccount name: rbd-provisioner namespace: default --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: rbd-provisioner spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: rbd-provisioner spec: containers: - name: rbd-provisioner image: quay.io/external_storage/rbd-provisioner:latest env: - name: PROVISIONER_NAME value: ceph.com/rbd serviceAccount: rbd-provisioner --- apiVersion: v1 kind: ServiceAccount metadata: name: rbd-provisione
kubectl apply -f rbd-provisioner.yaml
2.创建ceph-secret这个k8s的secret对象,这个secret对象用于k8s volume插件访问ceph集群用的
(1)在ceph集群的管理节点获取client.admin的keyring值,并用base64编码,在ceph集群的管理节点上操作
ceph auth get-key client.admin | base64
获取的结果如下所示
QVFBczlGOWRCVTkrSXhBQThLa1k4VERQQjhVT29wd0FnZkNDQmc9PQ==
(2)创建secret
cat ceph-secret.yaml
apiVersion: v1 kind: Secret metadata: name: ceph-secret type: "ceph.com/rbd" data: key: QVFBczlGOWRCVTkrSXhBQThLa1k4VERQQjhVT29wd0FnZkNDQmc9PQ==
kubectl apply -f ceph-secret.yaml
3.创建storageclass
(1)在ceph集群的管理节点创建pool池
ceph osd pool create k8stest 256 rbd create rbda -s 1024 -p k8stest rbd feature disable k8stest/rbda object-map fast-diff deep-flatten
(2)在k8s集群的master节点创建storageclass
cat storageclass.yaml
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: k8s-rbd provisioner: ceph.com/rbd parameters: monitors: 192.168.199.201:6789 adminId: admin adminSecretName: ceph-secret pool: k8stest userId: admin userSecretName: ceph-secret fsType: xfs imageFormat: "2" imageFeatures: "layering" apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: k8s-rbd provisioner: ceph.com/rbd parameters: monitors: 192.168.199.201:6789 adminId: admin adminSecretName: ceph-secret pool: k8stest userId: admin userSecretName: ceph-secret fsType: xfs imageFormat: "2" imageFeatures: "layering"
注:storageclass参数说明
monitors: 192.168.199.201:6789 #ceph集群的监控节点,如果monitor是多个,可以写多个monitor地址,用,分割 pool: k8stest #pool池,需要事先创建,在ceph集群的管理节点,按照上面创建pool的步骤创建即可 userId: admin #k8s访问ceph集群使用admin管理用户 userSecretName: ceph-secret #k8s访问ceph需要的密钥,就是我们上面创建的secret fsType: xfs #rbd块的文件系统类型,可以是xfs,也可以是ext4 imageFormat: "2" #默认即可 imageFeatures: "layering" #默认即可
kubectl apply -f storageclass.yaml
4.statefulset+ceph最佳实践测试
cat stat.yaml
apiVersion: v1 kind: Service metadata: name: storage labels: app: storage spec: ports: - port: 80 name: web clusterIP: None selector: app: storage --- apiVersion: apps/v1beta1 kind: StatefulSet metadata: name: storage spec: serviceName: "storage" replicas: 2 template: metadata: labels: app: storage spec: containers: - name: nginx image: nginx ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] volumeMode: Filesystem storageClassName: k8s-rbd resources: requests: storage: 1Gi
说明 volumeClaimTemplates
:
表示一类PVC的模板,系统会根据有状态服务-StatefulSet配置的replicas数量,创建相应数量的PVC。这些PVC除了名字不一样之外其他配置都是一样的。
https://mp.weixin.qq.com/s/dfUJZDUEyZupU4SBURZvLg
关于k8s存储类的“Delete“和“Retain“_荒-于嬉的博客-CSDN博客_k8s retain
K8S 快速入门(十六)实战篇:StorageClass(存储类)_八阿哥和菲克斯的博客-CSDN博客_storageclass
K8S 快速入门(十五)实战篇:Headless Services、StatefulSet 部署有状态服务_八阿哥和菲克斯的博客-CSDN博客_headless service