再谈有状态应用部署statefulset
1106字约4分钟
2024-09-29
无状态与有状态
Deployment控制器设计原则:管理的所有Pod一模一样,提供同一个服务,也不考虑在哪台Node 运行,可随意扩容和缩容。这种应用称为“无状态”,例如Web服务
在实际的场景中,并不能满足所有应用,尤其是分布式应用,会部署多个实例,这些实例之间往往有 依赖关系,例如主从关系、主备关系,这种应用称为“有状态”,例如MySQL主从、Etcd集群
StatefulSet 控制器概述
StatefulSet控制器用于部署有状态应用,满足一些有状态应 用的需求:
Pod有序的部署、扩容、删除和停止
Pod分配一个稳定的且唯一的网络标识
Pod分配一个独享的存储
StatefulSet 控制器:网络标识
稳定的网络标识:使用Headless Service(相比普通Service只是将spec.clusterIP定义为None)来维 护Pod网络身份,会为每个Pod分配一个数字编号并且按照编号顺序部署。还需要在StatefulSet添加 serviceName: “nginx”字段指定StatefulSet控制器要使用这个Headless Service。
稳定主要体现在主机名和Pod A记录:
主机名:<statefulset名称>-<编号>
Pod DNS A记录:<statefulset名称-编号>.<service-name>.<namespace>.svc.cluster.local
部署statefulset控制器
vim statefulset-web.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-web
spec:
serviceName: "handless-service"
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
部署handless-service
vim handless-service.yaml
apiVersion: v1
kind: Service
metadata:
name: handless-service
spec:
clusterIP: None
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 9376
验证查看
kubectl apply -f statefulset-web.yaml
kubectl apply -f handless-service.yaml
kubectl get pod,svc
kubectl get statefulsets.apps
查看Pod创建顺序:
查看主机名:
kubectl exec statefulset-web-0 -- hostname
kubectl exec statefulset-web-1 -- hostname
kubectl exec statefulset-web-2 -- hostname
测试A记录解析:
kubectl run -it dns-test --rm --image=busybox:1.28.4 -- sh
nslookup handless-service
解析出对应的三个Pod IP记录,其他Pod可使用这个名称访问:
StatefulSet 控制器:独享存储
独享存储:StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当StatefulSet使用 VolumeClaimTemplate创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC, 每个PVC绑定对应的PV,从而保证每个Pod都拥有独立的存储。
部署nfs
#安装nfs安装包(每个k8s节点都要安装)
yum install nfs-utils
#创建nfs共享目录
mkdir -p /nfs/kubernetes
#修改nfs配置文件
vim /etc/exports
/nfs/kubernetes *(rw,no_root_squash)
#启动nfs并加入开机自启
systemctl start nfs
systemctl enable nfs
#尝试在别的K8s节点挂载nfs共享目录
mount -t nfs 192.168.0.13:/nfs/kubernetes /mnt/
部署nfs-storage
git clone https://github.com/kubernetes-incubator/external-storage
cd nfs-client/deploy
kubectl apply -f rbac.yaml # 授权访问apiserver
kubectl apply -f deployment.yaml # 部署插件,需修改里面NFS服务器地址与共享目录
kubectl apply -f class.yaml # 创建存储类
kubectl get sc # 查看存储类
部署statefulset控制器
vim statefulset-web.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: statefulset-web
spec:
serviceName: "handless-service"
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
storageClassName: "managed-nfs-storage"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1G
kubectl delete -f statefulset-web.yaml
kubectl apply -f statefulset-web.yaml
nfs服务器共享目录
测试在这三个pv目录下创建三个不同内容的index.html页面,然后访问对应不同的Pod的IP
验证访问
从上面图中,我们可以看到每个pod的数据都是独立存储的。
测试删除statefulset控制器
从上图可以看出,当我们删除pod的时候,并没有删除对应pvc和pv,而是做了数据的持久化。
再次重建测试能否访问之前的数据
从上图可以看出,重建之后,数据还是之前的数据,每个pvc对应绑定每个pv,pod的IP发生了变化。
kubernetes根据pod的编号找同样编号的pvc去挂载,从而实现了数据持久化。
通过编号保证每个pod的启动顺序
通过编号为每个pod创建不同的主机名以及dns A记录
通过编号为每个pod创建独立的pvc
StatefulSet 控制器:小结
StatefulSet与Deployment区别:有身份的!
身份三要素:
域名
主机名
存储(PVC)