Kubernetes控制器 —— Statefulset

目录

一、Statefulset控制器概念

1.Statefulset是为了管理有状态服务的问提设计的

2.Statefulset资源清单文件编写技巧

3.Statefulset使用案例:部署web站点

4.Statefulset管理pod:扩容、缩容、更新


一、Statefulset控制器概念

1.Statefulset是为了管理有状态服务的问提设计的

什么是有服务状态?

StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、redis集群等。

什么是无状态服务?

RC、Deployment、DaemonSet都是管理无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的。个体对整体无影响,所有pod都是共用一个数据卷的,部署的tomcat就是无状态的服务,tomcat被删除,在启动一个新的tomcat,加入到集群即可,跟tomcat的名字无关。

StatefulSet由以下几个部分组成:

1. Headless Service:用来定义pod网络标识,生成可解析的DNS记录

2. volumeClaimTemplates:存储卷申请模板,创建pvc,指定pvc名称大小,自动创建pvc,且pvc由存储类供应。

3. StatefulSet:管理pod的

什么是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一个唯一的名称。

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

如 主机名是 duoduo

域名是 baidu.com

FQDN= duoduo.baidu.com

2.StatefulSet会为关联的Pod保持一个不变的Pod Name

statefulset中Pod的名字格式为$(StatefulSet name)-$(pod序号)

3.StatefulSet会为关联的Pod分配一个dnsName

$<Pod Name>.$<service name>.$<namespace name>.svc.cluster.local

为什么要用volumeClaimTemplate?

对于有状态应用都会用到持久化存储,比如mysql主从,由于主从数据库的数据是不能存放在一个目录下的,每个mysql节点都需要有自己独立的存储空间。而在deployment中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,它们数据是同步的,而statefulset定义中的每一个pod都不能使用同一个存储卷,这就需要使用volumeClainTemplate,当在使用statefulset创建pod时,volumeClainTemplate会自动生成一个PVC,从而请求绑定一个PV,每一个pod都有自己专用的存储卷。Pod、PVC和PV对应的关系图如下:

2.Statefulset资源清单文件编写技巧

#查看定义Statefulset资源需要的字段

[root@hd1.com ~]# kubectl explain statefulset

FIELDS:

   apiVersion       <string> #定义statefulset资源需要使用的api版本

   kind  <string>          #定义的资源类型

   metadata         <Object>     #元数据

   spec <Object>          #定义容器相关的信息

#查看statefulset.spec字段如何定义?

[root@hd1.com ~]# kubectl explain statefulset.spec

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@hd1.com ~]# kubectl explain statefulset.spec.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。

3.Statefulset使用案例:部署web站点

#创建存储类

[root@hd1.com ~]# cat class-web.yaml

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

  name: nfs-web

provisioner: example.com/nfs

#更新资源清单文件

[root@hd1.com ~]# kubectl apply -f class-web.yaml

  #把nginx的离线压缩包nginx.tar.gz上传到hd2.comhd3.com上,手动解压:

  [root@hd2.com ~]# docker load -i nginx.tar.gz

#编写一个Statefulset资源清单文件

[root@hd1.com ~]# cat statefulset.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: web

spec:

  selector:

    matchLabels:

      app: nginx

  serviceName: "nginx"

  replicas: 2

  template:

    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-web"

      resources:

        requests:

          storage: 1Gi

#更新资源清单文件

[root@hd1.com ~]# kubectl apply -f statefulset.yaml

service/nginx created

statefulset.apps/web created

#查看statefulset是否创建成功

[root@hd1.com ~]# kubectl get statefulset

NAME   READY   AGE

web      2/2      42s

#查看pod

[root@hd1.com ~]# kubectl get pods -l app=nginx

NAME    READY   STATUS    RESTARTS   AGE

web-0   1/1     Running   0          2m17s

web-1   1/1     Running   0          115s

#通过上面可以看到创建的pod是有序的

#查看headless service

[root@hd1.com ~]# kubectl get svc -l app=nginx

NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE

nginx    ClusterIP      None         <none>        80/TCP    3m19s

#查看pvc

[root@hd1.com ~]# kubectl get pvc

#查看pv

[root@hd1.com ~]# kubectl get pv   

#查看pod主机名

[root@hd1.com ~]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname';done

web-0

web-1

#使用k运行一个提供nslookup命令的容器(bubybox:1.28),这个命令来自于dnsutils包,通过对pod主机名执行nslookup,可以检查它们在集群内部的DNS地址:

[root@hd1 ~]# cat pod-second.yaml

apiVersion: v1

kind: Pod

