1、概念 StatefulSet是为了管理有状态服务的问题而设计的
有状态服务? StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、redis集群等。
无状态服务? RC、Deployment、DaemonSet都是管理无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。
2、组成
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。
在使用Deployment时,创建的Pod名称是没有顺序的,是随机字符串,在用statefulset管理pod时要求pod名称必须是有序的 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。因为pod IP是变化的,所以要用Pod名称来识别。pod名称是pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称。
headless service会为service分配一个域名
.$.svc.cluster.local
K8s中资源的全局FQDN格式: Service_NAME.NameSpace_NAME.Domain.LTD. Domain.LTD.=svc.cluster.local. ##这是默认k8s集群的域名。
FQDN 全称 Fully Qualified Domain Name
即全限定域名:同时带有主机名和域名的名称
FQDN = Hostname + DomainName
如 主机名是 xianchao
域名是 baidu.com
FQDN= xianchao.baidu.com
2.StatefulSet会为关联的Pod保持一个不变的Pod Name statefulset中Pod的名字格式为$(StatefulSet name)-$(pod序号)
3.StatefulSet会为关联的Pod分配一个dnsName $.$.$.svc.cluster.local
为什么要用volumeClaimTemplate? 对于有状态应用都会用到持久化存储,比如mysql主从,由于主从数据库的数据是不能存放在一个目录下的,每个mysql节点都需要有自己独立的存储空间。而在deployment中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,它们数据是同步的,而statefulset定义中的每一个pod都不能使用同一个存储卷,这就需要使用volumeClaimTemplate,当在使用statefulset创建pod时,volumeClaimTemplates会自动生成一个PVC,从而请求绑定一个PV,每一个pod都有自己专用的存储卷。Pod、PVC和PV对应的关系图如下:
3、statefulset资源清单编写技巧 1、查看定义statefulset资源清单所需字段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@master2 ~] KIND: StatefulSet VERSION: apps/v1 DESCRIPTION: StatefulSet represents a set of pods with consistent identities. Identities are defined as: - Network: A single stable DNS and hostname. - Storage: As many VolumeClaims as requested. The StatefulSet guarantees that a given network identity will always map to the same storage identity. FIELDS: apiVersion <string> kind <string> metadata <Object> spec <Object>
2、查看statefulset.spec字段定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@master2 ~] KIND: StatefulSet VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: Spec defines the desired identities of pods in this set . A StatefulSetSpec is the specification of a StatefulSet. FIELDS: podManagementPolicy <string> replicas <integer > revisionHistoryLimit <integer > selector <Object> -required- serviceName <string> -required- template <Object> -required- updateStrategy <Object> volumeClaimTemplates <[]Object>
3、查看statefulset的spec.template字段定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@xianchaomaster1 ~] KIND: StatefulSet VERSION: apps/v1 RESOURCE: template <Object> DESCRIPTION: template is the object that describes the pod that will be created if insufficient replicas are detected. Each pod stamped out by the StatefulSet will fulfill this Template, but have a unique identity from the rest of the StatefulSet. PodTemplateSpec describes the data a pod should have when created from a template FIELDS: metadata <Object> spec <Object>
statefulset资源中有两个spec字段。第一个spec声明的是statefulset定义多少个Pod副本(默认将仅部署1个Pod)、匹配Pod标签的选择器、创建pod的模板、存储卷申请模板,第二个spec是spec.template.spec:主要用于Pod里的容器属性等配置。
.spec.template里的内容是声明Pod对象时要定义的各种属性,所以这部分也叫做PodTemplate(Pod模板)。还有一个值得注意的地方是:在.spec.selector中定义的标签选择器必须能够匹配到spec.template.metadata.labels里定义的Pod标签,否则Kubernetes将不允许创建statefulset 。
4、statefulset配置文件 1、storage_web.yml 1 2 3 4 5 6 [root@master1 statefulset] apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-web provisioner: example.com/nfs
2、statefulset.yml 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 50 51 52 [root@master1 statefulset] 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: nfs-web namespace: default labels: app: statefulset-nginx spec: selector: matchLabels: app: nginx serviceName: "nginx" replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - name: web containerPort: 80 volumeMounts: - name: web-pvc mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: web-pvc spec: accessModes: ["ReadWriteOnce" ,"ReadWriteMany" ] storageClassName: nfs-web resources: requests: storage: 2Gi
3、查看pv、pvc、pod 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 [root@master1 statefulset] nfs-web-0 1/1 Running 0 12m nfs-web-1 1/1 Running 0 12m nfs-web-2 1/1 Running 0 12m [root@master1 statefulset] pvc-25a5b88a-c131-472b-bc8a-76acecd9f719 2Gi RWO,RWX Delete Bound default/web-pvc-nfs-web-1 nfs-web 22m pvc-cc8e5814-a794-4fe0-80c5-a3b052e0e249 2Gi RWO,RWX Delete Bound default/web-pvc-nfs-web-0 nfs-web 22m pvc-eb313078-e6c2-4f6c-b619-466706aa8d8d 2Gi RWO,RWX Delete Bound default/web-pvc-nfs-web-2 nfs-web [root@master1 statefulset] web-pvc-nfs-web-0 Bound pvc-cc8e5814-a794-4fe0-80c5-a3b052e0e249 2Gi RWO,RWX nfs-web 22m web-pvc-nfs-web-1 Bound pvc-25a5b88a-c131-472b-bc8a-76acecd9f719 2Gi RWO,RWX nfs-web 22m web-pvc-nfs-web-2 Bound pvc-eb313078-e6c2-4f6c-b619-466706aa8d8d 2Gi RWO,RWX nfs-web 22m [root@master1 statefulset] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.255.0.1 <none> 443/TCP 11d nginx ClusterIP None <none> 80/TCP 22m [root@master1 statefulset] NAME READY AGE CONTAINERS IMAGES nfs-web 3/3 23m nginx nginx [root@master1 statefulset] nfs-web-0 nfs-web-1 nfs-web-2
4、资源清单详细解读 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 50 51 52 [root@master1 statefulset] 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: nfs-web namespace: default labels: app: statefulset-nginx spec: selector: matchLabels: app: nginx serviceName: "nginx" replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent ports: - name: web containerPort: 80 volumeMounts: - name: web-pvc mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: web-pvc spec: accessModes: ["ReadWriteOnce" ,"ReadWriteMany" ] storageClassName: nfs-web resources: requests: storage: 2Gi
5、statefulset管理pod:扩容、缩容、更新 建议更新的时候直接更改yaml文件,直接edit会导致再次应用yaml文件的时候参数还是和原来的
1、动态扩容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@master1 statefulset] replicas: 5 [root@master1 statefulset] service/nginx unchanged statefulset.apps/nfs-web configured [root@master1 statefulset] nfs-web-0 1/1 Running 0 49m nfs-web-1 1/1 Running 0 49m nfs-web-2 1/1 Running 0 49m nfs-web-3 1/1 Running 0 12s nfs-web-4 1/1 Running 0 8s
2、动态缩容 1 2 3 4 5 6 7 8 9 10 11 12 13 [root@master1 statefulset] replicas: 2 [root@master1 statefulset] service/nginx unchanged statefulset.apps/nfs-web configured [root@master1 statefulset] nfs-web-0 1/1 Running 0 53m nfs-web-1 1/1 Running 0 53m
3、更新 1 2 3 4 5 [root@master1 statefulset] image: ikubernetes/myapp:v2 [root@master1 statefulset]
statefulset.spec.updateStrategy.rollingUpdate.partition :这个参数默认为0,如果为1,则生成的pod名字序列号大于等于1的进行更新,也就是说除了0都进行更新了。