StatefulSet控制器
StatefulSet 是用来管理有状态应用的控制器。
参考: https://kubernetes.io/zh/docs/concepts/workloads/controllers/statefulset/
无状态应用与有状态应用
无状态应用: 如nginx
- 请求本身包含了响应端为响应这一请求所需的全部信息。每一个请求都像首次执行一样,不会依赖之前的数据进行响应。
- 不需要持久化的数据
- 无状态应用的多个实例之间互不依赖,可以无序的部署、删除或伸缩
有状态应用: 如mysql
- 前后请求有关联与依赖
- 需要持久化的数据
- 有状态应用的多个实例之间有依赖,不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
StatefulSet的特点
- 稳定的、唯一的网络标识符。 (通过headless服务实现)
- 稳定的、持久的存储。 (通过PV,PVC,storageclass实现)
- 有序的、优雅的部署和缩放。
- 有序的、自动的滚动更新。
StatefulSet的YAML组成
需要三个组成部分:
- headless service: 实现稳定,唯一的网络标识
- statefulset类型资源: 写法和deployment几乎一致,就是类型不一样
- volumeClaimTemplate : 指定存储卷
nginx+statefulset+nfs案例
一、创建StatefulSet应用
参考: https://kubernetes.io/zh/docs/tutorials/stateful-application/basic-stateful-set/
温馨提示:做此实验前要先创建好pv,pvc等,可参考博客 https://blog.51cto.com/u_13760351/2639942
1.创建statelfulset应用
(来调用名为managed-nfs-storage的storageclass,以实现动态供给)
vim nginx-storageclass-nfs.yml
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None # 无头服务
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web # statefulset的名称
spec:
serviceName: "nginx" # 服务名与上面的无头服务名要一致
replicas: 3 # 3个副本
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15-alpine
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "managed-nfs-storage" # 与前面定义的storageclass名称对应
resources:
requests:
storage: 1Gi
kubectl apply -f nginx-storageclass-nfs.yml
kubectl get statefulsets # 可以简写成sts
二、验证pod、pv、pvc
kubectl get pods |grep web
自动产生了3个pv
kubectl get pv
自动产生了3个PVC
kubectl get pvc |grep web
三、验证nfs服务目录
在nfs服务器(这里为hostos)的共享目录中发现自动产生了3个子目录
[root@hostos ~]# ls /data/
3个子目录默认都为空目录
[root@hostos ~]# tree /data/
四、验证存储持久性
1.在3个pod中其中一个创建一个主页文件
kubectl exec -it web-0 -- /bin/sh
/ # echo "haha" > /usr/share/nginx/html/index.html
/ # exit
在nfs服务器上发现文件被创建到了对应的目录中
[root@hostos ~]# tree /data/
[root@hostos ~]# cat /data/default-www-web-0-pvc-2436b20d-1be3-4c2e-87a9-5533e5c5e2c6/index.html
2.删除web-0这个pod,再验证
kubectl delete pod web-0
kubectl get pods |grep web #因为控制器的原因,再拉起web-0这个pod
kubectl exec -it web-0 -- cat /usr/share/nginx/html/index.html
新拉起的pod仍然是相同的存储数据
[root@hostos ~]# cat /data/nfs/default-www-web-0-pvc-2436b20d-1be3-4c2e-87a9-5533e5c5e2c6/index.html
nfs服务器上的数据还在
3.结论: 说明数据可持久化
五、验证pod唯一名称
回顾域名格式:
service: <service name>.<namespace name>.svc.cluster.local.
pod: <PodName>.<service name>.<namespace name>.svc.cluster.local.
可以看到在 web-0这个pod中,nslookup查询service的域名,直接解析成了3个pod的域名
kubectl exec -it web-0 -- /bin/sh
/ # nslookup nginx.default.svc.cluster.local.
ping这三个pod的域名都可以ping通
/ # ping web-0.nginx.default.svc.cluster.local.
/ # ping web-1.nginx.default.svc.cluster.local
/ # ping ping web-2.nginx.default.svc.cluster.local
补充: 当pod被删除后,重新拉起来,pod-IP可能会变,但上面的pod域名仍然可以ping通
六、验证statefulset的伸缩
1.扩容
kubectl scale sts web --replicas=4
kubectl get pods
有序地扩展了一个pod,名称为web-3
2.裁剪
kubectl scale sts web --replicas=1
kubectl get pods |grep web
先裁剪web-3,再裁剪web-2,最后裁剪web-1,只留下web-0
mysql-statefulset-nfs案例
一、编写statefulset
vim statefulset-mysql-nfs.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
spec:
clusterIP: None # 无头服务
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-svc # 与上面服务名一致
replicas: 1 # 副本数为1就OK,这里不做mysql集群
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: c1
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD # mysql5.7的镜像必须要设置一下mysql的root密码
value: "123456"
- name: MYSQL_DATABASE # 给它建一个库名为daniel,用于验证
value: daniel
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "managed-nfs-storage"
resources:
requests:
storage: 3Gi
二、应用YAML
kubectl apply -f statefulset-mysql-nfs.yaml
三、验证资源
kubectl get pods |grep mysql
kubectl get sts |grep mysql
kubectl get pv |grep mysql
kubectl get pvc |grep mysql
四、验证mysql
1.进入容器
kubectl exec -it mysql-0 -- /bin/bash
root@mysql-0:/# mysql -p123456
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| daniel | # 这里daneil库就是帮我们创建的
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)
mysql> exit
2.验证nfs上的数据
[root@hostos ~]# ls /data/default-mysql-data-mysql-0-pvc-f936d526-f473-4b88-a0e6-b94a19b95fe6
删除mysql-0这个pod,会帮我们再次启动,并且数据还是用原来的数据