K8s资源第六篇(StatefulSet)
StatefulSet: RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群,Redis等。StatefulSet应用场景:稳定且唯一的网络标识符。稳定且持久的存储。有序,平滑地部署和扩展。有序,平滑地...
·
StatefulSet:
RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群,Redis等。
StatefulSet应用场景:
- 稳定且唯一的网络标识符。
- 稳定且持久的存储。
- 有序,平滑地部署和扩展。
- 有序,平滑地终止和删除。
- 有序的滚动更新。
StatefulSet组成:
- Headless Service:名为nginx,用来定义Pod网络标识。
- StatefulSet:定义具体应用,名为nginx,有三个Pod副本,并为每个Pod定义了一个域名。
- volumeClaim Templates:存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应。
#创建PV
[root@k8smaster data]# vim pv-demo.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/nfs/volumes/v1
server: k8snfs
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv002
labels:
name: pv002
spec:
nfs:
path: /data/nfs/volumes/v2
server: k8snfs
accessModes: ["ReadWriteOnce"]
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/nfs/volumes/v3
server: k8snfs
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv004
labels:
name: pv004
spec:
nfs:
path: /data/nfs/volumes/v4
server: k8snfs
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv005
labels:
name: pv005
spec:
nfs:
path: /data/nfs/volumes/v5
server: k8snfs
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 1Gi
[root@k8smaster data]# kubectl apply -f pv-demo.yaml
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created
[root@k8smaster data]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWO,RWX Retain Available 8s
pv002 5Gi RWO Retain Available 8s
pv003 5Gi RWO,RWX Retain Available 8s
pv004 1Gi RWO,RWX Retain Available 8s
pv005 1Gi RWO,RWX Retain Available 8s
#定义Statefulset
[root@k8smaster data]# vim statfulset-demo.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
labels:
app: myapp-svc
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: myapp
spec:
serviceName: myapp-svc
replicas: 3
selector:
matchLabels:
app: myapp-pod
template:
metadata:
labels:
app: myapp-pod
spec:
terminationGracePeriodSeconds: 10
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: web
volumeMounts:
- name: myappdata
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: myappdata
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
启停策略:
- 有序部署:部署StatefulSet时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态。
- 有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。
- 有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。
[root@k8smaster data]# kubectl apply -f statfulset-demo.yaml
service/myapp-svc created
statefulset.apps/myapp created
[root@k8smaster data]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 53d
myapp ClusterIP None <none> 80/TCP 10m
[root@k8smaster data]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 1Gi RWO,RWX Retain Available 16s
pv002 1Gi RWO Retain Bound default/myappdata-myapp-0 16s
pv003 1Gi RWO,RWX Retain Available 16s
pv004 1Gi RWO,RWX Retain Bound default/myappdata-myapp-1 16s
pv005 1Gi RWO,RWX Retain Bound default/myappdata-myapp-2 16s
[root@k8smaster data]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 5m23s
myapp-1 1/1 Running 0 5m20s
myapp-2 1/1 Running 0 5m16s
[root@k8smaster data]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myappdata-myapp-0 Bound pv002 1Gi RWO 5m28s
myappdata-myapp-1 Bound pv004 1Gi RWO,RWX 5m25s
myappdata-myapp-2 Bound pv005 1Gi RWO,RWX 5m21s
[root@k8smaster data]# kubectl get sts
NAME READY AGE
myapp 3/3 6m27s
#修改副本数为5个。
[root@k8smaster data]# kubectl scale sts myapp --replicas=5
statefulset.apps/myapp scaled
[root@k8smaster data]# kubectl get sts
NAME READY AGE
myapp 5/5 19m
#修改更新策略:对partition为4及以上的pod进行滚动更新。
[root@k8smaster data]# kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":4}}}}'
statefulset.apps/myapp patched
[root@k8smaster data]# kubectl set image sts/myapp myapp=ikubernetes/myapp:v2
statefulset.apps/myapp image updated
[root@k8smaster data]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-0 1/1 Running 0 44m 10.244.1.130 k8snode1 <none> <none>
myapp-1 1/1 Running 0 44m 10.244.2.118 k8snode2 <none> <none>
myapp-2 1/1 Running 0 44m 10.244.1.131 k8snode1 <none> <none>
myapp-3 1/1 Running 0 25m 10.244.2.119 k8snode2 <none> <none>
myapp-4 1/1 Running 0 12s 10.244.2.121 k8snode2 <none> <none>
#myapp-4的image已经发生改变了。
[root@k8smaster data]# kubectl get pod myapp-4 -o yaml
... ...
- containerID: docker://d6c48772d6bce56b9a81c9aebae921626949ff8d83f9610acd90f7b37ab4b275
image: ikubernetes/myapp:v2
... ...
#myapp-3的image并没有更新。
[root@k8smaster data]# kubectl get pod myapp-3 -o yaml
... ...
- containerID: docker://c78bc6eb8dccde06f07622bb265f6a2815ebae2e3a936f7893062a1c110e07a3
image: ikubernetes/myapp:v1
... ...
#打开一个终端进行监控。
[root@k8smaster ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 52m
myapp-1 1/1 Running 0 52m
myapp-2 1/1 Running 0 52m
myapp-3 1/1 Running 0 34m
myapp-4 1/1 Running 0 8m42s
#修改更新策略:对partition为0及以上的pod进行滚动更新。
[root@k8smaster data]# kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}'
statefulset.apps/myapp patched
#我们发现myapp-0~3的pod也都进行了滚动更新。
[root@k8smaster ~]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 52m
myapp-1 1/1 Running 0 52m
myapp-2 1/1 Running 0 52m
myapp-3 1/1 Running 0 34m
myapp-4 1/1 Running 0 8m42s
myapp-3 1/1 Terminating 0 34m
myapp-3 0/1 Terminating 0 34m
myapp-3 0/1 Terminating 0 34m
myapp-3 0/1 Terminating 0 34m
myapp-3 0/1 Pending 0 0s
myapp-3 0/1 Pending 0 0s
myapp-3 0/1 ContainerCreating 0 0s
myapp-3 1/1 Running 0 3s
myapp-2 1/1 Terminating 0 53m
myapp-2 0/1 Terminating 0 53m
myapp-2 0/1 Terminating 0 53m
myapp-2 0/1 Terminating 0 53m
myapp-2 0/1 Pending 0 0s
myapp-2 0/1 Pending 0 0s
myapp-2 0/1 ContainerCreating 0 0s
myapp-2 1/1 Running 0 1s
myapp-1 1/1 Terminating 0 53m
myapp-1 0/1 Terminating 0 53m
myapp-1 0/1 Terminating 0 53m
myapp-1 0/1 Terminating 0 53m
myapp-1 0/1 Pending 0 0s
myapp-1 0/1 Pending 0 0s
myapp-1 0/1 ContainerCreating 0 0s
myapp-1 1/1 Running 0 1s
myapp-0 1/1 Terminating 0 53m
myapp-0 0/1 Terminating 0 53m
myapp-0 0/1 Terminating 0 53m
myapp-0 0/1 Terminating 0 53m
myapp-0 0/1 Pending 0 0s
myapp-0 0/1 Pending 0 0s
myapp-0 0/1 ContainerCreating 0 0s
myapp-0 1/1 Running 0 1s
更新策略:
- OnDelete:通过.spec.updateStrategy.type 字段设置为OnDelete,StatefulSet控制器不会自动更新StatefulSet中的Pod。用户必须手动删除Pod,以使控制器创建新的Pod。
- RollingUpdate:通过.spec.updateStrategy.type 字段设置为RollingUpdate,实现了Pod的自动滚动更新,如果.spec.updateStrategy未指定,则此为默认策略。
StatefulSet控制器将删除并重新创建StatefulSet中的每个Pod。它将以Pod终止(从最大序数到最小序数)的顺序进行,一次更新每个Pod。在更新下一个Pod之前,必须等待这个Pod Running and Ready。 - Partitions:通过指定 .spec.updateStrategy.rollingUpdate.partition 来对 RollingUpdate 更新策略进行分区,如果指定了分区,则当 StatefulSet 的 .spec.template 更新时,具有大于或等于分区序数的所有 Pod 将被更新。
具有小于分区的序数的所有 Pod 将不会被更新,即使删除它们也将被重新创建。如果 StatefulSet 的 .spec.updateStrategy.rollingUpdate.partition 大于其 .spec.replicas,则其 .spec.template 的更新将不会传播到 Pod。在大多数情况下,不需要使用分区。
参考文档:https://blog.51cto.com/newfly/2140004
更多推荐
已为社区贡献5条内容
所有评论(0)