From 34e54ab71c56ce07790fc41192c91da128d2082a Mon Sep 17 00:00:00 2001 From: AdamDang Date: Mon, 10 Dec 2018 18:35:10 +0800 Subject: [PATCH] zh-trans: add statefulset.md (#11455) * zh-trans: add statefulset.md zh-trans: add statefulset.md * Update statefulset.md * Update statefulset.md * Update statefulset.md * Update statefulset.md * Update statefulset.md --- .../workloads/controllers/statefulset.md | 417 ++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 content/zh/docs/concepts/workloads/controllers/statefulset.md diff --git a/content/zh/docs/concepts/workloads/controllers/statefulset.md b/content/zh/docs/concepts/workloads/controllers/statefulset.md new file mode 100644 index 0000000000..3ecf219dc4 --- /dev/null +++ b/content/zh/docs/concepts/workloads/controllers/statefulset.md @@ -0,0 +1,417 @@ +--- +reviewers: +- enisoc +- erictune +- foxish +- janetkuo +- kow3ns +- smarterclayton +title: StatefulSets +content_template: templates/concept +weight: 40 +--- + + + +{{% capture overview %}} + + + +StatefulSet 是用来管理有状态应用的工作负载 API 对象。 + +{{< note >}} + +**注意:** StatefulSets 是在 1.9 版本中正式发布的。 +{{< /note >}} + +{{< glossary_definition term_id="statefulset" length="all" >}} +{{% /capture %}} + +{{% capture body %}} + + + +## 使用 StatefulSets + +StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值: + +* 稳定的、唯一的网络标识符。 +* 稳定的、持久的存储。 +* 有序的、优雅的部署和缩放。 +* 有序的、自动的滚动更新。 + +在上面,稳定意味着 Pod 调度或重调度的整个过程是有持久性的。如果应用程序不需要任何稳定的标识符或有序的部署、删除或伸缩,则应该使用一组无状态的副本控制器来部署应用程序,比如 [Deployment](/docs/concepts/workloads/controllers/deployment/) 或者 [ReplicaSet](/docs/concepts/workloads/controllers/replicaset/) 可能更适用于您的无状态需要。 + + + +## 限制 + +* StatefulSet 在 1.9 版本之前属于 beta 资源,在 1.5 版本之前的任何 Kubernetes 版本中都不可用。 +* 给定 Pod 的存储必须由 [PersistentVolume 驱动](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/staging/persistent-volume-provisioning/README.md) 基于所请求的 `storage class` 来提供,或者由管理员预先提供。 +* 删除和/或收缩 StatefulSet 并*不会*删除它关联的存储卷。这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。 +* StatefulSet 当前需要 [无头服务](/docs/concepts/services-networking/service/#headless-services) 来负责Pod 的网络标识。您需要负责创建此服务。 +* 当删除 StatefulSets 时,StatefulSet 不提供任何终止 Pod 的保证。为了实现 StatefulSet 中的 Pod 可以有序和优雅的终止,可以在删除之前将 StatefulSet 缩放为0。 + + + +## 组件 +下面的示例演示了 StatefulSet 的组件。 + +* 名为 nginx 的无头服务用来控制网络域。 +* 名为 web 的 StatefulSet 有一个Spec,它表明将在单个 Pod 中启动 nginx 容器的3个副本。 +* volumeClaimTemplates 将通过 [PersistentVolumes](/docs/concepts/storage/persistent-volumes/) 驱动提供的 PersistentVolume 来提供稳定的存储。 + + +```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 + template: + metadata: + labels: + app: nginx # has to match .spec.selector.matchLabels + spec: + terminationGracePeriodSeconds: 10 + 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" ] + storageClassName: "my-storage-class" + resources: + requests: + storage: 1Gi +``` + + + +## Pod 选择器 +您必须设置 StatefulSet 的 `.spec.selector` 字段来匹配它的`.spec.template.metadata.labels`标签。在 Kubernetes 1.8 版本之前,忽略`.spec.selector` 字段会提供默认设置。在 1.8 和以后的版本中,指定的 Pod 选择器匹配失败将在创建 StatefulSet 期间导致验证错误。 + + + +## Pod 的身份 + +StatefulSet Pod 具有唯一的标识,该标识包括顺序标识、稳定的网络标识和稳定的存储。该标识和 Pod 是绑定的,不管它被调度在哪个节点上。 + + + +### 序号索引 + +对于具有N个副本的 StatefulSet,StatefulSet 中的每个 Pod 将被分配一个整数序号,从 0 到 N-1,该序号在 StatefulSet 上是唯一的。 + + + +### 稳定的网络 ID + +StatefulSet 中的每个 Pod 根据 StatefulSet 的名称和 Pod 的序号派生出它的主机名。组合主机名的格式为 `$(statefulset name)-$(ordinal)`。上例将会创建三个名称为 `web-0,web-1,web-2` 的三个 Pod。 +StatefulSet 可以使用 [无头服务](/docs/concepts/services-networking/service/#headless-services) 控制它的 Pod 的网络域。管理域的这个服务的格式为: +`$(service name).$(namespace).svc.cluster.local`, 其中 "cluster.local" 是集群域。 + 一旦每个 Pod 创建成功,就会得到一个匹配的 DNS 子域,格式为:`$(podname).$(governing service domain)`,其中管理服务由 StatefulSet 的 `serviceName` 域来定义。 + + + + +下面给出一些选择集群域、服务名、StatefulSet 名、及其怎样影响 StatefulSet 的 Pod 上的 DNS 名称的示例: + +Cluster Domain | Service (ns/name) | StatefulSet (ns/name) | StatefulSet Domain | Pod DNS | Pod Hostname | +-------------- | ----------------- | ----------------- | -------------- | ------- | ------------ | + cluster.local | default/nginx | default/web | nginx.default.svc.cluster.local | web-{0..N-1}.nginx.default.svc.cluster.local | web-{0..N-1} | + cluster.local | foo/nginx | foo/web | nginx.foo.svc.cluster.local | web-{0..N-1}.nginx.foo.svc.cluster.local | web-{0..N-1} | + kube.local | foo/nginx | foo/web | nginx.foo.svc.kube.local | web-{0..N-1}.nginx.foo.svc.kube.local | web-{0..N-1} | + +{{< note >}} + +**注意** 集群域会被设置为 `cluster.local` 除非有[其他配置](/docs/concepts/services-networking/dns-pod-service/#how-it-works)。 +{{< /note >}} + + + +### 稳定的存储 + +Kubernetes 为每个 VolumeClaimTemplate 创建一个 [PersistentVolume](/docs/concepts/storage/persistent-volumes/)。在上面的 nginx 示例中,每个 Pod 将会得到基于 StorageClass `my-storage-class` 提供的 1 Gib 的 PersistentVolume。如果没有声明 StorageClass,就会使用默认的 StorageClass。当一个 Pod 被安排到节点上时,它的 `volumeMounts` 挂载了与其 PersistentVolumeClaims 相关联的 PersistentVolume。请注意,当 Pod 或者 StatefulSet 被删除时,与PersistentVolumeClaims 相关联的 PersistentVolume 并不会被删除。要删除它必须通过手动方式来完成。 + + + + +### Pod 名称标签 + +当 StatefulSet 创建 Pod 时,它会添加一个标签 `statefulset.kubernetes.io/pod-name`,该标签设置为 Pod 名称。这个标签允许您给 StatefulSet 中的特定 Pod 绑定一个 Service。 + + + +## 部署和伸缩保证 + +* 对于包含 N 个 副本的 StatefulSet,当部署 Pod 时,它们是依次创建的,顺序为 {0..N-1}。 +* 当删除 Pod 时,它们是逆序终止的,顺序为 {N-1..0}。 +* 在将缩放操作应用到 Pod 之前,它前面的所有 Pod 必须是 Running 和 Ready 状态。 +* 在 Pod 终止之前,所有的继任者必须完全关闭。 + + + +StatefulSet 不应该声明 `pod.Spec.TerminationGracePeriodSeconds` 为 0。这种做法是不安全的,要强烈阻止。更多的解释请参考 [强制删除 StatefulSet Pods](/docs/tasks/run-application/force-delete-stateful-set-pod/)。 + + + +在上面的 nginx 示例被创建后,会按照 web-0、web-1、web-2 的顺序部署三个 Pod。在 web-0 进入[Running 和 Ready](/docs/user-guide/pod-states/)状态前不会部署 web-1。在 web-1 进入Running 和 Ready 状态前不会部署 web-2。如果 web-1 已经处于 Running 和 Ready 状态,而 web-2 尚未部署,在此期间发生了 web-0 运行失败,那么 web-2 将不会被部署,要等到 web-0 部署完成并进入 Running 和 Ready 状态后,才会部署 web-2。 + + + + 如果用户想将示例中的 StatefulSet 收缩为 `replicas=1`,首先被终止的是 web-2。在 web-2 没有被完全停止和删除前,web-1 不会被终止。当 web-2 已被终止和删除、web-1尚未被终止,如果在此期间发生 web-0 运行失败,那么就不会终止 web-1,必须等到 web-0 进入 Running 和 Ready 状态后才会终止 web-1。 + + + +### Pod 管理策略 +在 Kubernetes 1.7及以后的版本中,StatefulSet 允许您放松其排序保证,同时通过它的 `.spec.podManagementPolicy` 域保持其唯一性和身份保证。 + +#### 有序的 Pod 管理 + +`有序的` Pod 管理是 StatefulSet 的默认功能。它实现了 [上面](#deployment-and-scaling-guarantees)描述的行为。 + +#### 并行的 Pod 管理 + +`并行` Pod 管理让 StatefulSet 控制器并行的启动或终止所有的 Pod,启动或者终止其他 Pod 前,无需等待 Pod 进入 Running 和 ready 或者完全停止状态。 + + + +## 更新策略 + +在 Kubernetes 1.7 及以后的版本中,StatefulSet 的 `.spec.updateStrategy` 字段让您可以配置和禁用掉自动滚动更新 Pod 的容器、标签、资源请求/限制、以及注解。 + + + + +### On Delete + +`OnDelete` 更新策略实现了 1.6 及以前版本的历史遗留行为。当 StatefulSet 的 `.spec.updateStrategy.type` 设置为 `OnDelete` 时,它的控制器将不会自动更新 StatefulSet 中的 Pod。用户必须手动删除 Pod 以便让控制器创建新的 Pod,以此来对 StatefulSet 的 `.spec.template` 的变动作出反应。 + + + + +### 滚动更新(Rolling Updates) + +`RollingUpdate` 更新策略对 StatefulSet 中的 Pod 执行自动的滚动更新。在没有声明`.spec.updateStrategy`时,`RollingUpdate` 是默认配置。 +当 StatefulSet 的 `.spec.updateStrategy.type` 被设置为 `RollingUpdate` 时,StatefulSet 控制器会删除和重建 StatefulSet 中的每个 Pod。 +它将按照与 Pod 终止相同的顺序(从最大序号到最小序号)进行,每次更新一个 Pod。它会等到被更新的 Pod 进入 Running 和 Ready状态,然后再更新其前身。 + + + +#### 分区 + +通过声明 `.spec.updateStrategy.rollingUpdate.partition`的方式,`RollingUpdate` 更新策略可以实现分区。如果声明了一个分区,当 StatefulSet 的`.spec.template` 被更新时,所有序号大于等于该分区序号的 Pod 都会被更新。所有序号小于该分区序号的 Pod 都不会被更新,并且,即使他们被删除也会依据之前的版本进行重建。如果 StatefulSet 的 `.spec.updateStrategy.rollingUpdate.partition` 大于它的 `.spec.replicas`,对它的 `.spec.template` 的更新将不会传递到它的 Pod。 +在大多数情况下,您不需要使用分区,但如果您希望进行阶段更新、执行金丝雀或执行分阶段展开,则这些分区会非常有用。 + + +{{% /capture %}} +{{% capture whatsnext %}} + + + +* 示例一: [部署有状态应用](/docs/tutorials/stateful-application/basic-stateful-set/)。 +* 示例二: [使用 StatefulSet 部署 Cassandra](/docs/tutorials/stateful-application/cassandra/)。 + + +{{% /capture %}} +