部署有状态应用

本页面介绍如何使用 Google Kubernetes Engine (GKE) 部署有状态应用。

概览

有状态应用将数据保存到永久性磁盘存储空间,以供服务器、客户端和其他应用使用。供其他应用在其中保存并检索数据的数据库或键值对存储区就是一种有状态应用的示例。

永久性存储空间可动态预配,因此可按需创建底层卷。在 Kubernetes 中,通过创建 StorageClass 来配置动态预配。在 GKE 中,默认 StorageClass 允许您动态预配 Compute Engine 永久性磁盘。

Kubernetes 使用 StatefulSet 控制器将有状态应用部署为 StatefulSet 对象。StatefulSet 中的 Pod 不可互换:每个 Pod 具有唯一的标识符,无论将 Pod 安排在何处,这个标识符都保持不变。

有状态应用与无状态应用不同,在切换会话时,无状态应用不会将客户端数据保存到服务器。

您可以进一步了解多地区集群和区域级集群中的永久性存储。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如需使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。

您可以遵循快速入门中的说明启用 GKE API,创建集群,并进一步了解 GKE。

在 StatefulSet 中请求永久性存储空间

应用可以通过 PersistentVolumeClaim 请求永久性存储空间。

通常,除了创建 Pod 之外,您还必须创建 PersistentVolumeClaim 对象。不过,StatefulSet 对象包含一个 volumeClaimTemplates 数组,可自动生成 PersistentVolumeClaim 对象。每个 StatefulSet 副本都有自己的 PersistentVolumeClaim 对象。

您还可以在 StatefulSet 中使用预先存在的磁盘。

动态拓扑绑定

创建使用可用区级 PersistentVolume 的 StatefulSet 时,最佳实践是使用 volumeBindingMode: WaitForFirstConsumer 字段值对配置 StorageClass 定义。此设置有助于确保卷预配延迟到 Pod 被调度到具有足够计算容量的可用区中的健康节点。如果您使用默认的即时绑定,则可能会在 Pod 调度之前将 Pod 的卷锁定到可能缺乏足够计算容量的可用区,从而使 Pod 陷入 Pending 状态。

创建 StatefulSet

如需创建 StatefulSet,请使用 kubectl apply 命令。

kubectl apply 命令使用清单文件来创建、更新和删除集群中的资源。这是对象配置的声明式方法。该方法可保留对活跃对象的写入,但不会将更改合并回到对象配置文件中。

Linux

以下清单文件是无头 Service 及其管理的 StatefulSet 的示例:

apiVersion: v1
kind: Service
metadata:
  name: SERVICE_NAME
  labels:
    app: APP_NAME
spec:
  ports:
  - port: 80
    name: PORT_NAME
  clusterIP: None
  selector:
    app: APP_NAME
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: STATEFULSET_NAME
spec:
  selector:
    matchLabels:
      # Selects Pods with this label.
      app: APP_NAME
  # Headless Service for network identity.
  serviceName: "SERVICE_NAME"
  replicas: 3
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: APP_NAME
    spec:
      containers:
      - name: CONTAINER_NAME
        image: IMAGE
        ports:
        - containerPort: 80
          name: PORT_NAME
        volumeMounts:
        - name: PVC_NAME
          mountPath: MOUNT_PATH
  volumeClaimTemplates:
  - metadata:
      name: PVC_NAME
      annotations:
        KEY: VALUE
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

替换以下内容:

  • STATEFULSET_NAME:StatefulSet 的名称,例如 web。
  • SERVICE_NAME:Service 的名称,例如 nginx。
  • APP_NAME:在 Pod 中运行的应用的名称,例如 nginx。
  • CONTAINER_NAME:Pod 中容器的名称,例如 nginx。
  • IMAGE:您的容器映像,例如 nginx:stable。
  • PORT_NAME:StatefulSet 打开的端口名称,例如 web。
  • PVC_NAME:PersistentVolumeClaim 的名称,例如 www。
  • MOUNT_PATH:容器中装载存储空间的路径,例如 /usr/share/nginx/html。
  • KEY 和 VALUE:要应用于 PersistentVolumeClaim 元数据的注释键值对。您可以使用注释将任意非身份元数据附加到可由工具和库等客户端检索的对象。如需了解详情,请参阅注解。

在该文件中,kind 字段指定 StatefulSet 对象应该使用文件中定义的规范来创建。该示例 StatefulSet 生成三个副本 Pod,并打开端口 80 以向互联网公开 StatefulSet。

