Kubernetes 第十三章 StatefulSet

StatefulSet

StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  • 有序收缩,有序删除(即从N-1到0)

从上面的应用场景可以发现,StatefulSet由以下几个部分组成:

  • 用于定义网络标志(DNS domain)的Headless Service
  • 用于创建PersistentVolumes的volumeClaimTemplates
  • 定义具体应用的StatefulSet

StatefulSet中每个Pod的DNS格式为statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local,其中

  • serviceName为Headless Service的名字
  • 0..N-1为Pod所在的序号,从0开始到N-1
  • statefulSetName为StatefulSet的名字
  • namespace为服务所在的namespace,Headless Servic和StatefulSet必须在相同的namespace
  • .cluster.local为Cluster Domain,

简单示例

以一个简单的 nginx 服务 web.yaml 为例:

[[email protected] pv-pvc]# cat pv_statefulset.yaml       //PV 需要事先创建//persistentVolumeReclaimPolicy: Recycle storageClassName: slow     这两个字段不定义,否则 volumeClaimTemplates: 无法动态生成pvc 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /nfs/data/v1
    server: 10.2.61.21
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0002
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /nfs/data/v2
    server: 10.2.61.21
[[email protected] pv-pvc]# 
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: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 2Gi
[[email protected] pv-pvc]# kubectl get pv  //查看 pv  ,pvc ,sts
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
pv0001   5Gi        RWO            Retain           Bound    default/www-web-0                           5m3s
pv0002   5Gi        RWO            Retain           Bound    default/www-web-1                           5m3s
[[email protected] pv-pvc]# kubectl get pvc
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pv0001   5Gi        RWO                           4m41s
www-web-1   Bound    pv0002   5Gi        RWO                           4m19s
[[email protected] pv-pvc]# kubectl get pods    //查看 pod  都是 有序的
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          4m46s
web-1   1/1     Running   0          4m24s
[[email protected] pv-pvc]# kubectl get sts
NAME   READY   AGE
web    2/2     4m53s
[[email protected] pv-pvc]# 
[[email protected] pv-pvc]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   10m
nginx        ClusterIP   None         <none>        80/TCP    6m9s   // Headless   service
[[email protected] pv-pvc]# 

还可以进行其他的操作:

//扩容[[email protected] pv-pvc]#  kubectl scale statefulset web --replicas=5
statefulset.apps/web scaled
[[email protected] pv-pvc]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          16m
web-1   1/1     Running   0          15m
web-2   1/1     Running   0          7m19s
web-3   1/1     Running   0          2m5s
web-4   1/1     Running   0          103s
//缩减[[email protected] pv-pvc]# kubectl patch statefulset web -p ‘{"spec":{"replicas":3}}‘
statefulset.apps/web patched
[[email protected] pv-pvc]# kubectl get pods
[[email protected] pv-pvc]# kubectl get pvc   //statefulset 缩减后 pvc 仍然保留
NAME        STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pv0001   5Gi        RWO                           19m
www-web-1   Bound    pv0002   5Gi        RWO                           19m
www-web-2   Bound    pv0003   5Gi        RWO                           11m
www-web-3   Bound    pv0005   5Gi        RWO                           5m52s
www-web-4   Bound    pv0004   5Gi        RWO                           5m30s

更新 StatefulSet

v1.7 + 支持 StatefulSet 的自动更新,通过 spec.updateStrategy 设置更新策略。目前支持两种策略

  • OnDelete:当 .spec.template 更新时,并不立即删除旧的 Pod,而是等待用户手动删除这些旧 Pod 后自动创建新 Pod。这是默认的更新策略,兼容 v1.6 版本的行为
  • RollingUpdate:当 .spec.template 更新时,自动删除旧的 Pod 并创建新 Pod 替换。在更新时,这些 Pod 是按逆序的方式进行,依次删除、创建并等待 Pod 变成 Ready 状态才进行下一个 Pod 的更新。

Partitions

RollingUpdate 还支持 Partitions,通过 .spec.updateStrategy.rollingUpdate.partition 来设置。当 partition 设置后,只有序号大于或等于 partition 的 Pod 会在 .spec.template 更新的时候滚动更新,而其余的 Pod 则保持不变(即便是删除后也是用以前的版本重新创建)。

Pod 管理策略

