K8S StatefulSet

清空K8S对象

为了避免之前学习的内容造成的影响,先手动把K8S集群中的所有对象清空,使用一个全新的环境来学习StatefulSet的基本使用。

查看对象

  • 查看service对象
kubectl get services

在这里插入图片描述

  • 查看ReplicaSet对象
kubectl get rs

在这里插入图片描述

  • 查看Replication Controller对象
kubectl get rc

在这里插入图片描述

还有其他K8S对象,就不一一罗列展示了

清空对象

  • 方法一 删除命名空间内所有的对象
# 1. 删除指定命名空间的所有对象
# kubectl delete all --all -n {namespace}
# 2. 删除默认命名空间(default) 所有对象
# kubectl delete all --all
kubectl delete all --all

在这里插入图片描述

  • 方法二 - 用户可以删除命名空间,然后重建
# 1. 删除命名空间
# kubectl delete namespace {namespace}
# 2. 重建命名空间
# kubectl create namespace {namespace}

在这里插入图片描述

注意:默认的命名空间不能删除,清空完毕后可以使用命令查看验证对象是否存在,如查看Pod对象

kubectl get pods

在这里插入图片描述

StatefulSet 基本概念

StatefulSet(有状态集)长用于部署有状态的应用程序,跟Deployment类似StatefulSet也可以管理多个Pod集群,不同的是StatefulSet为每一个Pod分配一个唯一的粘性标识。并管理Pod的扩容,并为每一个Pod赋予一个有序的Pod名称。如定义一个名为Redis的StatefulSet集群,指定三个Pod,那么创建出来的Pod名称就会为Redis-0、Redis-1、Redis-2.

如果想使用存储卷提供数据持久化服务,可以使用StatefulSet作为整体解决方案的一部分。尽管StatefulSet的单个Pod容易发生故障,但是持久Pod对象可以很容易的使存储卷匹配任何新创建的Pod对象。

使用指导

StatefulSet适用于以下需求的应用程序:

  • 稳定、唯一的网络标识
  • 稳定、持久话的数据存储
  • 有序、优雅的部署、扩容
  • 有序、自动滚动更新功能

如果应用程序并不要任何稳定的标识符、顺序部署、扩容扩展;应该使用无状态的K8S对象进行系统部署,如Deployment 或者 ReplicaSet。

使用限制

  • Pod 配置的存储必须根据实际需求使用 PersistentVolume Provisioner 进行定义,或者由管理员进行预分配
  • 删除、扩容StatefulSet 并不会删除关联的存储卷,其目的是 确保存储卷的数据安全
  • StatefulSet 需要 Headless Service 服务来创建Pod网络表示,开发者负责创建此服务
  • StatefulSet 不保证在删除StatefulSet时终止Pod,目的是为了实现有序、优雅停止Pod,可以在删除之前将集群数量设置为0
  • 当使用Pod默认管理策略(OrderedReady)进行滚动更新时,可能会进入需要手动干预才能修复的损坏状态

演示案例

配置文件

#vim 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 # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  minReadySeconds: 10 # by default is 0
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web

配置说明:

  • 定义一个名为nginx的Headless Service服务,用于控制网络服务
  • 定义一个名为web的StatefulSet对象,关联3个nginx容器,每个启动的容器有用唯一的名称
  • ClaimTemplates 使用PersistentVolumes提供稳定的存储功能

启动服务

  • 创建StatefulSet对象
kubectl apply -f StatefulSet.yaml

在这里插入图片描述

  • 检查新创建的StatefulSet对象
kubectl get sts

在这里插入图片描述

  • 检查关联的Pod对象
kubectl get pods

在这里插入图片描述

请细看以上Pod名称按照顺序从0到2开始,组成三个Pods集群。三个Pod按顺序启动,后续的Pod启动必须在前面Pod启动之后再启动,因此以上三个Pod的启动顺序为:web-0 > web-1 > web-2

  • 查看关联的Service对象
kubectl get svc

在这里插入图片描述

Pod Selector

在StatefulSet中必须设置Pod选择器(.spec.selector)用来匹配器标签(.spec.template.metadata.labels),如果未指定匹配的Pod Selector 将导致StatefulSet在创建期间出现验证错误。

Minimum ready seconds

.spec.minReadySeconds是一个可选字段,默认值为0(Pod一准备就绪就被视为可用). 用于指定新创建的Pod在没有任何容器奔溃的情况下运行和准备就绪的最短秒数,以便将其视为可用。用于在使用滚动更新时检查更新进度

