zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【Kubernetes】StatefulSet对象详解

Kubernetes对象 详解 StatefulSet
2023-09-14 09:14:15 时间

文章目录

简介

在 Kubernetes 中运行应用程序的常见方法是创建部署对象(Deployment),它管理一个或多个 Pod 实例的副本集。但是,某些应用程序需要保留唯一标识符和网络标识符,比如数据库应用程序。这时候就需要用到 StatefulSet 对象。

StatefulSet 是 Kubernetes 的一种对象类型,提供管理有状态应用程序的能力。它可以用于管理有唯一标识符和网络标识符要求的应用程序,如数据库、消息队列等。

1. StatefulSet对象的概述、作用及优点

1.1 对比Deployment对象和StatefulSet对象

Deployment 对象和 StatefulSet 对象都用于管理应用程序的实例,两者有以下区别:

  • 命名的稳定性:Deployment 管理的 Pod 实例在删除和重新创建时,它们的名称会发生变化,所以无法保证 Pod 的稳定标识符。而 StatefulSet 可以为 Pod 实例提供稳定的名称和网络标识符。

  • 滚动更新:Deployment 对象通过滚动更新,升级应用程序的实例。而 StatefulSet 对象需要逐个升级每个 Pod 实例,以确保应用程序稳定性。

  • ``持久化数据`:StatefulSet 对象支持对有状态应用程序的持久化数据进行管理。

因此,StatefulSet 适用于需要稳定标识符和网络标识符以及需要持久化存储的有状态应用程序。

1.2 以下是比较Deployment对象和StatefulSet对象的优缺点:

优缺点DeploymentStatefulSet
POD的管理Deployment对象主要用于管理无状态的POD。StatefulSet对象主要用于管理有状态的POD。
命名的稳定性当POD失败并被重建时,Deployment对象为其分配新的名称。当POD失败并被重建时,StatefulSet对象将保留相同的名称。
稳定的网络标识Deployment对象不保证每个POD的网络标识符。StatefulSet对象为每个POD提供稳定的网络标识符。
有序部署的支持Deployment对象不支持对有状态应用程序进行计划部署。StatefulSet对象支持有序部署,以避免应用程序在非有序器中跳跃。
存储卷的支持Deployment对象支持使用存储卷和容器映像一起使用。StatefulSet对象支持在多个POD之间共享磁盘状态。
可扩展性Deployment对象适合需要大量调整的长时间运行的任务StatefulSet对象适合需要有状态数据管理的长时间运行任务。

2. StatefulSet对象的基础知识

2.1 StatefulSet对象的定义

StatefulSet 对象是 Kubernetes API 中的一种对象类型,它管理 Pod 实例的唯一标识符和网络标识符。StatefulSet 以容器化应用程序为基础,保证了每个实例都有唯一的标识符,如 DNS 名称。

2.1.1 下表为StatefulSet对象的定义及其属性:

属性描述
apiVersion使用的Kubernetes API版本
kindStatefulSet对象类型
metadataStatefulSet对象的元数据,包括名称、命名空间、标签等
specStatefulSet对象的规格,包括副本数、pod模板、卷、服务名称等
statusStatefulSet对象的状态信息,包括当前状态、当前副本数、Ready副本数等

2.2 Pod对象和StatefulSet对象之间的关系

每个 StatefulSet 都在后台控制着与一个或多个相同配置的 Pod 组。使用 StatefulSet 能保证这些 Pod 按照一定的顺序部署,同时它们都有稳定的网络标识符。与 Deployment 不同,每个 Pod 的名称是固定的,并且即使重启也不会改变。

2.2.1 下表为 Pod对象和StatefulSet对象特征的对比:

特征PodStatefulSet
稳定性每次重新创建Pod会获得新ID,无法持久化存储每个pod都有固定的名称和唯一的ID,能够与持久化存储进行交互
调度顺序没有保证Pod调度顺序可以按照顺序部署、更新和删除Pod
管理策略单独操作,不受其他Pod影响以集合为单位操作Pod,可扩展性更强
扩容伸缩扩容、缩容需要手动操作自动调节Pod数量,保证每个Pod都有唯一名称和ID
存储无法保证Pod之间的存储共享确保每个Pod都可以访问相同的持久化存储

2.3 StatefulSet的命名规则

按照名称命名约定,StatefulSet 的名称必须以小写字母开头,只能包含小写字母、数字和连字符(-),长度不能超过 63 个字符。

2.3.1 下表为StatefulSet的命名规则的描述:

命名规则描述
字符集包括小写字母、数字和’-‘,不能以’-'结尾
长度不超过63个字符
命名空间如果命名空间存在,则命名空间和StatefulSet名称中间用’-'连接
名称格式由小写字母开头,可包含小写字母、数字和’-’

请注意,名称格式应符合DNS子域名的规则,这样才能被正常解析。建议使用短、有含义的名称,便于管理。|

2.4 StatefulSet的副本集管理

与 Deployment 类似,StatefulSet 也可以管理多个 Pod 的副本集。但它需要保证副本集中每个 Pod 的唯一标识符和网络标识符是不变的。在对 StatefulSet 进行扩展和缩容时,需要在每个 Pod 上的启动和终止之间保留稳定的标识符和网络标识符。

2.4.1 下表为StatefulSet的副本集管理的描述:

策略描述
创建在创建StatefulSet时,会根据指定的副本数自动创建相应的Pod
更新更新StatefulSet时,会根据更新策略分别进行更新。策略有:OnDelete(默认)、RollingUpdate
扩容使用kubectl scale命令或更新StatefulSet的spec.replicas字段进行扩容
缩容使用kubectl scale命令或更新StatefulSet的spec.replicas字段进行缩容
升级更新Pod模板时会根据更新策略开始升级。策略有:OnDelete(默认)、RollingUpdate
有序部署StatefulSet会按照其在spec中定义的Pod的名称顺序逐个启动和关闭Pod

请注意,StatefulSet的副本集管理相对于其他同级别的控制器来说更加复杂,理解和掌握其中的策略和规则非常重要。|

3. StatefulSet对象的部署

3.1 创建StatefulSet对象

要创建 StatefulSet 对象,需要指定该 StatefulSet 管理的 Pod 模板,并选择合适的 Pod 副本数。

3.1.1 以下是创建StatefulSet对象的基本步骤:

  1. 准备Pod模板:定义需要创建的StatefulSet对象中包含的Pod的配置,例如容器镜像、容器端口等。

  2. 创建StatefulSet对象:定义StatefulSet对象,包括元数据、规格等信息并指定Pod模板。

  3. 应用StatefulSet对象:使用kubectl apply等命令将定义的StatefulSet对象应用到Kubernetes集群中。

3.1.1.1 以下是创建StatefulSet对象的示例yaml文件:
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: webapp
  labels:
    app: simpleweb
spec:
  replicas: 3
  serviceName: webapp
  selector:
    matchLabels:
      app: simpleweb
  template:
    metadata:
      labels:
        app: simpleweb
    spec:
      containers:
        - name: simpleweb
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: "/usr/share/nginx/html"
              name: persistent-storage
  volumeClaimTemplates:
    - metadata:
        name: persistent-storage
        annotations:
          volume.beta.kubernetes.io/storage-class: "standard"
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 5Gi

这个示例创建了一个名为webapp的StatefulSet对象,包含3个Pod的副本,服务名称为webapp,使用nginx的最新版本镜像,并向容器内挂载了一个持久化存储。

可以使用 kubectl apply -f filename.yaml 命令来创建该StatefulSet对象和相关的Pod。

3.2 定义StatefulSet中每个Pod的唯一标识符

在 StatefulSet 中,每个 Pod 都会被赋予一个稳定的唯一标识符,格式为 StatefulSetName-Ordinal。 Ordinal 是从 0 开始的整数,表示 Pod 在 StatefulSet 中的顺序。

为了定义 StatefulSet 中每个 Pod 的唯一标识符,需要在 Pod 模板中指定以下两个属性:

  • metadata.name:为 Pod 设置一个基础名称。
  • spec.hostname:为 Pod 设置带 Ordinal 的完全限定域名,例如 PodNameOrdinal.ServiceName.HeadlessServiceNamespace.svc.cluster.local。

3.2.1 以下是 定义StatefulSet中每个Pod的唯一标识符的示例:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: webapp
  labels:
    app: simpleweb
spec:
  replicas: 3
  serviceName: webapp
  selector:
    matchLabels:
      app: simpleweb
  template:
    metadata:
      labels:
        app: simpleweb
      name: simpleweb
    spec:
      hostname: simpleweb-$(hostname).webapp
      containers:
        - name: simpleweb
          image: nginx:latest
          ports:
            - containerPort: 80

在这个示例中,我们通过将 spec.hostname 设置为 simpleweb-$(hostname).webapp 来定义每个 Pod 的唯一标识符。这里的 $(hostname) 会被替换为 Pod 的序号。例如,其中一个 Pod 的名称可能是 simpleweb-0.webapp。

3.3 使用Headless Service对象管理StatefulSet对象中的Pod

StatefulSet 可以使用 Headless Service 对象来管理它的 Pod,从而可以控制多个 Pod 之间的网络通信。Headless Service 不提供 Cluster IP,但它提供 DNS 记录,返回所有 Pod 的网络标识符。

3.3.1 StatefulSet 中使用 Headless Service 的基本步骤:

  1. 定义 Headless Service:定义一个 Service 类型为 Headless,用于管理相关的 Pod。Service 名称使用 .spec.serviceName 属性关联到 StatefulSet。
apiVersion: v1
kind: Service
metadata:
  name: webapp
  labels:
    app: simpleweb
spec:
  type: ClusterIP
  selector:
    app: simpleweb
  clusterIP: None
  1. 更新 StatefulSet:将 StatefulSet 的 .spec.serviceName 属性设置为上一步定义的 Headless Service 名称。另外,确保在 Pod 模板中配置了 hostname 和 subdomain 字段。
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: webapp
  labels:
    app: simpleweb
spec:
  replicas: 3
  serviceName: webapp
  selector:
    matchLabels:
      app: simpleweb
  template:
    metadata:
      labels:
        app: simpleweb
      name: simpleweb
    spec:
      hostname: simpleweb-$(hostname).webapp
      subdomain: webapp
      containers:
        - name: simpleweb
          image: nginx:latest
          ports:
            - containerPort: 80

4. StatefulSet对象的更新和扩缩容

4.1 更新StatefulSet的镜像版本

StatefulSet 对象可以通过更新镜像版本来更新应用程序。

4.1.1 操作步骤:

首先,您需要查找要升级的镜像版本。您可以通过Docker Hub或Kubernetes注册表等命令行工具来查找可用的版本。例如,使用下面的命令可以查找最新的nginx版本:

$ docker search nginx

确认要更新的StatefulSet名称和命名空间。使用下面的命令列出所有StatefulSets:

$ kubectl get statefulsets

停止StatefulSet中的所有Pod实例:

$ kubectl scale statefulsets <statefulset-name> --replicas=0

更新StatefulSet的镜像版本。使用下面的命令可以更新镜像版本:

$ kubectl set image statefulset/<statefulset-name> <container-name>=<new-image-version>

执行完更新后,重新启动StatefulSet Pod实例:

$ kubectl scale statefulsets <statefulset-name> --replicas=<desired-number-of-replicas>

在执行上述步骤时,请注意替换适当的名称,并根据需要更改其他标志,以适应您的环境。

4.2 横向扩展和缩小StatefulSet的实例数量

可以通过更新 StatefulSet 对象中的 Pod 副本数来横向扩展或缩小 StatefulSet 的实例数量。

4.2.1 操作示例:

横向扩展和缩小StatefulSet的实例数量可以使用kubectl命令行工具完成。

  1. 扩展StatefulSet的实例数:

使用kubectl scale命令扩展StatefulSet的实例数。语法如下:

kubectl scale statefulset <statefulset-name> --replicas=<desired-number-of-replicas>

StatefulSet名称和所需副本的数量是必需的参数。例如,如果要将名为 “my-statefulset”的 StatefulSet 的实例数扩展为 5,则可以运行以下命令:

kubectl scale statefulset my-statefulset --replicas=5

确认扩展已成功完成:

kubectl get statefulset <statefulset-name>

此命令将显示副本数等详细信息,以及一个READY列,该列显示了可用的副本数和所需的副本数。

  1. 缩小StatefulSet实例的数量:

使用kubectl scale命令缩小StatefulSet实例数。语法如下:

kubectl scale statefulset <statefulset-name> --replicas=<desired-number-of-replicas>

StatefulSet名称和所需副本的数量是必需的参数。例如,如果要将名为 “my-statefulset”的 StatefulSet 的实例数量缩小为 3,则可以运行以下命令:

kubectl scale statefulset my-statefulset --replicas=3

确认缩小已成功完成:

kubectl get statefulset <statefulset-name>

此命令将显示副本数等详细信息,以及一个READY列,该列显示了可用的副本数和所需的副本数。

4.3 Vertical Pod Autoscaler对象管理StatefulSet对象

Vertical Pod Autoscaler (VPA) 是 Kubernetes 中用于自动调整 Pod 的资源请求和限制的机制,它可以管理 StatefulSet 对象的资源请求和限制。

4.3.1下表是 Vertical Pod Autoscaler 对象管理 StatefulSet 对象的一些示例。

操作kubectl 命令
创建 Vertical Pod Autoscaler 对象kubectl apply -f <vpa-file.yaml>
删除 Vertical Pod Autoscaler 对象kubectl delete vpa <vpa-name>
获取 Vertical Pod Autoscaler 对象kubectl get vpa
更新 Vertical Pod Autoscaler 对象kubectl apply -f <vpa-file.yaml>
将 Vertical Pod Autoscaler 应用于 StatefulSetkubectl annotate statefulset <statefulset-name> verticalpodautoscaler.kubernetes.io/enable='true'

其中,<vpa-file.yaml> 是包含 Vertical Pod Autoscaler 对象的 YAML 文件的路径。<vpa-name> 是要删除的 Vertical Pod Autoscaler 的名称,<statefulset-name> 是要将 Vertical Pod Autoscaler 应用于的 StatefulSet 名称。

在针对 StatefulSet 配置 VPA 后,VPA 将自动计算每个 Pod 的资源需求,然后动态调整 Pod 的资源请求和限制。这可以提高集群的资源利用率和可靠性,因为 VPA 可以自动调整 Pod 的资源请求和限制,并在需要时增加或减少 Pod 的数量。

5. StatefulSet对象的数据管理

5.1 数据卷的定义和使用

数据卷是一种可以用来存储数据的方案,它可以被挂载到Pod中,这样数据就可以在不同的Pod之间共享。StatefulSet对象支持使用多种类型的数据卷,包括:

  • 空白目录卷
  • 主机路径卷
  • 配置映射卷
  • 存储卷

下面是数据卷的定义和使用示例:

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
configMap:
name: html-configmap
items:
- key: index.html
path: index.html

在这个示例中,我们使用了一个配置映射卷(html-configmap)来将一个目录(index.html)挂载到Nginx的容器中。请注意,在volumes段中,我们定义了该卷的名称(html),该名称然后被用于volumeMounts段中,表示将卷挂载到该路径。

5.2 PV和PVC的管理

PV(Persistent Volume)和PVC(Persistent Volume Claim)被设计用来对应用程序提供长期持久性的数据存储。PV是集群中的一个资源,它表示一个物理卷,如NFS共享卷、云存储、本地硬盘等等。而PVC则是一个请求,用于申请特定容量和属性的PV。StatefulSet对象可以使用由管理员创建的PV中分配出来的PVC:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: http
          containerPort: 80
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        persistentVolumeClaim:
          claimName: html-pvc

在这个示例中,我们使用了一个PVC(html-pvc),它是由管理员创建的,并且在StatefulSet对象的volumes段中引用它。在运行时,当顶部的Pod被调度到节点上时,Kubernetes将在集群中查找有足够容量、存储类型和访问模式的PV,将其绑定到PVC上,然后将数据挂载到容器中。

5.3 对数据进行备份和恢复

下表是一些常用的备份和恢复 StatefulSet 数据的 Kubernetes 资源和操作:

操作kubectl 命令
创建 PVCkubectl apply -f <pvc-file.yaml>
删除 PVCkubectl delete pvc <pvc-name>
获取 PVCkubectl get pvc
备份 PVC 中的数据使用备份工具(如 Velero)备份 PVC 中的数据
恢复 PVC 中的数据使用备份工具(如 Velero)恢复之前备份的 PVC 中的数据
创建 PVkubectl apply -f <pv-file.yaml>
删除 PVkubectl delete pv <pv-name>
获取 PVkubectl get pv
恢复 PV 中的数据将 PV 挂载到 Pod 中,并使用命令行/文件浏览器复制数据

在使用这些资源和操作时,我们可以先创建 PVC 和 PV,然后将 PVC 挂载到 StatefulSet 中的 Pod 中。使用备份工具备份 PVC 中的数据以及对应的 PV,如果需要恢复数据,可以先恢复 PV,然后将 PVC 挂载到新的 Pod 中,从 PV 中复制数据。

需要注意的是,备份和恢复数据时,需要考虑 StatefulSet 中 Pod 的稳定性和数据一致性,以避免数据损坏或丢失。

6. StatefulSet对象的操作和监控

6.1 使用kubectl命令行接口管理StatefulSet对象

  1. 创建StatefulSet对象

通过Kubernetes命令行工具kubectl可以创建一个新的StatefulSet对象,如下所示:

kubectl create -f statefulset.yaml

其中,statefulset.yaml是包含StatefulSet对象定义的YAML文件。

  1. 更新StatefulSet对象

如果需要修改StatefulSet对象的定义,可以使用kubectl命令进行更新。例如,修改StatefulSet的副本数量:

kubectl patch statefulset my-statefulset -p '{"spec":{"replicas":3}}'
  1. 删除StatefulSet对象

如果要删除已有的StatefulSet对象,可以使用以下命令:

kubectl delete statefulset my-statefulset

6.2 监控StatefulSet对象及其相关组件的运行情况

6.2.1 监控StatefulSet对象

可以使用kubectl get命令查看StatefulSet对象的状态:

kubectl get statefulset

该命令将显示StatefulSet对象的名称、副本数量、当前运行的Pod数量、以及相关的Selector和Pod模板信息。

此外,可以使用kubectl describe命令查看有关StatefulSet对象的更详细信息:

kubectl describe statefulset my-statefulset

6.2.2 监控StatefulSet中的Pod对象

可以使用kubectl get命令来查看StatefulSet中现有的Pod对象:

kubectl get pods -l app=my-app

其中,app=my-app指定了我们要查找的Pod的标签。

同样地,可以使用kubectl describe命令查看有关Pod的详细信息:

kubectl describe pod my-app-0

6.2.3 监控Kubernetes集群中的组件

Kubernetes集群中有多个重要的组件,包括API服务器、etcd、kube-scheduler、kube-controller-manager和kubelet等。这些组件在运行时可能会出现故障,影响整个集群的稳定性。

可以使用Kubernetes提供的各种监控工具来监控集群中的组件状态。例如,可以使用Prometheus来监控集群中各个组件的运行状况,以及各类指标的变化情况。

6.2.3.1 以下是监视Kubernetes集群中的组件的一些工具和方法的优缺点:
工具/方法优点缺点
kubectl 监视命令简单易用,无需安装额外的软件功能相对较为简单,只能检查少量的节点属性和当前状态
Kubernetes 监控监控 Kubernetes 集群各个组件的运行状态可视化展示较弱,使用起来相对不太方便
cAdvisor轻量级的孤立容器监测器,适用于 Docker 容器环境只能监测孤立容器环境下的参数,对于 Kubernetes 的控制面稍显力度不够
Prometheus对 Kubernetes 集群的监控非常适用部署和配置上相对较为复杂,需要一定的技术壁垒
Grafana用于接收和展示 Prometheus 的指标和警报需要部署 Prometheus 且配置在正确的位置,搭建上稍难

6.3 解决StatefulSet对象的故障

当StatefulSet对象发生故障时,可能会出现各种错误和警告。在处理这些问题之前,需要先查找出故障的原因,并尝试解决这些问题。

基本的调试工具包括Kubernetes提供的各种命令行工具,如kubectl、kubeadm和kubelet,以及各种监控工具,如Prometheus、Grafana和Elasticsearch等。

6.3.1 基本的调试工具的优缺点对比和下载地址

工具名称优点缺点下载地址
kubectl功能丰富,管理集群、Pod和服务相当方便缺少 GUI 插件; 学习曲线略为陡峭https://kubernetes.io/docs/tasks/tools/install-kubectl/
kubeadm快速部署Kubernetes集群需要一些基础知识;无法自定义集群https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
kubelet监管容器的状态无法独立使用;需要其他组件配合使用https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubelet-kubeadm-and-kubectl
kustomize自定义Kubernetes资源学习曲线陡峭;缺少 GUI 插件https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#kustomize-installation
kubespray快速部署复杂的Kubernetes集群繁琐的配置https://github.com/kubernetes-sigs/kubespray
kubectl diff显示Kubernetes资源之间的差异只能比较两个资源;缺少GUI插件https://github.com/cesanta/kubectl-diff
kube-ps1美化Shell提示符并且方便切换无法独立使用;需要在shell下安装https://github.com/jonmosco/kube-ps1
stern统一在单个终端监视多个Pod没有 GUI 插件; 学习曲线略为陡峭https://github.com/wercker/stern
kubetail将多个 Pod 的日志聚合到一个流中没有 GUI 插件;只能记录标准输出流;https://github.com/johanhaleby/kubetail

在这里插入图片描述