Deployment 和 StatefulSet 是 Kubernetes 里最常用的两种工作负载控制器,长得像但脾气完全不同。这篇从适用场景、存储和命名几个角度,把两者的区别梳理清楚。
适用场景
Deployment适用场景
无状态的应用
1.pod之间没有顺序
2.所有pod共享存储
3.pod名字包含随机数字
4.service都有ClusterIP,可以负载均衡
StatefulSet适用场景
有状态的应用
1.部署、扩展、更新、删除都要有顺序
2.每个pod都有自己存储,所以都用volumeClaimTemplates,为每个pod都生成一个自己的存储,保存自己的状态
3.pod名字始终是固定的
4.service没有ClusterIP,是headlessservice,所以无法负载均衡,返回的都是pod名,所以pod名字都必须固定,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名:$(podname).(headless server name).namespace.svc.cluster.local
部署StatefulSet和Deployment
部署StatefulSet
首先需要创建一个headlessService,其yaml文件如下:
apiVersion: v1
kind: Service
metadata:
name: my-sts
namespace: shield
labels:
app: my-sts
spec:
selector:
app: my-sts
clusterIP: None
ports:
- name: my-sts
port: 80
然后创建storageClass和PVC
storageClass的yaml文件如下(集群中已有,不用自己创建):
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
storageclass.kubernetes.io/is-default-class: "true"
creationTimestamp: "2023-05-29T05:32:23Z"
name: alibabacloud-cnfs-nas
resourceVersion: "1152865259"
uid: c0fafd32-a72c-497f-b89c-cc9e01d0865f
mountOptions:
- nolock,tcp,noresvport
- vers=3
parameters:
archiveOnDelete: "false"
containerNetworkFileSystem: cnfs-nas-c5f3de5c4331f4649bd8ac9b8d6f71431
path: /
volumeAs: subpath
provisioner: nasplugin.csi.alibabacloud.com
reclaimPolicy: Delete
volumeBindingMode: Immediate
创建PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-sts
namespace: shield
labels:
app: my-sts
spec:
storageClassName: alibabacloud-cnfs-nas
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
创建StatefulSet
StatefulSet的yaml文件如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: my-sts
namespace: shield
spec:
selector:
matchLabels:
app: my-sts # has to match .spec.template.metadata.labels
serviceName: "my-sts"
replicas: 3 # by default is 1
template:
metadata:
labels:
app: my-sts # has to match .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: my-sts
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "alibabacloud-cnfs-nas"
resources:
requests:
storage: 1Gi
成功部署一个含有3个副本的StatefulSet
[zenghui_wang@aprd4-master task]$ kubectl get sts
NAME READY AGE
my-sts 3/3 55m
部署Deployment
yaml文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deploy
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
成功部署一个含有3个副本的deployment
[zenghui_wang@aprd4-master task]$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
my-deploy 3/3 3 3 11s
Pods的命名区别
查看本命名空间下的所有Pods
[zenghui_wang@aprd4-master task]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-deploy-748c667d99-k4tnh 1/1 Running 0 11m
my-deploy-748c667d99-nhz89 1/1 Running 0 11m
my-deploy-748c667d99-pkm4s 1/1 Running 0 11m
my-sts-0 1/1 Running 0 73m
my-sts-1 1/1 Running 0 72m
my-sts-2 1/1 Running 0 72m
可以看到明显区别,StatefulSet创建的Pods是有序的,以StatefulSet的名字作为前缀,从序号0开始命名,而Deployment的名字为随机的。
扩容缩容和滚动更新的区别
扩容
修改StatefulSet和Deployment的yaml文件,replicas修改为10,执行kubectl get pods命令
StatefulSet的扩容结果
[zenghui_wang@aprd4-master task]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-sts-0 1/1 Running 0 92m
my-sts-1 1/1 Running 0 92m
my-sts-2 1/1 Running 0 92m
my-sts-3 1/1 Running 0 21s
my-sts-4 1/1 Running 0 18s
my-sts-5 1/1 Running 0 15s
my-sts-6 1/1 Running 0 12s
my-sts-7 1/1 Running 0 10s
my-sts-8 1/1 Running 0 7s
my-sts-9 1/1 Running 0 4s
Deployment的扩容结果
[zenghui_wang@aprd4-master task]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-deploy-748c667d99-7zzm8 1/1 Running 0 7s
my-deploy-748c667d99-94ppc 1/1 Running 0 7s
my-deploy-748c667d99-bw8fv 1/1 Running 0 7s
my-deploy-748c667d99-dqmzk 1/1 Running 0 7s
my-deploy-748c667d99-hg8bd 1/1 Running 0 7s
my-deploy-748c667d99-kn72g 1/1 Running 0 7s
my-deploy-748c667d99-nchjk 1/1 Running 0 12m
my-deploy-748c667d99-nhz89 1/1 Running 0 34m
my-deploy-748c667d99-q5klt 1/1 Running 0 12m
my-deploy-748c667d99-z2zqg 1/1 Running 0 7s
从各个Pods的创建时间可以看出,StatefulSet创建Pods是有序的,从编号从小到大开始创建,而Deployment创建Pods顺序是随机的。
缩容
对StatefulSet执行缩容操作,使用kubectl describe查看记录
Normal SuccessfulDelete 30s (x2 over 11m) statefulset-controller delete Pod my-sts-9 in StatefulSet my-sts successful
Normal SuccessfulDelete 29s (x2 over 11m) statefulset-controller delete Pod my-sts-8 in StatefulSet my-sts successful
Normal SuccessfulDelete 28s (x2 over 11m) statefulset-controller delete Pod my-sts-7 in StatefulSet my-sts successful
Normal SuccessfulDelete 27s (x2 over 11m) statefulset-controller delete Pod my-sts-6 in StatefulSet my-sts successful
Normal SuccessfulDelete 27s (x2 over 11m) statefulset-controller delete Pod my-sts-5 in StatefulSet my-sts successful
可以看出StatefulSet删除Pods也是有序的,从编号从大到小开始删除。Deployment为随机删除。
滚动更新
修改StatefulSet的容器的镜像版本,使用kubectl describe查看记录
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulDelete 11m statefulset-controller delete Pod my-sts-2 in StatefulSet my-sts successful
Normal SuccessfulCreate 11m (x2 over 21h) statefulset-controller create Pod my-sts-2 in StatefulSet my-sts successful
Normal SuccessfulDelete 11m statefulset-controller delete Pod my-sts-1 in StatefulSet my-sts successful
Normal SuccessfulCreate 11m (x2 over 21h) statefulset-controller create Pod my-sts-1 in StatefulSet my-sts successful
Normal SuccessfulCreate 11m (x3 over 21h) statefulset-controller create Pod my-sts-0 in StatefulSet my-sts successful
Normal SuccessfulDelete 11m statefulset-controller delete Pod my-sts-0 in StatefulSet my-sts successful
可以发现从序号最大的 Pod 开始,逐个删除和更新每一个 Pod,直到序号最小的 Pod 被更新。
对Deployment执行相同的操作:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 58s deployment-controller Scaled up replica set my-deploy-69849c999b to 1
Normal ScalingReplicaSet 53s deployment-controller Scaled down replica set my-deploy-748c667d99 to 2 from 3
Normal ScalingReplicaSet 53s deployment-controller Scaled up replica set my-deploy-69849c999b to 2 from 1
Normal ScalingReplicaSet 49s deployment-controller Scaled down replica set my-deploy-748c667d99 to 1 from 2
Normal ScalingReplicaSet 49s deployment-controller Scaled up replica set my-deploy-69849c999b to 3 from 2
Normal ScalingReplicaSet 44s deployment-controller Scaled down replica set my-deploy-748c667d99 to 0 from 1
可以看出Deployment的滚动更新策略是:
更新 Deployment 时,Deployment Controller 先创建一个新的 ReplicaSet (nginx-deployment-1564180365) 并将其 scale up 到 1 个副本,然后 scale down 旧的 ReplicaSet 到 2。Deployment Controller 继续 scale up 新的 ReplicaSet 并 scale down 旧的 ReplicaSet,直到最后,新旧两个 ReplicaSet,一个副本数为 3,另一个副本数为 0。
StatefulSet的特点
稳定、唯一的网络标识(dnsname)
每个Pod始终对应各自的存储路径(PersistantVolumeClaimTemplate)
按顺序地增加副本、减少副本,并在减少副本时执行清理
按顺序自动地执行滚动更新
评论讨论