v1.7 + 可以通过 .spec.podManagementPolicy 设置 Pod 管理策略,支持两种方式

  • OrderedReady:默认的策略,按照 Pod 的次序依次创建每个 Pod 并等待 Ready 之后才创建后面的 Pod
  • Parallel:并行创建或删除 Pod(不等待前面的 Pod Ready 就开始创建所有的 Pod)

StatefulSet 注意事项

  1. 推荐在 Kubernetes v1.9 或以后的版本中使用
  2. 所有 Pod 的 Volume 必须使用 PersistentVolume 或者是管理员事先创建好
  3. 为了保证数据安全,删除 StatefulSet 时不会删除 Volume
  4. StatefulSet 需要一个 Headless Service 来定义 DNS domain,需要在 StatefulSet 之前创建好

原文地址:https://www.cnblogs.com/zy09/p/11447275.html

时间: 2024-10-08 04:20:01

Kubernetes 第十三章 StatefulSet的相关文章

javascript高级程序设计 第十三章--事件

javascript高级程序设计 第十三章--事件js与HTML的交互就是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间. 事件流:事件流描述的是从页面中接收事件的顺序,IE的是事件冒泡流,Netscape的是事件捕获流,这个两个是完全相反的事件流概念. 事件冒泡:由最具体的元素接收,然后逐级向上传播到更高级的节点,即事件沿DOM树向上传播,直到document对象. 事件捕获:不大具体的节点应该更早接收到事件,相当于沿DOM节点树向下级传播直到事件的实际目标,在浏览器中,是

c++第十三章 -(副本构造器)

逐位复制(bitwise copy):编译器将生成必要的代码把“源”对象各属性的值分别赋值给“目标”对象的对应成员的行为.对对象的地址赋值操作,于是乎,当删除一个对象时,它包含的指针也将被删除,但万一此时另一个副本(对象)还在引用这个指针,就会出问题! 要是程序员在当初进行对象“复制”时能够精确地表明应该复制些什么和如何赋值,那就理想了.为解决该问题,我们可以对=操作符进行重载,其中对指针进行处理:MyClass &operator= (const MyClass &rhs);该语句的意思

java-第十三章-类的无参方法(一)-查找客户姓名

package 上机练习; public class A02class { String names[] = new String[30]; public void showA(String name) { for (int i = 0; i < names.length; i++) { if (names[i] == null) { names[i] = name; break; } } } public void showB() { System.out.println("\t客户列表

java-第十三章-类的无参方法(一)-实现图形生成器

package 上机练习; public class A03class { public String showA(int rows, String ch) { for (int i = 0; i < rows; i++) { for (int j = 0; j <= i; j++) { System.out.print(ch); } System.out.println(); } return ch; } } package 上机练习; import java.util.Scanner; p

java-第十三章-类的无参方法(一)-模拟账户查询,实现存取款

package 上机练习; import java.util.Scanner; public class A04class { double Money = 0; public double showA() { return Money; } public void showB(double money) { Money += money; System.out.println("当前余额:" + Money); } public void showC(double money2) {

java-第十三章-类的无参方法(一)-代参方法的编程计算器

package 本章总结; public class A01class { public int ope(int Operator, int num1, int num2) { switch (Operator) { case 1: num1 += num2; break; case 2: num1 -= num2; break; case 3: num1 *= num2; break; case 4: num1 /= num2; break; default: System.out.print

java-第十三章-类的无参方法(一)-模拟一个简单的购房商贷月供计算器

package 本章总结; public class A02class { double Money = 0; public double showA(double money, int choice) { switch (choice) { case 1: Money = (money + money * 0.0603) / 36; break; case 2: Money = (money + money * 0.0612) / 60; break; case 3: Money = (mon

java-第十三章-类的无参方法(一)-根据三角形的三条边长,判断是直角,锐角还是钝角三角形

package 本章总结; public class A03class { public boolean showA(int a ,int b ,int c){ boolean con=false; if((a+b)>c&&(a+c)>b&&(c+b)>a){ con=true; } return con; } public String Shape(int a,int b,int c){ String shape=""; if((a=

扣响C#之门笔记--第二十三章

23.1 泛型的概念 (1)在普通集合中,元素均被看做是object类型,会有以下缺点(a)赋值时候将类型转为object,使用时候又将object转为对应的类型,在装箱和拆箱时候造成一定性能损失:(b)任何类型的数据都可以放进集合里面,不利于类型安全检查: static void Main(string[] args) { Queue q = new Queue(); q.Enqueue(10); q.Enqueue("wo"); // q.Enqueue(1); foreach (