配置一个简单的StatefulSet

  RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群等。

  StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。

  在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。

  除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,这个域名的格式为:
$(podname).(headless server name)
  FQDN:$(podname).(server name).namespace.svc.cluster.local

  StatefulSet中每个Pod的DNS格式为statefulSetname-{0..N-1}.serviceName.namespace.svc.cluster.local,其中(用的时候只写到服务名就能通了)
    1. serviceName为headless Service的名字
    2. 0..N-1 为Pod所在的序号,从0开始到N-1
    3. statefulSetName 为StatefulSet的名字
    4. namespace为服务所在的namespace,Headless Servie和statefulSet必须在相同的namespace
    5. .cluster.local 为ClusterDomain

 

特点: 

  Pod一致性:包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关;
  稳定的次序:对于N个副本的StatefulSet,每个Pod都在[0,N)的范围内分配一个数字序号,且是唯一的;
  稳定的网络:Pod的hostname模式为( s t a t e f u l s e t 名 称 ) − (statefulset名称)-(statefulset名称)−(序号);
  稳定的存储:通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。

 

一个简单的nginx服务 web.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:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.2
        ports:
        - containerPort: 80
          name: web
#将上面配置文件保存为web.yaml 然后在另外起一个pod做客户端访问用,(pod命名方式上面有介绍)
kubectl apply -f web.yaml
kubectl get pod
        NAME     READY   STATUS    RESTARTS   AGE
        my-pod   1/1     Running   0          5m4s
        web-0    1/1     Running   0          19m
        web-1    1/1     Running   0          19m
        web-2    1/1     Running   0          16m
        
 kubectl exec -it my-pod -- bash
 curl web-0.nginx
 #会发现即使没有配置ip地址也能将这个解析为podip

 

StatefulSet扩缩容

创建:只有在上一个pod启动完成后才会开始启动下一个pod,如果上一个没有启动成功,将不会启动下一个pod

删除:相反从下往上删,在删除过程中,正在删除上面的所有pod必须是running状态,如果不是running将会暂停,直到上面的pod全部为running才会开始删

kubectl scale --replicas=2 sts web
#设置StatefulSet副本数,命令

 

 

StatefulSet更新策略

滚动更新:

updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate

StatefulSet更新策略和删除差不多,从下往上更新,如果更新途中上面的pod挂了,那么就会等到上面的pod running了在继续更新

 

OnDelete:

在设置成OnDelete时,只有在删除时候才会去更新镜像

updateStrategy:
    type: OnDelete
    
#修改完毕后可以删除一个镜像然后让他自动创建,创建之后才会更新

 

StatefulSet灰度更新

partition: 0
#在上上面有一个这个字段,那么这个字段是什么意思呢?
    #就是小于这个值的pod,不更新(不包括等于)

思路:

我们在更新的时候,通过控制partition这个字段,一个一个的更新,看看结果如何。如果没问题,在继续更新下一个

 

 

StatefulSet级联更新和级联删除

级联更新和级联删除

就是删除stat时 同时删除Pod,默认的是级联删除

kubectl delete sts web

 

非级联删除

删除sts时 不删除Pod

kubectl delete sts web --cascade=false
#非级联删除就是删除时候多加了一个选项
#删除statefulSet后,他所构建的pod就变成了孤儿,此时在删除pod就没有进程去重新构建他了