一,概念
为了管理有状态服务(如数据库mysql等)的问题,采用Statefulset来管理
【有状态服务】
StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、Redis集群等。
【无状态服务】
Replicaset、Deployment、DaemonSet都是管理无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷。
二,常用字段
# kubectl explain statefulset
apiVersion <string> #定义statefulset资源的api版本
kind <string> #定义的资源类型
metadata <Object> #元数据
spec <Object> #定义容器相关的信息
# kubectl explain statefulset.spec
podManagementPolicy <string> # pod管理策略
replicas <integer> # 副本数
revisionHistoryLimit <integer> # 保留的历史版本
selector <Object> -required- # 标签选择器,选择它所关联的pod
serviceName <string> -required- # headless service的名字 *特有字段*
template <Object> -required- # 生成pod的模板
updateStrategy <Object> # 更新策略
volumeClaimTemplates <[]Object> # 存储卷申请模板 *特有字段*
# 对于template而言,其内部定义的就是pod,pod模板是一个独立的对象
# kubectl explain statefulset.spec.template
metadata <Object>
spec <Object> #定义容器属性的
【注意】:
- 第一个spec声明的是statefulset定义多少个Pod副本(默认为1)、匹配Pod标签的选择器、创建pod的模板、存储卷申请模板。
- 第二个spec是
spec.template.spec
:主要用于Pod里的容器属性等配置。在声明Pod对象时,要定义的各种属性,所以这部分也叫做PodTemplate(Pod模板)。- 在.spec.selector中定义的标签选择器,必须能够匹配到
spec.template.metadata.labels
里定义的Pod标签,否则Kubernetes将不允许创建statefulset。
三,案例
本案例,用于模拟部署web站点。
# cat statefulset.yaml
apiVersion: v1 # 定义api版本
kind: Service # 定义要创建的资源:service
metadata:
name: nginx # 定义service的名字
labels:
app: nginx # service的标签
spec:
ports:
- port: 80
name: web
clusterIP: None # 创建service,并且其没有分配ip
selector:
app: nginx # 选择拥有app=nginx标签的pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
replicas: 2 # 副本数
selector:
matchLabels:
app: nginx
serviceName: "nginx" # headless service的名字(上方创建的service的名字)
template: # 定义pod的模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates: # 存储卷申请模板
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs # 指定从哪个存储类申请pv
resources:
requests:
storage: 1Gi # 需要1G的pvc,会自动跟符合条件的pv绑定
创建kubectl apply -f statefulset.yaml
后,查看如下资源是否创建成功:
# 查看statefulset是否创建成功
kubectl get statefulset
# 查看是否是有序的pod
kubectl get pods -l app=nginx
#查看pvc
kubectl get pvc
#查看pv
kubectl get pv
【备注】:
StatefulSet由以下几个部分组成:
- Headless Service:用来定义pod网路标识,生成可解析的DNS记录
- volumeClaimTemplates:存储卷申请模板,创建pvc,指定pvc名称大小,自动创建pvc,且pvc由存储类供应。
- StatefulSet:管理pod的
Statefulset总结:
1、Statefulset管理的pod,pod名字是有序的,由statefulset的名字-0、1、2这种格式组成
2、创建statefulset资源前,必须先创建出一个service。
- 如果创建的service没有ip,那对这个service做dns解析,会找到它所关联的所有pod ip;
- 如果创建的service有ip,那对这个service做dns解析,会解析到service本身ip;
3、在管理的pod中,删除pod后再新创建,pod名字跟删除的pod名字一样。
4、statefulset具有字段volumeclaimtemplate(卷申请模板)
,它会自动创建已绑定的pv和pvc。
5、创建的pod,数据目录是独享的。
6、关联的Pod分配一个dnsName,域名组成:pod-name.svc-name.svc-namespace.svc.cluster.local
四,扩容、缩容、更新
1,扩容、缩容
修改配置文件statefulset.yaml里的replicas的值即可。
扩容:将该值,调大;
缩容:将该值,调小;
然后执行:
kubectl apply -f statefulset.yaml
2,更新(一般指镜像更新)
A,更新策略类型sts.spec.updateStrategy.type
:rollingUpdate(默认)
【说明】:
partition: 1表示更新的时候,只会把pod序号大于等于1的进行更新。
B,更新策略类型sts.spec.updateStrategy.type
:OnDelete
测试更新,不会自动更新pod,需要手动删除,重新创建的pod才会实现更新。
【扩展】:
(1)Headless service 是什么意思?
Headless service不分配clusterIP,headless service可以通过解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通过解析service的DNS返回service的ClusterIP。
(2)K8s中资源的全局FQDN格式:
Service_NAME.NameSpace_NAME.Domain.LTD.
Domain.LTD.=svc.cluster.local. #这是默认k8s集群的域名。
FQDN( 全称 Fully Qualified Domain Name),即全限定域名:同时带有主机名和域名的名称
FQDN = Hostname + DomainName
(例如: 主机名是 boke ,域名是 baidu.com,则FQDN= boke.baidu.com)