13.headless、statefulset

一、headless

  通常会用service来为一组pod做负载均衡,但有时并不需要要这种负载均衡。比如一个集群服务(zk、kafka),客户端需要知道一组pod所有的ip;再比如由客户端自己处理的负载均衡逻辑(如两套mysql)。

  headless service配置就是把clusterIP改为None。spec.clusterIP.

  这样的执行kubectl describe svc zk 会显示两个Endpoints的地址,它们是两个POD的地址+端口。

  用nslookup查询headless service域名会出现两个IP。

  svc域名:servicename.namespace.svc.cluster.local

  每个pod都会拥有一个基于其顺序索引的稳定的主机名。重启pod,pod的IP会变化,名字不会变化。

在statefulset是一定要有headless

  在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。
    为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。

 

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx_web
spec:
  ports:
  - port: 80
    name: nginx-svcpord
  clusterIP: None
  selector:
    app: nginx_web

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-web
spec:
  selector:
    matchLabels:
      app: nginx_web
  serviceName: "nginx-svc"
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx_web
    spec:
      containers:
      - name: nginx-pod
        image: nginx
        ports:
        - containerPort: 80
          name: nginx-conpord

 

nslookup nginx-svc.default.svc.cluster.local 172.16.101.27  

 

 

 

这两个pod,是按顺序启动了,一台running了才会启动另外一个pod

 查询pod ip

pod域名:podname.svc名.default.cluster.local

 扩缩容statefulset

kubectl scale sts web --replicas=3 -n default   ##扩容
kubectl scale sts web --replicas=1 -n default    ##缩容

 

二、statefulset简介

  pod重新调度后podName及HostName不变。由Headless来实现。

  有序的部署,有序扩展,有序删除。pod的启动按定义好的顺序依次进行。下一个pod启动之前,前一个pod必须是running/ready。

  statefulset由3部分组成:

    Headless Service:

    volumeClaimTemplates:提供稳定的存储

    Statefulset:管理pod

 volumeClaimTemplates的作用:

  大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClainTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。Pod名称、PVC和PV关系图如下:

 

 statefulset使用时注意创建顺序:

  Volume--->Persistent Volume--->Persistent Volume Claim--->Service--->StatefulSet

 查看statefulset的定义

 

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>
   kind    <string>
   metadata    <Object>
   spec    <Object>
   status    <Object>
[root@k8s-master ~]# 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-    #选择器,必选项
   serviceName    <string> -required-  #服务名称,必选项
   template    <Object> -required-    #模板,必选项
   updateStrategy    <Object>       #更新策略
   volumeClaimTemplates    <[]Object>   #存储卷申请模板,列表对象形式

如上,一个完整的statefulset控制器由一个headless service、一个statefulset和一个volumeClaimTemplate组成。

三、例

vim stateful-demo.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-svc   ##定义headless service名,用于关联到每个pod资源创建DNS资源记录。
  labels:
    app: myapp-svc
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None  ##定义headless service
  selector:
    app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp  ##创建statefulset名
spec:
  serviceName: myapp-svc
  replicas: 3   ##3个副本
  selector:
    matchLabels:
      app: myapp-pod
  template:  ##定义pod template
    metadata:
      labels:
        app: myapp-pod
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: myappdata
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:  ##基于volumeclaimtemplates向已创建的pv进行请求存储卷
  - metadata:
      name: myappdata
    spec:
      accessModes: ["ReadWriteOnce"]
storageClassName: nfs resources: requests: storage: 2Gi ##请求2Gi的专用存储卷

 vim pv-demo.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
  labels:
    name: pv001
spec:
  persistentVolumeReclaimPolicy: Delete
  nfs:
    path: /data/volumes/v1
    server: nfs
  accessModes: ["ReadWriteMany","ReadWriteOnce"]
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: nfs
  accessModes: ["ReadWriteOnce"]
storageClassName: nfs capacity: storage: 2Gi
--- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: path: /data/volumes/v3 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv004 labels: name: pv004 spec: nfs: path: /data/volumes/v4 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"] storageClassName: nfs capacity: storage: 2Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv005 labels: name: pv005 spec: nfs: path: /data/volumes/v5 server: nfs accessModes: ["ReadWriteMany","ReadWriteOnce"]
storageClassName: nfs capacity: storage: 2Gi
kubectl get pv
kubectl get pvc
kubectl get sts
kubectl get pod -w

 

 

 

 

 

 

 

 启动pod是从myapp-0开始的。删除是从myapp-2开始的。用kubectl get pod -w       ##  -w实进刷新,可以看到myapp逐个启动/删除过程。

删除重建绑定的pv依然是原来的PVC,即myapp-0依然绑定的pv002

四、滚动更新、版本升级、更新策略

更新策略:.spec.updateStrategy.type   RollinUpdate    默认为RollingUpdate。

statefulset控制器将在statefulset中删除并重新创建每个pod。按序删除重建。

4.1.版本更新

把stateful-demo.yaml中的image版本修改为v2,再次kubectl apply -f stateful-demo.yaml更新

用kubectl get pod -w查看滚动更新过程。

在创建的每一个pod中,每个pod自已的名称都是可以被解析的。

 

4.2.扩展伸缩

kubectl scale sts myapp --replicas=4   ##副本增加到4个

 

 

 4.3.缩容

以补丁方式缩容

kubectl patch sts myapp -p '{"spec":{"replicas":2}}'

 

 

4.4.更新策略和版本升级

修改更新策略,让只有编号>=2的才会进行更新。

kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'

 

 版本升级,将image版本改为2,升级后对比myapp-2和myapp-1的image版本是不一样的,这样就实现金丝雀发布效果。

kubectl set image sts/myapp myapp=ikubernetes/myapp:v3

kubectl get pods myapp-2 -o yaml | grep image

把剩下的pod也更新版本,只需要将partition值改为0

kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}'

 

posted @ 2021-12-14 16:38  天涯160  阅读(629)  评论(0)    收藏  举报