文章目录
一、StatefulSet理论知识
1、StatefulSet Pod控制器特性
StatefulSet(简写sts)也是K8S集群中的一种Pod资源管理器,与deployment Pod控制器不同的是,StatefulSet用于管理无状态程序,特性如下:
- 稳定的网络标识符:管理的Pod都拥有一个稳定的网络标识符。可以通过网络标识符进行访问。
- 有序部署和扩展:StatefulSet会按照指定的顺序逐个部署Pod,每个Pod都有一个唯一的序号,这个序号在整个生命周期中都不会改变。在扩展时,也会按照指定的顺序逐个增加Pod。
- 稳定的存储:每个Pod都用一个独立的持久卷存储,比如NFS。
- 有状态服务:StatefulSet适用于有状态的服务,例如数据库、缓存等,这些服务需要稳定的网络标识符和持久化存储。
总之,StatefulSet提供了一种可靠的、有序的、有状态的服务部署和扩展方式,适用于需要稳定网络标识符和持久化存储的有状态服务。
2、什么是有状态服务和无状态服务?
无状态服务则是指不需要持久化存储和状态的服务,例如Web服务器、API服务器等。这些服务可以在任何节点上运行,因为它们不需要在不同节点之间共享数据,也不需要在节点故障时进行快速恢复。无状态服务可以通过水平扩展来提高性能和可用性。
有状态服务是指需要持久化存储并且需要保持状态的服务,例如数据库、缓存等。这些服务需要在不同的节点之间保持数据同步,并且需要在节点故障时能够快速恢复。
3、Deployment和StatefulSet区别
Deployment和StatefulSet是Kubernetes中常用的两种控制器,它们的主要区别如下:
-
Deployment是用于管理无状态应用的控制器,而StatefulSet则是用于管理有状态应用的控制器。
-
Deployment可以创建多个Pod副本,这些Pod副本之间没有任何顺序关系,可以随意调度和替换。而StatefulSet创建的Pod副本有固定的顺序,每个Pod副本都有唯一的标识符,可以保证有状态应用的数据持久性和稳定性。
-
Deployment可以进行滚动更新,即在更新过程中保持应用的可用性。而StatefulSet的更新过程需要手动控制,需要先删除旧的Pod副本,再创建新的Pod副本,因此更新过程中会有一定的停机时间。
-
Deployment可以使用RollingUpdate策略进行滚动更新,而StatefulSet则可以使用OnDelete和RollingUpdate两种策略进行更新。
总之,Deployment适用于管理无状态应用,而StatefulSet适用于管理有状态应用。如果应用需要保证数据的持久性和稳定性,建议使用StatefulSet。
二、案例:StatefulSet资源实战演示
1、创建WEB站点并验证StatefulSet特点
第一步:创建名为 sts-web-svc
的SVC ,用于创建statefulset资源时需要关联service,YAML如下:
cat sts-web-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: sts-web-svc
spec:
selector:
app: web-nginx
ports:
- port: 80
targetPort: 80
clusterIP: None # 设置无IP地址
创建 svc 资源:
kubectl apply -f sts-web-svc.yaml
查看创建的 svc 资源,如下图可以看到创建的svc并没有分配IP地址:
kubectl get svc sts-web-svc
第二步:创建statefulset资源
cat sts-web.yaml
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sts-web
namespace: default
spec:
serviceName: sts-web-svc # 关联SVC资源
replicas: 2 # 副本数
selector:
matchLabels: # 关联具有app=web-nginx标签的Pod
app: web-nginx
volumeClaimTemplates: # 卷申请模板
- metadata:
name: www # 卷申请模板名称
spec:
accessModes: ["ReadWriteOnce"] # 访问模式
storageClassName: nfs # 指定供应商,前提是需要存在此供应商
resources:
requests:
storage: 1Gi # 存储大小1G
template:
metadata:
labels:
app: web-nginx
spec:
containers:
- name: web-nginx
image: nginx:1.18.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www # 指定卷申请模板名称
mountPath: /usr/share/nginx/html
startupProbe: # 启动探测
tcpSocket:
port: 80
执行 YAML :
kubectl apply -f sts-web.yaml
第三步:特点测试
1、Pod都有一个唯一的序号:如下图Pod名字有序
kubectl get pods -l app=web-nginx -o wide
删除 sts-web-0,Pod后自动创建出来的Pod名称不会改变
kubectl delete pod sts-web-0
2、Pod独立持久卷存储:查看PVC,自动生成两个PVC,相互隔离
kubectl get pvc -l app=web-nginx
ls /data/nfs_pro|grep default-www-sts-web-*
3、稳定的网络标识符:我们使用busybox运行Pod,nslookup进行解析
2、StatefulSet滚动更新
滚动更新使用 spec.updateStrategy
字段定义,目前statefulset支持两种更新策略如下:
- RollingUpdate:滚动更新
- OnDelete:不会自动更新,手动删除Pod后进行更新
下面演示滚动更新:
第一步:创建并执行statefulset资源
cat web-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80
clusterIP: None
创建statefulset,使用nginx:1.18 镜像
cat web.yaml
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
namespace: default
spec:
serviceName: web
replicas: 5
selector:
matchLabels:
app: web
updateStrategy:
rollingUpdate:
maxUnavailable: 0 # 最多不可用Pod,0表示2个Pod可用
partition: 2 # 只更新序号大于等于partition值的Pod
volumeClaimTemplates:
- metadata:
name: web
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs
resources:
requests:
storage: 1Gi
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: nginx:1.18.0 # 使用1.18.0版本镜像
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: web
mountPath: /usr/share/nginx/html
执行YAML文件
kubectl apply -f web-svc.yaml
kubectl apply -f web.yaml
第二步:更新使用 nginx:latest
镜像
重新YAML 一下:
kubectl apply -f web.yaml
验证:由于我们partition: 2
所以Pod不会全部更新,只会更新序号大于2的Pod,包括2
三、总结
- statefulset管理的Pod名称是有序的,删除指定Pod后自动创建的Pod名称不会改变。
- statefulset创建时必须指定server名称,如果server没有IP地址,则会对server进行DNS解析,找到对应的Pod域名。
- statefulset具有volumeclaimtemplate卷管理模板,创建出来的Pod都具有独立卷,相互没有影响。
- statefulset创建出来的Pod,拥有独立域名,我们在指定访问Pod资源时,可以使用域名指定,IP会发生改变,但是域名不会(域名组成:Pod名称svc名称.svc名称空间.svc.cluster.local)