k8s-Statefulset
Statefulset控制器:概念、原理解读
- StatefulSet是为了管理有状态服务的问题而设计的
扩展:
有状态服务?
StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、redis集群等。
无状态服务?
RC、Deployment、DaemonSet都是管理无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。
StatefulSet由以下几个部分组成:
- Headless Service:用来定义pod网路标识,生成可解析的DNS记录
- volumeClaimTemplates:存储卷申请模板,创建pvc,指定pvc名称大小,自动创建pvc,且pvc由存储类供应。
- StatefulSet:管理pod的
Headless Service
扩展:什么是Headless service?
Headless service不分配clusterIP,headless service可以通过解析service的DNS,返回所有Pod的dns和ip地址 (statefulSet部署的Pod才有DNS),普通的service,只能通过解析service的DNS返回service的ClusterIP。
为什么要用headless service(没有service ip的service)?
在使用Deployment时,创建的Pod名称是没有顺序的,是随机字符串,在用statefulset管理pod时要求pod名称必须是有序的 ,每一个pod不能被随意取代,pod重建后pod名称还是一样的。因为pod IP是变化的,所以要用Pod名称来识别。pod名称是pod唯一性的标识符,必须持久稳定有效。这时候要用到无头服务,它可以给每个Pod一个唯一的名称。
Headless service的作用
- 1.headless service会为service分配一个域名
<service name>.$<namespace name>.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序号)
- statefulset中Pod的名字格式为$(StatefulSet name)-$(pod序号)
- 3.StatefulSet会为关联的Pod分配一个dnsName
- $<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local
volumeClaimTemplates
为什么要用volumeClaimTemplate?
对于有状态应用都会用到持久化存储,比如mysql主从,由于主从数据库的数据是不能存放在一个目录下的,每个mysql节点都需要有自己独立的存储空间。而在deployment中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,它们数据是同步的,而statefulset定义中的每一个pod都不能使用同一个存储卷,这就需要使用volumeClainTemplate,当在使用statefulset创建pod时,volumeClainTemplate会自动生成一个PVC,从而请求绑定一个PV,每一个pod都有自己专用的存储卷。Pod、PVC和PV对应的关系图如下
Statefulset资源清单文件编写技巧
#查看定义Statefulset资源需要的字段
[root@master01 w]# kubectl explain statefulset
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> #定义statefulset资源需要使用的api版本
kind <string> #定义的资源类型
metadata <Object> #元数据
spec <Object> #定义容器相关的信息
#查看statefulset.spec字段如何定义?
[root@master01 w]# kubectl explain statefulset.spec 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> #pod管理策略 replicas <integer> #副本数 revisionHistoryLimit <integer> #保留的历史版本 selector <Object> -required- #标签选择器,选择它所关联的pod serviceName <string> -required- #headless service的名字 template <Object> -required- #生成pod的模板 updateStrategy <Object> #更新策略 volumeClaimTemplates <[]Object> #存储卷申请模板
#查看statefulset的spec.template字段如何定义?
#对于template而言,其内部定义的就是pod,pod模板是一个独立的对象
[root@master01 w]# kubectl explain statefulset.spec.template 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。
Statefulset使用案例:部署web站点
#创建存储类-------------[这个存储类的前提要有供应商,供应商的创建请查看 k8s-持久化存储[PVC]]
[root@master01 w]# cat class-web.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-web provisioner: example.com/nfs
#更新资源清单文件
[root@master01 w]# kubectl apply -f class-web.yaml storageclass.storage.k8s.io/nfs-web created
#编写一个Statefulset资源清单文件
[root@master01 w]# cat nginx.yaml 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: nginx-sf labels: app: nginx spec: replicas: 2 serviceName: "nginx" ##svc的名字 selector: matchLabels: app: hwf 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 accessModes: ["ReadWriteOnce"] #访问模式 storageClassName: nfs-web #存储类的名字 resources: requests: storage: 1Gi
#更新资源清单文件
[root@master01 w]# kubectl apply -f nginx.yaml service/nginx unchanged statefulset.apps/nginx-sf created
#查看sc
[root@master01 w]# kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs example.com/nfs Delete Immediate false 17h nfs-web example.com/nfs Delete Immediate false 48m
[root@master01 w]# kubectl get statefulsets NAME READY AGE nginx-sf 2/2 3m33s
#查看容器主机名
[root@master01 w]# for i in 0 1;do kubectl exec nginx-sf-$i -- sh -c 'hostname';done
nginx-sf-0
nginx-sf-1
测试Pod的DNS解析
#使用kubectl run运行一个提供nslookup命令的容器的,这个命令来自于dnsutils包,通过对pod主机名执行nslookup,可以检查它们在集群内部的DNS地址:
[root@master01 w]# kubectl exec -it nginx-sf-0 -- sh # nslookup sh: 2: nslookup: not found # apt-get update # apt-get install dnsutils -y
# nslookup nginx-sf-0.nginx.default.svc.cluster.local Server: 10.1.0.10 Address: 10.1.0.10#53 Name: nginx-sf-0.nginx.default.svc.cluster.local Address: 172.16.196.169

评论