metadata:

  name: pod-second

  labels:

    app: backend

    tier: db

spec:

    containers:

    - name: busybox

      image: busybox:1.28

      imagePullPolicy: IfNotPresent

      command: ["sh","-c","sleep 3600"]

#更新资源清单

[root@hd1 ~]# kubectl apply -f pod-second.yaml

[root@hd1 ~]# kubectl exec -it pod-second -- /bin/sh

/ # nslookup  web-0.nginx.default.svc.cluster.local

Server:    10.96.0.10

Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      web-0.nginx.default.svc.cluster.local

Address 1: 10.244.156.137 web-0.nginx.default.svc.cluster.local

/ #

#statefulset创建的pod也是有dns记录的

Address: 10.244.209.154  #解析的是pod的ip地址

还可以解析  nginx.default.svc.cluster.local

/ # nslookup  nginx.default.svc.cluster.local

Server:    10.96.0.10

Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      nginx.default.svc.cluster.local

Address 1: 10.244.25.245 web-1.nginx.default.svc.cluster.local

Address 2: 10.244.156.137 web-0.nginx.default.svc.cluster.local

/ #

#资源清单详细解读:

apiVersion: v1  #定义api版本

kind: Service   #定义要创建的资源:service

metadata:

  name: nginx   #定义service的名字

  labels:

     app: nginx  #service的标签

spec:

  ports:

  - port: 80

    name: web

  clusterIP: None  #创建一个没有ip的service

  selector:

    app: nginx     #选择拥有app=nginx标签的pod

---

apiVersion: apps/v1

kind: StatefulSet

metadata:

  name: web

spec:

  selector:

    matchLabels:

      app: nginx

  serviceName: "nginx"  #headless service的名字

  replicas: 2              #副本数

  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-web"  #指定从哪个存储类申请pv

      resources:

        requests:

          storage: 1Gi   #需要1G的pvc,会自动跟符合条件的pv绑定

4.Statefulset管理pod:扩容、缩容、更新

#Statefulset实现pod的动态扩容

如果我们觉得两个副本太少了,想要增加,只需要修改配置文件statefulset.yaml里的replicas的值即可,原来replicas: 2,现在变成replicaset: 3,修改之后,执行如下命令更新:

[root@hd1.com ~]# kubectl apply -f statefulset.yaml

service/nginx unchanged

statefulset.apps/web configured

[root@hd1.com ~]# kubectl get sts

NAME   READY   AGE

web    3/3     60m

[root@hd1.com ~]# kubectl get pods -l app=nginx

NAME    READY   STATUS    RESTARTS   AGE

web-0   1/1     Running   0          61m

web-1   1/1     Running   0          60m

web-2   1/1     Running   0          79s

#也可以直接编辑控制器实现扩容

[root@hd1.com ~]# kubectl edit sts web

#这个是我们把请求提交给了apiserver,实时修改

把上面的spec下的replicas 后面的值改成4,保存退出

[root@hd1.com ~]#  kubectl get pods -l app=nginx

NAME    READY   STATUS    RESTARTS   AGE

web-0   1/1     Running   0          62m

web-1   1/1     Running   0          62m

web-2   1/1     Running   0          3m13s

web-3   1/1     Running   0          26s

#Statefulset实现pod的动态缩容

如果我们觉得4个Pod副本太多了,想要减少,只需要修改配置文件statefulset.yaml里的replicas的值即可,把replicaset:4变成replicas: 2,修改之后,执行如下命令更新:

[root@hd1.com ~]# kubectl apply -f statefulset.yaml

service/nginx unchanged

statefulset.apps/web configured

[root@hd1.com ~]#  kubectl get pods -l app=nginx

NAME    READY   STATUS    RESTARTS   AGE

web-0   1/1     Running   0          64m

web-1   1/1     Running   0          64m

#Statefulset实现pod的更新

# myapp.tar.gz上传到hd2.com上,手动解压

把[root@hd2.com ~]# docker load -i myapp.tar.gz

[root@hd1.com ~]# kubectl edit sts web

#修改镜像nginx变成- image: ikubernetes/myapp:v2,修改之后保存退出 

[root@hd1.com ~]# kubectl get pods -o wide -l app=nginx

NAME    READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATES

web-0   1/1     Running   0          18s   10.244.209.156   hd2.com  

web-1   1/1     Running   0          36s   10.244.187.115   hd3.com

#查看pod详细信息

[root@hd1.com ~]# kubectl describe pods web-0

通过上面可以看到pod已经使用刚才更新的镜像ikubernetes/myapp:v2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值