管理部署有状态的服务,statefulset为每个pod维护了一个粘性标识,这些pod 是根据相同的规范创建的,但是不可互换,每个pod都有一个持久的标识符,在重新调度时也会保留,一般格式为 StatefulSetName-Nmber 。比如定义一个名字是Redis-Sentinel 的statefulset,指定创建出三个pod,那么创建出来的pod名字为Redis-Sentinel-0,Redis-Sentinel-1 与 Redis-Sentinel-2。 而statufulset创建的pod一般使用Headless Service(无头服务)进行通信,和普通的service在于Headeless Service 没有ClusterIp, 它使用的是Endpoint进行互相通信的,Headless 一般的格式为:
statfulsetname-{0....N-1}.serviceName.namespace.svc.cluster.local
说明:
- serviceName 为headless service 的名字, 创建statefulset 时,必须指定headless service 的名称
- 0....N-1 是pod 的所在的序号,从0开始到N-1
- statefulsetname 是 StatefulSet 名字
- namespace 服务所在的命名空间
- .cluster.local 为 Cluster Domian(集群域)
statefulset 的列子:
apiVersion: v1
kind: Service
metadata:
name: nginx #Service定义了一个名字为Nginx的Headless Service
namespace: default
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None #设置None后不会有clusterIP
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: default
spec:
serviceName: "nginx" #指向上面所创建的service 的名字,一一对应
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
创建完成后可以通过创建一个busybox 来进行访问与解析:
cat<<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- name: busybox
image: busybox:1.28
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
restartPolicy: Always
EOF
可以通过以下进行扩容,来看sts 是如何进行跟新:
kubectl scale --replicas=4 sts web
通过labels 去过滤,然后动态查看sts 跟新的过程
kubectl get po -l app=nginx -w
[root@k8s-master01 ~]# kubectl get po -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 16s
web-1 1/1 Running 0 4m13s
web-2 1/1 Running 0 47s
web-3 0/1 ContainerCreating 0 46s
web-3 1/1 Running 0 55s
sts 是一个一个完成扩容的,第一个启动起来后会启动第二个,直至完成我们期望的副本数
删除也是同理,从最大开始删除,知道满足我们所期望的副本数
若: 最小的副本数被杀掉,会优先去启动最小的副本,然后再继续完成扩缩容
sts 部署的容器的名称是固定的:
[root@k8s-master01 ~]# kubectl exec -it web-0 -- sh
# hostname
web-0
sts 跟新方式:
[root@k8s-master01 ~]# kubectl get sts -oyaml
apiVersion: v1
items:
- apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: default
spec:
podManagementPolicy: OrderedReady
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
serviceName: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
ports:
- containerPort: 80
name: web
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
status:
collisionCount: 0
currentReplicas: 2
currentRevision: web-557c574fc9
observedGeneration: 3
readyReplicas: 2
replicas: 2
updateRevision: web-557c574fc9
updatedReplicas: 2
kind: List
metadata:
resourceVersion: ""
selfLink: ""
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
RollingUpdate: 滚动跟新,先跟新web-3 跟新完成后会跟新 web-2 .....直到web-0
OnDelete: 只有手动进行 kubectl delete po web-1 删除一个才会进行跟新一个,就不需要指定partition 这个参数:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 3
指定pod 的序号大于等于3的才会进行滚动跟新,小于3的不会进行跟新
通过以下命令执行跟新过程:
kubectl edit sts web
kubectl rollout status sts web
kubectl describe po web-1
[root@k8s-master01 ~]# kubectl rollout status sts web
Waiting for 1 pods to be ready...
[root@k8s-master01 ~]kubectl get po -l app=nginx -w
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 21m
web-1 0/1 ContainerCreating 0 42s
查看镜像版本:
kubectl get po -oyaml | grep image
级联删除与非级联删除
kubectl delete sts web
#非级联删除,pod 会编程孤儿pod,无人管理
kubectl delete sts web --cascade=false