Windows

如果将集群用于 Windows Server 节点池,您必须创建一个 StorageClass,因为默认 StorageClass 使用仅适用于 Linux 容器的 ext4 作为文件系统类型。如果您使用的是 Compute Engine 永久性磁盘,则必须使用 NTFS 作为文件存储类型,如以下示例所示:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  # Defines a name for this StorageClass.
  name: STORAGECLASS_NAME
parameters:
  # Specifies the type of Google Compute Engine persistent disk.
  type: pd-standard
  # Uses NTFS file system, which is crucial for Windows nodes
  fstype: NTFS
# The provisioner for Google Compute Engine persistent disks.
provisioner: kubernetes.io/gce-pd
# Specifies that the PersistentVolume will be deleted if the PersistentVolumeClaim is deleted.
reclaimPolicy: Delete
# Delays volume binding until a Pod using the PVC is scheduled.
volumeBindingMode: WaitForFirstConsumer

以下 StatefulSet 清单使用之前定义的 StorageClass。它会创建四个 PersistentVolume 和 PersistentVolumeClaim 对,以表示四个 Compute Engine 永久性磁盘。StatefulSet 中的每个 Pod 各使用一个永久性磁盘。

要确保将 Pod 正确调度到 Windows Server 节点上,您必须在 Pod 规范中添加节点选择器。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: STATEFULSET_NAME
spec:
  replicas: 4
  selector:
    matchLabels:
      # Selects Pods with this label.
      app: APP_NAME
  template:
    metadata:
      labels:
        # Labels applied to the Pods created by the StatefulSet.
        app: APP_NAME
      name: CONTAINER_NAME
    spec:
      nodeSelector:
        # Ensures Pods are scheduled on Windows nodes.
        kubernetes.io/os: windows
      containers:
      - name: CONTAINER_NAME
        image: IMAGE
        ports:
        - containerPort: 80
          name: PORT_NAME
        volumeMounts:
        - name: PVC_NAME
          mountPath: MOUNT_PATH
  volumeClaimTemplates:
  - metadata:
      name: PVC_NAME
    spec:
      # Specifies the StorageClass to use, which is crucial for Windows nodes.
      storageClassName: STORAGECLASS_NAME
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

替换以下内容:

  • STATEFULSET_NAME:StatefulSet 的名称,例如 web-windows。
  • APP_NAME:在 Pod 中运行的应用的名称,例如 iis。
  • CONTAINER_NAME:Pod 中容器的名称,例如 iis。
  • IMAGE:您的容器映像,例如 mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019。
  • PORT_NAME:StatefulSet 打开的端口名称,例如 http。
  • PVC_NAME:PersistentVolumeClaim 的名称,例如 iis-state。
  • MOUNT_PATH:容器中装载存储空间的路径,例如 C:\mnt\state。
  • STORAGECLASS_NAME:StorageClass 的名称,例如 my-storage-class。

如需创建 StatefulSet 资源,请运行以下命令,并将 STATEFULSET_FILE 替换为清单文件的名称:

kubectl apply -f STATEFULSET_FILE

您还可以使用 kubectl apply -f DIRECTORY/ 创建目录中所存储的配置文件中定义的所有对象(现有对象除外)。

检查 StatefulSet

kubectl

如需检查 StatefulSet,请运行以下命令:

kubectl get statefulset STATEFULSET_NAME -o yaml

此命令以 YAML 格式显示 StatefulSet 资源的当前配置。

如需列出由 StatefulSet 创建的 Pod,请运行以下命令:

kubectl get pods -l app=APP_NAME

在此命令中,-l 标志指示 kubectl 获取标有 APP_NAME 的所有 Pod。

输出类似于以下内容:

NAME                                READY     STATUS    RESTARTS   AGE
pod-name                            1/1       Running   0          1m
pod-name                            1/1       Running   0          1m

如需获取有关 StatefulSet 的详细信息,请运行以下命令:

kubectl describe statefulset STATEFULSET_NAME

如需获取有关特定 Pod 的信息,请运行以下命令:

kubectl describe pod POD_NAME

如需列出已创建的 PersistentVolumeClaim 对象,请运行以下命令:

kubectl get pvc

输出类似于以下内容:

