statefulset管理pod

statefulset管理pod

软件版本
docker最新版
kubernetes1.23.1
calico3.25
节点IP系统功能CPU内存硬盘
node110.80.10.1centos7.9k8s-master4核心8GB20GB
node210.80.10.2centos7.9k8s-node4核心8GB20GB

statefulset是为了管理有状态服务的问题而设计的:

有状态服务:statefulset是有状态的集合,管理有状态的服务,它所管理的pod的名称不能随意变化。数据持久化的目录也是不一样,每一个pod都有自己独有的数据持久化存储目录。比如mysql主从、redis集群等。

无状态服务:rc、deployment、daemonSet都是管理无状态的服务,它们所管理的pod的ip、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。

statefulset由以下几个部分组成:

  • headless service:用来定义pod网路标识,生成可解析的dns记录。

  • volumeclaimtemplates:存储卷申请模板,创建pvc,指定pvc名称大小,自动创建pvc,且pvc由存储类供应。

  • statefulset:管理pod的。

什么是headless service:

headless service不分配clusterip,headless service可以通过解析service的dns,返回所有pod的dns和ip地址(statefulset部署的pod才有dns),普通的service,只能通过解析service的dns返回service的clusterip。

statefulset会为关联的pod保持一个不变的pod name。

statefulset会为关联的pod分配一个dnsname。

为什么要用volumeclaimtemplate:

对于有状态应用都会用到持久化存储,比如mysql主从,由于主从数据库的数据是不能存放在一个目录下的,每个mysql节点都需要有自己独立的存储空间。而在deployment中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,它们数据是同步的,而statefulset定义中的每一个pod都不能使用同一个存储卷,这就需要使用volumeclaintemplate,当在使用statefulset创建pod时,volumeclaintemplate会自动生成一个pvc,从而请求绑定一个pv,每一个pod都有自己专用的存储卷。

node1

查看字段:

1
# kubectl explain statefulset

创建存储类:

1
2
3
4
5
6
7
# mkdir /root/statefulset && cd /root/statefulset
# vim class-web.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-web
provisioner: example.com/nfs
1
# kubectl apply -f class-web.yaml

编写一个statefulset资源清单文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# vim statefulset.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.10
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs-web"
resources:
requests:
storage: 1Gi
1
2
3
4
5
6
7
8
9
10
11
# kubectl apply -f statefulset.yaml
# kubectl get statefulset
NAME READY AGE
web 2/2 14s
# kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 27s
web-1 1/1 Running 0 24s
# kubectl get pvc | grep web
www-web-0 Bound pvc-223668d6-ac58-407a-89a5-909b6b1ebe72 1Gi RWO nfs-web 47s
www-web-1 Bound pvc-64125856-dd19-4c34-bd51-d4cf9e26d7b5 1Gi RWO nfs-web 44s

在共享目录创建文件夹:

1
2
# mkdir /data/nfs_pro/default-www-web-0-pvc-223668d6-ac58-407a-89a5-909b6b1ebe72/web-0
# mkdir /data/nfs_pro/default-www-web-1-pvc-64125856-dd19-4c34-bd51-d4cf9e26d7b5/web-1

进入容器查看:

1
2
3
4
# kubectl exec -it web-0 -- /bin/ls /usr/share/nginx/html
web-0
# kubectl exec -it web-1 -- /bin/ls /usr/share/nginx/html
web-1

查看pod的dns:

1
2
3
# kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh
# nslookup nginx.default.svc.cluster.local
# exit

statefulset实现pod的扩容:

1
2
3
# vim statefulset.yaml
# 24行,修改配置
replicas: 3
1
2
3
4
# kubectl apply -f statefulset.yaml
# kubectl get statefulset
NAME READY AGE
web 3/3 23m
1
2
3
# kubectl edit statefulset web
# 19行,修改配置
replicas: 4
1
2
3
# kubectl get statefulset
NAME READY AGE
web 4/4 24m
1
2
3
4
# kubectl apply -f statefulset.yaml
# kubectl get statefulset
NAME READY AGE
web 3/3 25m

statefulset实现pod的缩容:

1
2
3
# vim statefulset.yaml
# 24行,修改配置
replicas: 3
1
2
3
4
# kubectl apply -f statefulset.yaml
# kubectl get statefulset
NAME READY AGE
web 2/2 26m

statefulset实现pod的更新:

1
2
3
# vim statefulset.yaml
# 33行,修改配置
image: janakiramm/myapp:v2
1
2
3
# kubectl apply -f statefulset.yaml
# kubectl describe pods web-0 | grep image
Normal Pulled 37s kubelet Container image "janakiramm/myapp:v2" already present on machine