部署一个 StatefulSet 的时候,有个前置依赖对象,即 Service(服务)
$ cat nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-demo
namespace: demo
labels:
app: nginx
spec:
clusterIP: None
ports:
- port: 80
name: web
selector:
app: nginx
创建好了这个前置依赖的 Service,下面我们就可以开始创建真正的 StatefulSet 对象,可参照如下的 yaml 文件:
$ cat web-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web-demo
namespace: demo
spec:
serviceName: "nginx-demo"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.2-alpine
ports:
- containerPort: 80
name: web
上面 StatefulSet 的 API 对象定义,有没有发现跟 Deployment 的定义极其相似,主要的差异在spec.serviceName这个字段。它很重要,StatefulSet 根据这个字段,为每个 Pod 创建一个 DNS 域名,这个域名的格式为$(podname).(headless service name)。
/ # nslookup web-demo-0.nginx-demo
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-demo-0.nginx-demo
Address 1: 172.111.63.31 web-demo-0.nginx-demo.demo.svc.cluster.local
/ #
/ # nslookup web-demo-1.nginx-demo
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-demo-1.nginx-demo
Address 1: 172.111.17.54 web-demo-1.nginx-demo.demo.svc.cluster.local
每个 Pod 都有一个对应的 A 记录。
对于一个拥有 N 个副本的 StatefulSet 来说,Pod 在部署时按照 {0 …… N-1} 的序号顺序创建的,而删除的时候按照逆序逐个删除。
更新操作过程:
比如我们这个时候做了镜像更新操作,那么整个的升级过程大致如下,逆序删除所有的 Pod,每删除一个pod之后用新镜像创建一个出来,成功后,接着删除下一个。