1,什么是StatefulSet ?
StatefulSet又叫PetSet(以前的名称),它和RS,RC,Deployment等同样,都是pod控制器。
StatefulSet是为了解决有状态服务的问题(对应于deoloyment和RS,RC,ReplicaSet都是为无状态服务而设计的)。html
什么是无状态服务?
在生产环境中,pod的名称是随机的,扩缩容的是时候没有规律,每个pod均可以被新生成的pod代替。nginx
2,StatefulSet的应用场景包括:web
从上面的引用场景能够发现,statefulset由如下几个部分组成:
1)headless Service:无头服务。用来定义pod的网络标识的(域名解析)。
2)statefulSet:定义具体的应用
3)volumeClaimTemplate:该模板自动为每个pod建立pvc。vim
对比无状态服务,总结StatefulSet特色:pod的名称不变,每一个副本启停有顺序,持久化存储,每一个pod中的数据不一样,根据定义的模板自动建立pvc。api
3,接下来经过例子来实践statefulset资源的使用
部署nginx服务,经过storage class和statefulset实现有状态服务的数据持久化及其余操做。安全
操做流程以下: 1)经过nfs服务部署storage class(建立pv) 2)建立statefulset资源对象(建立pvc) 3)测试数据持久化 4)replicas扩容与缩容 5)分区更新
1)经过nfs部署storage class
如下直接进行部署,具体信息及参数解释请参考上章博文 k8s之StatefulSet
#开启nfs:服务器
[root@master yaml]# yum -y install nfs-utils [root@master yaml]# vim /etc/exports /nfsdata *(rw,sync,no_root_squash) [root@master yaml]# mkdir /nfsdata [root@master yaml]# systemctl start rpcbind [root@master yaml]# systemctl start nfs-server [root@master yaml]# systemctl enable nfs-server [root@master yaml]# showmount -e Export list for master: /nfsdata *
#建立rbac权限:网络
[root@master yaml]# vim rbac-rolebind.yaml apiVersion: v1 kind: ServiceAccount metadata: name: nfs-provisioner namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-provisioner-runner namespace: default 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: ["watch", "create", "update", "patch"] - apiGroups: [""] resources: ["services", "endpoints"] verbs: ["get","create","list", "watch","update"] - apiGroups: ["extensions"] resources: ["podsecuritypolicies"] resourceNames: ["nfs-provisioner"] verbs: ["use"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-provisioner subjects: - kind: ServiceAccount name: nfs-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io
运行yaml文件。
#建立nfs-Deployment:app
[root@master yaml]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nfs-client-provisioner namespace: default spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-client-provisioner spec: serviceAccount: nfs-provisioner containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: nfs-deploy #供给方的名称(自定义) - name: NFS_SERVER value: 172.16.1.30 #nfs服务器的ip地址 - name: NFS_PATH value: /nfsdata #nfs共享的目录 volumes: - name: nfs-client-root nfs: server: 172.16.1.30 path: /nfsdata
#建立storage class:less
[root@master yaml]# vim sc.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: statefu-nfs namespace: default provisioner: nfs-deploy reclaimPolicy: Retain
//运行yaml文件后,查看sc的信息: [root@master yaml]# kubectl get sc NAME PROVISIONER AGE statefu-nfs nfs-deploy 48s
2)建立statefulset资源:
[root@master yaml]# vim statefulset.yaml apiVersion: v1 kind: Service metadata: name: headless-svc #定义无头服务,须要定义标签 labels: app: headless-svc spec: ports: - name: testweb port: 80 clusterIP: None #须要将cluster ip定义为none selector: app: nginx #此处指定的标签须要在后边进行定义 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: sfs-web spec: serviceName: headless-svc #此处选择的服务名为上边定义的无头服务名 replicas: 3 selector: matchLabels: app: nginx #选择标签 template: metadata: labels: app: nginx #定义标签 spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: #定义数据持久化 - name: test-nginx mountPath: /usr/share/nginx/html #挂载到容器内的路径 volumeClaimTemplates: #经过该字段(模板)为每一个pod建立pvc - metadata: name: test-nginx annotations: volume.beta.kubernetes.io/storage-class: statefu-nfs #此处选择以前建立的storage class,名称要一致 spec: accessModes: - ReadWriteOnce #采用ReadWriteOnce的访问模式 resources: requests: storage: 100Mi #请求100M的空间
[root@master yaml]# kubectl apply -f statefulset.yaml service/headless-svc unchanged statefulset.apps/sfs-web created
//运行成功后,查看建立的headless service和statefulset的状态:
//查看svc的详细信息:
//查看建立的pod:(确保正常运行)
能够看到每一个pod都是有序的,它们的名称(域名)会以0,1,2....依次排序。
#根据上面咱们说到的,经过sc会建立pv,以及经过sts中的模板会自动建立pvc,咱们进行查看集群中的pv和pvc:
咱们能够看到pv和pvc建立成功,状态已是Bound了,访问模式是RWO(在sc中定义的模式),回收策略Delete ,都是经过sc和sts动态建立的,而并非咱们手动建立。
3)测试数据持久化
#查看挂载到nfs服务器上是否会生成每一个pvc的共享目录:
#进入某个pod目录下建立测试网页文件:
[root@master yaml]# cd /nfsdata/default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023/ [root@master default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023]# echo "<h1>hello world</h1>" > index.html [root@master default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023]# ll total 4 -rw-r--r-- 1 root root 21 Jan 12 17:13 index.html
#咱们进入到pod中,查看文件是否挂载成功:
#接下来咱们将该pod删除掉:
验证从新生成的pod是否被替换,数据是否丢失?
经过上面的测试结果,咱们能够得知有状态的服务不一样于无状态服务,从新生成的pod名称不会发生改变,即使删除后也不会被新生成的pod覆盖,且原有pod中的数据也一并会存在。
4)replicas的扩容与缩容:
(1)扩容操做:
[root@master yaml]# vim statefulset.yaml
//从新运行yaml文件,查看新生成的pod:
(2)缩容操做:(以倒序的方式依次缩减)
//从新运行服务,查看pod状态:
经过上面的扩缩容操做,咱们能够得知statefulset资源在生产环境中可以实现有序部署,即有序扩展,有序收缩,且pod的启停都是有必定顺序的。
5)分区更新操做:分区更新的主要目的是为pod进行一个分区,为了使咱们对某个应用全部pod中的某一部分或者有选择性的pod进行更新操做。
#在更新以前,咱们先来查看更新的参数:
[root@master yaml]# kubectl explain sts.spec.updateStrategy.rollingUpdate KIND: StatefulSet VERSION: apps/v1 RESOURCE: rollingUpdate <Object> DESCRIPTION: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType. FIELDS: partition <integer> Partition indicates the ordinal at which the StatefulSet should be partitioned. Default value is 0.
#根据以上参数,咱们对pod进行分区,而且对指定分区的pod进行版本升级:
咱们将replicas的数量设置为8个,且定义分区更新,表示从第四个pod(分区)开始(包括第四个分区)进行更新,以前的pod是不会进行更新操做的。
注意:若是不指定分区,则默认分区从0开始。
#版本升级就不进行测试了,只需将镜像更改成新的nginx版本,从新运行服务后,能够看到从第四个pod开始(包括第四个)以后的pod镜像版本将会进行升级,而以前分区的pod,版本不会发生改变。
4,StatefulSet限制
1)该资源对象还在beta(测试)状态,须要kubernetes v1.5版本以上才支持。 2)全部pod的volume必须使用pv或者是管理员事先建立好的。 3)为了保证数据安全,删除statefulset时不会删除volume。 4)statefulset须要一个Headless Service服务来定义DNS domin,须要在statefulset以前建立好。 5)目前statefulset功能还还没有完善,好比上面的更新操做还须要手动解决。
以上就是statefulset资源的理解与实践,若是应用程序不须要任何稳定的标识符,有序部署,删除和scale,则使用Deployment或RS等无状态控制器来部署。反之在生产中使用statefulset控制器为保证pod与volume的关系不会断开,即便pod挂了后还能使用以前挂载的磁盘