启动流程

StatefulSet管理的Pod部署和扩展规则如下:

  • 对于N个副本StatefulSet对象,将按照顺序从0到N-1开始创建Pod
  • 当删除Pod时,按照N-1到0逆序终止Pod
  • 在扩容伸缩Pod之前,必须保证之前的Pod处于Running状态
  • 在终止Pod之前,必须保证他它后续的Pod完全关闭

定义StatefulSet时,不应将参数 pod.Spec.TerminationGracePeriodSeconds指定为0,这种方式存在安全隐患,不鼓励使用。

当创建上面的Nginx实例时,将按照web-0、web-1、web-2的顺序部署三个Pod。在web-0处于Running或者Ready之前,web-1不会被创建;同理,web-2在web-1位处于Running状态之前不会被部署。如果web-1处于Running、Ready状态时,web-0变成Failed状态,那么web-2不会被启动,直到web-0恢复为Running状态。

如果用户将StatefulSet的replicas副本数设置为1,那么web-2首先将被终止,在web-2完全关闭之前,不会删除web-1.如果web-2终止关闭后,web-0突然失败,那么在web-0未恢复成Running状态前,web-1不会被删除

扩容伸缩

和Deployment一样,可以更过更新replicas字段扩容/伸缩StatefulSet,也可以使用kubectl scale、kubectl edit、kubectl patch来扩容/伸StatefulSet对象。

集群扩容

kubectl scale sts web --replicas=5

在这里插入图片描述

重新检查StatsfulSet 对象状态

kubectl get sts

在这里插入图片描述

重新检查扩容后Pod的数量及状态

kubectl get pod

在这里插入图片描述

根据上述几个图片显示web的节点从3变成了5,由此完成扩容。

集群缩容

使用patch命令将副本数重新设置为3

kubectl patch sts web -p '{"spec":{"replicas":3}}'

在这里插入图片描述

检查StatefulSet及其关联的Pod对象状态

在这里插入图片描述

StatefulSet 更新策略

StatefulSet也提供了多种更新策略,可以在**.spec.updateStrategy**指定更新策略。

OnDelete

当StatefulSet的.spec.updateStrategy.type设置为OnDelete时,StatefulSet控制器将不会自动更新StatefulSet中的Pod。用户必须手动删除Pod以使控制器创建新的Pod。

RollingUpdate

RollingUpdate更新策略自动更新StatefulSet中所有Pod的自动滚动更,这是默认的更新策略。采用与序号索引相反的顺序进行滚动更新。

  • 更新StatefulSet更新策略

比如更新一个名称为web的StatefulSet的使用RollingUpdate方式更新

kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
  • 查看更改后的StatefulSet
kubectl get sts web -o yaml | grep -A 1 "updateStrategy"

在这里插入图片描述

分段更新

Stateful可以使用RollingUpdate更新策略的partition参数来分段更新StatefulSet。分段更新将会使Stateful中其余的所有Pod(序号小于分区)保持当前版本,只更新序号大于等于分区的Pod,利用此特性可以简单实现金丝雀发布(灰色发布)

比如定义一个分区为3,可以使用patch直接对StatefulSet进行设置

kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}'

在这里插入图片描述

删除Pod触发更新

kubectl delete po web-2

由于,web-2的需要小区分区3,所以Pod不会被更新,还是会使用以前的容器恢复Pod。

将分区改为1,此时会自动更新web-2,但不会更新web-0、web-1, 重新执行以上删除命令,如下图由于集群需要维护指定数量的副本,因此重新创建了一个web-2.

在这里插入图片描述

StatefulSet 删除

删除StatefulSet有两种方式,级联删除和非级联删除。使用非级联方式删除StatefulSet对象时,Stateful的Pod不会被删除;使用级联方式删除StatefulSet时,StatefulSet和它关联的pod都会被删除

非级联删除

# 使用以下命令进行非级联删除
kubectl delete statefulset web --cascade=false

在这里插入图片描述

此时三个Pod对象无法管理到StatefulSet对象,因此只能被手动删除,删除时也不会被重建

在这里插入图片描述

级联删除

# 1. 重新创建StatefulSet集群
kubectl apply -f StatefulSet.yaml
# 2. 检查Stateful及关联对象

在这里插入图片描述

# 使用以下命令进行级联删除 去掉--cascade=false即可
kubectl delete statefulset web 

在这里插入图片描述

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