From c29ceebd83f3c71adb897f9233f85c36ff40028a Mon Sep 17 00:00:00 2001 From: Qiming Teng Date: Sun, 2 Aug 2020 11:10:28 +0800 Subject: [PATCH] [zh] Fix links in Concepts section (4) --- .../workloads/controllers/cron-jobs.md | 117 ++++++--- .../workloads/controllers/daemonset.md | 235 +++++++++++------- .../controllers/garbage-collection.md | 155 +++++------- .../concepts/workloads/controllers/job.md | 2 +- .../workloads/controllers/replicaset.md | 65 +++-- .../workloads/controllers/statefulset.md | 163 ++++++------ .../workloads/controllers/ttlafterfinished.md | 91 +++---- 7 files changed, 461 insertions(+), 367 deletions(-) diff --git a/content/zh/docs/concepts/workloads/controllers/cron-jobs.md b/content/zh/docs/concepts/workloads/controllers/cron-jobs.md index c4da73af47..f6a5eefa9c 100644 --- a/content/zh/docs/concepts/workloads/controllers/cron-jobs.md +++ b/content/zh/docs/concepts/workloads/controllers/cron-jobs.md @@ -5,15 +5,9 @@ weight: 80 --- @@ -26,10 +20,11 @@ A _Cron Job_ creates [Jobs](/docs/concepts/workloads/controllers/jobs-run-to-com One CronJob object is like one line of a _crontab_ (cron table) file. It runs a job periodically on a given schedule, written in [Cron](https://en.wikipedia.org/wiki/Cron) format. --> +_Cron Job_ 创建基于时间调度的 [Jobs](/zh/docs/concepts/workloads/controllers/jobs-run-to-completion/)。 -_Cron Job_ 创建基于时间调度的 [Jobs](/docs/concepts/workloads/controllers/jobs-run-to-completion/)。 - -一个 CronJob 对象就像 _crontab_ (cron table) 文件中的一行。它用 [Cron](https://en.wikipedia.org/wiki/Cron) 格式进行编写,并周期性地在给定的调度时间执行 Job。 +一个 CronJob 对象就像 _crontab_ (cron table) 文件中的一行。 +它用 [Cron](https://en.wikipedia.org/wiki/Cron) 格式进行编写, +并周期性地在给定的调度时间执行 Job。 {{< caution >}} -所有 **CronJob** 的 `schedule:` 时间都是基于初始 Job 的主控节点的时区。 +所有 **CronJob** 的 `schedule:` 时间都是基于 +{{< glossary_tooltip term_id="kube-controller-manager" text="kube-controller-manager" >}}. +的时区。 -如果你的控制平面在 Pod 或是裸容器中运行了主控程序 (kube-controller-manager), -那么为该容器设置的时区将会决定定时任务的控制器所使用的时区。 +如果你的控制平面在 Pod 或是裸容器中运行了 kube-controller-manager, +那么为该容器所设置的时区将会决定 Cron Job 的控制器所使用的时区。 {{< /caution >}} -为 CronJob 资源创建清单时,请确保创建的名称不超过 52 个字符。这是因为 CronJob 控制器将自动在提供的作业名称后附加 11 个字符,并且存在一个限制,即作业名称的最大长度不能超过 63 个字符。 - - - - -有关创建和使用 CronJob 的说明及规范文件的示例,请参见[使用 CronJob 运行自动化任务](/zh/docs/tasks/job/automated-tasks-with-cron-jobs/)。 - - - - +为 CronJob 资源创建清单时,请确保所提供的名称是一个合法的 +[DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). +名称不能超过 52 个字符。 +这是因为 CronJob 控制器将自动在提供的 Job 名称后附加 11 个字符,并且存在一个限制, +即 Job 名称的最大长度不能超过 63 个字符。 +## CronJob + +CronJobs 对于创建周期性的、反复重复的任务很有用,例如执行数据备份或者发送邮件。 +CronJobs 也可以用来计划在指定时间来执行的独立任务,例如计划当集群看起来很空闲时 +执行某个 Job。 + + +### 示例 + +下面的 CronJob 示例清单会在每分钟打印出当前时间和问候消息: + +{{< codenew file="application/job/cronjob.yaml" >}} + +[使用 CronJob 运行自动化任务](/zh/docs/tasks/job/automated-tasks-with-cron-jobs/) +一文会为你详细讲解此例。 + + +## CronJob 限制 {#cron-job-limitations} -## CronJob 限制 - -CronJob 创建 Job 对象,每个 Job 的执行次数大约为一次。 +CronJob 根据其计划编排,在每次该执行任务的时候大约会创建一个 Job。 我们之所以说 "大约",是因为在某些情况下,可能会创建两个 Job,或者不会创建任何 Job。 我们试图使这些情况尽量少发生,但不能完全杜绝。因此,Job 应该是 _幂等的_。 @@ -86,14 +103,15 @@ If `startingDeadlineSeconds` is set to a large value or left unset (the default) and if `concurrencyPolicy` is set to `Allow`, the jobs will always run at least once. --> - -如果 `startingDeadlineSeconds` 设置为很大的数值或未设置(默认),并且 `concurrencyPolicy` 设置为 `Allow`,则作业将始终至少运行一次。 +如果 `startingDeadlineSeconds` 设置为很大的数值或未设置(默认),并且 +`concurrencyPolicy` 设置为 `Allow`,则作业将始终至少运行一次。 - -对于每个 CronJob,CronJob {{< glossary_tooltip term_text="控制器" term_id="controller" >}} 检查从上一次调度的时间点到现在所错过了调度次数。如果错过的调度次数超过 100 次,那么它就不会启动这个任务,并记录这个错误: +对于每个 CronJob,CronJob {{< glossary_tooltip term_text="控制器" term_id="controller" >}} +检查从上一次调度的时间点到现在所错过了调度次数。如果错过的调度次数超过 100 次, +那么它就不会启动这个任务,并记录这个错误: ```` Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew. @@ -102,22 +120,24 @@ Cannot determine if job needs to be started. Too many missed start time (> 100). - -需要注意的是,如果 `startingDeadlineSeconds` 字段非空,则控制器会统计从 `startingDeadlineSeconds` 设置的值到现在而不是从上一个计划时间到现在错过了多少次 Job。例如,如果 `startingDeadlineSeconds` 是 `200`,则控制器会统计在过去 200 秒中错过了多少次 Job。 +需要注意的是,如果 `startingDeadlineSeconds` 字段非空,则控制器会统计从 +`startingDeadlineSeconds` 设置的值到现在而不是从上一个计划时间到现在错过了多少次 Job。 +例如,如果 `startingDeadlineSeconds` 是 `200`,则控制器会统计在过去 200 秒中错过了多少次 Job。 - -如果未能在调度时间内创建 CronJob,则计为错过。例如,如果 `concurrencyPolicy` 被设置为 `Forbid`,并且当前有一个调度仍在运行的情况下,试图调度的 CronJob 将被计算为错过。 +如果未能在调度时间内创建 CronJob,则计为错过。 +例如,如果 `concurrencyPolicy` 被设置为 `Forbid`,并且当前有一个调度仍在运行的情况下, +试图调度的 CronJob 将被计算为错过。 - -例如,假设一个 CronJob 被设置为 `08:30:00` 准时开始,它的 `startingDeadlineSeconds` 字段被设置为 10,如果在 `08:29:00` 时将 CronJob 控制器的时间改为 `08:42:00`,Job 将不会启动。 +例如,假设一个 CronJob 被设置为 `08:30:00` 准时开始,它的 `startingDeadlineSeconds` +字段被设置为 10,如果在 `08:29:00` 时将 CronJob 控制器的时间改为 `08:42:00`,Job 将不会启动。 如果觉得晚些开始比没有启动好,那请设置一个较长的 `startingDeadlineSeconds`。 -为了进一步阐述这个概念,假设将 CronJob 设置为从 `08:30:00` 开始每隔一分钟创建一个新的 Job,并将其 `startingDeadlineSeconds` 字段设置为 200 秒。 如果 CronJob 控制器恰好在与上一个示例相同的时间段(`08:29:00` 到 `10:21:00`)停机,则 Job 仍将从 `10:22:00` 开始。造成这种情况的原因是控制器现在检查在最近 200 秒(即 3 个错过的调度)中发生了多少次错过的 Job 调度,而不是从现在为止的最后一个调度时间开始。 +为了进一步阐述这个概念,假设将 CronJob 设置为从 `08:30:00` 开始每隔一分钟创建一个新的 Job, +并将其 `startingDeadlineSeconds` 字段设置为 200 秒。 +如果 CronJob 控制器恰好在与上一个示例相同的时间段(`08:29:00` 到 `10:21:00`)终止运行, +则 Job 仍将从 `10:22:00` 开始。 +造成这种情况的原因是控制器现在检查在最近 200 秒(即 3 个错过的调度)中发生了多少次错过的 +Job 调度,而不是从现在为止的最后一个调度时间开始。 CronJob 仅负责创建与其调度时间相匹配的 Job,而 Job 又负责管理其代表的 Pod。 +## {{% heading "whatsnext" %}} + + +* 进一步了解 [Cron 表达式的格式](https://en.wikipedia.org/wiki/Cron),学习设置 CronJob `schedule` 字段 +* 有关创建和使用 CronJob 的说明及示例规约文件,请参见 + [使用 CronJob 运行自动化任务](/zh/docs/tasks/job/automated-tasks-with-cron-jobs/)。 - diff --git a/content/zh/docs/concepts/workloads/controllers/daemonset.md b/content/zh/docs/concepts/workloads/controllers/daemonset.md index edcbc29399..c9b58f7bd5 100644 --- a/content/zh/docs/concepts/workloads/controllers/daemonset.md +++ b/content/zh/docs/concepts/workloads/controllers/daemonset.md @@ -5,17 +5,9 @@ weight: 50 --- @@ -25,35 +17,32 @@ A _DaemonSet_ ensures that all (or some) Nodes run a copy of a Pod. As nodes ar cluster, Pods are added to them. As nodes are removed from the cluster, those Pods are garbage collected. Deleting a DaemonSet will clean up the Pods it created. ---> -_DaemonSet_ 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, -也会为他们新增一个 Pod 。当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 +_DaemonSet_ 确保全部(或者某些)节点上运行一个 Pod 的副本。 +当有节点加入集群时, 也会为他们新增一个 Pod 。 +当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。 DaemonSet 的一些典型用法: -- 在每个节点上运行集群存储 DaemonSet,例如 `glusterd`、`ceph`。 -- 在每个节点上运行日志收集 DaemonSet,例如 `fluentd`、`logstash`。 -- 在每个节点上运行监控 DaemonSet,例如 [Prometheus Node Exporter](https://github.com/prometheus/node_exporter)、[Flowmill](https://github.com/Flowmill/flowmill-k8s/)、[Sysdig 代理](https://docs.sysdig.com)、`collectd`、[Dynatrace OneAgent](https://www.dynatrace.com/technologies/kubernetes-monitoring/)、[AppDynamics 代理](https://docs.appdynamics.com/display/CLOUD/Container+Visibility+with+Kubernetes)、[Datadog 代理](https://docs.datadoghq.com/agent/kubernetes/daemonset_setup/)、[New Relic 代理](https://docs.newrelic.com/docs/integrations/kubernetes-integration/installation/kubernetes-installation-configuration)、Ganglia `gmond` 或者 [Instana 代理](https://www.instana.com/supported-integrations/kubernetes-monitoring/)。 +- 在每个节点上运行集群存守护进程 +- 在每个节点上运行日志收集守护进程 +- 在每个节点上运行监控守护进程 -一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种类型的 daemon 使用。 - -一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志, +一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 +一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。 - - - -您可以在 YAML 文件中描述 DaemonSet。例如,下面的 daemonset.yaml 文件描述了一个运行 fluentd-elasticsearch Docker 镜像的 DaemonSet: +你可以在 YAML 文件中描述 DaemonSet。 +例如,下面的 daemonset.yaml 文件描述了一个运行 fluentd-elasticsearch Docker 镜像的 DaemonSet: {{< codenew file="controllers/daemonset.yaml" >}} -* 基于 YAML 文件创建 DaemonSet: +基于 YAML 文件创建 DaemonSet: + ``` kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml ``` @@ -84,22 +75,32 @@ kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml ### Required Fields As with all other Kubernetes config, a DaemonSet needs `apiVersion`, `kind`, and `metadata` fields. For -general information about working with config files, see [deploying applications](/docs/user-guide/deploying-applications/), +general information about working with config files, see + [running stateless applications](/docs/tasks/run-application/run-stateless-application-deployment/), [configuring containers](/docs/tasks/), and [object management using kubectl](/docs/concepts/overview/working-with-objects/object-management/) documents. +The name of a DaemonSet object must be a valid +[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). + A DaemonSet also needs a [`.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status) section. --> ### 必需字段 -和其它所有 Kubernetes 配置一样,DaemonSet 需要 `apiVersion`、`kind` 和 `metadata` 字段。有关配置文件的基本信息,详见文档 [部署应用](/docs/user-guide/deploying-applications/)、[配置容器](/docs/tasks/) 和 [使用 kubectl 进行对象管理](/docs/concepts/overview/object-management-kubectl/overview/)。 + +和所有其他 Kubernetes 配置一样,DaemonSet 需要 `apiVersion`、`kind` 和 `metadata` 字段。 +有关配置文件的基本信息,参见 +[部署应用](/zh/docs/tasks/run-application/run-stateless-application-deployment/)、 +[配置容器](/zh/docs/tasks/)和 +[使用 kubectl 进行对象管理](/zh/docs/concepts/overview/working-with-objects/object-management/) +文档。 + +DaemonSet 对象的名称必须是一个合法的 +[DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。 DaemonSet 也需要一个 [`.spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status) 配置段。 -### Pod 模板 - +### Pod 模板 {#pod-template} + `.spec` 中唯一必需的字段是 `.spec.template`。 -`.spec.template` 是一个 [Pod 模板](/docs/concepts/workloads/pods/pod-overview/#pod-templates)。除了它是嵌套的,而且不具有 `apiVersion` 或 `kind` 字段,它与 [Pod](/docs/concepts/workloads/pods/pod/) 具有相同的 schema。 +`.spec.template` 是一个 [Pod 模板](/zh/docs/concepts/workloads/pods/#pod-templates)。 +除了它是嵌套的,因而不具有 `apiVersion` 或 `kind` 字段之外,它与 +{{< glossary_tooltip text="Pod" term_id="pod" >}} 具有相同的 schema。 -除了 Pod 必需字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签(查看 [Pod Selector](#pod-selector))。 +除了 Pod 必需字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签(查看 [Pod 选择算符](#pod-selector))。 -在 DaemonSet 中的 Pod 模板必须具有一个值为 `Always` 的 [`RestartPolicy`](/docs/user-guide/pod-states),或者未指定它的值,默认是 `Always`。 +在 DaemonSet 中的 Pod 模板必须具有一个值为 `Always` 的 +[`RestartPolicy`](/zh/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy)。 +当该值未指定时,默认是 `Always`。 -### Pod Selector {#pod-selector} - -`.spec.selector` 字段表示 Pod Selector,它与 [Job](/docs/concepts/jobs/run-to-completion-finite-workloads/) 的 `.spec.selector` 的作用是相同的。 +### Pod 选择算符 {#pod-selector} -从 Kubernetes 1.8 开始,您必须指定与 `.spec.template` 的标签匹配的 pod selector。当不配置时,pod selector 将不再有默认值。selector 默认与 `kubectl apply` 不兼容。 此外,一旦创建了 DaemonSet,它的 `.spec.selector` 就不能修改。修改 pod selector 可能导致 Pod 意外悬浮,并且这对用户来说是困惑的。 +`.spec.selector` 字段表示 Pod 选择算符,它与 +[Job](/zh/docs/concepts/workloads/controllers/job/) 的 `.spec.selector` 的作用是相同的。 + +从 Kubernetes 1.8 开始,您必须指定与 `.spec.template` 的标签匹配的 Pod 选择算符。 +用户不指定 Pod 选择算符时,该字段不再有默认值。 +选择算符的默认值生成结果与 `kubectl apply` 不兼容。 +此外,一旦创建了 DaemonSet,它的 `.spec.selector` 就不能修改。 +修改 Pod 选择算符可能导致 Pod 意外悬浮,并且这对用户来说是费解的。 -`spec.selector` 表示一个对象,它由如下两个字段组成: +`spec.selector` 是一个对象,如下两个字段组成: -* `matchLabels` - 与 [ReplicationController](/docs/concepts/workloads/controllers/replicationcontroller/) 的 `.spec.selector` 的作用相同。 -* `matchExpressions` - 允许构建更加复杂的 Selector,可以通过指定 key、value 列表 -,以及与 key 和 value 列表相关的操作符。 +* `matchLabels` - 与 [ReplicationController](/zh/docs/concepts/workloads/controllers/replicationcontroller/) + 的 `.spec.selector` 的作用相同。 +* `matchExpressions` - 允许构建更加复杂的选择器,可以通过指定 key、value + 列表以及将 key 和 value 列表关联起来的 operator。 -当上述两个字段都指定时,结果表示的是 AND 关系。 +当上述两个字段都指定时,结果会按逻辑与(AND)操作处理。 -如果指定了 `.spec.selector`,必须与 `.spec.template.metadata.labels` 相匹配。如果与它们配置的不匹配,则会被 API 拒绝。 +如果指定了 `.spec.selector`,必须与 `.spec.template.metadata.labels` 相匹配。 +如果与后者不匹配,则 DeamonSet 会被 API 拒绝。 -另外,通常不应直接通过另一个 DaemonSet 或另一个工作负载资源(例如 ReplicaSet)来创建其标签与该选择器匹配的任何 Pod。否则,DaemonSet {{< glossary_tooltip term_text="控制器" term_id="controller" >}}会认为这些 Pod 是由它创建的。Kubernetes 不会阻止你这样做。您可能要执行此操作的一种情况是,手动在节点上创建具有不同值的 Pod 进行测试。 +另外,通常不应直接通过另一个 DaemonSet 或另一个工作负载资源(例如 ReplicaSet) +来创建其标签与该选择器匹配的任何 Pod。否则,DaemonSet +{{< glossary_tooltip term_text="控制器" term_id="controller" >}} +会认为这些 Pod 是由它创建的。 +Kubernetes 不会阻止你这样做。 +你可能要执行此操作的一种情况是,手动在节点上创建具有不同值的 Pod 进行测试。 -### 仅在某些节点上运行 Pod - +### 仅在某些节点上运行 Pod + 如果指定了 `.spec.template.spec.nodeSelector`,DaemonSet Controller 将在能够与 [Node Selector](/docs/concepts/configuration/assign-pod-node/) 匹配的节点上创建 Pod。类似这种情况,可以指定 `.spec.template.spec.affinity`,然后 DaemonSet Controller 将在能够与 [node Affinity](/docs/concepts/configuration/assign-pod-node/) 匹配的节点上创建 Pod。 如果根本就没有指定,则 DaemonSet Controller 将在所有节点上创建 Pod。 @@ -192,7 +209,7 @@ If you do not specify either, then the DaemonSet controller will create Pods on --> ## 如何调度 Daemon Pods -### 通过默认 scheduler 调度 +### 通过默认调度器调度 {{< feature-state state="stable" for-kubernetes-version="1.17" >}} @@ -209,10 +226,15 @@ That introduces the following issues: is handled by default scheduler. When preemption is enabled, the DaemonSet controller will make scheduling decisions without considering pod priority and preemption. --> -DaemonSet 确保所有符合条件的节点都运行该 Pod 的一个副本。通常,运行 Pod 的节点由 Kubernetes 调度器抉择。不过,DaemonSet pods 由 DaemonSet 控制器创建和调度。这将引入以下问题: +DaemonSet 确保所有符合条件的节点都运行该 Pod 的一个副本。 +通常,运行 Pod 的节点由 Kubernetes 调度器选择。 +不过,DaemonSet pods 由 DaemonSet 控制器创建和调度。这就带来了以下问题: - * Pod 行为的不一致性:等待调度的正常 Pod 已被创建并处于 `Pending` 状态,但 DaemonSet pods 未在 `Pending` 状态下创建。 这使用户感到困惑。 - * [Pod preemption](/docs/concepts/configuration/pod-priority-preemption/)由默认 scheduler 处理。 启用抢占后,DaemonSet 控制器将在不考虑 pod 优先级和抢占的情况下制定调度决策。 +* Pod 行为的不一致性:正常 Pod 在被创建后等待调度时处于 `Pending` 状态, + DaemonSet Pods 创建后不会处于 `Pending` 状态下。这使用户感到困惑。 +* [Pod 抢占](/zh/docs/concepts/configuration/pod-priority-preemption/) + 由默认调度器处理。启用抢占后,DaemonSet 控制器将在不考虑 Pod 优先级和抢占 + 的情况下制定调度决策。 -`ScheduleDaemonSetPods` 允许您使用默认调度器而不是 DaemonSet 控制器来调度 DaemonSets,方法是将 `NodeAffinity` 添加到 DaemonSet pods,而不是 `.spec.nodeName`。 然后使用默认调度器将 pod 绑定到目标主机。 如果 DaemonSet pod 的亲和节点已存在,则替换它。 DaemonSet 控制器仅在创建或修改 DaemonSet pods 时执行这些操作,并且不对 DaemonSet 的 `spec.template` 进行任何更改。 +`ScheduleDaemonSetPods` 允许您使用默认调度器而不是 DaemonSet 控制器来调度 DaemonSets, +方法是将 `NodeAffinity` 条件而不是 `.spec.nodeName` 条件添加到 DaemonSet Pods。 +默认调度器接下来将 Pod 绑定到目标主机。 +如果 DaemonSet Pod 的节点亲和性配置已存在,则被替换。 +DaemonSet 控制器仅在创建或修改 DaemonSet Pod 时执行这些操作, +并且不回更改 DaemonSet 的 `spec.template`。 ```yaml nodeAffinity: @@ -241,7 +268,8 @@ In addition, `node.kubernetes.io/unschedulable:NoSchedule` toleration is added automatically to DaemonSet Pods. The default scheduler ignores `unschedulable` Nodes when scheduling DaemonSet Pods. --> -此外,系统会自动添加 `node.kubernetes.io/unschedulable:NoSchedule` 容忍度到 DaemonSet Pods。 在调度 DaemonSet Pod 时,默认调度器会忽略 `unschedulable` 节点。 +此外,系统会自动添加 `node.kubernetes.io/unschedulable:NoSchedule` 容忍度到 +DaemonSet Pods。在调度 DaemonSet Pod 时,默认调度器会忽略 `unschedulable` 节点。 -### 污点和容忍度 +### 污点和容忍度 {#taint-and-toleration} -尽管 Daemon Pods 遵循[污点和容忍度](/docs/concepts/configuration/taint-and-toleration) 规则,根据相关特性,会自动将以下容忍度添加到 DaemonSet Pods 中。 +尽管 Daemon Pods 遵循[污点和容忍度](/zh/docs/concepts/scheduling-eviction/taint-and-toleration) +规则,根据相关特性,控制器会自动将以下容忍度添加到 DaemonSet Pod: -| 容忍度关键词 | 影响 | 版本 | 描述 | +| 容忍度键名 | 效果 | 版本 | 描述 | | ---------------------------------------- | ---------- | ------- | ------------------------------------------------------------ | -| `node.kubernetes.io/not-ready` | NoExecute | 1.13+ | DaemonSet pods will not be evicted when there are node problems such as a network partition. | -| `node.kubernetes.io/unreachable` | NoExecute | 1.13+ | DaemonSet pods will not be evicted when there are node problems such as a network partition. | -| `node.kubernetes.io/disk-pressure` | NoSchedule | 1.8+ | | -| `node.kubernetes.io/memory-pressure` | NoSchedule | 1.8+ | | -| `node.kubernetes.io/unschedulable` | NoSchedule | 1.12+ | DaemonSet pods tolerate unschedulable attributes by default scheduler. | -| `node.kubernetes.io/network-unavailable` | NoSchedule | 1.12+ | DaemonSet pods, who uses host network, tolerate network-unavailable attributes by default scheduler. | - - +| `node.kubernetes.io/not-ready` | NoExecute | 1.13+ | 当出现类似网络断开的情况导致节点问题时,DaemonSet Pod 不会被逐出。 | +| `node.kubernetes.io/unreachable` | NoExecute | 1.13+ | 当出现类似于网络断开的情况导致节点问题时,DaemonSet Pod 不会被逐出。 | +| `node.kubernetes.io/disk-pressure` | NoSchedule | 1.8+ | | +| `node.kubernetes.io/memory-pressure` | NoSchedule | 1.8+ | | +| `node.kubernetes.io/unschedulable` | NoSchedule | 1.12+ | DaemonSet Pod 能够容忍默认调度器所设置的 `unschedulable` 属性. | +| `node.kubernetes.io/network-unavailable` | NoSchedule | 1.12+ | DaemonSet 在使用宿主网络时,能够容忍默认调度器所设置的 `network-unavailable` 属性。 | -## 与 Daemon Pods 通信 +## 与 Daemon Pods 通信 + 与 DaemonSet 中的 Pod 进行通信的几种可能模式如下: -- **Push**:将 DaemonSet 中的 Pod 配置为将更新发送到另一个 Service,例如统计数据库。 -- **NodeIP 和已知端口**:DaemonSet 中的 Pod 可以使用 `hostPort`,从而可以通过节点 IP 访问到 Pod。客户端能通过某种方法获取节点 IP 列表,并且基于此也可以获取到相应的端口。 -- **DNS**:创建具有相同 Pod Selector 的 [Headless Service](/docs/concepts/services-networking/service/#headless-services),然后通过使用 `endpoints` 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。 -- **Service**:创建具有相同 Pod Selector 的 Service,并使用该 Service 随机访问到某个节点上的 daemon(没有办法访问到特定节点)。 +- **Push**:配置 DaemonSet 中的 Pod,将更新发送到另一个服务,例如统计数据库。 + 这些服务没有客户端。 + +- **NodeIP 和已知端口**:DaemonSet 中的 Pod 可以使用 `hostPort`,从而可以通过节点 IP + 访问到 Pod。客户端能通过某种方法获取节点 IP 列表,并且基于此也可以获取到相应的端口。 + +- **DNS**:创建具有相同 Pod 选择算符的 + [无头服务](/zh/docs/concepts/services-networking/service/#headless-services), + 通过使用 `endpoints` 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。 + +- **Service**:创建具有相同 Pod 选择算符的服务,并使用该服务随机访问到某个节点上的 + 守护进程(没有办法访问到特定节点)。 -## 更新 DaemonSet - -如果修改了节点标签,DaemonSet 将立刻向新匹配上的节点添加 Pod,同时删除不能够匹配的节点上的 Pod。 +## 更新 DaemonSet -您可以修改 DaemonSet 创建的 Pod。然而,不允许对 Pod 的所有字段进行更新。当下次 -节点(即使具有相同的名称)被创建时,DaemonSet Controller 还会使用最初的模板。 +如果节点的标签被修改,DaemonSet 将立刻向新匹配上的节点添加 Pod, +同时删除不匹配的节点上的 Pod。 + +你可以修改 DaemonSet 创建的 Pod。不过并非 Pod 的所有字段都可更新。 +下次当某节点(即使具有相同的名称)被创建时,DaemonSet 控制器还会使用最初的模板。 -您可以删除一个 DaemonSet。如果使用 `kubectl` 并指定 `--cascade=false` 选项,则 Pod 将被保留在节点上。然后可以创建具有不同模板的新 DaemonSet。具有不同模板的新 DaemonSet 将能够通过标签匹配并识别所有已经存在的 Pod。 -如果有任何 Pod 需要替换,则 DaemonSet 根据它的 `updateStrategy` 来替换。 +您可以删除一个 DaemonSet。如果使用 `kubectl` 并指定 `--cascade=false` 选项, +则 Pod 将被保留在节点上。接下来如果创建使用相同选择算符的新 DaemonSet, +新的 DaemonSet 会收养已有的 Pod。 +如果有 Pod 需要被替换,DaemonSet 会根据其 `updateStrategy` 来替换。 + +你可以对 DaemonSet [执行滚动更新](/zh/docs/tasks/manage-daemon/update-daemon-set/)操作。 -## DaemonSet 的可替代选择 +## DaemonSet 的替代方案 ### init 脚本 @@ -339,13 +379,16 @@ running such processes via a DaemonSet: containers. However, this can also be accomplished by running the daemons in a container but not in a Pod (e.g. start directly via Docker). --> -我们很可能希望直接在一个节点上启动 daemon 进程(例如,使用 `init`、`upstartd`、或 `systemd`)。这非常好,但基于 DaemonSet 来运行这些进程有如下一些好处: +直接在节点上启动守护进程(例如使用 `init`、`upstartd` 或 `systemd`)的做法当然是可行的。 +不过,基于 DaemonSet 来运行这些进程有如下一些好处: -- 像对待应用程序一样,具备为 daemon 提供监控和管理日志的能力。 +- 像所运行的其他应用一样,DaemonSet 具备为守护进程提供监控和日志管理的能力。 -- 为 daemon 和应用程序使用相同的配置语言和工具(如 Pod 模板、`kubectl`)。 +- 为守护进程和应用所使用的配置语言和工具(如 Pod 模板、`kubectl`)是相同的。 -- 在资源受限的容器中运行 daemon,能够增加 daemon 和应用容器的隔离性。然而,这也实现了在容器中运行 daemon,但却不能在 Pod 中运行(例如,直接基于 Docker 启动)。 +- 在资源受限的容器中运行守护进程能够增加守护进程和应用容器的隔离性。 + 然而,这一点也可以通过在容器中运行守护进程但却不在 Pod 中运行之来实现。 + 例如,直接基于 Docker 启动。 ### 裸 Pod -可能要直接创建 Pod,同时指定其运行在特定的节点上。然而,DaemonSet 替换了由于任何原因被删除或终止的 Pod,例如节点失败、例行节点维护、内核升级。由于这个原因,我们应该使用 DaemonSet 而不是单独创建 Pod。 +直接创建 Pod并指定其运行在特定的节点上也是可以的。 +然而,DaemonSet 能够替换由于任何原因(例如节点失败、例行节点维护、内核升级) +而被删除或终止的 Pod。 +由于这个原因,你应该使用 DaemonSet 而不是单独创建 Pod。 ### 静态 Pod -可能需要通过在一个指定目录下编写文件来创建 Pod,该目录受 Kubelet 所监视。这些 Pod 被称为 [静态 Pod](/docs/concepts/cluster-administration/static-pod/)。 -不像 DaemonSet,静态 Pod 不受 kubectl 和其它 Kubernetes API 客户端管理。静态 Pod 不依赖于 apiserver,这使得它们在集群启动的情况下非常有用。而且,未来静态 Pod 可能会被废弃掉。 +通过在一个指定的、受 `kubelet` 监视的目录下编写文件来创建 Pod 也是可行的。 +这类 Pod 被称为[静态 Pod](/zh/docs/tasks/configure-pod-container/static-pod/)。 +不像 DaemonSet,静态 Pod 不受 `kubectl` 和其它 Kubernetes API 客户端管理。 +静态 Pod 不依赖于 API 服务器,这使得它们在启动引导新集群的情况下非常有用。 +此外,静态 Pod 在将来可能会被废弃。 ### Deployments -DaemonSet 与 [Deployments](/docs/concepts/workloads/controllers/deployment/) 非常类似,它们都能创建 Pod,这些 Pod 对应的进程都不希望被终止掉(例如,Web 服务器、存储服务器)。 -为无状态的 Service 使用 Deployments,比如前端 Frontend 服务,实现对副本的数量进行扩缩容、平滑升级,比基于精确控制 Pod 运行在某个主机上要重要得多。 -需要 Pod 副本总是运行在全部或特定主机上,并需要先于其他 Pod 启动,当这被认为非常重要时,应该使用 Daemon Controller。 - +DaemonSet 与 [Deployments](/zh/docs/concepts/workloads/controllers/deployment/) 非常类似, +它们都能创建 Pod,并且 Pod 中的进程都不希望被终止(例如,Web 服务器、存储服务器)。 +建议为无状态的服务使用 Deployments,比如前端服务。 +对这些服务而言,对副本的数量进行扩缩容、平滑升级,比精确控制 Pod 运行在某个主机上要重要得多。 +当需要 Pod 副本总是运行在全部或特定主机上,并需要它们先于其他 Pod 启动时, +应该使用 DaemonSet。 diff --git a/content/zh/docs/concepts/workloads/controllers/garbage-collection.md b/content/zh/docs/concepts/workloads/controllers/garbage-collection.md index 7e7802999e..0c34eda433 100644 --- a/content/zh/docs/concepts/workloads/controllers/garbage-collection.md +++ b/content/zh/docs/concepts/workloads/controllers/garbage-collection.md @@ -1,15 +1,13 @@ --- title: 垃圾收集 content_type: concept -weight: 60 +weight: 70 --- @@ -18,11 +16,7 @@ weight: 60 The role of the Kubernetes garbage collector is to delete certain objects that once had an owner, but no longer have an owner. --> - -Kubernetes 垃圾收集器的作用是删除某些曾经拥有所有者(owner)但现在不再拥有所有者的对象。 - - - +Kubernetes 垃圾收集器的作用是删除某些曾经拥有属主(Owner)但现在不再拥有属主的对象。 @@ -41,24 +35,29 @@ automatically sets the value of `ownerReference` for objects created or adopted by ReplicationController, ReplicaSet, StatefulSet, DaemonSet, Deployment, Job and CronJob. +--> +## 属主和附属 {#owners-and-dependents} + +某些 Kubernetes 对象是其它一些对象的属主。 +例如,一个 ReplicaSet 是一组 Pod 的属主。 +具有属主的对象被称为是属主的 *附属* 。 +每个附属对象具有一个指向其所属对象的 `metadata.ownerReferences` 字段。 + +有时,Kubernetes 会自动设置 `ownerReference` 的值。 +例如,当创建一个 ReplicaSet 时,Kubernetes 自动设置 ReplicaSet 中每个 Pod 的 `ownerReference` 字段值。 +在 Kubernetes 1.8 版本,Kubernetes 会自动为某些对象设置 `ownerReference` 的值。 +这些对象是由 ReplicationController、ReplicaSet、StatefulSet、DaemonSet、Deployment、 +Job 和 CronJob 所创建或管理的。 + + +你也可以通过手动设置 `ownerReference` 的值,来指定属主和附属之间的关系。 -## 所有者和附属 - -某些 Kubernetes 对象是其它一些对象的所有者。例如,一个 ReplicaSet 是一组 Pod 的所有者。 -具有所有者的对象被称为是所有者的 *附属* 。 -每个附属对象具有一个指向其所属对象的 `metadata.ownerReferences` 字段。 - -有时,Kubernetes 会自动设置 `ownerReference` 的值。 -例如,当创建一个 ReplicaSet 时,Kubernetes 自动设置 ReplicaSet 中每个 Pod 的 `ownerReference` 字段值。 -在 Kubernetes 1.8 版本,Kubernetes 会自动为某些对象设置 `ownerReference` 的值,这些对象是由 ReplicationController、ReplicaSet、StatefulSet、DaemonSet、Deployment、Job 和 CronJob 所创建或管理。 -也可以通过手动设置 `ownerReference` 的值,来指定所有者和附属之间的关系。 - -这里有一个配置文件,表示一个具有 3 个 Pod 的 ReplicaSet: +下面的配置文件中包含一个具有 3 个 Pod 的 ReplicaSet: {{< codenew file="controllers/replicaset.yaml" >}} @@ -66,8 +65,7 @@ Here's a configuration file for a ReplicaSet that has three Pods: If you create the ReplicaSet and then view the Pod metadata, you can see OwnerReferences field: --> - -如果创建该 ReplicaSet,然后查看 Pod 的 metadata 字段,能够看到 OwnerReferences 字段: +如果你创建该 ReplicaSet,然后查看 Pod 的 metadata 字段,能够看到 OwnerReferences 字段: ```shell kubectl apply -f https://k8s.io/examples/controllers/replicaset.yaml @@ -77,8 +75,7 @@ kubectl get pods --output=yaml - -输出显示了 Pod 的所有者是名为 my-repset 的 ReplicaSet: +输出显示了 Pod 的属主是名为 my-repset 的 ReplicaSet: ```yaml apiVersion: v1 @@ -103,9 +100,9 @@ and owners that are cluster-scoped. namespace-scoped owners. --> {{< note >}} -根据设计,kubernetes 不允许跨命名空间指定所有者。这意味着: -1)命名空间范围的附属只能在相同的命名空间中指定所有者,并且只能指定集群范围的所有者。 -2)集群范围的附属只能指定集群范围的所有者,不能指定命名空间范围的。 +根据设计,kubernetes 不允许跨命名空间指定属主。这意味着: +1)命名空间范围的附属只能指定同一的命名空间中的或者集群范围的属主。 +2)集群范围的附属只能指定集群范围的属主,不能指定命名空间范围的属主。 {{< /note >}} -## 控制垃圾收集器删除附属者 +## 控制垃圾收集器删除附属 -当删除对象时,可以指定该对象的附属者是否也自动删除掉。 -自动删除 Dependent 也称为 *级联删除* 。 -Kubernetes 中有两种 *级联删除* 的模式:*background* 模式和 *foreground* 模式。 - -如果删除对象时,不自动删除它的附属者,这些附属者被称作是原对象的 *orphaned* 。 +当你删除对象时,可以指定该对象的附属是否也自动删除。 +自动删除附属的行为也称为 *级联删除(Cascading Deletion)* 。 +Kubernetes 中有两种 *级联删除* 模式:*后台(Background)* 模式和 *前台(Foreground)* 模式。 +如果删除对象时,不自动删除它的附属,这些附属被称作 *孤立对象(Orphaned)* 。 -### 显式级联删除 - -在 *显式级联删除* 模式下,根对象首先进入 `deletion in progress` 状态。在 `deletion in progress` 状态会有如下的情况: +### 前台级联删除 + +在 *前台级联删除* 模式下,根对象首先进入 `deletion in progress` 状态。 +在 `deletion in progress` 状态,会有如下的情况: * 对象仍然可以通过 REST API 可见。 - * 会设置对象的 `deletionTimestamp` 字段。 - * 对象的 `metadata.finalizers` 字段包含了值 `foregroundDeletion`。 + * 对象的 `deletionTimestamp` 字段被设置。 + * 对象的 `metadata.finalizers` 字段包含值 `foregroundDeletion`。 一旦对象被设置为 `deletion in progress` 状态,垃圾收集器会删除对象的所有附属。 -垃圾收集器在删除了所有 `Blocking` 状态的附属(对象的 `ownerReference.blockOwnerDeletion=true`)之后,它会删除拥有者对象。 +垃圾收集器在删除了所有有阻塞能力的附属(对象的 `ownerReference.blockOwnerDeletion=true`) +之后,删除属主对象。 -注意,在 `foregroundDeletion` 模式下,只有设置了 `ownerReference.blockOwnerDeletion` 值的附属者才能阻止删除拥有者对象。 -在 Kubernetes 1.7 版本中将增加[准入控制器](/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement),基于拥有者对象上的删除权限来控制用户去设置 `blockOwnerDeletion` 的值为 true,所以未授权的附属者不能够延迟拥有者对象的删除。 - -如果一个对象的 `ownerReferences` 字段被一个 Controller(例如 Deployment 或 ReplicaSet)设置,`blockOwnerDeletion` 会被自动设置,不需要手动修改这个字段。 +注意,在 `foregroundDeletion` 模式下,只有设置了 `ownerReference.blockOwnerDeletion` +值的附属才能阻止删除属主对象。 +在 Kubernetes 1.7 版本增加了 +[准入控制器](/zh/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement), +基于属主对象上的删除权限来控制用户设置 `blockOwnerDeletion` 的值为 True, +这样未经授权的附属不能够阻止属主对象的删除。 +如果一个对象的 `ownerReferences` 字段被一个控制器(例如 Deployment 或 ReplicaSet)设置, +`blockOwnerDeletion` 也会被自动设置,你不需要手动修改这个字段。 -### 隐式级联删除 +### 后台级联删除 -在 *隐式级联删除* 模式下,Kubernetes 会立即删除拥有者对象,然后垃圾收集器会在后台删除这些附属值。 +在 *后台级联删除* 模式下,Kubernetes 会立即删除属主对象,之后垃圾收集器 +会在后台删除其附属对象。 - ### 设置级联删除策略 -通过为拥有者对象设置 `deleteOptions.propagationPolicy` 字段,可以控制级联删除策略。 -可能的取值包括:`orphan`、`Foreground` 或者 `Background`。 - -对很多 Controller 资源,包括 ReplicationController、ReplicaSet、StatefulSet、DaemonSet 和 Deployment,默认的垃圾收集策略是 `orphan`。 -因此,对于使用 `extensions/v1beta1`、`apps/v1beta1` 和 `apps/v1beta2` 组版本中的 `Kind`,除非指定其它的垃圾收集策略,否则所有附属对象默认使用的都是 `orphan` 策略。 +通过为属主对象设置 `deleteOptions.propagationPolicy` 字段,可以控制级联删除策略。 +可能的取值包括:`Orphan`、`Foreground` 或者 `Background`。 -下面是一个在 `Background` 中删除 Dependent 对象的示例: +下面是一个在后台删除附属对象的示例: ```shell kubectl proxy --port=8080 @@ -223,7 +214,7 @@ curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-rep Here's an example that deletes dependents in foreground: --> -下面是一个在 `Foreground` 中删除附属对象的示例: +下面是一个在前台中删除附属对象的示例: ```shell kubectl proxy --port=8080 @@ -235,8 +226,7 @@ curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-rep - -这里是一个 `Orphan` 附属的示例: +下面是一个令附属成为孤立对象的示例: ```shell kubectl proxy --port=8080 @@ -247,17 +237,18 @@ curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/replicasets/my-rep +`kubectl` 命令也支持级联删除。 +通过设置 `--cascade` 为 `true`,可以使用 kubectl 自动删除附属对象。 +设置 `--cascade` 为 `false`,会使附属对象成为孤立附属对象。 +`--cascade` 的默认值是 true。 -kubectl 也支持级联删除。 -通过设置 `--cascade` 为 `true`,可以使用 kubectl 自动删除附属对象。设置 `--cascade` 为 `false`,会使附属对象成为孤儿附属对象。`--cascade` 的默认值是 true。 - -下面是一个例子,使一个 ReplicaSet 的附属对象成为孤儿附属: +下面是一个例子,使一个 ReplicaSet 的附属对象成为孤立附属: ```shell kubectl delete replicaset my-repset --cascade=false @@ -271,40 +262,30 @@ to delete not only the ReplicaSets created, but also their Pods. If this type of is not used, only the ReplicaSets will be deleted, and the Pods will be orphaned. See [kubeadm/#149](https://github.com/kubernetes/kubeadm/issues/149#issuecomment-284766613) for more information. --> +### Deployment 的附加说明 -### Deployment 的其他说明 +在 1.7 之前的版本中,当在 Deployment 中使用级联删除时,你 *必须*使用 +`propagationPolicy:Foreground` 模式以便在删除所创建的 ReplicaSet 的同时,还删除其 Pod。 +如果不使用这种类型的 `propagationPolicy`,将只删除 ReplicaSet,而 Pod 被孤立。 -在 1.7 之前的版本中,当在 Deployment 中使用级联删除时,您必须*使用* `propagationPolicy:Foreground` 模式。这样不仅删除所创建的 ReplicaSet,还删除其 Pod。如果不使用这种类型的 `propagationPolicy`,则将只删除 ReplicaSet,而 Pod 被孤立。 - -更多信息,请参考 [kubeadm/#149](https://github.com/kubernetes/kubeadm/issues/149#issuecomment-284766613)。 +有关信息请参考 [kubeadm/#149](https://github.com/kubernetes/kubeadm/issues/149#issuecomment-284766613)。 - ## 已知的问题 跟踪 [#26120](https://github.com/kubernetes/kubernetes/issues/26120) - - - ## {{% heading "whatsnext" %}} - - -[设计文档 1](https://git.k8s.io/community/contributors/design-proposals/api-machinery/garbage-collection.md) - -[设计文档 2](https://git.k8s.io/community/contributors/design-proposals/api-machinery/synchronous-garbage-collection.md) - - - - +* [设计文档 1](https://git.k8s.io/community/contributors/design-proposals/api-machinery/garbage-collection.md) +* [设计文档 2](https://git.k8s.io/community/contributors/design-proposals/api-machinery/synchronous-garbage-collection.md) diff --git a/content/zh/docs/concepts/workloads/controllers/job.md b/content/zh/docs/concepts/workloads/controllers/job.md index 0a5dfd8291..3156ff6a53 100644 --- a/content/zh/docs/concepts/workloads/controllers/job.md +++ b/content/zh/docs/concepts/workloads/controllers/job.md @@ -497,7 +497,7 @@ cleaned up by CronJobs based on the specified capacity-based cleanup policy. ### TTL mechanism for finished Jobs --> -## 自动清理完成的 Job +## 自动清理完成的 Job {#clean-up-finished-jobs-automatically} 完成的 Job 通常不需要留存在系统中。在系统中一直保留它们会给 API 服务器带来额外的压力。 diff --git a/content/zh/docs/concepts/workloads/controllers/replicaset.md b/content/zh/docs/concepts/workloads/controllers/replicaset.md index 962b7dfc0b..76e06b6490 100644 --- a/content/zh/docs/concepts/workloads/controllers/replicaset.md +++ b/content/zh/docs/concepts/workloads/controllers/replicaset.md @@ -1,8 +1,4 @@ --- -reviewers: -- Kashomon -- bprashanth -- madhusudancs title: ReplicaSet content_type: concept weight: 10 @@ -11,19 +7,59 @@ weight: 10 -ReplicaSet 是下一代的 Replication Controller。 _ReplicaSet_ 和 [_Replication Controller_](/docs/concepts/workloads/controllers/replicationcontroller/) 的唯一区别是选择器的支持。ReplicaSet 支持新的基于集合的选择器需求,这在[标签用户指南](/docs/concepts/overview/working-with-objects/labels/#label-selectors)中有描述。而 Replication Controller 仅支持基于相等选择器的需求。 - - +ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 +因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。 + +## ReplicaSet 的工作原理 {#how-a-replicaset-works} + +RepicaSet 是通过一组字段来定义的,包括一个用来识别可获得的 Pod +的集合的选择算符,一个用来标明应该维护的副本个数的数值,一个用来指定应该创建新 Pod +以满足副本个数条件时要使用的 Pod 模板等等。每个 ReplicaSet 都通过根据需要创建和 +删除 Pod 以使得副本个数达到期望值,进而实现其存在价值。当 ReplicaSet 需要创建 +新的 Pod 时,会使用所提供的 Pod 模板。 + + +ReplicaSet 通过 Pod 上的 +[metadata.ownerReferences](/zh/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents) +字段连接到附属 Pod,该字段给出当前对象的属主资源。 +ReplicaSet 所获得的 Pod 都在其 ownerReferences 字段中包含了属主 ReplicaSet +的标识信息。正是通过这一连接,ReplicaSet 知道它所维护的 Pod 集合的状态, +并据此计划其操作行为。 + + +ReplicaSet 使用其选择算符来辨识要获得的 Pod 集合。如果某个 Pod 没有 +OwnerReference 或者其 OwnerReference 不是一个 +{{< glossary_tooltip text="控制器" term_id="controller" >}},且其匹配到 +某 ReplicaSet 的选择算符,则该 Pod 立即被此 ReplicaSet 获得。 - -## 怎样使用 ReplicaSet +## 怎样使用 ReplicaSet {#how-to-use-a-replicaset} 大多数支持 Replication Controllers 的[`kubectl`](/docs/user-guide/kubectl/)命令也支持 ReplicaSets。但[`rolling-update`](/docs/reference/generated/kubectl/kubectl-commands#rolling-update) 命令是个例外。如果您想要滚动更新功能请考虑使用 Deployment。[`rolling-update`](/docs/reference/generated/kubectl/kubectl-commands#rolling-update) 命令是必需的,而 Deployment 是声明性的,因此我们建议通过 [`rollout`](/docs/reference/generated/kubectl/kubectl-commands#rollout)命令使用 Deployment。 diff --git a/content/zh/docs/concepts/workloads/controllers/statefulset.md b/content/zh/docs/concepts/workloads/controllers/statefulset.md index 3a27b68dd8..955774f469 100644 --- a/content/zh/docs/concepts/workloads/controllers/statefulset.md +++ b/content/zh/docs/concepts/workloads/controllers/statefulset.md @@ -5,18 +5,9 @@ weight: 40 --- @@ -24,23 +15,20 @@ weight: 40 - StatefulSet 是用来管理有状态应用的工作负载 API 对象。 {{< glossary_definition term_id="statefulset" length="all" >}} - -## 使用 StatefulSets - +## 使用 StatefulSets + StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值: -在上面,稳定意味着 Pod 调度或重调度的整个过程是有持久性的。如果应用程序不需要任何稳定的标识符或有序的部署、删除或伸缩,则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如 [Deployment](/docs/concepts/workloads/controllers/deployment/) 或者 [ReplicaSet](/docs/concepts/workloads/controllers/replicaset/) 可能更适用于您的无状态应用部署需要。 +在上面,稳定意味着 Pod 调度或重调度的整个过程是有持久性的。如果应用程序不需要任何稳定的标识符或有序的部署、删除或伸缩,则应该使用由一组无状态的副本控制器提供的工作负载来部署应用程序,比如 [Deployment](/zh/docs/concepts/workloads/controllers/deployment/) 或者 [ReplicaSet](/zh/docs/concepts/workloads/controllers/replicaset/) 可能更适用于您的无状态应用部署需要。 -## 限制 +## 限制 {#limitations} * 给定 Pod 的存储必须由 [PersistentVolume 驱动](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/staging/persistent-volume-provisioning/README.md) 基于所请求的 `storage class` 来提供,或者由管理员预先提供。 * 删除或者收缩 StatefulSet 并*不会*删除它关联的存储卷。这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。 -* StatefulSet 当前需要 [headless 服务](/docs/concepts/services-networking/service/#headless-services) 来负责 Pod 的网络标识。您需要负责创建此服务。 +* StatefulSet 当前需要[无头服务](/zh/docs/concepts/services-networking/service/#headless-services) 来负责 Pod 的网络标识。您需要负责创建此服务。 * 当删除 StatefulSets 时,StatefulSet 不提供任何终止 Pod 的保证。为了实现 StatefulSet 中的 Pod 可以有序和优雅的终止,可以在删除之前将 StatefulSet 缩放为 0。 * 在默认 [Pod 管理策略](#pod-management-policies)(`OrderedReady`) 时使用 [滚动更新](#rolling-updates),可能进入需要 [人工干预](#forced-rollback) 才能修复的损坏状态。 @@ -89,7 +77,7 @@ that provides a set of stateless replicas. ## Components The example below demonstrates the components of a StatefulSet. --> -## 组件 +## 组件 {#components} 下面的示例演示了 StatefulSet 的组件。 @@ -151,12 +139,13 @@ spec: --> * 名为 `nginx` 的 Headless Service 用来控制网络域名。 * 名为 `web` 的 StatefulSet 有一个 Spec,它表明将在独立的 3 个 Pod 副本中启动 nginx 容器。 -* `volumeClaimTemplates` 将通过 PersistentVolumes 驱动提供的 [PersistentVolumes](/docs/concepts/storage/persistent-volumes/) 来提供稳定的存储。 +* `volumeClaimTemplates` 将通过 PersistentVolumes 驱动提供的 + [PersistentVolumes](/zh/docs/concepts/storage/persistent-volumes/) 来提供稳定的存储。 -## Pod 选择器 {#pod-selector} +## Pod 选择算符 {#pod-selector} -## Pod 标识 - +## Pod 标识 {#pod-identity} + StatefulSet Pod 具有唯一的标识,该标识包括顺序标识、稳定的网络标识和稳定的存储。该标识和 Pod 是绑定的,不管它被调度在哪个节点上。 -### 有序索引 - +### 有序索引 {#ordinal-index} + 对于具有 N 个副本的 StatefulSet,StatefulSet 中的每个 Pod 将被分配一个整数序号,从 0 到 N-1,该序号在 StatefulSet 上是唯一的。 -### 稳定的网络 ID - -StatefulSet 中的每个 Pod 根据 StatefulSet 的名称和 Pod 的序号派生出它的主机名。组合主机名的格式为`$(StatefulSet 名称)-$(序号)`。上例将会创建三个名称分别为 `web-0、web-1、web-2` 的 Pod。 -StatefulSet 可以使用 [headless 服务](/docs/concepts/services-networking/service/#headless-services) 控制它的 Pod 的网络域。管理域的这个服务的格式为: +### 稳定的网络 ID {#stable-network-id} + +StatefulSet 中的每个 Pod 根据 StatefulSet 的名称和 Pod 的序号派生出它的主机名。 +组合主机名的格式为`$(StatefulSet 名称)-$(序号)`。上例将会创建三个名称分别为 `web-0、web-1、web-2` 的 Pod。 +StatefulSet 可以使用 [headless 服务](/zh/docs/concepts/services-networking/service/#headless-services) +控制它的 Pod 的网络域。管理域的这个服务的格式为: `$(服务名称).$(命名空间).svc.cluster.local`,其中 `cluster.local` 是集群域。 -一旦每个 Pod 创建成功,就会得到一个匹配的 DNS 子域,格式为:`$(pod 名称).$(所属服务的 DNS 域名)`,其中所属服务由 StatefulSet 的 `serviceName` 域来设定。 +一旦每个 Pod 创建成功,就会得到一个匹配的 DNS 子域,格式为: +`$(pod 名称).$(所属服务的 DNS 域名)`,其中所属服务由 StatefulSet 的 `serviceName` 域来设定。 - 下面给出一些选择集群域、服务名、StatefulSet 名、及其怎样影响 StatefulSet 的 Pod 上的 DNS 名称的示例: -Cluster Domain | Service (ns/name) | StatefulSet (ns/name) | StatefulSet Domain | Pod DNS | Pod Hostname | --------------- | ----------------- | ----------------- | -------------- | ------- | ------------ | +集群域名 | 服务(名字空间/名字)| StatefulSet(名字空间/名字) | StatefulSet 域名 | Pod DNS | Pod 主机名 | +-------------- | -------------------- | ---------------------------- | ---------------- | ------- | ------------ | 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} | @@ -227,15 +215,12 @@ Cluster Domain will be set to `cluster.local` unless [otherwise configured](/docs/concepts/services-networking/dns-pod-service/#how-it-works). --> {{< note >}} -集群域会被设置为 `cluster.local`,除非有[其他配置](/docs/concepts/services-networking/dns-pod-service/)。 +集群域会被设置为 `cluster.local`,除非有[其他配置](/zh/docs/concepts/services-networking/dns-pod-service/)。 {{< /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 并不会被删除。要删除它必须通过手动方式来完成。 +### 稳定的存储 {#stable-storage} + +Kubernetes 为每个 VolumeClaimTemplate 创建一个 [PersistentVolume](/zh/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 名称标签 - +### Pod 名称标签 {#pod-name-label} + 当 StatefulSet {{< glossary_tooltip term_id="controller" >}} 创建 Pod 时,它会添加一个标签 `statefulset.kubernetes.io/pod-name`,该标签设置为 Pod 名称。这个标签允许您给 StatefulSet 中的特定 Pod 绑定一个 Service。 -## 部署和扩缩保证 - +## 部署和扩缩保证 {#deployment-and-scaling-guarantees} + * 对于包含 N 个 副本的 StatefulSet,当部署 Pod 时,它们是依次创建的,顺序为 `0..N-1`。 * 当删除 Pod 时,它们是逆序终止的,顺序为 `N-1..0`。 * 在将缩放操作应用到 Pod 之前,它前面的所有 Pod 必须是 Running 和 Ready 状态。 @@ -279,8 +270,9 @@ the StatefulSet. - -StatefulSet 不应将 `pod.Spec.TerminationGracePeriodSeconds` 设置为 0。这种做法是不安全的,要强烈阻止。更多的解释请参考 [强制删除 StatefulSet Pod](/docs/tasks/run-application/force-delete-stateful-set-pod/)。 +StatefulSet 不应将 `pod.Spec.TerminationGracePeriodSeconds` 设置为 0。 +这种做法是不安全的,要强烈阻止。更多的解释请参考 +[强制删除 StatefulSet Pod](/zh/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。 +在上面的 nginx 示例被创建后,会按照 web-0、web-1、web-2 的顺序部署三个 Pod。 +在 web-0 进入 [Running 和 Ready](/zh/docs/concepts/workloads/pods/pod-lifecycle/) +状态前不会部署 web-1。在 web-1 进入 Running 和 Ready 状态前不会部署 web-2。 +如果 web-1 已经处于 Running 和 Ready 状态,而 web-2 尚未部署,在此期间发生了 +web-0 运行失败,那么 web-2 将不会被部署,要等到 web-0 部署完成并进入 Running 和 +Ready 状态后,才会部署 web-2。 -### Pod 管理策略 {#pod-management-policies} - +### Pod 管理策略 {#pod-management-policies} + 在 Kubernetes 1.7 及以后的版本中,StatefulSet 允许您不要求其排序保证,同时通过它的 `.spec.podManagementPolicy` 域保持其唯一性和身份保证。 在 Kubernetes 1.7 及以后的版本中,StatefulSet 允许您放宽其排序保证,同时通过它的 `.spec.podManagementPolicy` 域保持其唯一性和身份保证。 -#### OrderedReady Pod 管理 - +#### OrderedReady Pod 管理 + `OrderedReady` Pod 管理是 StatefulSet 的默认设置。它实现了[上面](#deployment-and-scaling-guarantees)描述的功能。 -#### Parallel Pod 管理 - -`Parallel` Pod 管理让 StatefulSet 控制器并行的启动或终止所有的 Pod,启动或者终止其他 Pod 前,无需等待 Pod 进入 Running 和 ready 或者完全停止状态。 +#### 并行 Pod 管理 {#parallel-pod-management} + +`Parallel` Pod 管理让 StatefulSet 控制器并行的启动或终止所有的 Pod, +启动或者终止其他 Pod 前,无需等待 Pod 进入 Running 和 ready 或者完全停止状态。 -## 更新策略 - +## 更新策略 {#update-strategies} + 在 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} - +### 滚动更新 {#rolling-updates} + `RollingUpdate` 更新策略对 StatefulSet 中的 Pod 执行自动的滚动更新。在没有声明 `.spec.updateStrategy` 时,`RollingUpdate` 是默认配置。 当 StatefulSet 的 `.spec.updateStrategy.type` 被设置为 `RollingUpdate` 时,StatefulSet 控制器会删除和重建 StatefulSet 中的每个 Pod。 它将按照与 Pod 终止相同的顺序(从最大序号到最小序号)进行,每次更新一个 Pod。它会等到被更新的 Pod 进入 Running 和 Ready 状态,然后再更新其前身。 -#### 分区 - +#### 分区 {#partitions} + 通过声明 `.spec.updateStrategy.rollingUpdate.partition` 的方式,`RollingUpdate` 更新策略可以实现分区。如果声明了一个分区,当 StatefulSet 的 `.spec.template` 被更新时,所有序号大于等于该分区序号的 Pod 都会被更新。所有序号小于该分区序号的 Pod 都不会被更新,并且,即使他们被删除也会依据之前的版本进行重建。如果 StatefulSet 的 `.spec.updateStrategy.rollingUpdate.partition` 大于它的 `.spec.replicas`,对它的 `.spec.template` 的更新将不会传递到它的 Pod。 在大多数情况下,您不需要使用分区,但如果您希望进行阶段更新、执行金丝雀或执行分阶段展开,则这些分区会非常有用。 -#### 强制回滚 {#forced-rollback} - +#### 强制回滚 {#forced-rollback} +在默认 [Pod 管理策略](#pod-management-policies)(`OrderedReady`) 时使用 [滚动更新](#rolling-updates) ,可能进入需要人工干预才能修复的损坏状态。 + +如果更新后 Pod 模板配置进入无法运行或就绪的状态(例如,由于错误的二进制文件或应用程序级配置错误),StatefulSet 将停止回滚并等待。 + + -在默认 [Pod 管理策略](#pod-management-policies)(`OrderedReady`) 时使用 [滚动更新](#rolling-updates) ,可能进入需要人工干预才能修复的损坏状态。 - -如果更新后 Pod 模板配置进入无法运行或就绪的状态(例如,由于错误的二进制文件或应用程序级配置错误),StatefulSet 将停止回滚并等待。 - -在这种状态下,仅将 Pod 模板还原为正确的配置是不够的。由于[已知问题](https://github.com/kubernetes/kubernetes/issues/67250),StatefulSet 将继续等待损坏状态的 Pod 准备就绪(永远不会发生),然后再尝试将其恢复为正常工作配置。 - -恢复模板后,还必须删除 StatefulSet 尝试使用错误的配置来运行的 Pod。这样,StatefulSet 才会开始使用被还原的模板来重新创建 Pod。 +在这种状态下,仅将 Pod 模板还原为正确的配置是不够的。由于 +[已知问题](https://github.com/kubernetes/kubernetes/issues/67250),StatefulSet +将继续等待损坏状态的 Pod 准备就绪(永远不会发生),然后再尝试将其恢复为正常工作配置。 +恢复模板后,还必须删除 StatefulSet 尝试使用错误的配置来运行的 Pod。这样, +StatefulSet 才会开始使用被还原的模板来重新创建 Pod。 ## {{% heading "whatsnext" %}} - -* 示例一:[部署有状态应用](/docs/tutorials/stateful-application/basic-stateful-set/)。 -* 示例二:[使用 StatefulSet 部署 Cassandra](/docs/tutorials/stateful-application/cassandra/)。 -* 示例三:[运行多副本的有状态应用程序](/docs/tasks/run-application/run-replicated-stateful-application/)。 +* 示例一:[部署有状态应用](/zh/docs/tutorials/stateful-application/basic-stateful-set/)。 +* 示例二:[使用 StatefulSet 部署 Cassandra](/zh/docs/tutorials/stateful-application/cassandra/)。 +* 示例三:[运行多副本的有状态应用程序](/zh/docs/tasks/run-application/run-replicated-stateful-application/)。 diff --git a/content/zh/docs/concepts/workloads/controllers/ttlafterfinished.md b/content/zh/docs/concepts/workloads/controllers/ttlafterfinished.md index 344363c5dd..3b2ddc60c7 100644 --- a/content/zh/docs/concepts/workloads/controllers/ttlafterfinished.md +++ b/content/zh/docs/concepts/workloads/controllers/ttlafterfinished.md @@ -4,13 +4,9 @@ content_type: concept weight: 65 --- @@ -20,36 +16,41 @@ weight: 65 -TTL 控制器提供了一种 TTL 机制来限制已完成执行的资源对象的生命周期。TTL 控制器目前只处理 [Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/),可能以后会扩展以处理将完成执行的其他资源,例如 Pod 和自定义资源。 +TTL 控制器提供了一种 TTL 机制来限制已完成执行的资源对象的生命周期。 +TTL 控制器目前只处理 {{< glossary_tooltip text="Job" term_id="job" >}}, +可能以后会扩展以处理将完成执行的其他资源,例如 Pod 和自定义资源。 -Alpha 免责声明:此功能目前是 alpha 版,并且可以通过 kube-apiserver 和 kube-controller-manager [特性开关](/docs/reference/command-line-tools-reference/feature-gates/) `TTLAfterFinished` 启用。 - - - +Alpha 免责声明:此功能目前是 alpha 版,并且可以通过 `kube-apiserver` 和 +`kube-controller-manager` 上的 +[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/) +`TTLAfterFinished` 启用。 -## TTL 控制器 - -TTL 控制器现在只支持 Job。集群操作员可以通过指定 Job 的 `.spec.ttlSecondsAfterFinished` 字段来自动清理已结束的作业(`Complete` 或 `Failed`),如下所示的[示例](/docs/concepts/workloads/controllers/jobs-run-to-completion/#clean-up-finished-jobs-automatically)。 +## TTL 控制器 + +TTL 控制器现在只支持 Job。集群操作员可以通过指定 Job 的 `.spec.ttlSecondsAfterFinished` +字段来自动清理已结束的作业(`Complete` 或 `Failed`),如 +[示例](/zh/docs/concepts/workloads/controllers/jobs-run-to-completion/#clean-up-finished-jobs-automatically) +所示。 + -TTL 控制器假设资源能在执行完成后的 TTL 秒内被清理,也就是当 TTL 过期后。当 TTL 控制器清理资源时,它将做级联删除操作,如删除资源对象的同时也删除其依赖对象。注意,当资源被删除时,由该资源的生命周期保证其终结器(finalizers)等被执行。 +TTL 控制器假设资源能在执行完成后的 TTL 秒内被清理,也就是当 TTL 过期后。 +当 TTL 控制器清理资源时,它将做级联删除操作,即删除资源对象的同时也删除其依赖对象。 +注意,当资源被删除时,由该资源的生命周期保证其终结器(Finalizers)等被执行。 * 在资源清单(manifest)中指定此字段,以便 Job 在完成后的某个时间被自动清除。 -* 将此字段设置为存在的、已完成的资源,以采用此新功能。 -* 在创建资源时使用 [mutating admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) 动态设置该字段。集群管理员可以使用它对完成的资源强制执行 TTL 策略。 -* 使用 [mutating admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) 在资源完成后动态设置该字段,并根据资源状态、标签等选择不同的 TTL 值。 +* 将此字段设置为现有的、已完成的资源,以采用此新功能。 +* 在创建资源时使用 [mutating admission webhook](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) + 动态设置该字段。集群管理员可以使用它对完成的资源强制执行 TTL 策略。 +* 使用 [mutating admission webhook](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) + 在资源完成后动态设置该字段,并根据资源状态、标签等选择不同的 TTL 值。 -## 警告 - -### 更新 TTL 秒 - -请注意,在创建资源或已经执行结束后,仍可以修改其 TTL 周期,例如 Job 的 `.spec.ttlSecondsAfterFinished` 字段。但是,一旦 Job 变为可被删除状态(当其 TTL 已过期时),即使您通过 API 扩展其 TTL 时长得到了成功的响应,系统也不保证 Job 将被保留。 +## 警告 + +### 更新 TTL 秒 + +请注意,在创建资源或已经执行结束后,仍可以修改其 TTL 周期,例如 Job 的 +`.spec.ttlSecondsAfterFinished` 字段。 +但是一旦 Job 变为可被删除状态(当其 TTL 已过期时),即使您通过 API 增加其 TTL +时长得到了成功的响应,系统也不保证 Job 将被保留。 -### 时间偏差 - -由于 TTL 控制器使用存储在 Kubernetes 资源中的时间戳来确定 TTL 是否已过期,因此该功能对集群中的时间偏差很敏感,这可能导致 TTL 控制器在错误的时间清理资源对象。 +### 时间偏差 {#time-skew} + +由于 TTL 控制器使用存储在 Kubernetes 资源中的时间戳来确定 TTL 是否已过期, +因此该功能对集群中的时间偏差很敏感,这可能导致 TTL 控制器在错误的时间清理资源对象。 -在 Kubernetes 中,需要在所有节点上运行 NTP(参见 [#6159](https://github.com/kubernetes/kubernetes/issues/6159#issuecomment-93844058))以避免时间偏差。时钟并不总是如此正确,但差异应该很小。设置非零 TTL 时请注意避免这种风险。 - - +在 Kubernetes 中,需要在所有节点上运行 NTP(参见 +[#6159](https://github.com/kubernetes/kubernetes/issues/6159#issuecomment-93844058)) +以避免时间偏差。时钟并不总是如此正确,但差异应该很小。 +设置非零 TTL 时请注意避免这种风险。 ## {{% heading "whatsnext" %}} - -[自动清理 Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/#clean-up-finished-jobs-automatically) - - -[设计文档](https://github.com/kubernetes/enhancements/blob/master/keps/sig-apps/0026-ttl-after-finish.md) - +* [自动清理 Job](/zh/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically) +* [设计文档](https://github.com/kubernetes/enhancements/blob/master/keps/sig-apps/0026-ttl-after-finish.md)