NAME                            STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
STATEFULSET_NAME-PVC_NAME-0     Bound     pvc-bdff4e1e-183e-11e8-bf6d-42010a800002   1G         RWO            standard        9s
STATEFULSET_NAME-PVC_NAME-1     Bound     pvc-bdff4e1e-183e-11e8-bf6d-42010a800003   1G         RWO            standard        9s
STATEFULSET_NAME-PVC_NAME-2     Bound     pvc-bdff4e1e-183e-11e8-bf6d-42010a800004   1G         RWO            standard        9s

如需获取有关特定 PersistentVolumeClaim 的信息,请运行以下命令:

kubectl describe pvc STATEFULSET_NAME-PVC_NAME-0

如需获取有关特定 PersistentVolume 的信息,请运行以下命令:

kubectl describe pv PV_NAME

控制台

要检查 StatefulSet,请执行以下步骤:

  1. 前往 Google Cloud 控制台中的工作负载页面。

    转到“工作负载”

  2. 在工作负载列表中,点击要检查的 StatefulSet 的名称。

  3. 在 StatefulSet 详情页面上,执行以下任一操作:

    • 点击修订历史记录标签页以查看 StatefulSet 的修订历史记录。
    • 点击事件标签页,以查看与 StatefulSet 相关的所有事件。
    • 点击日志标签页以查看 StatefulSet 的容器日志。
    • 点击 YAML 标签页以查看、复制或下载 StatefulSet 的配置 YAML。

更新 StatefulSet

您可以通过多种方式更新 StatefulSet。常用的声明式方法是 kubectl apply。您可以使用 kubectl edit 直接从 shell 或您的首选编辑器更新 StatefulSet。您还可以访问 Google Cloud 控制台的 GKE“工作负载”菜单,使用其中提供的 YAML 编辑器。

您可以发布对 StatefulSet 资源的 Pod 规范的更新,例如其映像、资源使用情况/请求或配置。

kubectl apply

您可以通过应用新的或更新的清单文件来更新 StatefulSet。 如果您要对 StatefulSet 进行各种更改,例如扩缩或者指定应用的新版本,则这种操作十分有用。

如需更新 StatefulSet,请运行以下命令:

kubectl apply -f STATEFULSET_FILE

将 STATEFULSET_FILE 替换为更新后的清单文件。

kubectl apply 命令可将清单文件应用于资源。如果指定的资源不存在,则命令将创建该资源。

如需详细了解 kubectl apply,请参阅 kubectl 参考文档。

控制台

要修改 StatefulSet 的活动配置,请执行以下步骤:

  1. 前往 Google Cloud 控制台中的工作负载页面。

    转到“工作负载”

  2. 在工作负载列表中,点击要修改的 StatefulSet 的名称。

  3. 点击 修改。

  4. 根据需要更改配置 YAML。

  5. 点击保存。

检查更新发布

如需检查 StatefulSet 的发布,请运行以下命令:

kubectl rollout status statefulset STATEFULSET_NAME

如需查看 StatefulSet 的发布历史记录,请运行以下命令:

kubectl rollout history statefulset STATEFULSET_NAME

如需撤消发布,请运行以下命令:

kubectl rollout undo statefulset STATEFULSET_NAME

更新策略

通过 StatefulSet 的 updateStrategy 字段,您可以为 StatefulSet 中 Pod 的容器、标签、资源请求、限制以及注解配置及停用自动滚动更新。

您可以在 Kubernetes 文档中详细了解 StatefulSet 的更新策略。

扩缩 StatefulSet

kubectl

您可以随时使用 kubectl scale 命令来扩缩 StatefulSet。

要手动扩缩 StatefulSet,请运行以下命令:

kubectl scale statefulset STATEFULSET_NAME --replicas NUMBER_OF_REPLICAS

将 NUMBER_OF_REPLICAS 替换为所需的副本 Pod 数。

控制台

要扩缩 StatefulSet,请执行以下步骤:

  1. 前往 Google Cloud 控制台中的工作负载页面。

    转到“工作负载”

  2. 在工作负载列表中,点击要修改的 StatefulSet 的名称。

  3. 点击 操作 > 扩缩 > 修改副本。

  4. 输入 StatefulSet 的新副本数量。

  5. 点击调节。

删除 StatefulSet

kubectl

如需删除 StatefulSet,请运行以下命令:

kubectl delete statefulset STATEFULSET_NAME

控制台

要删除 StatefulSet,请执行以下步骤:

  1. 前往 Google Cloud 控制台中的工作负载页面。

    转到“工作负载”

  2. 在工作负载列表中,选择一个或多个要删除的 StatefulSet。

  3. 点击 删除。

  4. 当系统提示您确认时,点击删除。

后续步骤