[zh] Fix links in concepts section (3)

This commit is contained in:
Qiming Teng 2020-08-01 14:49:49 +08:00
parent 91494d2e3c
commit b13b686e9c
5 changed files with 378 additions and 431 deletions

View File

@ -1,19 +1,13 @@
---
title: 干扰
title: 干扰Disruptions
content_type: concept
weight: 60
---
<!--
---
reviewers:
- erictune
- foxish
- davidopp
title: Disruptions
content_type: concept
weight: 60
---
-->
<!-- overview -->
@ -22,31 +16,23 @@ This guide is for application owners who want to build
highly available applications, and thus need to understand
what types of Disruptions can happen to Pods.
-->
本指南针对的是希望构建高可用性应用程序的应用所有者,他们有必要了解可能发生在 pod 上的干扰类型。
<!--
It is also for Cluster Administrators who want to perform automated
cluster actions, like upgrading and autoscaling clusters.
-->
文档同样适用于想要执行自动化集群操作(例如升级和自动扩展集群)的集群管理员。
<!-- body -->
<!--
## Voluntary and Involuntary Disruptions
-->
## 自愿干扰和非自愿干扰
<!--
Pods do not disappear until someone (a person or a controller) destroys them, or
there is an unavoidable hardware or system software error.
-->
## 自愿干扰和非自愿干扰 {#voluntary-and-involuntary-disruptions}
Pod 不会消失,除非有人(用户或控制器)将其销毁,或者出现了不可避免的硬件或软件系统错误。
@ -54,8 +40,7 @@ Pod 不会消失,除非有人(用户或控制器)将其销毁,或者出
We call these unavoidable cases *involuntary disruptions* to
an application. Examples are:
-->
我们把这些不可避免的情况称为应用的*非自愿干扰*。例如:
我们把这些不可避免的情况称为应用的*非自愿干扰Involuntary Disruptions*。例如:
<!--
- a hardware failure of the physical machine backing the node
@ -71,14 +56,13 @@ an application. Examples are:
- 云提供商或虚拟机管理程序中的故障导致的虚拟机消失
- 内核错误
- 节点由于集群网络隔离从集群中消失
- 由于节点[资源不足](/docs/tasks/administer-cluster/out-of-resource/)导致 pod 被驱逐。
- 由于节点[资源不足](/zh/docs/tasks/administer-cluster/out-of-resource/)导致 pod 被驱逐。
<!--
Except for the out-of-resources condition, all these conditions
should be familiar to most users; they are not specific
to Kubernetes.
-->
除了资源不足的情况,大多数用户应该都熟悉这些情况;它们不是特定于 Kubernetes 的。
<!--
@ -86,8 +70,8 @@ We call other cases *voluntary disruptions*. These include both
actions initiated by the application owner and those initiated by a Cluster
Administrator. Typical application owner actions include:
-->
我们称其他情况为*自愿干扰*。包括由应用程序所有者发起的操作和由集群管理员发起的操作。典型的应用程序所有者的操
我们称其他情况为*自愿干扰Voluntary Disruptions*。
包括由应用程序所有者发起的操作和由集群管理员发起的操作。典型的应用程序所有者的操
作包括:
<!--
@ -95,34 +79,29 @@ Administrator. Typical application owner actions include:
- updating a deployment's pod template causing a restart
- directly deleting a pod (e.g. by accident)
-->
- 删除 deployment 或其他管理 pod 的控制器
- 更新了 deployment 的 pod 模板导致 pod 重启
- 直接删除 pod例如因为误操作
- 删除 Deployment 或其他管理 Pod 的控制器
- 更新了 Deployment 的 Pod 模板导致 Pod 重启
- 直接删除 Pod例如因为误操作
<!--
Cluster Administrator actions include:
-->
集群管理员操作包括:
<!--
- [Draining a node](/docs/tasks/administer-cluster/safely-drain-node/) for repair or upgrade.
- Draining a node from a cluster to scale the cluster down (learn about
[Cluster Autoscaling](/docs/tasks/administer-cluster/cluster-management/#cluster-autoscaler)
).
- Removing a pod from a node to permit something else to fit on that node.
-->
集群管理员操作包括:
- [排空drain节点](/docs/tasks/administer-cluster/safely-drain-node/)进行修复或升级。
- 从集群中排空节点以缩小集群(了解[集群自动扩缩](/docs/tasks/administer-cluster/cluster-management/#cluster-autoscaler))。
- 从节点中移除一个 pod以允许其他 pod 使用该节点。
- [排空drain节点](/zh/docs/tasks/administer-cluster/safely-drain-node/)进行修复或升级。
- 从集群中排空节点以缩小集群(了解[集群自动扩缩](/zh/docs/tasks/administer-cluster/cluster-management/#cluster-autoscaler))。
- 从节点中移除一个 Pod以允许其他 Pod 使用该节点。
<!--
These actions might be taken directly by the cluster administrator, or by automation
run by the cluster administrator, or by your cluster hosting provider.
-->
这些操作可能由集群管理员直接执行,也可能由集群管理员所使用的自动化工具执行,或者由集群托管提供商自动执行。
<!--
@ -130,29 +109,24 @@ Ask your cluster administrator or consult your cloud provider or distribution do
to determine if any sources of voluntary disruptions are enabled for your cluster.
If none are enabled, you can skip creating Pod Disruption Budgets.
-->
咨询集群管理员或联系云提供商,或者查询发布文档,以确定是否为集群启用了任何资源干扰源。如果没有启用,可以不用创建 Pod Disruption BudgetsPod 干扰预算)
{{< caution >}}
咨询集群管理员或联系云提供商,或者查询发布文档,以确定是否为集群启用了任何资源干扰源。
如果没有启用,可以不用创建 Pod Disruption BudgetsPod 干扰预算)
<!--
Not all voluntary disruptions are constrained by Pod Disruption Budgets. For example,
deleting deployments or pods bypasses Pod Disruption Budgets.
-->
并非所有的自愿干扰都会受到 pod 干扰预算的限制。例如,删除 deployment 或 pod 的删除操作就会跳过 pod 干扰预算检查
{{< caution >}}
并非所有的自愿干扰都会受到 Pod 干扰预算的限制
例如,删除 Peployment 或 Pod 的删除操作就会跳过 Pod 干扰预算检查。
{{< /caution >}}
<!--
## Dealing with Disruptions
-->
## 处理干扰
<!--
Here are some ways to mitigate involuntary disruptions:
-->
## 处理干扰
以下是减轻非自愿干扰的一些方法:
@ -167,10 +141,13 @@ spread applications across racks (using
or across zones (if using a
[multi-zone cluster](/docs/setup/multiple-zones).)
-->
- 确保 pod[请求所需资源](/docs/tasks/configure-pod-container/assign-cpu-ram-container)。
- 如果需要更高的可用性,请复制应用程序。(了解有关运行多副本的[无状态](/docs/tasks/run-application/run-stateless-application-deployment/)和[有状态](/docs/tasks/run-application/run-replicated-stateful-application/)应用程序的信息。)
- 为了在运行复制应用程序时获得更高的可用性,请跨机架(使用[反亲和性](/docs/user-guide/node-selection/#inter-pod-affinity-and-anti-affinity-beta-feature))或跨区域(如果使用[多区域集群](/docs/setup/multiple-zones))扩展应用程序。
- 确保 Pod 在请求中给出[所需资源](/zh/docs/tasks/configure-pod-container/assign-memory-resource/)。
- 如果需要更高的可用性,请复制应用程序。
(了解有关运行多副本的[无状态](/zh/docs/tasks/run-application/run-stateless-application-deployment/)
和[有状态](/zh/docs/tasks/run-application/run-replicated-stateful-application/)应用程序的信息。)
- 为了在运行复制应用程序时获得更高的可用性,请跨机架(使用
[反亲和性](/zh/docs/concepts/scheduling-eviction/assign-pod-node/))或跨区域
(如果使用[多区域集群](/zh/docs/setup/best-practices/multiple-zones/))扩展应用程序。
<!--
The frequency of voluntary disruptions varies. On a basic Kubernetes cluster, there are
@ -181,7 +158,6 @@ of cluster (node) autoscaling may cause voluntary disruptions to defragment and
Your cluster administrator or hosting provider should have documented what level of voluntary
disruptions, if any, to expect.
-->
自愿干扰的频率各不相同。在一个基本的 Kubernetes 集群中,根本没有自愿干扰。然而,集群管理
或托管提供商可能运行一些可能导致自愿干扰的额外服务。例如,节点软
更新可能导致自愿干扰。另外,集群(节点)自动缩放的某些
@ -193,16 +169,15 @@ Kubernetes offers features to help run highly available applications at the same
time as frequent voluntary disruptions. We call this set of features
*Disruption Budgets*.
-->
Kubernetes 提供特性来满足在出现频繁自愿干扰的同时运行高可用的应用程序。我们称这些特性为*干扰预算*
Kubernetes 提供特性来满足在出现频繁自愿干扰的同时运行高可用的应用程序。我们称这些特性为
*干扰预算Disruption Budget*
<!--
## How Disruption Budgets Work
-->
## Pod disruption budgets
## 干扰预算工作原理
Kubernetes offers features to help you run highly available applications even when you
introduce frequent voluntary disruptions.
<!--
An Application Owner can create a `PodDisruptionBudget` object (PDB) for each application.
A PDB limits the number of pods of a replicated application that are down simultaneously from
voluntary disruptions. For example, a quorum-based application would
@ -211,9 +186,16 @@ number needed for a quorum. A web front end might want to
ensure that the number of replicas serving load never falls below a certain
percentage of the total.
-->
## 干扰预算
应用程序所有者可以为每个应用程序创建 `PodDisruptionBudget` 对象PDB。PDB 将限制在同一时间因自愿干扰导致的复制应用程序中宕机的 pod 数量。例如,基于定额的应用程序希望确保运行的副本数
永远不会低于仲裁所需的数量。Web 前端可能希望确保提供负载的副本数量永远不会低于总数的某个百分比。
{{< feature-state for_k8s_version="v1.5" state="beta" >}}
即使你会经常引入自愿性干扰Kubernetes 也能够支持你运行高度可用的应用。
应用程序所有者可以为每个应用程序创建 `PodDisruptionBudget` 对象PDB
PDB 将限制在同一时间因自愿干扰导致的复制应用程序中宕机的 pod 数量。
例如,基于票选机制的应用程序希望确保运行的副本数永远不会低于仲裁所需的数量。
Web 前端可能希望确保提供负载的副本数量永远不会低于总数的某个百分比。
<!--
Cluster managers and hosting providers should use tools which
@ -221,18 +203,21 @@ respect Pod Disruption Budgets by calling the [Eviction API](/docs/tasks/adminis
instead of directly deleting pods or deployments. Examples are the `kubectl drain` command
and the Kubernetes-on-GCE cluster upgrade script (`cluster/gce/upgrade.sh`).
-->
集群管理员和托管提供商应该使用遵循 Pod Disruption Budgets 的接口(通过调用[驱逐 API](/docs/tasks/administer-cluster/safely-drain-node/#the-eviction-api)),而不是直接删除 pod 或 deployment。示例包括 `kubectl drain` 命令和 Kubernetes-on-GCE 集群升级脚本(`cluster/gce/upgrade.sh`)。
集群管理员和托管提供商应该使用遵循 Pod Disruption Budgets 的接口
(通过调用[Eviction API](/zh/docs/tasks/administer-cluster/safely-drain-node/#the-eviction-api)
而不是直接删除 Pod 或 Deployment。
<!--
When a cluster administrator wants to drain a node
they use the `kubectl drain` command. That tool tries to evict all
the pods on the machine. The eviction request may be temporarily rejected,
For example, the `kubectl drain` subcommand lets you mark a node as going out of
service. When you run `kubectl drain`, the tool tries to evict all of the Pods on
the Node you'are taking out of service. The eviction request may be temporarily rejected,
and the tool periodically retries all failed requests until all pods
are terminated, or until a configurable timeout is reached.
-->
当集群管理员想排空一个节点时,可以使用 `kubectl drain` 命令。该命令试图驱逐机器上的所有 pod。驱逐请求可能会暂时被拒绝且该工具定时重试失败的请求直到所有的 pod 都被终止,或者达到配置的超时时间。
例如,`kubectl drain` 命令可以用来标记某个节点即将停止服务。
运行 `kubectl drain` 命令时,工具会尝试驱逐机器上的所有 Pod。
`kubectl` 所提交的驱逐请求可能会暂时被拒绝,所以该工具会定时重试失败的请求,
直到所有的 Pod 都被终止,或者达到配置的超时时间。
<!--
A PDB specifies the number of replicas that an application can tolerate having, relative to how
@ -240,64 +225,66 @@ many it is intended to have. For example, a Deployment which has a `.spec.repli
supposed to have 5 pods at any given time. If its PDB allows for there to be 4 at a time,
then the Eviction API will allow voluntary disruption of one, but not two pods, at a time.
-->
PDB 指定应用程序可以容忍的副本数量(相当于应该有多少副本)。例如,具有 `.spec.replicas: 5` 的 deployment 在任何时间都应该有 5 个 pod。如果 PDB 允许其在某一时刻有 4 个副本,那么驱逐 API 将允许同一时刻仅有一个而不是两个 pod 自愿干扰。
PDB 指定应用程序可以容忍的副本数量(相当于应该有多少副本)。
例如,具有 `.spec.replicas: 5` 的 Deployment 在任何时间都应该有 5 个 Pod。
如果 PDB 允许其在某一时刻有 4 个副本,那么驱逐 API 将允许同一时刻仅有一个而不是两个 Pod 自愿干扰。
<!--
The group of pods that comprise the application is specified using a label selector, the same
as the one used by the application's controller (deployment, stateful-set, etc).
-->
使用标签选择器来指定构成应用程序的一组 pod这与应用程序的控制器deploymentstateful-set 等)选择 pod 的逻辑一样。
使用标签选择器来指定构成应用程序的一组 Pod这与应用程序的控制器DeploymentStatefulSet 等)
选择 Pod 的逻辑一样。
<!--
The "intended" number of pods is computed from the `.spec.replicas` of the pods controller.
The controller is discovered from the pods using the `.metadata.ownerReferences` of the object.
-->
Pod 控制器的 `.spec.replicas` 计算“预期的” pod 数量。根据 pod 对象的 `.metadata.ownerReferences` 字段来发现控制器。
Pod 控制器的 `.spec.replicas` 计算“预期的” Pod 数量。
根据 Pod 对象的 `.metadata.ownerReferences` 字段来发现控制器。
<!--
PDBs cannot prevent [involuntary disruptions](#voluntary-and-involuntary-disruptions) from
occurring, but they do count against the budget.
-->
PDB 不能阻止[非自愿干扰](#voluntary-and-involuntary-disruptions)的发生,但是确实会计入
算。
算。
<!--
Pods which are deleted or unavailable due to a rolling upgrade to an application do count
against the disruption budget, but controllers (like deployment and stateful-set)
are not limited by PDBs when doing rolling upgrades -- the handling of failures
during application updates is configured in the controller spec.
(Learn about [updating a deployment](/docs/concepts/workloads/controllers/deployment/#updating-a-deployment).)
are not limited by PDBs when doing rolling upgrades - the handling of failures
during application updates is configured in spec for the specific workload resource.
-->
由于应用程序的滚动升级而被删除或不可用的 pod 确实会计入干扰预算,但是控制器(如 deployment 和 stateful-set在进行滚动升级时不受 PDB
的限制。应用程序更新期间的故障处理是在控制器的 spec 中配置的。(了解[更新 deployment](/docs/concepts/workloads/controllers/deployment/#updating-a-deployment)。)
由于应用程序的滚动升级而被删除或不可用的 Pod 确实会计入干扰预算,
但是控制器(如 Deployment 和 StatefulSet在进行滚动升级时不受 PDB
的限制。应用程序更新期间的故障处理方式是在对应的工作负载资源的 `spec` 中配置的。
<!--
When a pod is evicted using the eviction API, it is gracefully terminated (see
`terminationGracePeriodSeconds` in [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core).)
When a pod is evicted using the eviction API, it is gracefully
[terminated](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination),
hornoring the
`terminationGracePeriodSeconds` setting in its [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core).)
-->
当使用驱逐 API 驱逐 pod 时pod 会被优雅地终止(参考 [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) 中的 `terminationGracePeriodSeconds`)。
当使用驱逐 API 驱逐 Pod 时Pod 会被体面地
[终止](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination),期间会
参考 [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)
中的 `terminationGracePeriodSeconds` 配置值。
<!--
## PDB Example
-->
## PDB 例子
<!--
Consider a cluster with 3 nodes, `node-1` through `node-3`.
The cluster is running several applications. One of them has 3 replicas initially called
`pod-a`, `pod-b`, and `pod-c`. Another, unrelated pod without a PDB, called `pod-x`, is also shown.
Initially, the pods are laid out as follows:
-->
## PDB 例子 {#pdb-example}
假设集群有 3 个节点,`node-1` 到 `node-3`。集群上运行了一些应用。其中一个应用有 3 个副本,分别是 `pod-a``pod-b` 和 `pod-c`。另外,还有一个不带 PDB 的无关 pod `pod-x` 也同样显示。最初,所有的 pod 分布如下:
假设集群有 3 个节点,`node-1` 到 `node-3`。集群上运行了一些应用。
其中一个应用有 3 个副本,分别是 `pod-a``pod-b` 和 `pod-c`
另外,还有一个不带 PDB 的无关 pod `pod-x` 也同样显示出来。
最初,所有的 Pod 分布如下:
| node-1 | node-2 | node-3 |
|:--------------------:|:-------------------:|:------------------:|
@ -308,8 +295,7 @@ Initially, the pods are laid out as follows:
All 3 pods are part of a deployment, and they collectively have a PDB which requires
there be at least 2 of the 3 pods to be available at all times.
-->
3 个 pod 都是 deployment 的一部分,并且共同拥有同一个 PDB要求 3 个 pod 中至少有 2 个 pod 始终处于可用状态。
3 个 Pod 都是 deployment 的一部分,并且共同拥有同一个 PDB要求 3 个 Pod 中至少有 2 个 Pod 始终处于可用状态。
<!--
For example, assume the cluster administrator wants to reboot into a new kernel version to fix a bug in the kernel.
@ -319,7 +305,10 @@ Both pods go into the `terminating` state at the same time.
This puts the cluster in this state:
-->
例如,假设集群管理员想要重启系统,升级内核版本来修复内核中的 bug。集群管理员首先使用 `kubectl drain` 命令尝试排空 `node-1` 节点。命令尝试驱逐 `pod-a``pod-x`。操作立即就成功了。两个 pod 同时进入 `terminating` 状态。这时的集群处于下面的状态:
例如,假设集群管理员想要重启系统,升级内核版本来修复内核中的权限。
集群管理员首先使用 `kubectl drain` 命令尝试排空 `node-1` 节点。
命令尝试驱逐 `pod-a``pod-x`。操作立即就成功了。
两个 Pod 同时进入 `terminating` 状态。这时的集群处于下面的状态:
| node-1 *draining* | node-2 | node-3 |
|:--------------------:|:-------------------:|:------------------:|
@ -331,21 +320,21 @@ The deployment notices that one of the pods is terminating, so it creates a repl
called `pod-d`. Since `node-1` is cordoned, it lands on another node. Something has
also created `pod-y` as a replacement for `pod-x`.
-->
Deployment 控制器观察到其中一个 pod 正在终止,因此它创建了一个替代 pod `pod-d`。由于 `node-1` 被封锁cordon`pod-d` 落在另一个节点上。同样其他控制器也创建了 `pod-y` 作为 `pod-x` 的替代品。
Deployment 控制器观察到其中一个 Pod 正在终止,因此它创建了一个替代 Pod `pod-d`
由于 `node-1` 被封锁cordon`pod-d` 落在另一个节点上。
同样其他控制器也创建了 `pod-y` 作为 `pod-x` 的替代品。
<!--
(Note: for a StatefulSet, `pod-a`, which would be called something like `pod-0`, would need
to terminate completely before its replacement, which is also called `pod-0` but has a
different UID, could be created. Otherwise, the example applies to a StatefulSet as well.)
-->
(注意:对于 StatefulSet 来说,`pod-a`(也称为 `pod-0`)需要在替换 pod 创建之前完全终止,替代它的也称为 `pod-0`,但是具有不同的 UID。反之,样例也适用于 StatefulSet。
(注意:对于 StatefulSet 来说,`pod-a`(也称为 `pod-0`)需要在替换 Pod 创建之前完全终止,
替代它的也称为 `pod-0`,但是具有不同的 UID。除此之外,此示例也适用于 StatefulSet。
<!--
Now the cluster is in this state:
-->
当前集群的状态如下:
| node-1 *draining* | node-2 | node-3 |
@ -356,8 +345,7 @@ Now the cluster is in this state:
<!--
At some point, the pods terminate, and the cluster looks like this:
-->
在某一时刻pod 被终止,集群如下所示:
在某一时刻Pod 被终止,集群如下所示:
| node-1 *drained* | node-2 | node-3 |
|:--------------------:|:-------------------:|:------------------:|
@ -369,13 +357,13 @@ At this point, if an impatient cluster administrator tries to drain `node-2` or
`node-3`, the drain command will block, because there are only 2 available
pods for the deployment, and its PDB requires at least 2. After some time passes, `pod-d` becomes available.
-->
此时如果一个急躁的集群管理员试图排空drain`node-2` 或 `node-3`drain 命令将被阻塞,因为对于 deployment 来说只有 2 个可用的 pod并且它的 PDB 至少需要 2 个。经过一段时间,`pod-d` 变得可用。
此时如果一个急躁的集群管理员试图排空drain`node-2` 或 `node-3`drain 命令将被阻塞,
因为对于 Deployment 来说只有 2 个可用的 Pod并且它的 PDB 至少需要 2 个。
经过一段时间,`pod-d` 变得可用。
<!--
The cluster state now looks like this:
-->
集群状态如下所示:
| node-1 *drained* | node-2 | node-3 |
@ -390,8 +378,10 @@ The drain command will try to evict the two pods in some order, say
But, when it tries to evict `pod-d`, it will be refused because that would leave only
one pod available for the deployment.
-->
现在集群管理员试图排空drain`node-2`。drain 命令将尝试按照某种顺序驱逐两个 pod假设先是 `pod-b`,然后是 `pod-d`。命令成功驱逐 `pod-b`,但是当它尝试驱逐 `pod-d`时将被拒绝,因为对于 deployment 来说只剩一个可用的 pod 了。
现在集群管理员试图排空drain`node-2`。
drain 命令将尝试按照某种顺序驱逐两个 Pod假设先是 `pod-b`,然后是 `pod-d`
命令成功驱逐 `pod-b`,但是当它尝试驱逐 `pod-d`时将被拒绝,因为对于
Deployment 来说只剩一个可用的 Pod 了。
<!--
The deployment creates a replacement for `pod-b` called `pod-e`.
@ -399,8 +389,8 @@ Because there are not enough resources in the cluster to schedule
`pod-e` the drain will again block. The cluster may end up in this
state:
-->
Deployment 创建 `pod-b` 的替代 pod `pod-e`因为集群中没有足够的资源来调度 `pod-e`drain 命令再次阻塞。集群最终将是下面这种状态:
Deployment 创建 `pod-b` 的替代 Pod `pod-e`
因为集群中没有足够的资源来调度 `pod-e`drain 命令再次阻塞。集群最终将是下面这种状态:
| node-1 *drained* | node-2 | node-3 | *no node* |
|:--------------------:|:-------------------:|:------------------:|:------------------:|
@ -411,14 +401,12 @@ Deployment 创建 `pod-b` 的替代 pod `pod-e`。因为集群中没有足够的
At this point, the cluster administrator needs to
add a node back to the cluster to proceed with the upgrade.
-->
此时,集群管理员需要增加一个节点到集群中以继续升级操作。
<!--
You can see how Kubernetes varies the rate at which disruptions
can happen, according to:
-->
可以看到 Kubernetes 如何改变干扰发生的速率,根据:
<!--
@ -428,7 +416,6 @@ can happen, according to:
- the type of controller
- the cluster's resource capacity
-->
- 应用程序需要多少个副本
- 优雅关闭应用实例需要多长时间
- 启动应用新实例需要多长时间
@ -437,16 +424,13 @@ can happen, according to:
<!--
## Separating Cluster Owner and Application Owner Roles
-->
## 分离集群所有者和应用所有者角色
<!--
Often, it is useful to think of the Cluster Manager
and Application Owner as separate roles with limited knowledge
of each other. This separation of responsibilities
may make sense in these scenarios:
-->
## 分离集群所有者和应用所有者角色
通常,将集群管理者和应用所有者视为彼此了解有限的独立角色是很有用的。这种责任分离在下面这些场景下是有意义的:
@ -455,7 +439,6 @@ may make sense in these scenarios:
there is natural specialization of roles
- when third-party tools or services are used to automate cluster management
-->
- 当有许多应用程序团队共用一个 Kubernetes 集群,并且有自然的专业角色
- 当第三方工具或服务用于集群自动化管理
@ -463,30 +446,24 @@ may make sense in these scenarios:
Pod Disruption Budgets support this separation of roles by providing an
interface between the roles.
-->
Pod 干扰预算通过在角色之间提供接口来支持这种分离。
<!--
If you do not have such a separation of responsibilities in your organization,
you may not need to use Pod Disruption Budgets.
-->
如果你的组织中没有这样的责任分离,则可能不需要使用 Pod 干扰预算。
<!--
## How to perform Disruptive Actions on your Cluster
-->
## 如何在集群上执行干扰操作
<!--
If you are a Cluster Administrator, and you need to perform a disruptive action on all
the nodes in your cluster, such as a node or system software upgrade, here are some options:
-->
## 如何在集群上执行干扰性操作
如果你是集群管理员,并且需要对集群中的所有节点执行干扰操作,例如节点或系统软件升级,则可以使用以下选项
<!--
- Accept downtime during the upgrade.
- Failover to another complete replica cluster.
@ -509,25 +486,18 @@ the nodes in your cluster, such as a node or system software upgrade, here are s
- 最小的资源重复。
- 允许更多的集群管理自动化。
- 编写可容忍干扰的应用程序是棘手的,但对于支持容忍自愿干扰所做的工作,和支持自动扩缩和容忍非
愿干扰所做工作相比,有大量的重叠
自愿干扰所做工作相比,有大量的重叠
## {{% heading "whatsnext" %}}
<!--
* Follow steps to protect your application by [configuring a Pod Disruption Budget](/docs/tasks/run-application/configure-pdb/).
-->
* 参考[配置 Pod 干扰预算](/docs/tasks/run-application/configure-pdb/)中的方法来保护你的
用。
<!--
* Learn more about [draining nodes](/docs/tasks/administer-cluster/safely-drain-node/)
* Learn about [updating a deployment](/docs/concepts/workloads/controllers/deployment/#updating-a-deployment)
including steps to maintain its availability during the rollout.
-->
* 了解更多关于[排空节点](/docs/tasks/administer-cluster/safely-drain-node/)的信息。
* 参考[配置 Pod 干扰预算](/zh/docs/tasks/run-application/configure-pdb/)中的方法来保护你的应用。
* 进一步了解[排空节点](/zh/docs/tasks/administer-cluster/safely-drain-node/)的信息。
* 了解[更新 Deployment](/zh/docs/concepts/workloads/controllers/deployment/#updating-a-deployment)
的过程,包括如何在其进程中维持应用的可用性

View File

@ -5,14 +5,9 @@ weight: 80
---
<!--
---
reviewers:
- verb
- yujuhong
title: Ephemeral Containers
content_type: concept
weight: 80
---
-->
<!-- overview -->
@ -21,12 +16,13 @@ weight: 80
<!--
This page provides an overview of ephemeral containers: a special type of container
that runs temporarily in an existing {{< glossary_tooltip term_id="pod" >}} to accomplish user-initiated actions such
as troubleshooting. You use ephemeral containers to inspect services rather than
to build applications.
that runs temporarily in an existing {{< glossary_tooltip term_id="pod" >}} to
accomplish user-initiated actions such as troubleshooting. You use ephemeral
containers to inspect services rather than to build applications.
-->
此页面概述了临时容器:一种特殊的容器,该容器在现有 {{< glossary_tooltip term_id="pod" >}} 中临时运行,为了完成用户启动的操作,例如故障排查。使用临时容器来检查服务,而不是构建应用程序。
本页面概述了临时容器:一种特殊的容器,该容器在现有 {{< glossary_tooltip text="Pod" term_id="pod" >}}
中临时运行,以便完成用户发起的操作,例如故障排查。
你会使用临时容器来检查服务,而不是用它来构建应用程序。
<!--
Ephemeral containers are in early alpha state and are not suitable for production
@ -35,30 +31,30 @@ when targeting the namespaces of a container. In accordance with the [Kubernetes
Deprecation Policy](/docs/reference/using-api/deprecation-policy/), this alpha
feature could change significantly in the future or be removed entirely.
-->
{{< warning >}}
临时容器处于早期的 alpha 阶段,不适用于生产环境集群。应该预料到临时容器在某些情况下不起作用,例如在定位容器的命名空间时。根据 [Kubernetes 弃用政策](/docs/reference/using-api/deprecation-policy/),该 alpha 功能将来可能发生重大变化或完全删除。
临时容器处于早期的 alpha 阶段,不适用于生产环境集群。
应该预料到临时容器在某些情况下不起作用,例如在定位容器的命名空间时。
根据 [Kubernetes 弃用政策](/zh/docs/reference/using-api/deprecation-policy/)
此 alpha 功能将来可能发生重大变化或被完全删除。
{{< /warning >}}
<!-- body -->
<!--
## Understanding ephemeral containers
-->
## 了解临时容器
<!--
{{< glossary_tooltip text="Pods" term_id="pod" >}} are the fundamental building
block of Kubernetes applications. Since Pods are intended to be disposable and
replaceable, you cannot add a container to a Pod once it has been created.
Instead, you usually delete and replace Pods in a controlled fashion using
{{< glossary_tooltip text="deployments" term_id="deployment" >}}.
-->
## 了解临时容器
{{< glossary_tooltip text="Pods" term_id="pod" >}} 是 Kubernetes 应用程序的基本构建块。由于 pod 是一次性且可替换的,因此一旦 Pod 创建,就无法将容器加入到 Pod 中。取而代之的是,通常使用 {{< glossary_tooltip text="deployments" term_id="deployment" >}} 以受控的方式来删除并替换 Pod。
{{< glossary_tooltip text="Pod" term_id="pod" >}} 是 Kubernetes 应用程序的基本构建块。
由于 Pod 是一次性且可替换的,因此一旦 Pod 创建,就无法将容器加入到 Pod 中。
取而代之的是,通常使用 {{< glossary_tooltip text="Deployment" term_id="deployment" >}}
以受控的方式来删除并替换 Pod。
<!--
Sometimes it's necessary to inspect the state of an existing Pod, however, for
@ -66,24 +62,23 @@ example to troubleshoot a hard-to-reproduce bug. In these cases you can run
an ephemeral container in an existing Pod to inspect its state and run
arbitrary commands.
-->
有时有必要检查现有 Pod 的状态,例如,对于难以复现的故障进行排查。在这些场景中,可以在现有 Pod 中运行临时容器来检查其状态并运行任意命令。
有时有必要检查现有 Pod 的状态。例如,对于难以复现的故障进行排查。
在这些场景中,可以在现有 Pod 中运行临时容器来检查其状态并运行任意命令。
<!--
### What is an ephemeral container?
-->
### 什么是临时容器?
<!--
Ephemeral containers differ from other containers in that they lack guarantees
for resources or execution, and they will never be automatically restarted, so
they are not appropriate for building applications. Ephemeral containers are
described using the same `ContainerSpec` as regular containers, but many fields
are incompatible and disallowed for ephemeral containers.
-->
### 什么是临时容器?
临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启,因此不适用于构建应用程序。临时容器使用与常规容器相同的 `ContainerSpec` 段进行描述,但许多字段是不相容且不允许的。
临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启,
因此不适用于构建应用程序。
临时容器使用与常规容器相同的 `ContainerSpec` 节来描述,但许多字段是不兼容和不允许的。
<!--
- Ephemeral containers may not have ports, so fields such as `ports`,
@ -92,39 +87,39 @@ are incompatible and disallowed for ephemeral containers.
- For a complete list of allowed fields, see the [EphemeralContainer reference
documentation](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#ephemeralcontainer-v1-core).
-->
- 临时容器没有端口配置,因此像 `ports``livenessProbe``readinessProbe`
这样的字段是不允许的。
- 临时容器没有端口配置,因此像 `ports``livenessProbe``readinessProbe` 这样的字段是不允许的。
- Pod 资源分配是不可变的,因此 `resources` 配置是不允许的。
- 有关允许字段的完整列表,请参见[临时容器参考文档](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#ephemeralcontainer-v1-core)。
- 有关允许字段的完整列表,请参见
[EphemeralContainer 参考文档](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#ephemeralcontainer-v1-core)。
<!--
Ephemeral containers are created using a special `ephemeralcontainers` handler
in the API rather than by adding them directly to `pod.spec`, so it's not
possible to add an ephemeral container using `kubectl edit`.
-->
临时容器是使用 API 中的一种特殊的 `ephemeralcontainers` 处理器进行创建的,而不是直接添加到 `pod.spec` 段,因此无法使用 `kubectl edit` 来添加一个临时容器。
临时容器是使用 API 中的一种特殊的 `ephemeralcontainers` 处理器进行创建的,
而不是直接添加到 `pod.spec` 段,因此无法使用 `kubectl edit` 来添加一个临时容器。
<!--
Like regular containers, you may not change or remove an ephemeral container
after you have added it to a Pod.
-->
与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。
<!--
## Uses for ephemeral containers
-->
## 临时容器的用途
<!--
Ephemeral containers are useful for interactive troubleshooting when `kubectl
exec` is insufficient because a container has crashed or a container image
doesn't include debugging utilities.
-->
## 临时容器的用途
当由于容器崩溃或容器镜像不包含调试实用程序而导致 `kubectl exec` 无用时,临时容器对于交互式故障排查很有用。
当由于容器崩溃或容器镜像不包含调试工具而导致 `kubectl exec` 无用时,
临时容器对于交互式故障排查很有用。
<!--
In particular, [distroless images](https://github.com/GoogleContainerTools/distroless)
@ -133,31 +128,32 @@ and exposure to bugs and vulnerabilities. Since distroless images do not include
shell or any debugging utilities, it's difficult to troubleshoot distroless
images using `kubectl exec` alone.
-->
尤其是,[distroless 镜像](https://github.com/GoogleContainerTools/distroless)能够使得部署最小的容器镜像,从而减少攻击面并减少故障和漏洞的暴露。由于 distroless 镜像不包含 shell 或任何的调试工具,因此很难单独使用 `kubectl exec` 命令进行故障排查。
尤其是,[distroless 镜像](https://github.com/GoogleContainerTools/distroless)
允许用户部署最小的容器镜像,从而减少攻击面并减少故障和漏洞的暴露。
由于 distroless 镜像不包含 Shell 或任何的调试工具,因此很难单独使用
`kubectl exec` 命令进行故障排查。
<!--
When using ephemeral containers, it's helpful to enable [process namespace
sharing](/docs/tasks/configure-pod-container/share-process-namespace/) so
you can view processes in other containers.
-->
使用临时容器时,启用[进程命名空间共享](/docs/tasks/configure-pod-container/share-process-namespace/)很有帮助,可以查看其他容器中的进程。
使用临时容器时,启用[进程名字空间共享](/zh/docs/tasks/configure-pod-container/share-process-namespace/)
很有帮助,可以查看其他容器中的进程。
<!--
### Examples
-->
### 示例
<!--
The examples in this section require the `EphemeralContainers` [feature
gate](/docs/reference/command-line-tools-reference/feature-gates/) to be
enabled, and Kubernetes client and server version v1.16 or later.
-->
### 示例
{{< note >}}
本节中的示例要求启用 `EphemeralContainers` [特性](/docs/reference/command-line-tools-reference/feature-gates/),并且 kubernetes 客户端和服务端版本要求为 v1.16 或更高版本。
本节中的示例要求启用 `EphemeralContainers`
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)
并且 kubernetes 客户端和服务端版本要求为 v1.16 或更高版本。
{{< /note >}}
<!--
@ -165,16 +161,17 @@ The examples in this section demonstrate how ephemeral containers appear in
the API. You would normally use a `kubectl` plugin for troubleshooting that
automates these steps.
-->
本节中的示例演示了临时容器如何出现在 API 中。 通常,您可以使用 `kubectl` 插件进行故障排查,从而自动化执行这些步骤。
本节中的示例演示了临时容器如何出现在 API 中。
通常,你可以使用 `kubectl` 插件进行故障排查,从而自动化执行这些步骤。
<!--
Ephemeral containers are created using the `ephemeralcontainers` subresource
of Pod, which can be demonstrated using `kubectl --raw`. First describe
of Pod, which can be demonstrated using `kubectl -raw`. First describe
the ephemeral container to add as an `EphemeralContainers` list:
-->
临时容器是使用 Pod 的 `ephemeralcontainers` 子资源创建的,可以使用 `kubectl --raw` 命令进行显示。首先描述临时容器被添加为一个 `EphemeralContainers` 列表:
临时容器是使用 Pod 的 `ephemeralcontainers` 子资源创建的,可以使用
`kubectl --raw` 命令进行显示。
首先描述临时容器被添加为一个 `EphemeralContainers` 列表:
```json
{
@ -200,7 +197,6 @@ the ephemeral container to add as an `EphemeralContainers` list:
<!--
To update the ephemeral containers of the already running `example-pod`:
-->
使用如下命令更新已运行的临时容器 `example-pod`
```shell
@ -210,7 +206,6 @@ kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralconta
<!--
This will return the new list of ephemeral containers:
-->
这将返回临时容器的新列表:
```json
@ -247,13 +242,14 @@ This will return the new list of ephemeral containers:
<!--
You can view the state of the newly created ephemeral container using `kubectl describe`:
-->
可以使用以下命令查看新创建的临时容器的状态:
```shell
kubectl describe pod example-pod
```
输出为:
```
...
Ephemeral Containers:
@ -277,7 +273,6 @@ Ephemeral Containers:
<!--
You can attach to the new ephemeral container using `kubectl attach`:
-->
可以使用以下命令连接到新的临时容器:
```shell
@ -288,22 +283,16 @@ kubectl attach -it example-pod -c debugger
If process namespace sharing is enabled, you can see processes from all the containers in that Pod.
For example, after attaching, you run `ps` in the debugger container:
-->
如果启用了进程命名空间共享,则可以查看该 Pod 所有容器中的进程。
例如,运行上述 `attach` 操作后,在调试器容器中运行 `ps` 操作:
<!--
# Run this in a shell inside the "debugger" ephemeral container
# 在 "debugger" 临时容器内中运行此 shell 命令
The output is similar to:
-->
```shell
# 在 "debugger" 临时容器内中运行此 shell 命令
ps auxww
```
运行命令后,输出类似于:
```
PID USER TIME COMMAND
1 root 0:00 /pause
@ -321,4 +310,3 @@ PID USER TIME COMMAND
29 root 0:00 ps auxww
```

View File

@ -12,30 +12,26 @@ This page provides an overview of init containers: specialized containers that r
Init containers can contain utilities or setup scripts not present in an app image.
-->
本页提供了 Init 容器的概览,它是一种专用的容器,在{{< glossary_tooltip text="Pod" term_id="pod" >}}内的应用容器启动之前运行,并包括一些应用镜像中不存在的实用工具和安装脚本。
本页提供了 Init 容器的概览,它是一种特殊容器,在 {{< glossary_tooltip text="Pod" term_id="pod" >}}
内的应用容器启动之前运行,可以包括一些应用镜像中不存在的实用工具和安装脚本。
<!--
You can specify init containers in the Pod specification alongside the `containers` array (which describes app containers).
-->
你可以在Pod的规格信息中与containers数组同级的位置指定 Init 容器。
<!-- body -->
你可以在 Pod 的规约中与用来描述应用容器的 `containers` 数组平行的位置指定
Init 容器。
<!-- body -->
<!--
## Understanding init containers
A {{< glossary_tooltip text="Pod" term_id="pod" >}} can have multiple containers running apps within it, but it can also have one or more init containers, which are run before the app containers are started.
-->
## 理解 Init 容器
{{< glossary_tooltip text="Pod" term_id="pod" >}} 可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
每个 {{< glossary_tooltip text="Pod" term_id="pod" >}} 中可以包含多个容器,
应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
<!--
Init containers are exactly like regular containers, except:
@ -47,21 +43,22 @@ Init 容器与普通的容器非常像,除了如下两点:
* 它们总是运行到完成。
* 每个都必须在下一个启动之前成功完成。
<!--
If a Pod's init container fails, Kubernetes repeatedly restarts the Pod until the init container succeeds. However, if the Pod has a `restartPolicy` of Never, Kubernetes does not restart the Pod.
-->
如果 Pod 的 Init 容器失败Kubernetes 会不断地重启该 Pod直到 Init 容器成功为止。然而,如果 Pod 对应的 `restartPolicy` 值为 Never它不会重新启动。
如果 Pod 的 Init 容器失败Kubernetes 会不断地重启该 Pod直到 Init 容器成功为止。
然而,如果 Pod 对应的 `restartPolicy` 值为 NeverKubernetes 不会重新启动 Pod。
<!--
To specify an init container for a Pod, add the `initContainers` field into the Pod specification, as an array of objects of type [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core), alongside the app `containers` array.
The status of the init containers is returned in `.status.initContainerStatuses` field as an array of the container statuses (similar to the `.status.containerStatuses` field).
-->
指定容器为 Init 容器,需要在 Pod 的 spec 中添加 `initContainers` 字段, 该字段內以[Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core) 类型对象数组的形式组织,和应用的 `containers` 数组同级相邻。
Init 容器的状态在 `status.initContainerStatuses` 字段中以容器状态数组的格式返回(类似 `status.containerStatuses` 字段)。
为 Pod 设置 Init 容器需要在 Pod 的 `spec` 中添加 `initContainers` 字段,
该字段以 [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
类型对象数组的形式组织,和应用的 `containers` 数组同级相邻。
Init 容器的状态在 `status.initContainerStatuses` 字段中以容器状态数组的格式返回
(类似 `status.containerStatuses` 字段)。
<!--
### Differences from regular containers
@ -69,15 +66,17 @@ Init containers support all the fields and features of app containers, including
Also, init containers do not support `lifecycle`, `livenessProbe`, `readinessProbe`, or `startupProbe` because they must run to completion before the Pod can be ready.
If you specify multiple init containers for a Pod, Kubelet runs each init container sequentially. Each init container must succeed before the next can run. When all of the init containers have run to completion, Kubelet initializes the application containers for the Pod and runs them as usual.
-->
### 与普通容器的不同之处
Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。 然而Init 容器对资源请求和限制的处理稍有不同,在下面 [资源](#资源) 处有说明。
Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。
然而Init 容器对资源请求和限制的处理稍有不同,在下面[资源](#resources)节有说明。
同时 Init 容器不支持 `lifecycle`、`livenessProbe`、`readinessProbe` 和 `startupProbe`,因为它们必须在 Pod 就绪之前运行完成。
如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。
同时 Init 容器不支持 `lifecycle`、`livenessProbe`、`readinessProbe` 和 `startupProbe`
因为它们必须在 Pod 就绪之前运行完成。
如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。
每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时,
Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。
<!--
## Using init containers
@ -88,16 +87,24 @@ Because init containers have separate images from app containers, they have some
* Init containers can run with a different view of the filesystem than app containers in the same Pod. Consequently, they can be given access to {{< glossary_tooltip text="Secrets" term_id="secret" >}} that app containers cannot access.
* Because init containers run to completion before any app containers start, init containers offer a mechanism to block or delay app container startup until a set of preconditions are met. Once preconditions are met, all of the app containers in a Pod can start in parallel.
-->
## Init 容器能做什么?
## 使用 Init 容器
因为 Init 容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:
* Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。例如,没有必要仅为了在安装过程中使用类似 `sed``awk``python``dig` 这样的工具而去`FROM` 一个镜像来生成一个新的镜像。
* Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
* 应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
* Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此Init容器可具有访问 {{< glossary_tooltip text="Secrets" term_id="secret" >}} 的权限,而应用容器不能够访问。
* 由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动直到满足了一组先决条件。一旦前置条件满足Pod内的所有的应用容器会并行启动。
* Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
例如,没有必要仅为了在安装过程中使用类似 `sed`、`awk`、`python` 或 `dig`
这样的工具而去 `FROM` 一个镜像来生成一个新的镜像。
* Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
* 应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
* Init 容器能以不同于 Pod 内应用容器的文件系统视图运行。因此Init 容器可以访问
应用容器不能访问的 {{< glossary_tooltip text="Secret" term_id="secret" >}} 的权限。
* 由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器
提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。
一旦前置条件满足Pod 内的所有的应用容器会并行启动。
<!--
### Examples
@ -118,28 +125,34 @@ Here are some ideas for how to use init containers:
* Clone a Git repository into a {{< glossary_tooltip text="Volume" term_id="volume" >}}
* Place values into a configuration file and run a template tool to dynamically generate a configuration file for the main app container. For example, place the `POD_IP` value in a configuration and generate the main app configuration file using Jinja.
-->
### 示例
### 示例 {#examples}
下面是一些如何使用 Init 容器的想法:
* 等待一个 Service 完成创建,通过类似如下 shell 命令:
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
```shell
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
```
* 注册这个 Pod 到远程服务器,通过在命令中调用 API类似如下
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
```shell
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register \
-d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
```
* 在启动应用容器之前等一段时间,使用类似命令:
sleep 60
```shell
sleep 60
```
* 克隆 Git 仓库到 {{< glossary_tooltip text="Volume" term_id="volume" >}}。
* 将配置值放到配置文件中,运行模板工具为主应用容器动态地生成配置文件。例如,在配置文件中存放 POD_IP 值,并使用 Jinja 生成主应用配置文件。
* 克隆 Git 仓库到{{< glossary_tooltip text="卷" term_id="volume" >}}中。
* 将配置值放到配置文件中,运行模板工具为主应用容器动态地生成配置文件。
例如,在配置文件中存放 `POD_IP` 值,并使用 Jinja 生成主应用配置文件。
<!--
#### Init containers in use
@ -162,9 +175,10 @@ And check on its status with:
```shell
```
-->
### 使用 Init 容器
### 使用 Init 容器的情况
下面的例子定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 `myservice` 启动,第二个等待 `mydb` 启动。 一旦这两个 Init容器 都启动完成Pod 将启动`spec`区域中的应用容器。
下面的例子定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 `myservice` 启动,
第二个等待 `mydb` 启动。 一旦这两个 Init容器 都启动完成Pod 将启动 `spec` 节中的应用容器。
```yaml
apiVersion: v1
@ -211,24 +225,26 @@ spec:
targetPort: 9377
```
要启动这个 Pod可以执行如下命令
```
```shell
kubectl apply -f myapp.yaml
```
输出为:
```
pod/myapp-pod created
```
要检查其状态:
```
```shell
kubectl get -f myapp.yaml
```
输出类似于:
```
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
@ -236,10 +252,12 @@ myapp-pod 0/1 Init:0/2 0 6m
如需更详细的信息:
```
```shell
kubectl describe -f myapp.yaml
```
输出类似于:
```
Name: myapp-pod
Namespace: default
@ -275,11 +293,11 @@ Events:
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
```
如需查看Pod内 Init 容器的日志,请执行:
如需查看 Pod 内 Init 容器的日志,请执行:
```
$ kubectl logs myapp-pod -c init-myservice # Inspect the first init container
$ kubectl logs myapp-pod -c init-mydb # Inspect the second init container
```shell
kubectl logs myapp-pod -c init-myservice # 查看第一个 Init 容器
kubectl logs myapp-pod -c init-mydb # 查看第二个 Init 容器
```
<!--
@ -287,12 +305,11 @@ At this point, those init containers will be waiting to discover Services named
Here's a configuration you can use to make those Services appear:
-->
在这一刻Init 容器将会等待至发现名称为`mydb`和`myservice`的 Service。
在这一刻Init 容器将会等待至发现名称为 `mydb``myservice` 的 Service。
如下为创建这些 Service 的配置文件:
```
```yaml
---
apiVersion: v1
kind: Service
@ -315,75 +332,90 @@ spec:
targetPort: 9377
```
创建`mydb`和`myservice`的 service 命令:
创建 `mydb``myservice` 服务的命令:
```shell
$ kubectl create -f services.yaml
kubectl create -f services.yaml
```
输出类似于:
```
service "myservice" created
service "mydb" created
```
这样你将能看到这些 Init容器 执行完毕,随后`my-app`的Pod转移进入 Running 状态:
这样你将能看到这些 Init 容器执行完毕,随后 `my-app` 的 Pod 进入 `Running` 状态:
```shell
$ kubectl get -f myapp.yaml
```
```shell
```
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
```
一旦我们启动了 `mydb``myservice` 这两个 Service我们能够看到 Init 容器完成,并且 `myapp-pod` 被创建:
一旦我们启动了 `mydb``myservice` 这两个服务,我们能够看到 Init 容器完成,
并且 `myapp-pod` 被创建。
<!--
This simple example should provide some inspiration for you to create your own init containers. [What's next](#what-s-next) contains a link to a more detailed example.
-->
这个简单例子应该能为你创建自己的 Init 容器提供一些启发。 [What's next](#what-s-next) 部分提供了更详细例子的链接。
这个简单例子应该能为你创建自己的 Init 容器提供一些启发。
[接下来](#what-s-next)节提供了更详细例子的链接。
<!--
## Detailed behavior
During the startup of a Pod, each init container starts in order, after the network and volumes are initialized. Each container must exit successfully before the next container starts. If a container fails to start due to the runtime or exits with failure, it is retried according to the Pod `restartPolicy`. However, if the Pod `restartPolicy` is set to Always, the init containers use `restartPolicy` OnFailure.
A Pod cannot be `Ready` until all init containers have succeeded. The ports on an init container are not aggregated under a Service. A Pod that is initializing
is in the `Pending` state but should have a condition `Initializing` set to true.
If the Pod [restarts](#pod-restart-reasons), or is restarted, all init containers must execute again.
-->
## 具体行为 {#detailed-behavior}
在 Pod 启动过程中,每个 Init 容器在网络和数据卷初始化之后会按顺序启动。
每个 Init 容器成功退出后才会启动下一个 Init 容器。
如果它们因为容器运行时的原因无法启动,或以错误状态退出,它会根据 Pod 的 `restartPolicy` 策略进行重试。
然而,如果 Pod 的 `restartPolicy` 设置为 "Always"Init 容器失败时会使用 `restartPolicy`
的 "OnFailure" 策略。
在所有的 Init 容器没有成功之前Pod 将不会变成 `Ready` 状态。
Init 容器的端口将不会在 Service 中进行聚集。正在初始化中的 Pod 处于 `Pending` 状态,
但会将状况 `Initializing` 设置为 true。
如果 Pod [重启](#pod-restart-reasons),所有 Init 容器必须重新执行。
<!--
Changes to the init container spec are limited to the container image field. Altering an init container image field is equivalent to restarting the Pod.
Because init containers can be restarted, retried, or re-executed, init container code should be idempotent. In particular, code that writes to files on `EmptyDirs` should be prepared for the possibility that an output file already exists.
Init containers have all of the fields of an app container. However, Kubernetes prohibits `readinessProbe` from being used because init containers cannot define readiness distinct from completion. This is enforced during validation.
-->
对 Init 容器规约的修改仅限于容器的 `image` 字段。
更改 Init 容器的 `image` 字段,等同于重启该 Pod。
因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的。
特别地,基于 `emptyDirs` 写文件的代码,应该对输出文件可能已经存在做好准备。
Init 容器具有应用容器的所有字段。然而 Kubernetes 禁止使用 `readinessProbe`
因为 Init 容器不能定义不同于完成态Completion的就绪态Readiness
Kubernetes 会在校验时强制执行此检查。
<!--
Use `activeDeadlineSeconds` on the Pod and `livenessProbe` on the container to prevent init containers from failing forever. The active deadline includes init containers.
The name of each app and init container in a Pod must be unique; avalidation error is thrown for any container sharing a name with another.
-->
在 Pod 上使用 `activeDeadlineSeconds` 和在容器上使用 `livenessProbe` 可以避免
Init 容器一直重复失败。`activeDeadlineSeconds` 时间包含了 Init 容器启动的时间。
## 具体行为
在 Pod 启动过程中每个Init 容器在网络和数据卷初始化之后会按顺序启动。每个 Init容器 成功退出后才会启动下一个 Init容器。 如果因为运行或退出时失败引发容器启动失败,它会根据 Pod 的 `restartPolicy` 策略进行重试。
然而,如果 Pod 的 `restartPolicy` 设置为 AlwaysInit 容器失败时会使用 `restartPolicy` 的 OnFailure 策略。
在所有的 Init 容器没有成功之前Pod 将不会变成 `Ready` 状态。 Init 容器的端口将不会在 Service 中进行聚集。 正在初始化中的 Pod 处于 `Pending` 状态,但会将条件 `Initializing` 设置为 true。
如果 Pod [重启](#pod-restart-reasons),所有 Init 容器必须重新执行。
对 Init 容器 spec 的修改仅限于容器的 image 字段。 更改 Init 容器的 image 字段,等同于重启该 Pod。
因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的。 特别地,基于 `EmptyDirs` 写文件的代码,应该对输出文件可能已经存在做好准备。
Init 容器具有应用容器的所有字段。 然而 Kubernetes 禁止使用 `readinessProbe`,因为 Init 容器不能定义不同于完成completion的就绪readiness。 这一点会在校验时强制执行。
在 Pod 上使用 `activeDeadlineSeconds`和在容器上使用 `livenessProbe` 可以避免 Init 容器一直重复失败。 `activeDeadlineSeconds` 时间包含了 Init 容器启动的时间。
在 Pod 中的每个应用容器和 Init 容器的名称必须唯一;与任何其它容器共享同一个名称,会在校验时抛出错误。
在 Pod 中的每个应用容器和 Init 容器的名称必须唯一;
与任何其它容器共享同一个名称,会在校验时抛出错误。
<!--
### Resources
@ -398,50 +430,48 @@ Given the ordering and execution for init containers, the following rules for re
Quota and limits are applied based on the effective Pod request and limit.
Pod level control groups (cgroups) are based on the effective Pod request and limit, the same as the scheduler.
-->
### 资源 {#resources}
### 资源
给定Init 容器的执行顺序下,资源使用适用于如下规则:
在给定的 Init 容器执行顺序下,资源使用适用于如下规则:
* 所有 Init 容器上定义的任何特定资源的 limit 或 request 的最大值,作为 Pod *有效初始 request/limit*
* Pod 对资源的 *有效 limit/request* 是如下两者的较大者:
* 所有应用容器对某个资源的 limit/request 之和
* 对某个资源的有效初始 limit/request
* 基于有效 limit/request 完成调度,这意味着 Init 容器能够为初始化过程预留资源,这些资源在 Pod 生命周期过程中并没有被使用。
* 基于有效 limit/request 完成调度,这意味着 Init 容器能够为初始化过程预留资源,
这些资源在 Pod 生命周期过程中并没有被使用。
* Pod 的 *有效 QoS 层* ,与 Init 容器和应用容器的一样。
配额和限制适用于有效 Pod的 limit/request。
Pod 级别的 cgroups 是基于有效 Pod 的 limit/request和调度器相同。
<!--
### Pod restart reasons
A Pod can restart, causing re-execution of init containers, for the following reasons:
* A user updates the Pod specification, causing the init container image to change. Any changes to the init container image restarts the Pod. App container image changes only restart the app container.
* The Pod infrastructure container is restarted. This is uncommon and would have to be done by someone with root access to nodes.
* All containers in a Pod are terminated while `restartPolicy` is set to Always, forcing a restart, and the init container completion record has been lost due to garbage collection.
-->
### Pod 重启的原因
Pod重启导致 Init 容器重新执行,主要有如下几个原因:
* 用户更新 Pod 的 Spec 导致 Init 容器镜像发生改变。Init 容器镜像的变更会引起 Pod 重启. 应用容器镜像的变更仅会重启应用容器。
* Pod 的基础设施容器 (译者注:如 pause 容器) 被重启。 这种情况不多见,必须由具备 root 权限访问 Node 的人员来完成。
* 当 `restartPolicy` 设置为 AlwaysPod 中所有容器会终止而强制重启,由于垃圾收集导致 Init 容器的完成记录丢失。
### Pod 重启的原因 {#pod-restart-reasons}
Pod 重启会导致 Init 容器重新执行,主要有如下几个原因:
* 用户更新 Pod 的规约导致 Init 容器镜像发生改变。Init 容器镜像的变更会引起 Pod 重启。
应用容器镜像的变更仅会重启应用容器。
* Pod 的基础设施容器 (译者注:如 `pause` 容器) 被重启。这种情况不多见,
必须由具备 root 权限访问节点的人员来完成。
* 当 `restartPolicy` 设置为 "`Always`"Pod 中所有容器会终止而强制重启。
由于垃圾收集机制的原因Init 容器的完成记录将会丢失。
## {{% heading "whatsnext" %}}
<!--
* Read about [creating a Pod that has an init container](/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container)
* Learn how to [debug init containers](/docs/tasks/debug-application-cluster/debug-init-containers/)
-->
* 阅读[创建包含 Init 容器的 Pod](/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container)
* 学习如何[调测 Init 容器](/docs/tasks/debug-application-cluster/debug-init-containers/)
* 阅读[创建包含 Init 容器的 Pod](/zh/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container)
* 学习如何[调试 Init 容器](/zh/docs/tasks/debug-application-cluster/debug-init-containers/)

View File

@ -5,13 +5,9 @@ weight: 50
---
<!--
title: Pod Topology Spread Constraints
content_type: concept
weight: 50
---
-->
<!-- overview -->
@ -24,20 +20,16 @@ You can use _topology spread constraints_ to control how {{< glossary_tooltip te
可以使用*拓扑扩展约束*来控制 {{< glossary_tooltip text="Pods" term_id="Pod" >}} 在集群内故障域(例如地区,区域,节点和其他用户自定义拓扑域)之间的分布。这可以帮助实现高可用以及提升资源利用率。
<!-- body -->
<!--
## Prerequisites
-->
## 先决条件
<!--
### Enable Feature Gate
-->
### 启用功能
<!--
@ -48,24 +40,24 @@ for an explanation of enabling feature gates. The `EvenPodsSpread` feature gate
{{< glossary_tooltip text="scheduler" term_id="kube-scheduler" >}}.
-->
确保 `EvenPodsSpread` 功能已开启(在 1.16 版本中该功能默认关闭)。阅读[功能选项](/docs/reference/command-line-tools-reference/feature-gates/)了解如何开启该功能。`EvenPodsSpread` 必须在 {{< glossary_tooltip text="API Server" term_id="kube-apiserver" >}} **和** {{< glossary_tooltip text="scheduler" term_id="kube-scheduler" >}} 中都要开启。
确保 `EvenPodsSpread` 功能已开启(在 1.16 版本中该功能默认关闭)。
阅读[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)了解如何开启该功能。
`EvenPodsSpread` 必须在 {{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}} **和**
{{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}} 中都开启。
<!--
### Node Labels
-->
### 节点标签
<!--
Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in. For example, a Node might have labels: `node=node1,zone=us-east-1a,region=us-east-1`
-->
拓扑扩展约束依赖于节点标签来标识每个节点所在的拓扑域。例如,一个节点可能具有标签:`node=node1,zone=us-east-1a,region=us-east-1`
<!--
Suppose you have a 4-node cluster with the following labels:
-->
假设你拥有一个具有以下标签的 4 节点集群:
```
@ -79,7 +71,6 @@ node4 Ready <none> 2m43s v1.16.0 node=node4,zone=zoneB
<!--
Then the cluster is logically viewed as below:
-->
然后从逻辑上看集群如下:
```
@ -93,13 +84,11 @@ Then the cluster is logically viewed as below:
<!--
Instead of manually applying labels, you can also reuse the [well-known labels](/docs/reference/kubernetes-api/labels-annotations-taints/) that are created and populated automatically on most clusters.
-->
可以复用在大多数集群上自动创建和填充的[知名标签](/docs/reference/kubernetes-api/labels-annotations-taints/),而不是手动添加标签。
可以复用在大多数集群上自动创建和填充的[常用标签](/zh/docs/reference/kubernetes-api/labels-annotations-taints/),而不是手动添加标签。
<!--
## Spread Constraints for Pods
-->
## Pod 的拓扑约束
### API
@ -107,7 +96,6 @@ Instead of manually applying labels, you can also reuse the [well-known labels](
<!--
The field `pod.spec.topologySpreadConstraints` is introduced in 1.16 as below:
-->
`pod.spec.topologySpreadConstraints` 字段定义如下所示:
```yaml
@ -126,7 +114,6 @@ spec:
<!--
You can define one or multiple `topologySpreadConstraint` to instruct the kube-scheduler how to place each incoming Pod in relation to the existing Pods across your cluster. The fields are:
-->
可以定义一个或多个 `topologySpreadConstraint` 来指示 kube-scheduler 如何将每个传入的 Pod 根据与现有的 Pod 的关联关系在集群中部署。字段包括:
<!--
@ -143,23 +130,20 @@ You can define one or multiple `topologySpreadConstraint` to instruct the kube-s
- **whenUnsatisfiable** 指示如果 pod 不满足扩展约束时如何处理:
- `DoNotSchedule`(默认)告诉调度器不用进行调度。
- `ScheduleAnyway` 告诉调度器在对最小化倾斜的节点进行优先级排序时仍对其进行调度。
- **labelSelector** 用于查找匹配的 pod。匹配此标签的 pod 将被统计,以确定相应拓扑域中 pod 的数量。有关详细信息,请参考[标签选择器](/docs/concepts/overview/working-with-objects/labels/#label-selectors)。
- **labelSelector** 用于查找匹配的 pod。匹配此标签的 pod 将被统计,以确定相应拓扑域中 pod 的数量。
有关详细信息,请参考[标签选择算符](/zh/docs/concepts/overview/working-with-objects/labels/#label-selectors)。
<!--
You can read more about this field by running `kubectl explain Pod.spec.topologySpreadConstraints`.
-->
执行 `kubectl explain Pod.spec.topologySpreadConstraints` 命令了解更多关于 topologySpreadConstraints 的信息。
<!--
### Example: One TopologySpreadConstraint
-->
### 例子:单个拓扑扩展约束
<!--
Suppose you have a 4-node cluster where 3 Pods labeled `foo:bar` are located in node1, node2 and node3 respectively (`P` represents Pod):
-->
### 例子:单个拓扑扩展约束
假设你拥有一个 4 节点集群,其中标记为 `foo:bar` 的 3 个 pod 分别位于 node1node2 和 node3 中(`P` 表示 pod
@ -176,7 +160,6 @@ Suppose you have a 4-node cluster where 3 Pods labeled `foo:bar` are located in
<!--
If we want an incoming Pod to be evenly spread with existing Pods across zones, the spec can be given as:
-->
如果希望传入的 pod 均匀散布在现有的 pod 区域,则可以指定字段如下:
{{< codenew file="pods/topology-spread-constraints/one-constraint.yaml" >}}
@ -184,14 +167,15 @@ If we want an incoming Pod to be evenly spread with existing Pods across zones,
<!--
`topologyKey: zone` implies the even distribution will only be applied to the nodes which have label pair "zone:&lt;any value&gt;" present. `whenUnsatisfiable: DoNotSchedule` tells the scheduler to let it stay pending if the incoming Pod cant satisfy the constraint.
-->
`topologyKey: zone` 意味着均匀分布将只应用于存在标签对为 "zone:&lt;any value&gt;" 的节点上。`whenUnsatisfiable: DoNotSchedule` 告诉调度器,如果传入的 pod 不满足约束,则让它保持挂起状态。
`topologyKey: zone` 意味着均匀分布将只应用于存在标签对为 "zone:&lt;any value&gt;" 的节点上。
`whenUnsatisfiable: DoNotSchedule` 告诉调度器,如果传入的 pod 不满足约束,则让它保持悬决状态。
<!--
If the scheduler placed this incoming Pod into "zoneA", the Pods distribution would become [3, 1], hence the actual skew is 2 (3 - 1) - which violates `maxSkew: 1`. In this example, the incoming Pod can only be placed onto "zoneB":
If the scheduler placed this incoming Pod into "zoneA", the Pods distribution would become [3, 1],
hence the actual skew is 2 (3 - 1) - which violates `maxSkew: 1`. In this example, the incoming Pod can only be placed onto "zoneB":
-->
如果调度器将传入的 pod 放入 "zoneA"pod 分布将变为 [3, 1],因此实际的倾斜为 23 - 1这违反了 `maxSkew: 1`。此示例中,传入的 pod 只能放置在 "zoneB" 上:
如果调度器将传入的 pod 放入 "zoneA"pod 分布将变为 [3, 1],因此实际的倾斜为 23 - 1
这违反了 `maxSkew: 1`。此示例中,传入的 pod 只能放置在 "zoneB" 上:
```
+---------------+---------------+ +---------------+---------------+
@ -206,7 +190,6 @@ If the scheduler placed this incoming Pod into "zoneA", the Pods distribution wo
<!--
You can tweak the Pod spec to meet various kinds of requirements:
-->
可以调整 pod 规格以满足各种要求:
<!--
@ -214,22 +197,25 @@ You can tweak the Pod spec to meet various kinds of requirements:
- Change `topologyKey` to "node" so as to distribute the Pods evenly across nodes instead of zones. In the above example, if `maxSkew` remains "1", the incoming Pod can only be placed onto "node4".
- Change `whenUnsatisfiable: DoNotSchedule` to `whenUnsatisfiable: ScheduleAnyway` to ensure the incoming Pod to be always schedulable (suppose other scheduling APIs are satisfied). However, its preferred to be placed onto the topology domain which has fewer matching Pods. (Be aware that this preferability is jointly normalized with other internal scheduling priorities like resource usage ratio, etc.)
-->
- 将 `maxSkew` 更改为更大的值,比如 "2",这样传入的 pod 也可以放在 "zoneA" 上。
- 将 `topologyKey` 更改为 "node",以便将 pod 均匀分布在节点上而不是区域中。在上面的例子中,如果 `maxSkew` 保持为 "1",那么传入的 pod 只能放在 "node4" 上。
- 将 `whenUnsatisfiable: DoNotSchedule` 更改为 `whenUnsatisfiable: ScheduleAnyway`,以确保传入的 pod 始终可以调度(假设满足其他的调度 API。但是最好将其放置在具有较少匹配 pod 的拓扑域中。(请注意,此优先性与其他内部调度优先级(如资源使用率等)一起进行标准化。)
- 将 `topologyKey` 更改为 "node",以便将 pod 均匀分布在节点上而不是区域中。
在上面的例子中,如果 `maxSkew` 保持为 "1",那么传入的 pod 只能放在 "node4" 上。
- 将 `whenUnsatisfiable: DoNotSchedule` 更改为 `whenUnsatisfiable: ScheduleAnyway`
以确保传入的 Pod 始终可以调度(假设满足其他的调度 API
但是,最好将其放置在具有较少匹配 Pod 的拓扑域中。
(请注意,此优先性与其他内部调度优先级(如资源使用率等)一起进行标准化。)
<!--
### Example: Multiple TopologySpreadConstraints
-->
### 例子:多个拓扑扩展约束
<!--
This builds upon the previous example. Suppose you have a 4-node cluster where 3 Pods labeled `foo:bar` are located in node1, node2 and node3 respectively (`P` represents Pod):
-->
下面的例子建立在前面例子的基础上。假设你拥有一个 4 节点集群,其中 3 个标记为 `foo:bar` 的 pod 分别位于 node1node2 和 node3 上(`P` 表示 pod
下面的例子建立在前面例子的基础上。假设你拥有一个 4 节点集群,其中 3 个标记为 `foo:bar`
Pod 分别位于 node1node2 和 node3 上(`P` 表示 Pod
```
+---------------+---------------+
@ -244,7 +230,6 @@ This builds upon the previous example. Suppose you have a 4-node cluster where 3
<!--
You can use 2 TopologySpreadConstraints to control the Pods spreading on both zone and node:
-->
可以使用 2 个拓扑扩展约束来控制 pod 在 区域和节点两个维度上进行分布:
{{< codenew file="pods/topology-spread-constraints/two-constraints.yaml" >}}
@ -252,13 +237,12 @@ You can use 2 TopologySpreadConstraints to control the Pods spreading on both zo
<!--
In this case, to match the first constraint, the incoming Pod can only be placed onto "zoneB"; while in terms of the second constraint, the incoming Pod can only be placed onto "node4". Then the results of 2 constraints are ANDed, so the only viable option is to place on "node4".
-->
在这种情况下,为了匹配第一个约束,传入的 pod 只能放置在 "zoneB" 中;而在第二个约束中,传入的 pod 只能放置在 "node4" 上。然后两个约束的结果加在一起,因此唯一可行的选择是放置在 "node4" 上。
在这种情况下,为了匹配第一个约束,传入的 pod 只能放置在 "zoneB" 中;而在第二个约束中,
传入的 Pod 只能放置在 "node4" 上。然后两个约束的结果加在一起,因此唯一可行的选择是放置在 "node4" 上。
<!--
Multiple constraints can lead to conflicts. Suppose you have a 3-node cluster across 2 zones:
-->
多个约束可能导致冲突。假设有一个跨越 2 个区域的 3 节点集群:
```
@ -274,58 +258,53 @@ Multiple constraints can lead to conflicts. Suppose you have a 3-node cluster ac
<!--
If you apply "two-constraints.yaml" to this cluster, you will notice "mypod" stays in `Pending` state. This is because: to satisfy the first constraint, "mypod" can only be put to "zoneB"; while in terms of the second constraint, "mypod" can only put to "node2". Then a joint result of "zoneB" and "node2" returns nothing.
-->
如果对集群应用 "two-constraints.yaml",会发现 "mypod" 处于 `Pending` 状态。这是因为:为了满足第一个约束,"mypod" 只能放在 "zoneB" 中,而第二个约束要求 "mypod" 只能放在 "node2" 上。pod 调度无法满足两种约束。
如果对集群应用 "two-constraints.yaml",会发现 "mypod" 处于 `Pending` 状态。
这是因为:为了满足第一个约束,"mypod" 只能放在 "zoneB" 中,而第二个约束要求
"mypod" 只能放在 "node2" 上。pod 调度无法满足两种约束。
<!--
To overcome this situation, you can either increase the `maxSkew` or modify one of the constraints to use `whenUnsatisfiable: ScheduleAnyway`.
-->
为了克服这种情况,可以增加 `maxSkew` 或修改其中一个约束,让其使用 `whenUnsatisfiable: ScheduleAnyway`
为了克服这种情况,可以增加 `maxSkew` 或修改其中一个约束,让其使用
`whenUnsatisfiable: ScheduleAnyway`
<!--
### Conventions
-->
### 约定
<!--
There are some implicit conventions worth noting here:
-->
### 约定
这里有一些值得注意的隐式约定:
<!--
- Only the Pods holding the same namespace as the incoming Pod can be matching candidates.
-->
- 只有与传入 pod 具有相同命名空间的 pod 才能作为匹配候选者。
<!--
- Nodes without `topologySpreadConstraints[*].topologyKey` present will be bypassed. It implies that:
1. the Pods located on those nodes do not impact `maxSkew` calculation - in the above example, suppose "node1" does not have label "zone", then the 2 Pods will be disregarded, hence the incomingPod will be scheduled into "zoneA".
2. the incoming Pod has no chances to be scheduled onto this kind of nodes - in the above example, suppose a "node5" carrying label `{zone-typo: zoneC}` joins the cluster, it will be bypassed due to the absence of label key "zone".
-->
- 只有与传入 pod 具有相同命名空间的 pod 才能作为匹配候选者。
- 没有 `topologySpreadConstraints[*].topologyKey` 的节点将被忽略。这意味着:
1. 位于这些节点上的 pod 不影响 `maxSkew` 的计算。在上面的例子中,假设 "node1" 没有标签 "zone",那么 2 个 pod 将被忽略,因此传入的 pod 将被调度到 "zoneA" 中。
2. 传入的 pod 没有机会被调度到这类节点上。在上面的例子中,假设一个带有标签 `{zone-typo: zoneC}` 的 "node5" 加入到集群,它将由于没有标签键 "zone" 而被忽略。
1. 位于这些节点上的 pod 不影响 `maxSkew` 的计算。
在上面的例子中,假设 "node1" 没有标签 "zone",那么 2 个 Pod 将被忽略,
因此传入的 Pod 将被调度到 "zoneA" 中。
2. 传入的 Pod 没有机会被调度到这类节点上。
在上面的例子中,假设一个带有标签 `{zone-typo: zoneC}` 的 "node5" 加入到集群,
它将由于没有标签键 "zone" 而被忽略。
<!--
- Be aware of what will happen if the incomingPods `topologySpreadConstraints[*].labelSelector` doesnt match its own labels. In the above example, if we remove the incoming Pods labels, it can still be placed onto "zoneB" since the constraints are still satisfied. However, after the placement, the degree of imbalance of the cluster remains unchanged - its still zoneA having 2 Pods which hold label {foo:bar}, and zoneB having 1 Pod which holds label {foo:bar}. So if this is not what you expect, we recommend the workloads `topologySpreadConstraints[*].labelSelector` to match its own labels.
-->
注意,如果传入 pod 的 `topologySpreadConstraints[*].labelSelector` 与自身的标签不匹配,将会发生什么。在上面的例子中,如果移除传入 pod 的标签pod 仍然可以调度到 "zoneB"因为约束仍然满足。然而在调度之后集群的不平衡程度保持不变。zoneA 仍然有 2 个带有 {foo:bar} 标签的 podzoneB 有 1 个带有 {foo:bar} 标签的 pod。因此如果这不是你所期望的建议工作负载的 `topologySpreadConstraints[*].labelSelector` 与其自身的标签匹配。
注意,如果传入 Pod 的 `topologySpreadConstraints[*].labelSelector` 与自身的标签不匹配,将会发生什么。
在上面的例子中,如果移除传入 Pod 的标签Pod 仍然可以调度到 "zoneB",因为约束仍然满足。
然而在调度之后集群的不平衡程度保持不变。zoneA 仍然有 2 个带有 {foo:bar} 标签的 Pod
zoneB 有 1 个带有 {foo:bar} 标签的 Pod。
因此,如果这不是你所期望的,建议工作负载的 `topologySpreadConstraints[*].labelSelector`
与其自身的标签匹配。
<!--
- If the incoming Pod has `spec.nodeSelector` or `spec.affinity.nodeAffinity` defined, nodes not matching them will be bypassed.
-->
<!--
Suppose you have a 5-node cluster ranging from zoneA to zoneC:
-->
<!--
and you know that "zoneC" must be excluded. In this case, you can compose the yaml as below, so that "mypod" will be placed onto "zoneB" instead of "zoneC". Similarly `spec.nodeSelector` is also respected.
-->
@ -349,14 +328,11 @@ There are some implicit conventions worth noting here:
<!--
## Comparison with PodAffinity/PodAntiAffinity
-->
## 与 PodAffinity/PodAntiAffinity 相比较
<!--
In Kubernetes, directives related to "Affinity" control how Pods are
scheduled - more packed or more scattered.
-->
## 与 PodAffinity/PodAntiAffinity 相比较
在 Kubernetes 中,与 "Affinity" 相关的指令控制 pod 的调度方式(更密集或更分散)。
@ -366,7 +342,6 @@ topology domain(s)
- For `PodAntiAffinity`, only one Pod can be scheduled into a
single topology domain.
-->
- 对于 `PodAffinity`,可以尝试将任意数量的 pod 打包到符合条件的拓扑域中。
- 对于 `PodAntiAffinity`,只能将一个 pod 调度到单个拓扑域中。
@ -376,26 +351,24 @@ topology domains - to achieve high availability or cost-saving. This can also he
workloads and scaling out replicas smoothly.
See [Motivation](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20190221-pod-topology-spread.md#motivation) for more details.
-->
"EvenPodsSpread" 功能提供灵活的选项来将 pod 均匀分布到不同的拓扑域中,以实现高可用性或节省成本。这也有助于滚动更新工作负载和平滑扩展副本。有关详细信息,请参考[动机](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20190221-pod-topology-spread.md#motivation)。
"EvenPodsSpread" 功能提供灵活的选项来将 pod 均匀分布到不同的拓扑域中,以实现高可用性或节省成本。
这也有助于滚动更新工作负载和平滑扩展副本。
有关详细信息,请参考[动机](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20190221-pod-topology-spread.md#motivation)。
<!--
## Known Limitations
As of 1.16, at which this feature is Alpha, there are some known limitations:
-->
## 已知局限性
<!--
As of 1.16, at which this feature is Alpha, there are some known limitations:
-->
1.16 版本(此功能为 alpha存在下面的一些限制
<!--
- Scaling down a `Deployment` may result in imbalanced Pods distribution.
- Pods matched on tainted nodes are respected. See [Issue 80921](https://github.com/kubernetes/kubernetes/issues/80921)
-->
- `Deployment` 的缩容可能导致 pod 分布不平衡。
- pod 匹配到污点节点是允许的。参考 [Issue 80921](https://github.com/kubernetes/kubernetes/issues/80921)。

View File

@ -5,13 +5,9 @@ weight: 50
---
<!--
---
reviewers:
- jessfraz
title: Pod Preset
content_type: concept
weight: 50
---
-->
<!--
@ -20,9 +16,10 @@ certain information into pods at creation time. The information can include
secrets, volumes, volume mounts, and environment variables.
-->
<!-- overview -->
本文提供了 PodPreset 的概述。 在 Pod 创建时,用户可以使用 PodPreset 对象将特定信息注入 Pod 中,这些信息可以包括 secret、 卷、卷挂载和环境变量。
{{< feature-state for_k8s_version="v1.6" state="alpha" >}}
本文提供了 PodPreset 的概述。 在 Pod 创建时,用户可以使用 PodPreset 对象将特定信息注入 Pod 中,这些信息可以包括 Secret、卷、卷挂载和环境变量。
<!-- body -->
@ -38,7 +35,8 @@ You use [label selectors](/docs/concepts/overview/working-with-objects/labels/#l
to specify the Pods to which a given Pod Preset applies.
-->
`Pod Preset` 是一种 API 资源,在 Pod 创建时,用户可以用它将额外的运行时需求信息注入 Pod。
使用[标签选择器label selector](/docs/concepts/overview/working-with-objects/labels/#label-selectors)来指定 Pod Preset 所适用的 Pod。
使用[标签选择算符](/zh/docs/concepts/overview/working-with-objects/labels/#label-selectors)
来指定 Pod Preset 所适用的 Pod。
<!--
Using a Pod Preset allows pod template authors to not have to explicitly provide
@ -50,10 +48,39 @@ specific service do not need to know all the details about that service.
这样,使用特定服务的 Pod 模板编写者不需要了解该服务的所有细节。
<!--
For more information about the background, see the [design proposal for PodPreset](https://git.k8s.io/community/contributors/design-proposals/service-catalog/pod-preset.md).
-->
## Enable PodPreset in your cluster {#enable-pod-preset}
了解更多的相关背景信息,请参考 [ PodPreset 设计提案](https://git.k8s.io/community/contributors/design-proposals/service-catalog/pod-preset.md)。
In order to use Pod Presets in your cluster you must ensure the following:
-->
## 在你的集群中启用 Pod Preset {#enable-pod-preset}
为了在集群中使用 Pod Preset必须确保以下几点
<!--
1. You have enabled the API type `settings.k8s.io/v1alpha1/podpreset`. For
example, this can be done by including `settings.k8s.io/v1alpha1=true` in
the `--runtime-config` option for the API server. In minikube add this flag
`--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true` while
starting the cluster.
1. You have enabled the admission controller `PodPreset`. One way to doing this
is to include `PodPreset` in the `--enable-admission-plugins` option value specified
for the API server. In minikube add this flag
```shell
--extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
```
while starting the cluster.
-->
1. 已启用 API 类型 `settings.k8s.io/v1alpha1/podpreset`。 例如,这可以通过在 API 服务器的 `--runtime-config`
配置项中包含 `settings.k8s.io/v1alpha1=true` 来实现。
在 minikube 部署的集群中,启动集群时添加此参数 `--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true`
1. 已启用准入控制器 `PodPreset`。 启用的一种方式是在 API 服务器的 `--enable-admission-plugins`
配置项中包含 `PodPreset` 。在 minikube 部署的集群中,启动集群时添加以下参数:
```shell
--extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
```
<!--
## How It Works
@ -62,7 +89,6 @@ Kubernetes provides an admission controller (`PodPreset`) which, when enabled,
applies Pod Presets to incoming pod creation requests.
When a pod creation request occurs, the system does the following:
-->
## PodPreset 如何工作
Kubernetes 提供了准入控制器 (`PodPreset`),该控制器被启用时,会将 Pod Preset
@ -87,7 +113,7 @@ Kubernetes 提供了准入控制器 (`PodPreset`),该控制器被启用时,
1. 尝试合并 `PodPreset` 中定义的各种资源,并注入要创建的 Pod。
1. 发生错误时抛出事件,该事件记录了 pod 信息合并错误,同时在 _不注入_ `PodPreset` 信息的情况下创建 Pod。
1. 为改动的 Pod spec 添加注解,来表明它被 `PodPreset` 所修改。 注解形如:
`podpreset.admission.kubernetes.io/podpreset-<pod-preset name>": "<resource version>"`。
`podpreset.admission.kubernetes.io/podpreset-<pod-preset 名称>": "<资源版本>"`。
<!--
Each Pod can be matched by zero or more Pod Presets; and each `PodPreset` can be
@ -100,77 +126,37 @@ the Pod; for changes to `Volume`, Kubernetes modifies the Pod Spec.
一个 Pod 可能不与任何 Pod Preset 匹配,也可能匹配多个 Pod Preset。 同时,一个 `PodPreset`
可能不应用于任何 Pod也可能应用于多个 Pod。 当 `PodPreset` 应用于一个或多个 Pod 时Kubernetes
修改 pod spec。 对于 `Env``EnvFrom``VolumeMounts` 的改动, Kubernetes 修改 pod
中所有容器的规格对于卷的改动Kubernetes 修改 Pod spec
中所有容器的规格对于卷的改动Kubernetes 会修改 Pod 规约
<!--
A Pod Preset is capable of modifying the following fields in a Pod spec when appropriate:
- The `.spec.containers` field.
- The `initContainers` field (requires Kubernetes version 1.14.0 or later).
- The `initContainers` field
-->
{{< note >}}
适当时候Pod Preset 可以修改 Pod 规范中的以下字段:
- `.spec.containers` 字段
- `initContainers` 字段 (需要 Kubernetes 1.14.0 或更高版本)。
- `initContainers` 字段
{{< /note >}}
<!--
### Disable Pod Preset for a Specific Pod
-->
### 为特定 Pod 禁用 Pod Preset
<!--
There may be instances where you wish for a Pod to not be altered by any Pod
Preset mutations. In these cases, you can add an annotation in the Pod Spec
of the form: `podpreset.admission.kubernetes.io/exclude: "true"`.
-->
在一些情况下,用户不希望 Pod 被 Pod Preset 所改动,这时,用户可以在 Pod spec 中添加形如 `podpreset.admission.kubernetes.io/exclude: "true"` 的注解。
<!--
## Enable Pod Preset
-->
## 启用 Pod Preset
<!--
In order to use Pod Presets in your cluster you must ensure the following:
-->
为了在集群中使用 Pod Preset必须确保以下几点
<!--
1. You have enabled the API type `settings.k8s.io/v1alpha1/podpreset`. For
example, this can be done by including `settings.k8s.io/v1alpha1=true` in
the `--runtime-config` option for the API server. In minikube add this flag
`--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true` while
starting the cluster.
1. You have enabled the admission controller `PodPreset`. One way to doing this
is to include `PodPreset` in the `--enable-admission-plugins` option value specified
for the API server. In minikube add this flag
```shell
--extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
```
while starting the cluster.
1. You have defined your Pod Presets by creating `PodPreset` objects in the
namespace you will use.
-->
1. 已启用 API 类型 `settings.k8s.io/v1alpha1/podpreset`。 例如,这可以通过在 API 服务器的 `--runtime-config` 配置项中包含 `settings.k8s.io/v1alpha1=true` 来实现。在 minikube 部署的集群中,启动集群时添加此参数 `--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=true`
1. 已启用准入控制器 `PodPreset`。 启用的一种方式是在 API 服务器的 `--enable-admission-plugins` 配置项中包含 `PodPreset` 。在 minikube 部署的集群中,启动集群时添加以下参数:
```shell
--extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset
```
1. 已经通过在相应的命名空间中创建 `PodPreset` 对象,定义了 Pod Preset。
### 为特定 Pod 禁用 Pod Preset
在一些情况下,用户不希望 Pod 被 Pod Preset 所改动,这时,用户可以在 Pod
`.spec` 中添加形如 `podpreset.admission.kubernetes.io/exclude: "true"` 的注解。
## {{% heading "whatsnext" %}}
<!--
* [Injecting data into a Pod using PodPreset](/docs/tasks/inject-data-application/podpreset/)
* For more information about the background, see the [design proposal for PodPreset](https://git.k8s.io/community/contributors/design-proposals/service-catalog/pod-preset.md).
-->
* [使用 PodPreset 将信息注入 Pod](/docs/tasks/inject-data-application/podpreset/)
* 参考[使用 PodPreset 将信息注入 Pod](/zh/docs/tasks/inject-data-application/podpreset/)。
* 若要更多地了解背景知识,请参阅 [PodPreset 的设计提案](https://git.k8s.io/community/contributors/design-proposals/service-catalog/pod-preset.md)。