Switch language name 'zh' to 'zh-cn'

This is the first step to rename 'zh' to 'zh-cn'. There are several reasons why we rename the language name.

- The upstream docsy theme changed the language name, leading to many warnings during site build;
  The side-effect is that the i18n strings are no longer working.
- We believe renaming the language is the right thing to do, because this move can make room for other variants of Chinese language, such as 'zh-tw', 'zh-sg' etc.

There would be several follow-ups to this PR, such as fixing the intra-site links, adding redirects etc.

We will lock up changes to zh/zh-cn pages for the moment, until this one gets in.

This PR is based on commit cdad0a7342.
This commit is contained in:
Qiming Teng
2022-06-10 20:25:27 +08:00
parent 3d345b1816
commit c52818c03d
1347 changed files with 8 additions and 6 deletions
@@ -0,0 +1,5 @@
---
title: "配置 Pods 和容器"
weight: 20
description: 对 Pod 和容器执行常见的配置任务。
---
@@ -0,0 +1,439 @@
---
title: 为容器和 Pods 分配 CPU 资源
content_type: task
weight: 20
---
<!--
title: Assign CPU Resources to Containers and Pods
content_type: task
weight: 20
-->
<!-- overview -->
<!--
This page shows how to assign a CPU *request* and a CPU *limit* to
a container. Containers cannot use more CPU than the configured limit.
Provided the system has CPU time free, a container is guaranteed to be
allocated as much CPU as it requests.
-->
本页面展示如何为容器设置 CPU *request(请求)* 和 CPU *limit(限制)*
容器使用的 CPU 不能超过所配置的限制。
如果系统有空闲的 CPU 时间,则可以保证给容器分配其所请求数量的 CPU 资源。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!--
Each node in your cluster must have at least 1 CPU.
A few of the steps on this page require you to run the
[metrics-server](https://github.com/kubernetes-sigs/metrics-server)
service in your cluster. If you have the metrics-server
running, you can skip those steps.
If you are running {{< glossary_tooltip term_id="minikube" >}}, run the
following command to enable metrics-server:
-->
集群中的每个节点必须至少有 1 个 CPU 可用才能运行本任务中的示例。
本页的一些步骤要求你在集群中运行
[metrics-server](https://github.com/kubernetes-sigs/metrics-server)
服务。如果你的集群中已经有正在运行的 metrics-server 服务,可以跳过这些步骤。
如果你正在运行{{< glossary_tooltip term_id="minikube" >}},请运行以下命令启用 metrics-server
```shell
minikube addons enable metrics-server
```
<!--
To see whether metrics-server (or another provider of the resource metrics
API, `metrics.k8s.io`) is running, type the following command:
-->
查看 metrics-server(或者其他资源度量 API `metrics.k8s.io` 服务提供者)是否正在运行,
请键入以下命令:
```shell
kubectl get apiservices
```
<!--
If the resource metrics API is available, the output will include a
reference to `metrics.k8s.io`.
-->
如果资源指标 API 可用,则会输出将包含一个对 `metrics.k8s.io` 的引用。
```
NAME
v1beta1.metrics.k8s.io
```
<!-- steps -->
<!--
## Create a namespace
Create a {{< glossary_tooltip term_id="namespace" >}} so that the resources you
create in this exercise are isolated from the rest of your cluster.
-->
## 创建一个名字空间
创建一个{{< glossary_tooltip text="名字空间" term_id="namespace" >}},以便将
本练习中创建的资源与集群的其余部分资源隔离。
```shell
kubectl create namespace cpu-example
```
<!--
## Specify a CPU request and a CPU limit
To specify a CPU request for a container, include the `resources:requests` field
in the Container resource manifest. To specify a CPU limit, include `resources:limits`.
In this exercise, you create a Pod that has one container. The container has a request
of 0.5 CPU and a limit of 1 CPU. Here is the configuration file for the Pod:
{{< codenew file="pods/resource/cpu-request-limit.yaml" >}}
The `args` section of the configuration file provides arguments for the container when it starts.
The `-cpus "2"` argument tells the Container to attempt to use 2 CPUs.
Create the Pod:
-->
## 指定 CPU 请求和 CPU 限制
要为容器指定 CPU 请求,请在容器资源清单中包含 `resources: requests` 字段。
要指定 CPU 限制,请包含 `resources:limits`
在本练习中,你将创建一个具有一个容器的 Pod。容器将会请求 0.5 个 CPU,而且最多限制使用 1 个 CPU。
这是 Pod 的配置文件:
{{< codenew file="pods/resource/cpu-request-limit.yaml" >}}
配置文件的 `args` 部分提供了容器启动时的参数。
`-cpus "2"` 参数告诉容器尝试使用 2 个 CPU。
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example
```
<!--
Verify that the Pod is running:
-->
验证所创建的 Pod 处于 Running 状态
```shell
kubectl get pod cpu-demo --namespace=cpu-example
```
<!--
View detailed information about the Pod:
-->
查看显示关于 Pod 的详细信息:
```shell
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
```
<!--
The output shows that the one container in the Pod has a CPU request of 500 milliCPU
and a CPU limit of 1 CPU.
-->
输出显示 Pod 中的一个容器的 CPU 请求为 500 milli CPU,并且 CPU 限制为 1 个 CPU。
```yaml
resources:
limits:
cpu: "1"
requests:
cpu: 500m
```
<!--
Use `kubectl top` to fetch the metrics for the pod:
-->
使用 `kubectl top` 命令来获取该 Pod 的度量值数据:
```shell
kubectl top pod cpu-demo --namespace=cpu-example
```
<!--
This example output shows that the Pod is using 974 milliCPU, which is
slightly less than the limit of 1 CPU specified in the Pod configuration.
-->
此示例输出显示 Pod 使用的是 974 milliCPU,即略低于 Pod 配置中指定的 1 个 CPU 的限制。
```
NAME CPU(cores) MEMORY(bytes)
cpu-demo 974m <something>
```
<!--
Recall that by setting `-cpu "2"`, you configured the Container to attempt to use 2 CPUs, but the Container is only being allowed to use about 1 CPU. The container's CPU use is being throttled, because the container is attempting to use more CPU resources than its limit.
-->
回想一下,通过设置 `-cpu "2"`,你将容器配置为尝试使用 2 个 CPU,
但是容器只被允许使用大约 1 个 CPU。
容器的 CPU 用量受到限制,因为该容器正尝试使用超出其限制的 CPU 资源。
<!--
Another possible explanation for the CPU use being below 1.0 is that the Node might not have
enough CPU resources available. Recall that the prerequisites for this exercise require each of
your Nodes to have at least 1 CPU. If your Container runs on a Node that has only 1 CPU, the Container
cannot use more than 1 CPU regardless of the CPU limit specified for the Container.
-->
{{< note >}}
CPU 使用率低于 1.0 的另一种可能的解释是,节点可能没有足够的 CPU 资源可用。
回想一下,此练习的先决条件需要你的节点至少具有 1 个 CPU 可用。
如果你的容器在只有 1 个 CPU 的节点上运行,则容器无论为容器指定的 CPU 限制如何,
都不能使用超过 1 个 CPU。
{{< /note >}}
<!--
## CPU units
The CPU resource is measured in *CPU* units. One CPU, in Kubernetes, is equivalent to:
* 1 AWS vCPU
* 1 GCP Core
* 1 Azure vCore
* 1 Hyperthread on a bare-metal Intel processor with Hyperthreading
-->
## CPU 单位 {#cpu-units}
CPU 资源以 *CPU* 单位度量。Kubernetes 中的一个 CPU 等同于:
* 1 个 AWS vCPU
* 1 个 GCP核心
* 1 个 Azure vCore
* 裸机上具有超线程能力的英特尔处理器上的 1 个超线程
<!--
Fractional values are allowed. A Container that requests 0.5 CPU is guaranteed half as much
CPU as a Container that requests 1 CPU. You can use the suffix m to mean milli. For example
100m CPU, 100 milliCPU, and 0.1 CPU are all the same. Precision finer than 1m is not allowed.
CPU is always requested as an absolute quantity, never as a relative quantity; 0.1 is the same
amount of CPU on a single-core, dual-core, or 48-core machine.
Delete your Pod:
-->
小数值是可以使用的。一个请求 0.5 CPU 的容器保证会获得请求 1 个 CPU 的容器的 CPU 的一半。
你可以使用后缀 `m` 表示毫。例如 `100m` CPU、100 milliCPU 和 0.1 CPU 都相同。
精度不能超过 1m。
CPU 请求只能使用绝对数量,而不是相对数量。0.1 在单核、双核或 48 核计算机上的 CPU 数量值是一样的。
删除 Pod
```shell
kubectl delete pod cpu-demo --namespace=cpu-example
```
<!--
## Specify a CPU request that is too big for your Nodes
CPU requests and limits are associated with Containers, but it is useful to think
of a Pod as having a CPU request and limit. The CPU request for a Pod is the sum
of the CPU requests for all the Containers in the Pod. Likewise, the CPU limit for
a Pod is the sum of the CPU limits for all the Containers in the Pod.
Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if
the Node has enough CPU resources available to satisfy the Pod CPU request.
In this exercise, you create a Pod that has a CPU request so big that it exceeds
the capacity of any Node in your cluster. Here is the configuration file for a Pod
that has one Container. The Container requests 100 CPU, which is likely to exceed the
capacity of any Node in your cluster.
{{< codenew file="pods/resource/cpu-request-limit-2.yaml" >}}
Create the Pod:
-->
## 设置超过节点能力的 CPU 请求
CPU 请求和限制与都与容器相关,但是我们可以考虑一下 Pod 具有对应的 CPU 请求和限制这样的场景。
Pod 对 CPU 用量的请求等于 Pod 中所有容器的请求数量之和。
同样,Pod 的 CPU 资源限制等于 Pod 中所有容器 CPU 资源限制数之和。
Pod 调度是基于资源请求值来进行的。
仅在某节点具有足够的 CPU 资源来满足 Pod CPU 请求时,Pod 将会在对应节点上运行:
在本练习中,你将创建一个 Pod,该 Pod 的 CPU 请求对于集群中任何节点的容量而言都会过大。
下面是 Pod 的配置文件,其中有一个容器。容器请求 100 个 CPU,这可能会超出集群中任何节点的容量。
{{< codenew file="pods/resource/cpu-request-limit-2.yaml" >}}
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example
```
<!--
View the Pod status:
-->
查看该 Pod 的状态:
```shell
kubectl get pod cpu-demo-2 --namespace=cpu-example
```
<!--
The output shows that the Pod status is Pending. That is, the Pod has not been
scheduled to run on any Node, and it will remain in the Pending state indefinitely:
-->
输出显示 Pod 状态为 Pending。也就是说,Pod 未被调度到任何节点上运行,
并且 Pod 将无限期地处于 Pending 状态:
```
NAME READY STATUS RESTARTS AGE
cpu-demo-2 0/1 Pending 0 7m
```
<!--
View detailed information about the Pod, including events:
-->
查看有关 Pod 的详细信息,包含事件:
```shell
kubectl describe pod cpu-demo-2 --namespace=cpu-example
```
<!--
The output shows that the Container cannot be scheduled because of insufficient
CPU resources on the Nodes:
-->
输出显示由于节点上的 CPU 资源不足,无法调度容器:
```
Events:
Reason Message
------ -------
FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3).
```
<!--
Delete your Pod:
-->
删除你的 Pod
```shell
kubectl delete pod cpu-demo-2 --namespace=cpu-example
```
<!--
## If you do not specify a CPU limit
If you do not specify a CPU limit for a Container, then one of these situations applies:
* The Container has no upper bound on the CPU resources it can use. The Container
could use all of the CPU resources available on the Node where it is running.
* The Container is running in a namespace that has a default CPU limit, and the
Container is automatically assigned the default limit. Cluster administrators can use a
[LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core/)
to specify a default value for the CPU limit.
-->
## 如果不指定 CPU 限制
如果你没有为容器指定 CPU 限制,则会发生以下情况之一:
* 容器在可以使用的 CPU 资源上没有上限。因而可以使用所在节点上所有的可用 CPU 资源。
* 容器在具有默认 CPU 限制的名字空间中运行,系统会自动为容器设置默认限制。
集群管理员可以使用
[LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core/)
指定 CPU 限制的默认值。
<!--
## If you specify a CPU limit but do not specify a CPU request
If you specify a CPU limit for a Container but do not specify a CPU request, Kubernetes automatically
assigns a CPU request that matches the limit. Similarly, if a Container specifies its own memory limit,
but does not specify a memory request, Kubernetes automatically assigns a memory request that matches
the limit.
-->
## 如果你设置了 CPU 限制但未设置 CPU 请求
如果你为容器指定了 CPU 限制值但未为其设置 CPU 请求,Kubernetes 会自动为其
设置与 CPU 限制相同的 CPU 请求值。类似的,如果容器设置了内存限制值但未设置
内存请求值,Kubernetes 也会为其设置与内存限制值相同的内存请求。
<!--
## Motivation for CPU requests and limits
By configuring the CPU requests and limits of the Containers that run in your
cluster, you can make efficient use of the CPU resources available on your cluster
Nodes. By keeping a Pod CPU request low, you give the Pod a good chance of being
scheduled. By having a CPU limit that is greater than the CPU request, you accomplish two things:
* The Pod can have bursts of activity where it makes use of CPU resources that happen to be available.
* The amount of CPU resources a Pod can use during a burst is limited to some reasonable amount.
-->
## CPU 请求和限制的初衷
通过配置你的集群中运行的容器的 CPU 请求和限制,你可以有效利用集群上可用的 CPU 资源。
通过将 Pod CPU 请求保持在较低水平,可以使 Pod 更有机会被调度。
通过使 CPU 限制大于 CPU 请求,你可以完成两件事:
* Pod 可能会有突发性的活动,它可以利用碰巧可用的 CPU 资源。
* Pod 在突发负载期间可以使用的 CPU 资源数量仍被限制为合理的数量。
<!--
## Clean up
Delete your namespace:
-->
## 清理
删除名称空间:
```shell
kubectl delete namespace cpu-example
```
## {{% heading "whatsnext" %}}
<!--
### For app developers
* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/)
-->
### 针对应用开发者
* [将内存资源分配给容器和 Pod](/zh/docs/tasks/configure-pod-container/assign-memory-resource/)
* [配置 Pod 服务质量](/zh/docs/tasks/configure-pod-container/quality-service-pod/)
<!--
### For cluster administrators
* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/memory-default-namespace/)
* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/cpu-default-namespace/)
* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/)
* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/)
* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)
* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/)
* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
-->
### 针对集群管理员
* [配置名称空间的默认内存请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/)
* [为名字空间配置默认 CPU 请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/)
* [为名字空间配置最小和最大内存限制](/zh/docs/tasks/administer-cluster//manage-resources/memory-constraint-namespace/)
* [为名字空间配置最小和最大 CPU 约束](/zh/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)
* [为名字空间配置内存和 CPU 配额](/zh/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)
* [为名字空间配置 Pod 配额](/zh/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/)
* [配置 API 对象的配额](/zh/docs/tasks/administer-cluster/quota-api-object/)
@@ -0,0 +1,557 @@
---
title: 为容器和 Pod 分配内存资源
content_type: task
weight: 10
---
<!--
title: Assign Memory Resources to Containers and Pods
content_type: task
weight: 10
-->
<!-- overview -->
<!--
This page shows how to assign a memory *request* and a memory *limit* to a
Container. A Container is guaranteed to have as much memory as it requests,
but is not allowed to use more memory than its limit.
-->
此页面展示如何将内存 *请求* request)和内存 *限制* limit)分配给一个容器。
我们保障容器拥有它请求数量的内存,但不允许使用超过限制数量的内存。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!--
Each node in your cluster must have at least 300 MiB of memory.
-->
你集群中的每个节点必须拥有至少 300 MiB 的内存。
<!--
A few of the steps on this page require you to run the
[metrics-server](https://github.com/kubernetes-sigs/metrics-server)
service in your cluster. If you have the metrics-server
running, you can skip those steps.
-->
该页面上的一些步骤要求你在集群中运行
[metrics-server](https://github.com/kubernetes-sigs/metrics-server) 服务。
如果你已经有在运行中的 metrics-server,则可以跳过这些步骤。
<!--
If you are running Minikube, run the following command to enable the
metrics-server:
-->
如果你运行的是 Minikube,可以运行下面的命令启用 metrics-server
```shell
minikube addons enable metrics-server
```
<!--
To see whether the metrics-server is running, or another provider of the resource metrics
API (`metrics.k8s.io`), run the following command:
-->
要查看 metrics-server 或资源指标 API (`metrics.k8s.io`) 是否已经运行,请运行以下命令:
```shell
kubectl get apiservices
```
<!--
If the resource metrics API is available, the output includes a
reference to `metrics.k8s.io`.
-->
如果资源指标 API 可用,则输出结果将包含对 `metrics.k8s.io` 的引用信息。
```
NAME
v1beta1.metrics.k8s.io
```
<!-- steps -->
<!--
## Create a namespace
Create a namespace so that the resources you create in this exercise are
isolated from the rest of your cluster.
-->
## 创建命名空间 {#create-a-namespace}
创建一个命名空间,以便将本练习中创建的资源与集群的其余部分隔离。
```shell
kubectl create namespace mem-example
```
<!--
## Specify a memory request and a memory limit
To specify a memory request for a Container, include the `resources:requests` field
in the Container's resource manifest. To specify a memory limit, include `resources:limits`.
In this exercise, you create a Pod that has one Container. The Container has a memory
request of 100 MiB and a memory limit of 200 MiB. Here's the configuration file
for the Pod:
-->
## 指定内存请求和限制 {#specify-a-memory-request-and-a-memory-limit}
要为容器指定内存请求,请在容器资源清单中包含 `resourcesrequests` 字段。
同理,要指定内存限制,请包含 `resourceslimits`
在本练习中,你将创建一个拥有一个容器的 Pod。
容器将会请求 100 MiB 内存,并且内存会被限制在 200 MiB 以内。
这是 Pod 的配置文件:
{{< codenew file="pods/resource/memory-request-limit.yaml" >}}
<!--
The `args` section in the configuration file provides arguments for the Container when it starts.
The `"--vm-bytes", "150M"` arguments tell the Container to attempt to allocate 150 MiB of memory.
Create the Pod:
-->
配置文件的 `args` 部分提供了容器启动时的参数。
`"--vm-bytes", "150M"` 参数告知容器尝试分配 150 MiB 内存。
开始创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
```
<!--
Verify that the Pod Container is running:
-->
验证 Pod 中的容器是否已运行:
```shell
kubectl get pod memory-demo --namespace=mem-example
```
<!--
View detailed information about the Pod:
-->
查看 Pod 相关的详细信息:
```shell
kubectl get pod memory-demo --output=yaml --namespace=mem-example
```
<!--
The output shows that the one Container in the Pod has a memory request of 100 MiB
and a memory limit of 200 MiB.
-->
输出结果显示:该 Pod 中容器的内存请求为 100 MiB,内存限制为 200 MiB。
```yaml
...
resources:
requests:
memory: 100Mi
limits:
memory: 200Mi
...
```
<!--
Run `kubectl top` to fetch the metrics for the pod:
-->
运行 `kubectl top` 命令,获取该 Pod 的指标数据:
```shell
kubectl top pod memory-demo --namespace=mem-example
```
<!--
The output shows that the Pod is using about 162,900,000 bytes of memory, which
is about 150 MiB. This is greater than the Pod's 100 MiB request, but within the
Pod's 200 MiB limit.
-->
输出结果显示:Pod 正在使用的内存大约为 162,900,000 字节,约为 150 MiB。
这大于 Pod 请求的 100 MiB,但在 Pod 限制的 200 MiB之内。
```
NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960
```
<!--
Delete your Pod:
-->
删除 Pod
```shell
kubectl delete pod memory-demo --namespace=mem-example
```
<!--
## Exceed a Container's memory limit
A Container can exceed its memory request if the Node has memory available. But a Container
is not allowed to use more than its memory limit. If a Container allocates more memory than
its limit, the Container becomes a candidate for termination. If the Container continues to
consume memory beyond its limit, the Container is terminated. If a terminated Container can be
restarted, the kubelet restarts it, as with any other type of runtime failure.
-->
## 超过容器限制的内存 {#exceed-a-container-s-memory-limit}
当节点拥有足够的可用内存时,容器可以使用其请求的内存。
但是,容器不允许使用超过其限制的内存。
如果容器分配的内存超过其限制,该容器会成为被终止的候选容器。
如果容器继续消耗超出其限制的内存,则终止容器。
如果终止的容器可以被重启,则 kubelet 会重新启动它,就像其他任何类型的运行时失败一样。
<!--
In this exercise, you create a Pod that attempts to allocate more memory than its limit.
Here is the configuration file for a Pod that has one Container with a
memory request of 50 MiB and a memory limit of 100 MiB:
-->
在本练习中,你将创建一个 Pod,尝试分配超出其限制的内存。
这是一个 Pod 的配置文件,其拥有一个容器,该容器的内存请求为 50 MiB,内存限制为 100 MiB
{{< codenew file="pods/resource/memory-request-limit-2.yaml" >}}
<!--
In the `args` section of the configuration file, you can see that the Container
will attempt to allocate 250 MiB of memory, which is well above the 100 MiB limit.
Create the Pod:
-->
在配置文件的 `args` 部分中,你可以看到容器会尝试分配 250 MiB 内存,这远高于 100 MiB 的限制。
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
```
<!--
View detailed information about the Pod:
-->
查看 Pod 相关的详细信息:
```shell
kubectl get pod memory-demo-2 --namespace=mem-example
```
<!--
At this point, the Container might be running or killed. Repeat the preceding command until the Container is killed:
-->
此时,容器可能正在运行或被杀死。重复前面的命令,直到容器被杀掉:
```shell
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
```
<!--
Get a more detailed view of the Container status:
-->
获取容器更详细的状态信息:
```shell
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
```
<!--
The output shows that the Container was killed because it is out of memory (OOM):
-->
输出结果显示:由于内存溢出(OOM),容器已被杀掉:
```yaml
lastState:
terminated:
containerID: 65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null
```
<!--
The Container in this exercise can be restarted, so the kubelet restarts it. Repeat
this command several times to see that the Container is repeatedly killed and restarted:
-->
本练习中的容器可以被重启,所以 kubelet 会重启它。
多次运行下面的命令,可以看到容器在反复的被杀死和重启:
```shell
kubectl get pod memory-demo-2 --namespace=mem-example
```
<!--
The output shows that the Container is killed, restarted, killed again, restarted again, and so on:
-->
输出结果显示:容器被杀掉、重启、再杀掉、再重启……:
```
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
```
```
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s
```
<!--
View detailed information about the Pod history:
-->
查看关于该 Pod 历史的详细信息:
```
kubectl describe pod memory-demo-2 --namespace=mem-example
```
<!--
The output shows that the Container starts and fails repeatedly:
-->
输出结果显示:该容器反复的在启动和失败:
```
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container
```
<!--
View detailed information about your cluster's Nodes:
-->
查看关于集群节点的详细信息:
```
kubectl describe nodes
```
<!--
The output includes a record of the Container being killed because of an out-of-memory condition:
-->
输出结果包含了一条练习中的容器由于内存溢出而被杀掉的记录:
```
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
```
<!--
Delete your Pod:
-->
删除 Pod:
```shell
kubectl delete pod memory-demo-2 --namespace=mem-example
```
<!--
## Specify a memory request that is too big for your Nodes
Memory requests and limits are associated with Containers, but it is useful to think
of a Pod as having a memory request and limit. The memory request for the Pod is the
sum of the memory requests for all the Containers in the Pod. Likewise, the memory
limit for the Pod is the sum of the limits of all the Containers in the Pod.
-->
## 超过整个节点容量的内存 {#specify-a-memory-request-that-is-too-big-for-your-nodes}
内存请求和限制是与容器关联的,但将 Pod 视为具有内存请求和限制,也是很有用的。
Pod 的内存请求是 Pod 中所有容器的内存请求之和。
同理,Pod 的内存限制是 Pod 中所有容器的内存限制之和。
<!--
Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if the Node
has enough available memory to satisfy the Pod's memory request.
In this exercise, you create a Pod that has a memory request so big that it exceeds the
capacity of any Node in your cluster. Here is the configuration file for a Pod that has one
Container with a request for 1000 GiB of memory, which likely exceeds the capacity
of any Node in your cluster.
-->
Pod 的调度基于请求。只有当节点拥有足够满足 Pod 内存请求的内存时,才会将 Pod 调度至节点上运行。
在本练习中,你将创建一个 Pod,其内存请求超过了你集群中的任意一个节点所拥有的内存。
这是该 Pod 的配置文件,其拥有一个请求 1000 GiB 内存的容器,这应该超过了你集群中任何节点的容量。
{{< codenew file="pods/resource/memory-request-limit-3.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
```
<!--
View the Pod status:
-->
查看 Pod 状态:
```shell
kubectl get pod memory-demo-3 --namespace=mem-example
```
<!--
The output shows that the Pod status is PENDING. That is, the Pod is not scheduled to run on any Node, and it will remain in the PENDING state indefinitely:
-->
输出结果显示:Pod 处于 PENDING 状态。
这意味着,该 Pod 没有被调度至任何节点上运行,并且它会无限期的保持该状态:
```
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
```
<!--
View detailed information about the Pod, including events:
-->
查看关于 Pod 的详细信息,包括事件:
```shell
kubectl describe pod memory-demo-3 --namespace=mem-example
```
<!--
The output shows that the Container cannot be scheduled because of insufficient memory on the Nodes:
-->
输出结果显示:由于节点内存不足,该容器无法被调度:
```
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
```
<!--
## Memory units
The memory resource is measured in bytes. You can express memory as a plain integer or a
fixed-point integer with one of these suffixes: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.
For example, the following represent approximately the same value:
-->
## 内存单位 {#memory-units}
内存资源的基本单位是字节(byte)。你可以使用这些后缀之一,将内存表示为
纯整数或定点整数:E、P、T、G、M、K、Ei、Pi、Ti、Gi、Mi、Ki。
例如,下面是一些近似相同的值:
```
128974848, 129e6, 129M, 123Mi
```
<!--
Delete your Pod:
-->
删除 Pod
```shell
kubectl delete pod memory-demo-3 --namespace=mem-example
```
<!--
## If you do not specify a memory limit
If you do not specify a memory limit for a Container, one of the following situations applies:
-->
## 如果你没有指定内存限制 {#if-you-do-not-specify-a-memory-limit}
如果你没有为一个容器指定内存限制,则自动遵循以下情况之一:
<!--
* The Container has no upper bound on the amount of memory it uses. The Container
could use all of the memory available on the Node where it is running which in turn could invoke the OOM Killer. Further, in case of an OOM Kill, a container with no resource limits will have a greater chance of being killed.
* The Container is running in a namespace that has a default memory limit, and the
Container is automatically assigned the default limit. Cluster administrators can use a
[LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core)
to specify a default value for the memory limit.
-->
* 容器可无限制地使用内存。容器可以使用其所在节点所有的可用内存,
进而可能导致该节点调用 OOM Killer。
此外,如果发生 OOM Kill,没有资源限制的容器将被杀掉的可行性更大。
* 运行的容器所在命名空间有默认的内存限制,那么该容器会被自动分配默认限制。
集群管理员可用使用 [LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core)
来指定默认的内存限制。
<!--
## Motivation for memory requests and limits
By configuring memory requests and limits for the Containers that run in your
cluster, you can make efficient use of the memory resources available on your cluster's
Nodes. By keeping a Pod's memory request low, you give the Pod a good chance of being
scheduled. By having a memory limit that is greater than the memory request, you accomplish two things:
-->
## 内存请求和限制的目的 {#motivation-for-memory-requests-and-limits}
通过为集群中运行的容器配置内存请求和限制,你可以有效利用集群节点上可用的内存资源。
通过将 Pod 的内存请求保持在较低水平,你可以更好地安排 Pod 调度。
通过让内存限制大于内存请求,你可以完成两件事:
<!--
* The Pod can have bursts of activity where it makes use of memory that happens to be available.
* The amount of memory a Pod can use during a burst is limited to some reasonable amount.
-->
* Pod 可以进行一些突发活动,从而更好的利用可用内存。
* Pod 在突发活动期间,可使用的内存被限制为合理的数量。
<!--
## Clean up
Delete your namespace. This deletes all the Pods that you created for this task:
-->
## 清理 {#clean-up}
删除命名空间。下面的命令会删除你根据这个任务创建的所有 Pod:
```shell
kubectl delete namespace mem-example
```
## {{% heading "whatsnext" %}}
<!--
### For app developers
* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)
* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/)
-->
### 应用开发者扩展阅读 {#for-app-developers}
* [为容器和 Pod 分配 CPU 资源](/zh/docs/tasks/configure-pod-container/assign-cpu-resource/)
* [配置 Pod 的服务质量](/zh/docs/tasks/configure-pod-container/quality-service-pod/)
<!--
### For cluster administrators
* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/)
* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/)
* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/manage-resources/memory-constraint-namespace/)
* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)
* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)
* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/)
* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
-->
### 集群管理员扩展阅读 {#for-cluster-administrators}
* [为命名空间配置默认的内存请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/)
* [为命名空间配置默认的 CPU 请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/)
* [配置命名空间的最小和最大内存约束](/zh/docs/tasks/administer-cluster/manage-resources/memory-constraint-namespace/)
* [配置命名空间的最小和最大 CPU 约束](/zh/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)
* [为命名空间配置内存和 CPU 配额](/zh/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)
* [配置命名空间下 Pod 总数](/zh/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/)
* [配置 API 对象配额](/zh/docs/tasks/administer-cluster/quota-api-object/)
@@ -0,0 +1,186 @@
---
title: 用节点亲和性把 Pods 分配到节点
min-kubernetes-server-version: v1.10
content_type: task
weight: 120
---
<!--
title: Assign Pods to Nodes using Node Affinity
min-kubernetes-server-version: v1.10
content_type: task
weight: 120
-->
<!-- overview -->
<!--
This page shows how to assign a Kubernetes Pod to a particular node using Node Affinity in a
Kubernetes cluster.
-->
本页展示在 Kubernetes 集群中,如何使用节点亲和性把 Kubernetes Pod 分配到特定节点。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Add a label to a node
1. List the nodes in your cluster, along with their labels:
-->
## 给节点添加标签
1. 列出集群中的节点及其标签:
```shell
kubectl get nodes --show-labels
```
<!--
The output is similar to this:
-->
输出类似于此:
```
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
```
<!--
1. Chose one of your nodes, and add a label to it:
-->
1. 选择一个节点,给它添加一个标签:
```shell
kubectl label nodes <your-node-name> disktype=ssd
```
<!--
where `<your-node-name>` is the name of your chosen node.
1. Verify that your chosen node has a `disktype=ssd` label:
-->
其中 `<your-node-name>` 是你所选节点的名称。
2. 验证你所选节点具有 `disktype=ssd` 标签:
```shell
kubectl get nodes --show-labels
```
<!--
The output is similar to this:
-->
输出类似于此:
```
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
```
<!--
In the preceding output, you can see that the `worker0` node has a
`disktype=ssd` label.
-->
在前面的输出中,可以看到 `worker0` 节点有一个 `disktype=ssd` 标签。
<!--
## Schedule a Pod using required node affinity
This manifest describes a Pod that has a `requiredDuringSchedulingIgnoredDuringExecution` node affinity,`disktype: ssd`.
This means that the pod will get scheduled only on a node that has a `disktype=ssd` label.
-->
## 依据强制的节点亲和性调度 Pod {#schedule-a-Pod-using-required-node-affinity}
下面清单描述了一个 Pod,它有一个节点亲和性配置 `requiredDuringSchedulingIgnoredDuringExecution``disktype=ssd`。
这意味着 pod 只会被调度到具有 `disktype=ssd` 标签的节点上。
{{< codenew file="pods/pod-nginx-required-affinity.yaml" >}}
<!--
1. Apply the manifest to create a Pod that is scheduled onto your
chosen node:
-->
1. 执行(Apply)此清单来创建一个调度到所选节点上的 Pod:
```shell
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml
```
<!--
1. Verify that the pod is running on your chosen node:
-->
1. 验证 pod 已经在所选节点上运行:
```shell
kubectl get pods --output=wide
```
<!--
The output is similar to this:
-->
输出类似于此:
```
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
```
<!--
## Schedule a Pod using preferred node affinity
This manifest describes a Pod that has a `preferredDuringSchedulingIgnoredDuringExecution` node affinity,`disktype: ssd`.
This means that the pod will prefer a node that has a `disktype=ssd` label.
-->
## 使用首选的节点亲和性调度 Pod {#schedule-a-Pod-using-preferred-node-affinity}
本清单描述了一个Pod,它有一个节点亲和性设置 `preferredDuringSchedulingIgnoredDuringExecution``disktype: ssd`。
这意味着 pod 将首选具有 `disktype=ssd` 标签的节点。
{{< codenew file="pods/pod-nginx-preferred-affinity.yaml" >}}
<!--
1. Apply the manifest to create a Pod that is scheduled onto your
chosen node:
-->
1. 执行此清单创建一个会调度到所选节点上的 Pod:
```shell
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-preferred-affinity.yaml
```
<!--
1. Verify that the pod is running on your chosen node:
-->
1. 验证 pod 是否在所选节点上运行:
```shell
kubectl get pods --output=wide
```
<!--
The output is similar to this:
-->
输出类似于此:
```
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
```
## {{% heading "whatsnext" %}}
<!--
Learn more about
[Node Affinity](/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity).
-->
进一步了解
[节点亲和性](/zh/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity).
@@ -0,0 +1,138 @@
---
title: 将 Pod 分配给节点
content_type: task
weight: 120
---
<!--
title: Assign Pods to Nodes
content_type: task
weight: 120
-->
<!-- overview -->
<!--
This page shows how to assign a Kubernetes Pod to a particular node in a
Kubernetes cluster.
-->
此页面显示如何将 Kubernetes Pod 分配给 Kubernetes 集群中的特定节点。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Add a label to a node
1. List the nodes in your cluster:
-->
## 给节点添加标签
1. 列出集群中的节点
```shell
kubectl get nodes
```
<!-- The output is similar to this: -->
输出类似如下:
```
NAME STATUS AGE VERSION
worker0 Ready 1d v1.6.0+fff5156
worker1 Ready 1d v1.6.0+fff5156
worker2 Ready 1d v1.6.0+fff5156
```
<!--
1. Chose one of your nodes, and add a label to it:
-->
2. 选择其中一个节点,为它添加标签:
```shell
kubectl label nodes <your-node-name> disktype=ssd
```
<!--
where `<your-node-name>` is the name of your chosen node.
-->
`<your-node-name>` 是你选择的节点的名称。
<!--
1. Verify that your chosen node has a `disktype=ssd` label:
-->
3. 验证你选择的节点是否有 `disktype=ssd` 标签:
```shell
kubectl get nodes --show-labels
```
<!--
The output is similar to this:
-->
输出类似如下:
```
NAME STATUS AGE VERSION LABELS
worker0 Ready 1d v1.6.0+fff5156 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready 1d v1.6.0+fff5156 ...,kubernetes.io/hostname=worker1
worker2 Ready 1d v1.6.0+fff5156 ...,kubernetes.io/hostname=worker2
```
<!--
In the preceding output, you can see that the `worker0` node has a
`disktype=ssd` label.
-->
在前面的输出中,你可以看到 `worker0` 节点有 `disktype=ssd` 标签。
<!--
## Create a pod that gets scheduled to your chosen node
This pod configuration file describes a pod that has a node selector,
`disktype: ssd`. This means that the pod will get scheduled on a node that has
a `disktype=ssd` label.
-->
## 创建一个调度到你选择的节点的 pod
此 Pod 配置文件描述了一个拥有节点选择器 `disktype: ssd` 的 Pod。这表明该 Pod 将被调度到
有 `disktype=ssd` 标签的节点。
{{< codenew file="pods/pod-nginx.yaml" >}}
<!--
1. Use the configuration file to create a pod that will get scheduled on your
chosen node:
-->
1. 使用该配置文件去创建一个 pod,该 pod 将被调度到你选择的节点上:
```shell
kubectl create -f https://k8s.io/examples/pods/pod-nginx.yaml
```
<!--
1. Verify that the pod is running on your chosen node:
-->
2. 验证 pod 是不是运行在你选择的节点上:
```shell
kubectl get pods --output=wide
```
<!-- The output is similar to this: -->
输出类似如下:
```
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
```
## {{% heading "whatsnext" %}}
<!--
Learn more about
[labels and selectors](/docs/concepts/overview/working-with-objects/labels/).
-->
进一步了解[标签和选择器](/zh/docs/concepts/overview/working-with-objects/labels/)
@@ -0,0 +1,164 @@
---
title: 为容器的生命周期事件设置处理函数
content_type: task
weight: 140
---
<!--
title: Attach Handlers to Container Lifecycle Events
content_type: task
weight: 140
-->
<!-- overview -->
<!--
This page shows how to attach handlers to Container lifecycle events. Kubernetes supports
the postStart and preStop events. Kubernetes sends the postStart event immediately
after a Container is started, and it sends the preStop event immediately before the
Container is terminated.A Container may specify one handler per event.
-->
这个页面将演示如何为容器的生命周期事件挂接处理函数。Kubernetes 支持 postStart 和 preStop 事件。
当一个容器启动后,Kubernetes 将立即发送 postStart 事件;在容器被终结之前,
Kubernetes 将发送一个 preStop 事件。容器可以为每个事件指定一个处理程序。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Define postStart and preStop handlers
In this exercise, you create a Pod that has one Container. The Container has handlers
for the postStart and preStop events.
-->
## 定义 postStart 和 preStop 处理函数
在本练习中,你将创建一个包含一个容器的 Pod,该容器为 postStart 和 preStop 事件提供对应的处理函数。
<!--
Here is the configuration file for the Pod:
-->
下面是对应 Pod 的配置文件:
{{< codenew file="pods/lifecycle-events.yaml" >}}
<!--
In the configuration file, you can see that the postStart command writes a `message`
file to the Container's `/usr/share` directory. The preStop command shuts down
nginx gracefully. This is helpful if the Container is being terminated because of a failure.
-->
在上述配置文件中,你可以看到 postStart 命令在容器的 `/usr/share` 目录下写入文件 `message`
命令 preStop 负责优雅地终止 nginx 服务。当因为失效而导致容器终止时,这一处理方式很有用。
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/lifecycle-events.yaml
```
<!--
Verify that the Container in the Pod is running:
-->
验证 Pod 中的容器已经运行:
```shell
kubectl get pod lifecycle-demo
```
<!--
Get a shell into the Container running in your Pod:
-->
使用 shell 连接到你的 Pod 里的容器:
```
kubectl exec -it lifecycle-demo -- /bin/bash
```
<!--
In your shell, verify that the `postStart` handler created the `message` file:
-->
在 shell 中,验证 `postStart` 处理函数创建了 `message` 文件:
```
root@lifecycle-demo:/# cat /usr/share/message
```
<!--
The output shows the text written by the postStart handler:
-->
命令行输出的是 `postStart` 处理函数所写入的文本
```
Hello from the postStart handler
```
<!-- discussion -->
<!--
## Discussion
Kubernetes sends the postStart event immediately after the Container is created.
There is no guarantee, however, that the postStart handler is called before
the Container's entrypoint is called. The postStart handler runs asynchronously
relative to the Container's code, but Kubernetes' management of the container
blocks until the postStart handler completes. The Container's status is not
set to RUNNING until the postStart handler completes.
-->
## 讨论
Kubernetes 在容器创建后立即发送 postStart 事件。
然而,postStart 处理函数的调用不保证早于容器的入口点(entrypoint)
的执行。postStart 处理函数与容器的代码是异步执行的,但 Kubernetes
的容器管理逻辑会一直阻塞等待 postStart 处理函数执行完毕。
只有 postStart 处理函数执行完毕,容器的状态才会变成
RUNNING。
<!--
Kubernetes sends the preStop event immediately before the Container is terminated.
Kubernetes' management of the Container blocks until the preStop handler completes,
unless the Pod's grace period expires. For more details, see
[Termination of Pods](/docs/user-guide/pods/#termination-of-pods).
-->
Kubernetes 在容器结束前立即发送 preStop 事件。除非 Pod 宽限期限超时,Kubernetes 的容器管理逻辑
会一直阻塞等待 preStop 处理函数执行完毕。更多的相关细节,可以参阅
[Pods 的结束](/zh/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination)。
<!--
Kubernetes only sends the preStop event when a Pod is *terminated*.
This means that the preStop hook is not invoked when the Pod is *completed*.
This limitation is tracked in [issue #55087](https://github.com/kubernetes/kubernetes/issues/55807).
-->
{{< note >}}
Kubernetes 只有在 Pod *结束(Terminated* 的时候才会发送 preStop 事件,
这意味着在 Pod *完成(Completed*
preStop 的事件处理逻辑不会被触发。这个限制在
[issue #55087](https://github.com/kubernetes/kubernetes/issues/55807) 中被追踪。
{{< /note >}}
## {{% heading "whatsnext" %}}
<!--
* Learn more about [Container lifecycle hooks](/docs/concepts/containers/container-lifecycle-hooks/).
* Learn more about the [lifecycle of a Pod](/docs/concepts/workloads/pods/pod-lifecycle/).
-->
* 进一步了解[容器生命周期回调](/zh/docs/concepts/containers/container-lifecycle-hooks/)。
* 进一步了解[Pod 的生命周期](/zh/docs/concepts/workloads/pods/pod-lifecycle/)。
<!--
### Reference
* [Lifecycle](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#lifecycle-v1-core)
* [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
* See `terminationGracePeriodSeconds` in [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)
-->
### 参考
* [Lifecycle](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#lifecycle-v1-core)
* [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
* 参阅 [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) 中关于`terminationGracePeriodSeconds` 的部分
@@ -0,0 +1,500 @@
---
title: 为 Windows Pod 和容器配置 GMSA
content_type: task
weight: 20
---
<!--
title: Configure GMSA for Windows Pods and containers
content_type: task
weight: 20
-->
<!-- overview -->
{{< feature-state for_k8s_version="v1.18" state="stable" >}}
<!--
This page shows how to configure [Group Managed Service Accounts](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview) (GMSA) for Pods and containers that will run on Windows nodes. Group Managed Service Accounts are a specific type of Active Directory account that provides automatic password management, simplified service principal name (SPN) management, and the ability to delegate the management to other administrators across multiple servers.
-->
本页展示如何为将运行在 Windows 节点上的 Pod 和容器配置
[组管理的服务账号(Group Managed Service AccountsGMSA](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview)。
组管理的服务账号是活动目录(Active Directory)的一种特殊类型,提供自动化的
密码管理、简化的服务主体名称(Service Principal NameSPN)管理以及跨多个
服务器将管理操作委派给其他管理员等能力。
<!--
In Kubernetes, GMSA credential specs are configured at a Kubernetes cluster-wide scope as Custom Resources. Windows Pods, as well as individual containers within a Pod, can be configured to use a GMSA for domain based functions (e.g. Kerberos authentication) when interacting with other Windows services.
-->
在 Kubernetes 环境中,GMSA 凭据规约配置为 Kubernetes 集群范围的自定义资源
Custom Resources)形式。Windows Pod 以及各 Pod 中的每个容器可以配置为
使用 GMSA 来完成基于域(Domain)的操作(例如,Kerberos 身份认证),以便
与其他 Windows 服务相交互。
## {{% heading "prerequisites" %}}
<!--
You need to have a Kubernetes cluster and the `kubectl` command-line tool must be configured to communicate with your cluster. The cluster is expected to have Windows worker nodes. This section covers a set of initial steps required once for each cluster:
-->
你需要一个 Kubernetes 集群,以及 `kubectl` 命令行工具,且工具必须已配置
为能够与你的集群通信。集群预期包含 Windows 工作节点。
本节讨论需要为每个集群执行一次的初始操作。
<!--
### Install the GMSACredentialSpec CRD
A [CustomResourceDefinition](/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)(CRD) for GMSA credential spec resources needs to be configured on the cluster to define the custom resource type `GMSACredentialSpec`. Download the GMSA CRD [YAML](https://github.com/kubernetes-sigs/windows-gmsa/blob/master/admission-webhook/deploy/gmsa-crd.yml) and save it as gmsa-crd.yaml.
Next, install the CRD with `kubectl apply -f gmsa-crd.yaml`
-->
### 安装 GMSACredentialSpec CRD
你需要在集群上配置一个用于 GMSA 凭据规约资源的
[CustomResourceDefinition](/zh/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)(CRD)
以便定义类型为 `GMSACredentialSpec` 的自定义资源。
首先下载 GMSA CRD [YAML](https://github.com/kubernetes-sigs/windows-gmsa/blob/master/admission-webhook/deploy/gmsa-crd.yml)
并将其保存为 `gmsa-crd.yaml`。接下来执行 `kubectl apply -f gmsa-crd.yaml`
安装 CRD。
<!--
### Install webhooks to validate GMSA users
Two webhooks need to be configured on the Kubernetes cluster to populate and validate GMSA credential spec references at the Pod or container level:
1. A mutating webhook that expands references to GMSAs (by name from a Pod specification) into the full credential spec in JSON form within the Pod spec.
1. A validating webhook ensures all references to GMSAs are authorized to be used by the Pod service account.
-->
### 安装 Webhook 来验证 GMSA 用户
你需要为 Kubernetes 集群配置两个 Webhook,在 Pod 或容器级别填充和检查
GMSA 凭据规约引用。
1. 一个修改模式(Mutating)的 Webhook,将对 GMSA 的引用(在 Pod 规约中体现为名字)
展开为完整凭据规约的 JSON 形式,并保存回 Pod 规约中。
1. 一个验证模式(Validating)的 Webhook,确保对 GMSA 的所有引用都是已经授权
给 Pod 的服务账号使用的。
<!--
Installing the above webhooks and associated objects require the steps below:
1. Create a certificate key pair (that will be used to allow the webhook container to communicate to the cluster)
1. Install a secret with the certificate from above.
1. Create a deployment for the core webhook logic.
1. Create the validating and mutating webhook configurations referring to the deployment.
-->
安装以上 Webhook 及其相关联的对象需要执行以下步骤:
1. 创建一个证书密钥对(用于允许 Webhook 容器与集群通信)
1. 安装一个包含如上证书的 Secret
1. 创建一个包含核心 Webhook 逻辑的 Deployment
1. 创建引用该 Deployment 的 Validating Webhook 和 Mutating Webhook 配置
<!--
A [script](https://github.com/kubernetes-sigs/windows-gmsa/blob/master/admission-webhook/deploy/deploy-gmsa-webhook.sh) can be used to deploy and configure the GMSA webhooks and associated objects mentioned above. The script can be run with a `-dry-run=server` option to allow you to review the changes that would be made to your cluster.
The [YAML template](https://github.com/kubernetes-sigs/windows-gmsa/blob/master/admission-webhook/deploy/gmsa-webhook.yml.tpl) used by the script may also be used to deploy the webhooks and associated objects manually (with appropriate substitutions for the parameters)
-->
你可以使用[这个脚本](https://github.com/kubernetes-sigs/windows-gmsa/blob/master/admission-webhook/deploy/deploy-gmsa-webhook.sh)
来部署和配置上述 GMSA Webhook 及相关联的对象。你还可以在运行脚本时设置 `--dry-run=server`
选项以便审查脚本将会对集群做出的变更。
脚本所使用的[YAML 模板](https://github.com/kubernetes-sigs/windows-gmsa/blob/master/admission-webhook/deploy/gmsa-webhook.yml.tpl)
也可用于手动部署 Webhook 及相关联的对象,不过需要对其中的参数作适当替换。
<!-- steps -->
<!--
## Configure GMSAs and Windows nodes in Active Directory
Before Pods in Kubernetes can be configured to use GMSAs, the desired GMSAs need to be provisioned in Active Directory as described in the [Windows GMSA documentation](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/getting-started-with-group-managed-service-accounts#BKMK_Step1). Windows worker nodes (that are part of the Kubernetes cluster) need to be configured in Active Directory to access the secret credentials associated with the desired GMSA as described in the [Windows GMSA documentation](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/getting-started-with-group-managed-service-accounts#to-add-member-hosts-using-the-set-adserviceaccount-cmdlet)
-->
## 在活动目录中配置 GMSA 和 Windows 节点
在配置 Kubernetes 中的 Pod 以使用 GMSA 之前,需要按
[Windows GMSA 文档](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/getting-started-with-group-managed-service-accounts#BKMK_Step1)
中描述的那样先在活动目录中准备好期望的 GMSA。
Windows 工作节点(作为 Kubernetes 集群的一部分)需要被配置到活动目录中,以便
访问与期望的 GSMA 相关联的秘密凭据数据。这一操作的描述位于
[Windows GMSA 文档](https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/getting-started-with-group-managed-service-accounts#to-add-member-hosts-using-the-set-adserviceaccount-cmdlet)
中。
<!--
## Create GMSA credential spec resources
With the GMSACredentialSpec CRD installed (as described earlier), custom resources containing GMSA credential specs can be configured. The GMSA credential spec does not contain secret or sensitive data. It is information that a container runtime can use to describe the desired GMSA of a container to Windows. GMSA credential specs can be generated in YAML format with a utility [PowerShell script](https://github.com/kubernetes-sigs/windows-gmsa/tree/master/scripts/GenerateCredentialSpecResource.ps1).
-->
## 创建 GMSA 凭据规约资源
当(如前所述)安装了 GMSACredentialSpec CRD 之后,你就可以配置包含 GMSA 凭据
规约的自定义资源了。GMSA 凭据规约中并不包含秘密或敏感数据。
其中包含的信息主要用于容器运行时,便于后者向 Windows 描述容器所期望的 GMSA。
GMSA 凭据规约可以使用
[PowerShell 脚本](https://github.com/kubernetes-sigs/windows-gmsa/tree/master/scripts/GenerateCredentialSpecResource.ps1)
以 YAML 格式生成。
<!--
Following are the steps for generating a GMSA credential spec YAML manually in JSON format and then converting it:
1. Import the CredentialSpec [module](https://github.com/MicrosoftDocs/Virtualization-Documentation/blob/live/windows-server-container-tools/ServiceAccounts/CredentialSpec.psm1): `ipmo CredentialSpec.psm1`
1. Create a credential spec in JSON format using `New-CredentialSpec`. To create a GMSA credential spec named WebApp1, invoke `New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)`
1. Use `Get-CredentialSpec` to show the path of the JSON file.
1. Convert the credspec file from JSON to YAML format and apply the necessary header fields `apiVersion`, `kind`, `metadata` and `credspec` to make it a GMSACredentialSpec custom resource that can be configured in Kubernetes.
-->
下面是手动以 JSON 格式生成 GMSA 凭据规约并对其进行 YAML 转换的步骤:
1. 导入 CredentialSpec [模块](https://github.com/MicrosoftDocs/Virtualization-Documentation/blob/live/windows-server-container-tools/ServiceAccounts/CredentialSpec.psm1): `ipmo CredentialSpec.psm1`
1. 使用 `New-CredentialSpec` 来创建一个 JSON 格式的凭据规约。
要创建名为 `WebApp1` 的 GMSA 凭据规约,调用
`New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)`
1. 使用 `Get-CredentialSpec` 来显示 JSON 文件的路径。
1. 将凭据规约从 JSON 格式转换为 YAML 格式,并添加必要的头部字段
`apiVersion``kind``metadata``credspec`,使其成为一个可以在
Kubernetes 中配置的 GMSACredentialSpec 自定义资源。
<!--
The following YAML configuration describes a GMSA credential spec named `gmsa-WebApp1`:
```yaml
apiVersion: windows.k8s.io/v1alpha1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 #This is an arbitrary name but it will be used as a reference
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 #Username of the GMSA account
Scope: CONTOSO #NETBIOS Domain Name
- Name: WebApp1 #Username of the GMSA account
Scope: contoso.com #DNS Domain Name
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com #DNS Domain Name
DnsTreeName: contoso.com #DNS Domain Name Root
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a #GUID
MachineAccountName: WebApp1 #Username of the GMSA account
NetBiosName: CONTOSO #NETBIOS Domain Name
Sid: S-1-5-21-2126449477-2524075714-3094792973 #SID of GMSA
```
-->
下面的 YAML 配置描述的是一个名为 `gmsa-WebApp1` 的 GMSA 凭据规约:
```yaml
apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 # 这是随意起的一个名字,将用作引用
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 # GMSA 账号的用户名
Scope: CONTOSO # NETBIOS 域名
- Name: WebApp1 # GMSA 账号的用户名
Scope: contoso.com # DNS 域名
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com # DNS 域名
DnsTreeName: contoso.com # DNS 域名根
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a # GUID
MachineAccountName: WebApp1 # GMSA 账号的用户名
NetBiosName: CONTOSO # NETBIOS 域名
Sid: S-1-5-21-2126449477-2524075714-3094792973 # GMSA 的 SID
```
<!--
The above credential spec resource may be saved as `gmsa-Webapp1-credspec.yaml` and applied to the cluster using: `kubectl apply -f gmsa-Webapp1-credspec.yml`
-->
上面的凭据规约资源可以保存为 `gmsa-Webapp1-credspec.yaml`,之后使用
`kubectl apply -f gmsa-Webapp1-credspec.yml` 应用到集群上。
<!--
## Configure cluster role to enable RBAC on specific GMSA credential specs
A cluster role needs to be defined for each GMSA credential spec resource. This authorizes the `use` verb on a specific GMSA resource by a subject which is typically a service account. The following example shows a cluster role that authorizes usage of the `gmsa-WebApp1` credential spec from above. Save the file as gmsa-webapp1-role.yaml and apply using `kubectl apply -f gmsa-webapp1-role.yaml`
-->
## 配置集群角色以启用对特定 GMSA 凭据规约的 RBAC
你需要为每个 GMSA 凭据规约资源定义集群角色。
该集群角色授权某主体(通常是一个服务账号)对特定的 GMSA 资源执行 `use` 动作。
下面的示例显示的是一个集群角色,对前文创建的凭据规约 `gmsa-WebApp1` 执行鉴权。
将此文件保存为 `gmsa-webapp1-role.yaml` 并执行 `kubectl apply -f gmsa-webapp1-role.yaml`
<!--
```yaml
#Create the Role to read the credspec
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
```
-->
```yaml
# 创建集群角色读取凭据规约
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
```
<!--
## Assign role to service accounts to use specific GMSA credspecs
A service account (that Pods will be configured with) needs to be bound to the cluster role create above. This authorizes the service account to use the desired GMSA credential spec resource. The following shows the default service account being bound to a cluster role `webapp1-role` to use `gmsa-WebApp1` credential spec resource created above.
-->
## 将角色指派给要使用特定 GMSA 凭据规约的服务账号
你需要将某个服务账号(Pod 配置所对应的那个)绑定到前文创建的集群角色上。
这一绑定操作实际上授予该服务账号使用所指定的 GMSA 凭据规约资源的访问权限。
下面显示的是一个绑定到集群角色 `webapp1-role` 上的 default 服务账号,使之
能够使用前面所创建的 `gmsa-WebApp1` 凭据规约资源。
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: allow-default-svc-account-read-on-gmsa-WebApp1
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: webapp1-role
apiGroup: rbac.authorization.k8s.io
```
<!--
## Configure GMSA credential spec reference in Pod spec
The Pod spec field `securityContext.windowsOptions.gmsaCredentialSpecName` is used to specify references to desired GMSA credential spec custom resources in Pod specs. This configures all containers in the Pod spec to use the specified GMSA. A sample Pod spec with the annotation populated to refer to `gmsa-WebApp1`:
-->
## 在 Pod 规约中配置 GMSA 凭据规约引用
Pod 规约字段 `securityContext.windowsOptions.gmsaCredentialSpecName` 可用来
设置对指定 GMSA 凭据规约自定义资源的引用。
设置此引用将会配置 Pod 中的所有容器使用所给的 GMSA。
下面是一个 Pod 规约示例,其中包含了对 `gmsa-WebApp1` 凭据规约的引用:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-webapp1
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
nodeSelector:
kubernetes.io/os: windows
```
<!--
Individual containers in a Pod spec can also specify the desired GMSA credspec using a per-container `securityContext.windowsOptions.gmsaCredentialSpecName` field. For example:
-->
Pod 中的各个容器也可以使用对应容器的 `securityContext.windowsOptions.gmsaCredentialSpecName`
字段来设置期望使用的 GMSA 凭据规约。
例如:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-Webapp1
nodeSelector:
kubernetes.io/os: windows
```
<!--
As Pod specs with GMSA fields populated (as described above) are applied in a cluster, the following sequence of events take place:
1. The mutating webhook resolves and expands all references to GMSA credential spec resources to the contents of the GMSA credential spec.
1. The validating webhook ensures the service account associated with the Pod is authorized for the `use` verb on the specified GMSA credential spec.
1. The container runtime configures each Windows container with the specified GMSA credential spec so that the container can assume the identity of the GMSA in Active Directory and access services in the domain using that identity.
-->
当 Pod 规约中填充了 GMSA 相关字段(如上所述),在集群中应用 Pod 规约时会依次
发生以下事件:
1. Mutating Webhook 解析对 GMSA 凭据规约资源的引用,并将其全部展开,
得到 GMSA 凭据规约的实际内容。
1. Validating Webhook 确保与 Pod 相关联的服务账号有权在所给的 GMSA 凭据规约
上执行 `use` 动作。
1. 容器运行时为每个 Windows 容器配置所指定的 GMSA 凭据规约,这样容器就可以以
活动目录中该 GMSA 所代表的身份来执行操作,使用该身份来访问域中的服务。
## 使用主机名或 FQDN 对网络共享进行身份验证
<!--
If you are experiencing issues connecting to SMB shares from Pods using hostname or FQDN, but are able to access the shares via their IPv4 address then make sure the following registry key is set on the Windows nodes.
-->
如果你在使用主机名或 FQDN 从 Pod 连接到 SMB 共享时遇到问题,但能够通过其 IPv4 地址访问共享,
请确保在 Windows 节点上设置了以下注册表项。
```cmd
reg add "HKLM\SYSTEM\CurrentControlSet\Services\hns\State" /v EnableCompartmentNamespace /t REG_DWORD /d 1
```
<!--
Running Pods will then need to be recreated to pick up the behavior changes.
More information on how this registry key is used can be found [here](
https://github.com/microsoft/hcsshim/blob/885f896c5a8548ca36c88c4b87fd2208c8d16543/internal/uvm/create.go#L74-L83)
-->
然后需要重新创建正在运行的 Pod 以使行为更改生效。
有关如何使用此注册表项的更多信息,请参见[此处](https://github.com/microsoft/hcsshim/blob/885f896c5a8548ca36c88c4b87fd2208c8d16543/internal/uvm/create.go#L74-L83)。
<!--
## Troubleshooting
If you are having difficulties getting GMSA to work in your environment, there are a few troubleshooting steps you can take.
-->
## 故障排查
如果在你的环境中配置 GMSA 时遇到了困难,你可以采取若干步骤来排查可能的故障。
<!--
First, make sure the credspec has been passed to the Pod. To do this you will need to `exec` into one of your Pods and check the output of the `nltest.exe /parentdomain` command.
-->
首先,确保 credspec 已传递给 Pod。为此,你需要先运行 `exec` 进入到你的一个 Pod 中并检查 `nltest.exe /parentdomain` 命令的输出。
在下面的例子中,Pod 未能正确地获得凭据规约:
```PowerShell
kubectl exec -it iis-auth-7776966999-n5nzr powershell.exe
```
<!--
`nltest.exe /parentdomain` results in the following error:
-->
`nltest.exe /parentdomain` 导致以下错误:
```output
Getting parent domain failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
```
<!--
If your Pod did get the credspec correctly, then next check communication with the domain. First, from inside of your Pod, quickly do an nslookup to find the root of your domain.
This will tell us 3 things:
1. The Pod can reach the DC
1. The DC can reach the Pod
1. DNS is working correctly.
-->
如果 Pod 未能正确获得凭据规约,则下一步就要检查与域之间的通信。
首先,从 Pod 内部快速执行一个 nslookup 操作,找到域根。
这一操作会告诉我们三件事情:
1. Pod 能否访问域控制器(DC
1. DC 能否访问 Pod
1. DNS 是否正常工作
<!--
If the DNS and communication test passes, next you will need to check if the Pod has established secure channel communication with the domain. To do this, again, `exec` into your Pod and run the `nltest.exe /query` command.
-->
如果 DNS 和通信测试通过,接下来你需要检查是否 Pod 已经与域之间建立了
安全通信通道。要执行这一检查,你需要再次通过 `exec` 进入到你的 Pod 中
并执行 `nltest.exe /query` 命令。
```PowerShell
nltest.exe /query
```
<!--
This tells us that for some reason, the Pod was unable to logon to the domain using the account specified in the credspec. You can try to repair the secure channel by running the following:
-->
这告诉我们,由于某种原因,Pod 无法使用 credspec 中指定的帐户登录到域。
你可以尝试通过运行以下命令来修复安全通道:
```PowerShell
nltest /sc_reset:domain.example
```
<!--
If the command is successful you will see and output similar to this:
-->
如果命令成功,你将看到类似以下内容的输出:
```
Flags: 30 HAS_IP HAS_TIMESERV
Trusted DC Name \\dc10.domain.example
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully
```
<!--
If the above corrects the error, you can automate the step by adding the following lifecycle hook to your Pod spec. If it did not correct the error, you will need to examine your credspec again and confirm that it is correct and complete.
-->
如果以上命令修复了错误,你可以通过将以下生命周期回调添加到你的 Pod 规约中来自动执行该步骤。
如果这些操作没有修复错误,你将需要再次检查你的 credspec 并确认它是正确和完整的。
```yaml
image: registry.domain.example/iis-auth:1809v1
lifecycle:
postStart:
exec:
command: ["powershell.exe","-command","do { Restart-Service -Name netlogon } while ( $($Result = (nltest.exe /query); if ($Result -like '*0x0 NERR_Success*') {return $true} else {return $false}) -eq $false)"]
imagePullPolicy: IfNotPresent
```
<!--
If you add the `lifecycle` section show above to your Pod spec, the Pod will execute the commands listed to restart the `netlogon` service until the `nltest.exe /query` command exits without error.
-->
如果你向你的 Pod 规约中添加如上所示的 `lifecycle` 节,则 Pod 会自动执行所
列举的命令来重启 `netlogon` 服务,直到 `nltest.exe /query`
命令返回时没有错误信息。
@@ -0,0 +1,877 @@
---
title: 配置存活、就绪和启动探测器
content_type: task
weight: 110
---
<!-- overview -->
<!--
This page shows how to configure liveness, readiness and startup probes for Containers.
The [kubelet](/docs/reference/command-line-tools-reference/kubelet/) uses liveness probes to know when to
restart a container. For example, liveness probes could catch a deadlock,
where an application is running, but unable to make progress. Restarting a
container in such a state can help to make the application more available
despite bugs.
-->
这篇文章介绍如何给容器配置活跃(Liveness)、就绪(Readiness)和启动(Startup)探测器。
[kubelet](/zh/docs/reference/command-line-tools-reference/kubelet/)
使用存活探测器来确定什么时候要重启容器。
例如,存活探测器可以探测到应用死锁(应用程序在运行,但是无法继续执行后面的步骤)情况。
重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。
<!--
The kubelet uses readiness probes to know when a container is ready to start
accepting traffic. A Pod is considered ready when all of its containers are ready.
One use of this signal is to control which Pods are used as backends for Services.
When a Pod is not ready, it is removed from Service load balancers.
The kubelet uses startup probes to know when a container application has started.
If such a probe is configured, it disables liveness and readiness checks until
it succeeds, making sure those probes don't interfere with the application startup.
This can be used to adopt liveness checks on slow starting containers, avoiding them
getting killed by the kubelet before they are up and running.
-->
kubelet 使用就绪探测器可以知道容器何时准备好接受请求流量,当一个 Pod
内的所有容器都就绪时,才能认为该 Pod 就绪。
这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。
若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除。
kubelet 使用启动探测器来了解应用容器何时启动。
如果配置了这类探测器,你就可以控制容器在启动成功后再进行存活性和就绪态检查,
确保这些存活、就绪探测器不会影响应用的启动。
启动探测器可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
<!-- steps -->
<!--
## Define a liveness command
Many applications running for long periods of time eventually transition to
broken states, and cannot recover except by being restarted. Kubernetes provides
liveness probes to detect and remedy such situations.
In this exercise, you create a Pod that runs a container based on the
`k8s.gcr.io/busybox` image. Here is the configuration file for the Pod:
-->
## 定义存活命令 {#define-a-liveness-command}
许多长时间运行的应用最终会进入损坏状态,除非重新启动,否则无法被恢复。
Kubernetes 提供了存活探测器来发现并处理这种情况。
在本练习中,你会创建一个 Pod,其中运行一个基于 `k8s.gcr.io/busybox` 镜像的容器。
下面是这个 Pod 的配置文件。
{{< codenew file="pods/probe/exec-liveness.yaml" >}}
<!--
In the configuration file, you can see that the Pod has a single `Container`.
The `periodSeconds` field specifies that the kubelet should perform a liveness
probe every 5 seconds. The `initialDelaySeconds` field tells the kubelet that it
should wait 5 seconds before performing the first probe. To perform a probe, the
kubelet executes the command `cat /tmp/healthy` in the target container. If the
command succeeds, it returns 0, and the kubelet considers the container to be alive and
healthy. If the command returns a non-zero value, the kubelet kills the container
and restarts it.
When the container starts, it executes this command:
-->
在这个配置文件中,可以看到 Pod 中只有一个 `Container`
`periodSeconds` 字段指定了 kubelet 应该每 5 秒执行一次存活探测。
`initialDelaySeconds` 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒。
kubelet 在容器内执行命令 `cat /tmp/healthy` 来进行探测。
如果命令执行成功并且返回值为 0,kubelet 就会认为这个容器是健康存活的。
如果这个命令返回非 0 值,kubelet 会杀死这个容器并重新启动它。
当容器启动时,执行如下的命令:
```shell
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"
```
<!--
For the first 30 seconds of the container's life, there is a `/tmp/healthy` file.
So during the first 30 seconds, the command `cat /tmp/healthy` returns a success
code. After 30 seconds, `cat /tmp/healthy` returns a failure code.
Create the Pod:
-->
这个容器生命的前 30 秒,`/tmp/healthy` 文件是存在的。
所以在这最开始的 30 秒内,执行命令 `cat /tmp/healthy` 会返回成功代码。
30 秒之后,执行命令 `cat /tmp/healthy` 就会返回失败代码。
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
```
<!--
Within 30 seconds, view the Pod events:
-->
在 30 秒内,查看 Pod 的事件:
```shell
kubectl describe pod liveness-exec
```
<!--
The output indicates that no liveness probes have failed yet:
-->
输出结果表明还没有存活探测器失败:
```
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
```
<!--
After 35 seconds, view the Pod events again:
-->
35 秒之后,再来看 Pod 的事件:
```shell
kubectl describe pod liveness-exec
```
<!--
At the bottom of the output, there are messages indicating that the liveness
probes have failed, and the containers have been killed and recreated.
-->
在输出结果的最下面,有信息显示存活探测器失败了,这个容器被杀死并且被重建了。
```
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
```
<!--
Wait another 30 seconds, and verify that the Container has been restarted:
-->
再等 30 秒,确认这个容器被重启了:
```shell
kubectl get pod liveness-exec
```
<!--
The output shows that `RESTARTS` has been incremented:
-->
输出结果显示 `RESTARTS` 的值增加了 1。
```
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
```
<!--
## Define a liveness HTTP request
Another kind of liveness probe uses an HTTP GET request. Here is the configuration
file for a Pod that runs a container based on the `k8s.gcr.io/liveness`
image.
-->
## 定义一个存活态 HTTP 请求接口 {#define-a-liveness-HTTP-request}
另外一种类型的存活探测方式是使用 HTTP GET 请求。
下面是一个 Pod 的配置文件,其中运行一个基于 `k8s.gcr.io/liveness` 镜像的容器。
{{< codenew file="pods/probe/http-liveness.yaml" >}}
<!--
In the configuration file, you can see that the Pod has a single container.
The `periodSeconds` field specifies that the kubelet should perform a liveness
probe every 3 seconds. The `initialDelaySeconds` field tells the kubelet that it
should wait 3 seconds before performing the first probe. To perform a probe, the
kubelet sends an HTTP GET request to the server that is running in the container
and listening on port 8080. If the handler for the server's `/healthz` path
returns a success code, the kubelet considers the container to be alive and
healthy. If the handler returns a failure code, the kubelet kills the container
and restarts it.
-->
在这个配置文件中,你可以看到 Pod 也只有一个容器。
`periodSeconds` 字段指定了 kubelet 每隔 3 秒执行一次存活探测。
`initialDelaySeconds` 字段告诉 kubelet 在执行第一次探测前应该等待 3 秒。
kubelet 会向容器内运行的服务(服务在监听 8080 端口)发送一个 HTTP GET 请求来执行探测。
如果服务器上 `/healthz` 路径下的处理程序返回成功代码,则 kubelet 认为容器是健康存活的。
如果处理程序返回失败代码,则 kubelet 会杀死这个容器并将其重启。
<!--
Any code greater than or equal to 200 and less than 400 indicates success. Any
other code indicates failure.
You can see the source code for the server in
[server.go](https://github.com/kubernetes/kubernetes/blob/master/test/images/agnhost/liveness/server.go).
For the first 10 seconds that the container is alive, the `/healthz` handler
returns a status of 200. After that, the handler returns a status of 500.
-->
返回大于或等于 200 并且小于 400 的任何代码都标示成功,其它返回代码都标示失败。
你可以访问 [server.go](https://github.com/kubernetes/kubernetes/blob/master/test/images/agnhost/liveness/server.go)。
阅读服务的源码。
容器存活期间的最开始 10 秒中,`/healthz` 处理程序返回 200 的状态码。
之后处理程序返回 500 的状态码。
```go
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
```
<!--
The kubelet starts performing health checks 3 seconds after the container starts.
So the first couple of health checks will succeed. But after 10 seconds, the health
checks will fail, and the kubelet will kill and restart the container.
To try the HTTP liveness check, create a Pod:
-->
kubelet 在容器启动之后 3 秒开始执行健康检测。所以前几次健康检查都是成功的。
但是 10 秒之后,健康检查会失败,并且 kubelet 会杀死容器再重新启动容器。
创建一个 Pod 来测试 HTTP 的存活检测:
```shell
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
```
<!--
After 10 seconds, view Pod events to verify that liveness probes have failed and
the container has been restarted:
-->
10 秒之后,通过查看 Pod 事件来确认活跃探测器已经失败,并且容器被重新启动了。
```shell
kubectl describe pod liveness-http
```
<!--
In releases prior to v1.13 (including v1.13), if the environment variable
`http_proxy` (or `HTTP_PROXY`) is set on the node where a Pod is running,
the HTTP liveness probe uses that proxy.
In releases after v1.13, local HTTP proxy environment variable settings do not
affect the HTTP liveness probe.
-->
在 1.13 之前(包括 1.13)的版本中,如果在 Pod 运行的节点上设置了环境变量
`http_proxy`(或者 `HTTP_PROXY`),HTTP 的存活探测会使用这个代理。
在 1.13 之后的版本中,设置本地的 HTTP 代理环境变量不会影响 HTTP 的存活探测。
<!--
## Define a TCP liveness probe
A third type of liveness probe uses a TCP socket. With this configuration, the
kubelet will attempt to open a socket to your container on the specified port.
If it can establish a connection, the container is considered healthy, if it
can't it is considered a failure.
-->
## 定义 TCP 的存活探测 {#define-a-TCP-liveness-probe}
第三种类型的存活探测是使用 TCP 套接字。
使用这种配置时,kubelet 会尝试在指定端口和容器建立套接字链接。
如果能建立连接,这个容器就被看作是健康的,如果不能则这个容器就被看作是有问题的。
{{< codenew file="pods/probe/tcp-liveness-readiness.yaml" >}}
<!--
As you can see, configuration for a TCP check is quite similar to an HTTP check.
This example uses both readiness and liveness probes. The kubelet will send the
first readiness probe 5 seconds after the container starts. This will attempt to
connect to the `goproxy` container on port 8080. If the probe succeeds, the Pod
will be marked as ready. The kubelet will continue to run this check every 10
seconds.
In addition to the readiness probe, this configuration includes a liveness probe.
The kubelet will run the first liveness probe 15 seconds after the container
starts. Similar to the readiness probe, this will attempt to connect to the
`goproxy` container on port 8080. If the liveness probe fails, the container
will be restarted.
To try the TCP liveness check, create a Pod:
-->
如你所见,TCP 检测的配置和 HTTP 检测非常相似。
下面这个例子同时使用就绪和存活探测器。kubelet 会在容器启动 5 秒后发送第一个就绪探测。
探测器会尝试连接 `goproxy` 容器的 8080 端口。
如果探测成功,这个 Pod 会被标记为就绪状态,kubelet 将继续每隔 10 秒运行一次检测。
除了就绪探测,这个配置包括了一个存活探测。
kubelet 会在容器启动 15 秒后进行第一次存活探测。
与就绪探测类似,活跃探测器会尝试连接 `goproxy` 容器的 8080 端口。
如果存活探测失败,容器会被重新启动。
```shell
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
```
<!--
After 15 seconds, view Pod events to verify that liveness probes:
-->
15 秒之后,通过看 Pod 事件来检测存活探测器:
```shell
kubectl describe pod goproxy
```
<!--
## Define a gRPC liveness probe
-->
## 定义 gRPC 活跃探测器
{{< feature-state for_k8s_version="v1.24" state="beta" >}}
<!--
If your application implements [gRPC Health Checking Protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md),
kubelet can be configured to use it for application liveness checks.
You must enable the `GRPCContainerProbe`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
in order to configure checks that rely on gRPC.
Here is an example manifest:
-->
如果你的应用实现了 [gRPC 健康检查协议](https://github.com/grpc/grpc/blob/master/doc/health-checking.md)
kubelet 可以配置为使用该协议来执行应用活跃性检查。
你必须启用 `GRPCContainerProbe`
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)
才能配置依赖于 gRPC 的检查机制。
下面是一个示例清单:
{{< codenew file="pods/probe/grpc-liveness.yaml" >}}
<!--
To use a gRPC probe, `port` must be configured. If the health endpoint is configured
on a non-default service, you must also specify the `service`.
-->
要使用 gRPC 探测器,必须配置 `port` 属性。如果健康状态端点配置在非默认服务之上,
你还必须设置 `service` 属性。
{{< note >}}
<!--
Unlike HTTP and TCP probes, named ports cannot be used and custom host cannot be configured.
-->
与 HTTP 和 TCP 探测器不同,gRPC 探测不能使用命名端口或定制主机。
{{< /note >}}
<!--
Configuration problems (for example: incorrect port and service, unimplemented health checking protocol)
are considered a probe failure, similar to HTTP and TCP probes.
To try the gRPC liveness check, create a Pod using the command below.
In the example below, the etcd pod is configured to use gRPC liveness probe.
-->
配置问题(例如:错误的 `port``service`、未实现健康检查协议)
都被认作是探测失败,这一点与 HTTP 和 TCP 探测器类似。
```shell
kubectl apply -f https://k8s.io/examples/pods/probe/grpc-liveness.yaml
```
<!--
After 15 seconds, view Pod events to verify that the liveness check has not failed:
-->
15 秒钟之后,查看 Pod 事件确认活跃性检查并未失败:
```shell
kubectl describe pod etcd-with-grpc
```
<!--
Before Kubernetes 1.23, gRPC health probes were often implemented using [grpc-health-probe](https://github.com/grpc-ecosystem/grpc-health-probe/),
as described in the blog post [Health checking gRPC servers on Kubernetes](/blog/2018/10/01/health-checking-grpc-servers-on-kubernetes/).
The built-in gRPC probes behavior is similar to one implemented by grpc-health-probe.
When migrating from grpc-health-probe to built-in probes, remember the following differences:
-->
在 Kubernetes 1.23 之前,gRPC 健康探测通常使用
[grpc-health-probe](https://github.com/grpc-ecosystem/grpc-health-probe/)
来实现,如博客 [Health checking gRPC servers on Kubernetes(对 Kubernetes 上的 gRPC 服务器执行健康检查)](/blog/2018/10/01/health-checking-grpc-servers-on-kubernetes/)所描述。
内置的 gRPC 探测器行为与 `grpc-health-probe` 所实现的行为类似。
`grpc-health-probe` 迁移到内置探测器时,请注意以下差异:
<!--
- Built-in probes run against the pod IP address, unlike grpc-health-probe that often runs against `127.0.0.1`.
Be sure to configure your gRPC endpoint to listen on the Pod's IP address.
- Built-in probes do not support any authentication parameters (like `-tls`).
- There are no error codes for built-in probes. All errors are considered as probe failures.
- If `ExecProbeTimeout` feature gate is set to `false`, grpc-health-probe does **not** respect the `timeoutSeconds` setting (which defaults to 1s),
while built-in probe would fail on timeout.
-->
- 内置探测器运行时针对的是 Pod 的 IP 地址,不像 `grpc-health-probe`
那样通常针对 `127.0.0.1` 执行探测;
请一定配置你的 gRPC 端点使之监听于 Pod 的 IP 地址之上。
- 内置探测器不支持任何身份认证参数(例如 `tls`)。
- 对于内置的探测器而言,不存在错误代码。所有错误都被视作探测失败。
- 如果 `ExecProbeTimeout` 特性门控被设置为 `false`,则 `grpc-health-probe`
不会考虑 `timeoutSeconds` 设置状态(默认值为 1s),
而内置探测器则会在超时时返回失败。
<!--
## Use a named port
You can use a named
[ContainerPort](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#containerport-v1-core)
for HTTP or TCP liveness checks:
-->
## 使用命名端口 {#use-a-named-port}
对于 HTTP 或者 TCP 存活检测可以使用命名的
[ContainerPort](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#containerport-v1-core)。
```yaml
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
```
<!--
## Protect slow starting containers with startup probes {#define-startup-probes}
Sometimes, you have to deal with legacy applications that might require
an additional startup time on their first initialization.
In such cases, it can be tricky to set up liveness probe parameters without
compromising the fast response to deadlocks that motivated such a probe.
The trick is to set up a startup probe with the same command, HTTP or TCP
check, with a `failureThreshold * periodSeconds` long enough to cover the
worse case startup time.
So, the previous example would become:
-->
## 使用启动探测器保护慢启动容器 {#define-startup-probes}
有时候,会有一些现有的应用在启动时需要较长的初始化时间。
要这种情况下,若要不影响对死锁作出快速响应的探测,设置存活探测参数是要技巧的。
技巧就是使用相同的命令来设置启动探测,针对 HTTP 或 TCP 检测,可以通过将
`failureThreshold * periodSeconds` 参数设置为足够长的时间来应对糟糕情况下的启动时间。
这样,前面的例子就变成了:
```yaml
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
```
<!--
Thanks to the startup probe, the application will have a maximum of 5 minutes
(30 * 10 = 300s) to finish its startup.
Once the startup probe has succeeded once, the liveness probe takes over to
provide a fast response to container deadlocks.
If the startup probe never succeeds, the container is killed after 300s and
subject to the pod's `restartPolicy`.
-->
幸亏有启动探测,应用程序将会有最多 5 分钟(30 * 10 = 300s)的时间来完成其启动过程。
一旦启动探测成功一次,存活探测任务就会接管对容器的探测,对容器死锁作出快速响应。
如果启动探测一直没有成功,容器会在 300 秒后被杀死,并且根据 `restartPolicy`
执行进一步处置。
<!--
## Define readiness probes
Sometimes, applications are temporarily unable to serve traffic.
For example, an application might need to load large data or configuration
files during startup, or depend on external services after startup.
In such cases, you don't want to kill the application,
but you don't want to send it requests either. Kubernetes provides
readiness probes to detect and mitigate these situations. A pod with containers
reporting that they are not ready does not receive traffic through Kubernetes
Services.
-->
## 定义就绪探测器 {#define-readiness-probes}
有时候,应用会暂时性地无法为请求提供服务。
例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。
在这种情况下,既不想杀死应用,也不想给它发送请求。
Kubernetes 提供了就绪探测器来发现并缓解这些情况。
容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量。
<!--
Readiness probes runs on the container during its whole lifecycle.
-->
{{< note >}}
就绪探测器在容器的整个生命周期中保持运行状态。
{{< /note >}}
<!--
Liveness probes *do not* wait for readiness probes to succeed. If you want to wait before executing a liveness probe you should use initialDelaySeconds or a startupProbe.
-->
{{< caution >}}
活跃探测器 **不等待** 就绪性探测器成功。
如果要在执行活跃探测器之前等待,应该使用 `initialDelaySeconds``startupProbe`
{{< /caution >}}
<!--
Readiness probes are configured similarly to liveness probes. The only difference
is that you use the `readinessProbe` field instead of the `livenessProbe` field.
-->
就绪探测器的配置和存活探测器的配置相似。
唯一区别就是要使用 `readinessProbe` 字段,而不是 `livenessProbe` 字段。
```yaml
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
```
<!--
Configuration for HTTP and TCP readiness probes also remains identical to
liveness probes.
Readiness and liveness probes can be used in parallel for the same container.
Using both can ensure that traffic does not reach a container that is not ready
for it, and that containers are restarted when they fail.
-->
HTTP 和 TCP 的就绪探测器配置也和存活探测器的配置完全相同。
就绪和存活探测可以在同一个容器上并行使用。
两者都可以确保流量不会发给还未就绪的容器,当这些探测失败时容器会被重新启动。
<!--
## Configure Probes
-->
## 配置探测器 {#configure-probes}
<!--
Eventually, some of this section could be moved to a concept topic.
-->
{{< comment >}}
最后,本节的一些内容可以放到某个概念主题里。
{{< /comment >}}
<!--
[Probes](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#probe-v1-core) have a number of fields that
you can use to more precisely control the behavior of liveness and readiness
checks:
-->
[Probe](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#probe-v1-core)
有很多配置字段,可以使用这些字段精确地控制活跃和就绪检测的行为:
<!--
* `initialDelaySeconds`: Number of seconds after the container has started
before liveness or readiness probes are initiated. Defaults to 0 seconds. Minimum value is 0.
* `periodSeconds`: How often (in seconds) to perform the probe. Default to 10
seconds. Minimum value is 1.
* `timeoutSeconds`: Number of seconds after which the probe times out. Defaults
to 1 second. Minimum value is 1.
* `successThreshold`: Minimum consecutive successes for the probe to be
considered successful after having failed. Defaults to 1. Must be 1 for liveness
and startup Probes. Minimum value is 1.
* `failureThreshold`: When a probe fails, Kubernetes will
try `failureThreshold` times before giving up. Giving up in case of liveness probe means restarting the container. In case of readiness probe the Pod will be marked Unready.
Defaults to 3. Minimum value is 1.
-->
* `initialDelaySeconds`:容器启动后要等待多少秒后才启动存活和就绪探测器,
默认是 0 秒,最小值是 0。
* `periodSeconds`:执行探测的时间间隔(单位是秒)。默认是 10 秒。最小值是 1。
* `timeoutSeconds`:探测的超时后等待多少秒。默认值是 1 秒。最小值是 1。
* `successThreshold`:探测器在失败后,被视为成功的最小连续成功数。默认值是 1。
存活和启动探测的这个值必须是 1。最小值是 1。
* `failureThreshold`:当探测失败时,Kubernetes 的重试次数。
对存活探测而言,放弃就意味着重新启动容器。
对就绪探测而言,放弃意味着 Pod 会被打上未就绪的标签。默认值是 3。最小值是 1。
{{< note >}}
<!--
Before Kubernetes 1.20, the field `timeoutSeconds` was not respected for exec probes:
probes continued running indefinitely, even past their configured deadline,
until a result was returned.
-->
在 Kubernetes 1.20 版本之前,`exec` 探针会忽略 `timeoutSeconds`
探针会无限期地持续运行,甚至可能超过所配置的限期,直到返回结果为止。
<!--
This defect was corrected in Kubernetes v1.20. You may have been relying on the previous behavior,
even without realizing it, as the default timeout is 1 second.
As a cluster administrator, you can disable the [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) `ExecProbeTimeout` (set it to `false`)
on each kubelet to restore the behavior from older versions, then remove that override
once all the exec probes in the cluster have a `timeoutSeconds` value set.
If you have pods that are impacted from the default 1 second timeout,
you should update their probe timeout so that you're ready for the
eventual removal of that feature gate.
-->
这一缺陷在 Kubernetes v1.20 版本中得到修复。你可能一直依赖于之前错误的探测行为,
甚至都没有觉察到这一问题的存在,因为默认的超时值是 1 秒钟。
作为集群管理员,你可以在所有的 kubelet 上禁用 `ExecProbeTimeout`
[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)
(将其设置为 `false`),从而恢复之前版本中的运行行为。之后当集群中所有的
exec 探针都设置了 `timeoutSeconds` 参数后,移除此标志重载。
如果你有 Pod 受到此默认 1 秒钟超时值的影响,你应该更新这些 Pod 对应的探针的超时值,
这样才能为最终去除该特性门控做好准备。
<!--
With the fix of the defect, for exec probes, on Kubernetes `1.20+` with the `dockershim` container runtime,
the process inside the container may keep running even after probe returned failure because of the timeout.
-->
当此缺陷被修复之后,在使用 `dockershim` 容器运行时的 Kubernetes `1.20+`
版本中,对于 exec 探针而言,容器中的进程可能会因为超时值的设置保持持续运行,
即使探针返回了失败状态。
{{< /note >}}
{{< caution >}}
<!--
Incorrect implementation of readiness probes may result in an ever growing number
of processes in the container, and resource starvation if this is left unchecked.
-->
如果就绪态探针的实现不正确,可能会导致容器中进程的数量不断上升。
如果不对其采取措施,很可能导致资源枯竭的状况。
{{< /caution >}}
<!--
### HTTP probes
[HTTP probes](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#httpgetaction-v1-core)
have additional fields that can be set on `httpGet`:
* `host`: Host name to connect to, defaults to the pod IP. You probably want to
set "Host" in httpHeaders instead.
* `scheme`: Scheme to use for connecting to the host (HTTP or HTTPS). Defaults to HTTP.
* `path`: Path to access on the HTTP server. Defaults to /.
* `httpHeaders`: Custom headers to set in the request. HTTP allows repeated headers.
* `port`: Name or number of the port to access on the container. Number must be
in the range 1 to 65535.
-->
### HTTP 探测 {#http-probes}
[HTTP Probes](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#httpgetaction-v1-core)
允许针对 `httpGet` 配置额外的字段:
* `host`:连接使用的主机名,默认是 Pod 的 IP。也可以在 HTTP 头中设置 “Host” 来代替。
* `scheme` :用于设置连接主机的方式(HTTP 还是 HTTPS)。默认是 "HTTP"。
* `path`:访问 HTTP 服务的路径。默认值为 "/"。
* `httpHeaders`:请求中自定义的 HTTP 头。HTTP 头字段允许重复。
* `port`:访问容器的端口号或者端口名。如果数字必须在 1~65535 之间。
<!--
For an HTTP probe, the kubelet sends an HTTP request to the specified path and
port to perform the check. The kubelet sends the probe to the pod's IP address,
unless the address is overridden by the optional `host` field in `httpGet`. If
`scheme` field is set to `HTTPS`, the kubelet sends an HTTPS request skipping the
certificate verification. In most scenarios, you do not want to set the `host` field.
Here's one scenario where you would set it. Suppose the container listens on 127.0.0.1
and the Pod's `hostNetwork` field is true. Then `host`, under `httpGet`, should be set
to 127.0.0.1. If your pod relies on virtual hosts, which is probably the more common
case, you should not use `host`, but rather set the `Host` header in `httpHeaders`.
-->
对于 HTTP 探测,kubelet 发送一个 HTTP 请求到指定的路径和端口来执行检测。
除非 `httpGet` 中的 `host` 字段设置了,否则 kubelet 默认是给 Pod 的 IP 地址发送探测。
如果 `scheme` 字段设置为了 `HTTPS`,kubelet 会跳过证书验证发送 HTTPS 请求。
大多数情况下,不需要设置`host` 字段。
这里有个需要设置 `host` 字段的场景,假设容器监听 127.0.0.1,并且 Pod 的 `hostNetwork`
字段设置为了 `true`。那么 `httpGet` 中的 `host` 字段应该设置为 127.0.0.1。
可能更常见的情况是如果 Pod 依赖虚拟主机,你不应该设置 `host` 字段,而是应该在
`httpHeaders` 中设置 `Host`
<!--
For an HTTP probe, the kubelet sends two request headers in addition to the mandatory `Host` header:
`User-Agent`, and `Accept`. The default values for these headers are `kube-probe/{{< skew latestVersion >}}`
(where `{{< skew latestVersion >}}` is the version of the kubelet ), and `*/*` respectively.
You can override the default headers by defining `.httpHeaders` for the probe; for example
-->
针对 HTTP 探针,kubelet 除了必需的 `Host` 头部之外还发送两个请求头部字段:
`User-Agent``Accept`。这些头部的默认值分别是 `kube-probe/{{ skew latestVersion >}}`
(其中 `{{< skew latestVersion >}}` 是 kubelet 的版本号)和 `*/*`
你可以通过为探测设置 `.httpHeaders` 来重载默认的头部字段值;例如:
```yaml
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: application/json
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: MyUserAgent
```
<!--
You can also remove these two headers by defining them with an empty value.
-->
你也可以通过将这些头部字段定义为空值,从请求中去掉这些头部字段。
```yaml
livenessProbe:
httpGet:
httpHeaders:
- name: Accept
value: ""
startupProbe:
httpGet:
httpHeaders:
- name: User-Agent
value: ""
```
<!--
### TCP probes
For a TCP probe, the kubelet makes the probe connection at the node, not in the pod, which
means that you can not use a service name in the `host` parameter since the kubelet is unable
to resolve it.
-->
### TCP 探测 {#tcp-probes}
对于 TCP 探测而言,kubelet 在节点上(不是在 Pod 里面)发起探测连接,
这意味着你不能在 `host` 参数上配置服务名称,因为 kubelet 不能解析服务名称。
<!--
### Probe-level `terminationGracePeriodSeconds`
-->
### 探测器层面的 `terminationGracePeriodSeconds`
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
<!--
Prior to release 1.21, the pod-level `terminationGracePeriodSeconds` was used
for terminating a container that failed its liveness or startup probe. This
coupling was unintended and may have resulted in failed containers taking an
unusually long time to restart when a pod-level `terminationGracePeriodSeconds`
was set.
-->
在 1.21 发行版之前,Pod 层面的 `terminationGracePeriodSeconds`
被用来终止活跃探测或启动探测失败的容器。
这一行为上的关联不是我们想要的,可能导致 Pod 层面设置了 `terminationGracePeriodSeconds`
时容器要花非常长的时间才能重新启动。
<!--
In 1.21 and beyond, when the feature gate `ProbeTerminationGracePeriod` is
enabled, users can specify a probe-level `terminationGracePeriodSeconds` as
part of the probe specification. When the feature gate is enabled, and both a
pod- and probe-level `terminationGracePeriodSeconds` are set, the kubelet will
use the probe-level value.
-->
在 1.21 及更高版本中,当特性门控 `ProbeTerminationGracePeriod` 被启用时,
用户可以指定一个探测器层面的 `terminationGracePeriodSeconds` 作为探测器规约的一部分。
当该特性门控被启用,并且 Pod 层面和探测器层面的 `terminationGracePeriodSeconds`
都已设置,kubelet 将使用探测器层面设置的值。
<!--
As of Kubernetes 1.22, the `ProbeTerminationGracePeriod` feature gate is only
available on the API Server. The kubelet always honors the probe-level
`terminationGracePeriodSeconds` field if it is present on a Pod.
-->
在 Kubernetes 1.22 中,`ProbeTerminationGracePeriod` 特性门控只能用在 API 服务器上。
kubelet 始终遵守探针级别 `terminationGracePeriodSeconds` 字段
(如果它存在于 Pod 上)。
<!--
If you have existing Pods where the `terminationGracePeriodSeconds` field is set and
you no longer wish to use per-probe termination grace periods, you must delete
those existing Pods.
-->
如果你已经为现有 Pod 设置了 `terminationGracePeriodSeconds`
字段并且不再希望使用针对每个探针的终止宽限期,则必须删除现有的这类 Pod。
<!--
When you (or the control plane, or some other component) create replacement
Pods, and the feature gate `ProbeTerminationGracePeriod` is disabled, then the
API server ignores the Pod-level `terminationGracePeriodSeconds` field, even if
a Pod or pod template specifies it.
-->
当你(或控制平面或某些其他组件)创建替换 Pod,并且特性门控 `ProbeTerminationGracePeriod`
被禁用时,API 服务器会忽略 Pod 级别的 `terminationGracePeriodSeconds` 字段设置,
即使 Pod 或 Pod 模板指定了它。
例如:
```yaml
spec:
terminationGracePeriodSeconds: 3600 # pod-level
containers:
- name: test
image: ...
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 60
# Override pod-level terminationGracePeriodSeconds #
terminationGracePeriodSeconds: 60
```
<!--
Probe-level `terminationGracePeriodSeconds` cannot be set for readiness probes.
It will be rejected by the API server.
-->
探测器层面的 `terminationGracePeriodSeconds` 不能用于就绪态探针。
这一设置将被 API 服务器拒绝。
## {{% heading "whatsnext" %}}
<!--
* Learn more about
[Container Probes](/docs/concepts/workloads/pods/pod-lifecycle/#container-probes).
-->
* 进一步了解[容器探针](/zh/docs/concepts/workloads/pods/pod-lifecycle/#container-probes)。
<!--
You can also read the API references for:
* [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)
* [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
* [Probe](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#probe-v1-core)
-->
你也可以阅读以下的 API 参考资料:
* [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)
* [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
* [Probe](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#probe-v1-core)
@@ -0,0 +1,480 @@
---
title: 配置 Pod 以使用 PersistentVolume 作为存储
content_type: task
weight: 60
---
<!--
title: Configure a Pod to Use a PersistentVolume for Storage
content_type: task
weight: 60
-->
<!-- overview -->
<!--
This page shows how to configure a Pod to use a
{{< glossary_tooltip text="PersistentVolumeClaim" term_id="persistent-volume-claim" >}}
for storage.
Here is a summary of the process:
1. You, as cluster administrator, create a PersistentVolume backed by physical
storage. You do not associate the volume with any Pod.
1. You, now taking the role of a developer / cluster user, create a
PersistentVolumeClaim that is automatically bound to a suitable
PersistentVolume.
1. You create a Pod that uses the above PersistentVolumeClaim for storage.
-->
本文介绍如何配置 Pod 使用
{{< glossary_tooltip text="PersistentVolumeClaim" term_id="persistent-volume-claim" >}}
作为存储。
以下是该过程的总结:
1. 你作为集群管理员创建由物理存储支持的 PersistentVolume。你不会将卷与任何 Pod 关联。
1. 你现在以开发人员或者集群用户的角色创建一个 PersistentVolumeClaim
它将自动绑定到合适的 PersistentVolume。
1. 你创建一个使用 PersistentVolumeClaim 作为存储的 Pod。
## {{% heading "prerequisites" %}}
<!--
* You need to have a Kubernetes cluster that has only one Node, and the kubectl
command-line tool must be configured to communicate with your cluster. If you
do not already have a single-node cluster, you can create one by using
[Minikube](https://minikube.sigs.k8s.io/docs/).
* Familiarize yourself with the material in
[Persistent Volumes](/docs/concepts/storage/persistent-volumes/).
-->
* 你需要一个包含单个节点的 Kubernetes 集群,并且必须配置 kubectl 命令行工具以便与集群交互。
如果还没有单节点集群,可以使用
[Minikube](https://minikube.sigs.k8s.io/docs/) 创建一个。
.
* 熟悉[持久卷](/zh/docs/concepts/storage/persistent-volumes/)中的材料。
<!-- steps -->
<!--
## Create an index.html file on your Node
Open a shell to the Node in your cluster. How you open a shell depends on how
you set up your cluster. For example, if you are using Minikube, you can open a
shell to your Node by entering `minikube ssh`.
In your shell, create a `/mnt/data` directory:
-->
## 在你的节点上创建一个 index.html 文件
打开集群中节点的一个 Shell。
如何打开 Shell 取决于集群的设置。
例如,如果你正在使用 Minikube,那么可以通过输入 `minikube ssh` 来打开节点的 Shell。
在 Shell 中,创建一个 `/mnt/data` 目录:
<!--
# This assumes that your Node uses "sudo" to run commands
# as the superuser
-->
```shell
# 这里假定你的节点使用 "sudo" 来以超级用户角色执行命令
sudo mkdir /mnt/data
```
<!--
In the `/mnt/data` directory, create an `index.html` file:
-->
`/mnt/data` 目录中创建一个 index.html 文件:
<!--
# This again assumes that your Node uses "sudo" to run commands
# as the superuser
-->
```
# 这里再次假定你的节点使用 "sudo" 来以超级用户角色执行命令
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"
```
<!--
If your Node uses a tool for superuser access other than `sudo`, you can
usually make this work if you replace `sudo` with the name of the other tool.
-->
{{< note >}}
如果你的节点使用某工具而不是 `sudo` 来完成超级用户访问,你可以将上述命令
中的 `sudo` 替换为该工具的名称。
{{< /note >}}
<!--
Test that the `index.html` file exists:
-->
测试 `index.html` 文件确实存在:
```shell
cat /mnt/data/index.html
```
<!--
The output should be:
-->
输出应该是:
```
Hello from Kubernetes storage
```
<!--
You can now close the shell to your Node.
-->
现在你可以关闭节点的 Shell 了。
<!--
## Create a PersistentVolume
In this exercise, you create a *hostPath* PersistentVolume. Kubernetes supports
hostPath for development and testing on a single-node cluster. A hostPath
PersistentVolume uses a file or directory on the Node to emulate network-attached storage.
-->
## 创建 PersistentVolume
在本练习中,你将创建一个 *hostPath* 类型的 PersistentVolume。
Kubernetes 支持用于在单节点集群上开发和测试的 hostPath 类型的 PersistentVolume。
hostPath 类型的 PersistentVolume 使用节点上的文件或目录来模拟网络附加存储。
<!--
In a production cluster, you would not use hostPath. Instead a cluster administrator
would provision a network resource like a Google Compute Engine persistent disk,
an NFS share, or an Amazon Elastic Block Store volume. Cluster administrators can also
use [StorageClasses](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#storageclass-v1-storage)
to set up
[dynamic provisioning](https://kubernetes.io/blog/2016/10/dynamic-provisioning-and-storage-in-kubernetes).
Here is the configuration file for the hostPath PersistentVolume:
-->
在生产集群中,你不会使用 hostPath。
集群管理员会提供网络存储资源,比如 Google Compute Engine 持久盘卷、NFS 共享卷或 Amazon Elastic Block Store 卷。
集群管理员还可以使用 [StorageClasses](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#storageclass-v1-storage) 来设置[动态提供存储](https://kubernetes.io/blog/2016/10/dynamic-provisioning-and-storage-in-kubernetes)。
下面是 hostPath PersistentVolume 的配置文件:
{{< codenew file="pods/storage/pv-volume.yaml" >}}
<!--
Create the PersistentVolume:
-->
创建 PersistentVolume
```shell
kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml
```
<!--
View information about the PersistentVolume:
-->
查看 PersistentVolume 的信息:
```shell
kubectl get pv task-pv-volume
```
<!--
The output shows that the PersistentVolume has a `STATUS` of `Available`. This
means it has not yet been bound to a PersistentVolumeClaim.
-->
输出结果显示该 PersistentVolume 的`状态(STATUS``Available`
这意味着它还没有被绑定给 PersistentVolumeClaim。
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 4s
<!--
## Create a PersistentVolumeClaim
The next step is to create a PersistentVolumeClaim. Pods use PersistentVolumeClaims
to request physical storage. In this exercise, you create a PersistentVolumeClaim
that requests a volume of at least three gibibytes that can provide read-write
access for at least one Node.
Here is the configuration file for the PersistentVolumeClaim:
-->
## 创建 PersistentVolumeClaim
下一步是创建一个 PersistentVolumeClaim。
Pod 使用 PersistentVolumeClaim 来请求物理存储。
在本练习中,你将创建一个 PersistentVolumeClaim,它请求至少 3 GB 容量的卷,
该卷至少可以为一个节点提供读写访问。
下面是 PersistentVolumeClaim 的配置文件:
{{< codenew file="pods/storage/pv-claim.yaml" >}}
<!--
Create the PersistentVolumeClaim:
-->
创建 PersistentVolumeClaim
```shell
kubectl create -f https://k8s.io/examples/pods/storage/pv-claim.yaml
```
<!--
After you create the PersistentVolumeClaim, the Kubernetes control plane looks
for a PersistentVolume that satisfies the claim's requirements. If the control
plane finds a suitable PersistentVolume with the same StorageClass, it binds the
claim to the volume.
Look again at the PersistentVolume:
-->
创建 PersistentVolumeClaim 之后,Kubernetes 控制平面将查找满足申领要求的 PersistentVolume。
如果控制平面找到具有相同 StorageClass 的适当的 PersistentVolume
则将 PersistentVolumeClaim 绑定到该 PersistentVolume 上。
再次查看 PersistentVolume 信息:
```shell
kubectl get pv task-pv-volume
```
<!--
Now the output shows a `STATUS` of `Bound`.
-->
现在输出的 `STATUS``Bound`
```
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
```
<!--
Look at the PersistentVolumeClaim:
-->
查看 PersistentVolumeClaim
```
kubectl get pvc task-pv-claim
```
<!--
The output shows that the PersistentVolumeClaim is bound to your PersistentVolume,
`task-pv-volume`.
-->
输出结果表明该 PersistentVolumeClaim 绑定了你的 PersistentVolume `task-pv-volume`
```
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
```
<!--
## Create a Pod
The next step is to create a Pod that uses your PersistentVolumeClaim as a volume.
Here is the configuration file for the Pod:
-->
## 创建 Pod
下一步是创建一个 Pod, 该 Pod 使用你的 PersistentVolumeClaim 作为存储卷。
下面是 Pod 的 配置文件:
{{< codenew file="pods/storage/pv-pod.yaml" >}}
<!--
Notice that the Pod's configuration file specifies a PersistentVolumeClaim, but
it does not specify a PersistentVolume. From the Pod's point of view, the claim
is a volume.
Create the Pod:
-->
注意 Pod 的配置文件指定了 PersistentVolumeClaim,但没有指定 PersistentVolume。
对 Pod 而言,PersistentVolumeClaim 就是一个存储卷。
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml
```
<!--
Verify that the Container in the Pod is running;
-->
检查 Pod 中的容器是否运行正常:
```shell
kubectl get pod task-pv-pod
```
<!--
Get a shell to the Container running in your Pod:
-->
打开一个 Shell 访问 Pod 中的容器:
```shell
kubectl exec -it task-pv-pod -- /bin/bash
```
<!--
In your shell, verify that nginx is serving the `index.html` file from the
hostPath volume:
-->
在 Shell 中,验证 nginx 是否正在从 hostPath 卷提供 `index.html` 文件:
<!--
# Be sure to run these 3 commands inside the root shell that comes from
# running "kubectl exec" in the previous step
-->
```
# 一定要在上一步 "kubectl exec" 所返回的 Shell 中执行下面三个命令
root@task-pv-pod:/# apt-get update
root@task-pv-pod:/# apt-get install curl
root@task-pv-pod:/# curl localhost
```
<!--
The output shows the text that you wrote to the `index.html` file on the
hostPath volume:
-->
输出结果是你之前写到 hostPath 卷中的 `index.html` 文件中的内容:
```
Hello from Kubernetes storage
```
<!--
If you see that message, you have successfully configured a Pod to
use storage from a PersistentVolumeClaim.
-->
如果你看到此消息,则证明你已经成功地配置了 Pod 使用 PersistentVolumeClaim
的存储。
<!--
## Clean up
Delete the Pod, the PersistentVolumeClaim and the PersistentVolume:
-->
## 清理 {#clean-up}
删除 Pod、PersistentVolumeClaim 和 PersistentVolume 对象:
```shell
kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume
```
<!--
If you don't already have a shell open to the Node in your cluster,
open a new shell the same way that you did earlier.
In the shell on your Node, remove the file and directory that you created:
-->
如果你还没有连接到集群中节点的 Shell,可以按之前所做操作,打开一个新的 Shell。
在节点的 Shell 上,删除你所创建的目录和文件:
```shell
# 这里假定你使用 "sudo" 来以超级用户的角色执行命令
sudo rm /mnt/data/index.html
sudo rmdir /mnt/data
```
<!--
You can now close the shell to your Node.
-->
你现在可以关闭连接到节点的 Shell。
<!--
## Mounting the same persistentVolume in two places
-->
## 在两个地方挂载相同的 persistentVolume
{{< codenew file="pods/storage/pv-duplicate.yaml" >}}
<!--
You can perform 2 volume mounts on your nginx container:
`/usr/share/nginx/html` for the static website
`/etc/nginx/nginx.conf` for the default config
-->
你可以在 nginx 容器上执行两个卷挂载:
`/usr/share/nginx/html` 用于静态网站
`/etc/nginx/nginx.conf` 作为默认配置
<!-- discussion -->
<!--
## Access control
Storage configured with a group ID (GID) allows writing only by Pods using the same
GID. Mismatched or missing GIDs cause permission denied errors. To reduce the
need for coordination with users, an administrator can annotate a PersistentVolume
with a GID. Then the GID is automatically added to any Pod that uses the
PersistentVolume.
Use the `pv.beta.kubernetes.io/gid` annotation as follows:
-->
## 访问控制 {#access-control}
使用组 ID(GID)配置的存储仅允许 Pod 使用相同的 GID 进行写入。
GID 不匹配或缺失将会导致无权访问错误。
为了减少与用户的协调,管理员可以对 PersistentVolume 添加 GID 注解。
这样 GID 就能自动添加到使用 PersistentVolume 的任何 Pod 中。
使用 `pv.beta.kubernetes.io/gid` 注解的方法如下所示:
```yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv1
annotations:
pv.beta.kubernetes.io/gid: "1234"
```
<!--
When a Pod consumes a PersistentVolume that has a GID annotation, the annotated GID
is applied to all Containers in the Pod in the same way that GIDs specified in the
Pod's security context are. Every GID, whether it originates from a PersistentVolume
annotation or the Pod's specification, is applied to the first process run in
each Container.
-->
当 Pod 使用带有 GID 注解的 PersistentVolume 时,注解的 GID 会被应用于 Pod 中的所有容器,
应用的方法与 Pod 的安全上下文中指定的 GID 相同。
每个 GID,无论是来自 PersistentVolume 注解还是来自 Pod 规约,都会被应用于每个容器中
运行的第一个进程。
<!--
When a Pod consumes a PersistentVolume, the GIDs associated with the
PersistentVolume are not present on the Pod resource itself.
-->
{{< note >}}
当 Pod 使用 PersistentVolume 时,与 PersistentVolume 关联的 GID 不会在 Pod
资源本身的对象上出现。
{{< /note >}}
## {{% heading "whatsnext" %}}
<!--
* Learn more about [PersistentVolumes](/docs/concepts/storage/persistent-volumes/).
* Read the [Persistent Storage design document](https://git.k8s.io/community/contributors/design-proposals/storage/persistent-storage.md).
-->
* 进一步了解 [PersistentVolumes](/zh/docs/concepts/storage/persistent-volumes/)
* 阅读[持久存储设计文档](https://git.k8s.io/community/contributors/design-proposals/storage/persistent-storage.md)
<!--
### Reference
-->
### 参考
* [PersistentVolume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolume-v1-core)
* [PersistentVolumeSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolumespec-v1-core)
* [PersistentVolumeClaim](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolumeclaim-v1-core)
* [PersistentVolumeClaimSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolumeclaimspec-v1-core)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,145 @@
---
title: 配置 Pod 初始化
content_type: task
weight: 130
---
<!--
title: Configure Pod Initialization
content_type: task
weight: 130
-->
<!-- overview -->
<!--
This page shows how to use an Init Container to initialize a Pod before an
application Container runs.
-->
本文介绍在应用容器运行前,怎样利用 Init 容器初始化 Pod。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Create a Pod that has an Init Container
In this exercise you create a Pod that has one application Container and one
Init Container. The init container runs to completion before the application
container starts.
Here is the configuration file for the Pod:
-->
## 创建一个包含 Init 容器的 Pod {#creating-a-pod-that-has-an-init-container}
本例中你将创建一个包含一个应用容器和一个 Init 容器的 Pod。Init 容器在应用容器启动前运行完成。
下面是 Pod 的配置文件:
{{< codenew file="pods/init-containers.yaml" >}}
<!--
In the configuration file, you can see that the Pod has a Volume that the init
container and the application container share.
The init container mounts the
shared Volume at `/work-dir`, and the application container mounts the shared
Volume at `/usr/share/nginx/html`. The init container runs the following command
and then terminates:
-->
配置文件中,你可以看到应用容器和 Init 容器共享了一个卷。
Init 容器将共享卷挂载到了 `/work-dir` 目录,应用容器将共享卷挂载到了 `/usr/share/nginx/html` 目录。
Init 容器执行完下面的命令就终止:
```shell
wget -O /work-dir/index.html http://info.cern.ch
```
<!--
Notice that the init container writes the `index.html` file in the root directory
of the nginx server.
Create the Pod:
-->
请注意 Init 容器在 nginx 服务器的根目录写入 `index.html`
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/init-containers.yaml
```
<!--
Verify that the nginx container is running:
-->
检查 nginx 容器运行正常:
```shell
kubectl get pod init-demo
```
<!--
The output shows that the nginx container is running:
-->
结果表明 nginx 容器运行正常:
```
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 1m
```
<!--
Get a shell into the nginx container running in the init-demo Pod:
-->
通过 shell 进入 init-demo Pod 中的 nginx 容器:
```shell
kubectl exec -it init-demo -- /bin/bash
```
<!--
In your shell, send a GET request to the nginx server:
-->
在 shell 中,发送个 GET 请求到 nginx 服务器:
```
root@nginx:~# apt-get update
root@nginx:~# apt-get install curl
root@nginx:~# curl localhost
```
<!--
The output shows that nginx is serving the web page that was written by the init container:
-->
结果表明 nginx 正在为 Init 容器编写的 web 页面服务:
```
<html><head></head><body><header>
<title>http://info.cern.ch</title>
</header>
<h1>http://info.cern.ch - home of the first website</h1>
...
<li><a href="http://info.cern.ch/hypertext/WWW/TheProject.html">Browse the first website</a></li>
...
```
## {{% heading "whatsnext" %}}
<!--
* Learn more about
[communicating between Containers running in the same Pod](/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/).
* Learn more about [Init Containers](/docs/concepts/workloads/pods/init-containers/).
* Learn more about [Volumes](/docs/concepts/storage/volumes/).
* Learn more about [Debugging Init Containers](/docs/tasks/debug/debug-application/debug-init-containers/)
-->
* 进一步了解[同一 Pod 中的容器间的通信](/zh/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/)。
* 进一步了解 [Init 容器](/zh/docs/concepts/workloads/pods/init-containers/)。
* 进一步了解[](/zh/docs/concepts/storage/volumes/)。
* 进一步了解 [Init 容器排错](/zh/docs/tasks/debug/debug-application/debug-init-containers/)。
@@ -0,0 +1,131 @@
---
title: 配置 Pod 使用投射卷作存储
content_type: task
weight: 70
---
<!--
reviewers:
- jpeeler
- pmorie
title: Configure a Pod to Use a Projected Volume for Storage
content_type: task
weight: 70
-->
<!-- overview -->
<!--
This page shows how to use a [`projected`](/docs/concepts/storage/volumes/#projected) volume to mount
several existing volume sources into the same directory. Currently, `secret`, `configMap`, `downwardAPI`,
and `serviceAccountToken` volumes can be projected.
-->
本文介绍怎样通过[`projected`](/zh/docs/concepts/storage/volumes/#projected) 卷将现有的多个卷资源挂载到相同的目录。
当前,`secret``configMap``downwardAPI``serviceAccountToken` 卷可以被投射。
<!--
`serviceAccountToken` is not a volume type.
-->
{{< note >}}
`serviceAccountToken` 不是一种卷类型
{{< /note >}}
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Configure a projected volume for a pod
In this exercise, you create username and password Secrets from local files. You then create a Pod that runs one Container, using a [`projected`](/docs/concepts/storage/volumes/#projected) Volume to mount the Secrets into the same shared directory.
Here is the configuration file for the Pod:
-->
## 为 Pod 配置 projected 卷
本练习中,你将从本地文件来创建包含有用户名和密码的 Secret。然后创建运行一个容器的 Pod,
该 Pod 使用[`projected`](/zh/docs/concepts/storage/volumes/#projected) 卷将 Secret 挂载到相同的路径下。
下面是 Pod 的配置文件:
{{< codenew file="pods/storage/projected.yaml" >}}
1. <!--Create the Secrets:-->
创建 Secret:
```shell
# 创建包含用户名和密码的文件:
echo -n "admin" > ./username.txt
echo -n "1f2d1e2e67df" > ./password.txt
# 将上述文件引用到 Secret:
kubectl create secret generic user --from-file=./username.txt
kubectl create secret generic pass --from-file=./password.txt
```
2. <!--Create the Pod:-->
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/storage/projected.yaml
```
3. <!--
Verify that the Pod's Container is running, and then watch for changes to
the Pod:
-->
确认 Pod 中的容器运行正常,然后监视 Pod 的变化:
```shell
kubectl get --watch pod test-projected-volume
```
<!--The output looks like this:-->
输出结果和下面类似:
```
NAME READY STATUS RESTARTS AGE
test-projected-volume 1/1 Running 0 14s
```
4. <!--In another terminal, get a shell to the running Container:-->
在另外一个终端中,打开容器的 shell:
```shell
kubectl exec -it test-projected-volume -- /bin/sh
```
5. <!--In your shell, verify that the `projected-volume` directory contains your projected sources:-->
在 shell 中,确认 `projected-volume` 目录包含你的投射源:
```shell
ls /projected-volume/
```
<!--
## Clean up
-->
## 清理
<!--
Delete the Pod and the Secrets:
-->
删除 Pod 和 Secret:
```shell
kubectl delete pod test-projected-volume
kubectl delete secret user pass
```
## {{% heading "whatsnext" %}}
<!--
* Learn more about [`projected`](/docs/concepts/storage/volumes/#projected) volumes.
* Read the [all-in-one volume](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/all-in-one-volume.md) design document.
-->
* 进一步了解[`projected`](/zh/docs/concepts/storage/volumes/#projected) 卷。
* 阅读[一体卷](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/all-in-one-volume.md)设计文档。
@@ -0,0 +1,227 @@
---
title: 为 Windows 的 Pod 和容器配置 RunAsUserName
content_type: task
weight: 20
---
<!--
title: Configure RunAsUserName for Windows pods and containers
content_type: task
weight: 20
-->
<!-- overview -->
{{< feature-state for_k8s_version="v1.18" state="stable" >}}
<!--
This page shows how to use the `runAsUserName` setting for Pods and containers that will run on Windows nodes. This is roughly equivalent of the Linux-specific `runAsUser` setting, allowing you to run applications in a container as a different username than the default.
-->
本页展示如何为运行为在 Windows 节点上运行的 Pod 和容器配置 `RunAsUserName`
大致相当于 Linux 上的 `runAsUser`,允许在容器中以与默认值不同的用户名运行应用。
## {{% heading "prerequisites" %}}
<!--
You need to have a Kubernetes cluster and the kubectl command-line tool must be configured to communicate with your cluster. The cluster is expected to have Windows worker nodes where pods with containers running Windows workloads will get scheduled.
-->
你必须有一个 Kubernetes 集群,并且 kubectl 必须能和集群通信。
集群应该要有 Windows 工作节点,将在其中调度运行 Windows 工作负载的 pod 和容器。
<!--
## Set the Username for a Pod
To specify the username with which to execute the Pod's container processes, include the
`securityContext` field ([PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core))
in the Pod specification, and within it, the `windowsOptions`
([WindowsSecurityContextOptions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#windowssecuritycontextoptions-v1-core)) field containing the `runAsUserName` field.
-->
## 为 Pod 设置 Username {#set-the-username-for-a-pod}
要指定运行 Pod 容器时所使用的用户名,请在 Pod 声明中包含 `securityContext`
([PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core)) 字段,
并在其内部包含 `windowsOptions`
([WindowsSecurityContextOptions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#windowssecuritycontextoptions-v1-core))
字段的 `runAsUserName` 字段。
<!--
The Windows security context options that you specify for a Pod apply to all Containers and init Containers in the Pod.
Here is a configuration file for a Windows Pod that has the `runAsUserName` field set:
-->
你为 Pod 指定的 Windows SecurityContext 选项适用于该 Pod 中(包括 init 容器)的所有容器。
这儿有一个已经设置了 `runAsUserName` 字段的 Windows Pod 的配置文件:
{{< codenew file="windows/run-as-username-pod.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/windows/run-as-username-pod.yaml
```
<!--
Verify that the Pod's Container is running:
-->
验证 Pod 容器是否在运行:
```shell
kubectl get pod run-as-username-pod-demo
```
<!--
Get a shell to the running Container:
-->
获取该容器的 shell
```shell
kubectl exec -it run-as-username-pod-demo -- powershell
```
<!--
Check that the shell is running user the correct username:
-->
检查运行 shell 的用户的用户名是否正确:
```powershell
echo $env:USERNAME
```
<!--
The output should be:
-->
输出结果应该是这样:
```
ContainerUser
```
<!--
## Set the Username for a Container
To specify the username with which to execute a Container's processes, include the `securityContext` field
([SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core))
in the Container manifest, and within it, the
`windowsOptions` ([WindowsSecurityContextOptions](/docs/reference/generated/kubernetes-api/{{< param
"version" >}}/#windowssecuritycontextoptions-v1-core)) field containing the `runAsUserName` field.
-->
## 为容器设置 Username {#set-the-username-for-a-container}
要指定运行容器时所使用的用户名,请在容器清单中包含 `securityContext`
([SecurityContext](/zh/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core))
字段,并在其内部包含 `windowsOptions`
[WindowsSecurityContextOptions](/zh/docs/reference/generated/kubernetes-api/{{< param
"version" >}}/#windowssecuritycontextoptions-v1-core)
字段的 `runAsUserName` 字段。
<!--
The Windows security context options that you specify for a Container apply only to that individual Container, and they override the settings made at the Pod level.
Here is the configuration file for a Pod that has one Container, and the `runAsUserName` field is set at the Pod level and the Container level:
-->
你为容器指定的 Windows SecurityContext 选项仅适用于该容器,并且它会覆盖 Pod 级别设置。
这里有一个 Pod 的配置文件,其中只有一个容器,并且在 Pod 级别和容器级别都设置了 `runAsUserName`
{{< codenew file="windows/run-as-username-container.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/windows/run-as-username-container.yaml
```
<!--
Verify that the Pod's Container is running:
-->
验证 Pod 容器是否在运行:
```shell
kubectl get pod run-as-username-container-demo
```
<!--
Get a shell to the running Container:
-->
获取该容器的 shell
```shell
kubectl exec -it run-as-username-container-demo -- powershell
```
<!--
Check that the shell is running user the correct username (the one set at the Container level):
-->
检查运行 shell 的用户的用户名是否正确(应该是容器级别设置的那个):
```powershell
echo $env:USERNAME
```
<!--
The output should be:
-->
输出结果应该是这样:
```
ContainerAdministrator
```
<!--
## Windows Username limitations
In order to use this feature, the value set in the `runAsUserName` field must be a valid username. It must have the following format: `DOMAIN\USER`, where `DOMAIN\` is optional. Windows user names are case insensitive. Additionally, there are some restrictions regarding the `DOMAIN` and `USER`:
-->
## Windows Username 的局限性 {#windows-username-limitations}
想要使用此功能,在 `runAsUserName` 字段中设置的值必须是有效的用户名。
它必须是 `DOMAIN\USER` 这种格式,其中 `DOMAIN\` 是可选的。
Windows 用户名不区分大小写。此外,关于 `DOMAIN``USER` 还有一些限制:
<!--
- The `runAsUserName` field cannot be empty, and it cannot contain control characters (ASCII values: `0x00-0x1F`, `0x7F`)
- The `DOMAIN` must be either a NetBios name, or a DNS name, each with their own restrictions:
- NetBios names: maximum 15 characters, cannot start with `.` (dot), and cannot contain the following characters: `\ / : * ? " < > |`
- DNS names: maximum 255 characters, contains only alphanumeric characters, dots, and dashes, and it cannot start or end with a `.` (dot) or `-` (dash).
- The `USER` must have at most 20 characters, it cannot contain *only* dots or spaces, and it cannot contain the following characters: `" / \ [ ] : ; | = , + * ? < > @`.
-->
- `runAsUserName` 字段不能为空,并且不能包含控制字符(ASCII 值:`0x00-0x1F``0x7F`
- `DOMAIN` 必须是 NetBios 名称或 DNS 名称,每种名称都有各自的局限性:
- NetBios 名称:最多 15 个字符,不能以 `.`(点)开头,并且不能包含以下字符:`\ / : * ? " < > |`
- DNS 名称:最多 255 个字符,只能包含字母、数字、点和中划线,并且不能以 `.`(点)或 `-`(中划线)开头和结尾。
- `USER` 最多不超过 20 个字符,不能 **只** 包含点或空格,并且不能包含以下字符:`" / \ [ ] : ; | = , + * ? < > @`
<!--
Examples of acceptable values for the `runAsUserName` field: `ContainerAdministrator`, `ContainerUser`, `NT AUTHORITY\NETWORK SERVICE`, `NT AUTHORITY\LOCAL SERVICE`.
For more information about these limtations, check [here](https://support.microsoft.com/en-us/help/909264/naming-conventions-in-active-directory-for-computers-domains-sites-and) and [here](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/new-localuser?view=powershell-5.1).
-->
`runAsUserName` 字段接受的值的一些示例:`ContainerAdministrator``ContainerUser`
`NT AUTHORITY\NETWORK SERVICE``NT AUTHORITY\LOCAL SERVICE`
关于这些限制的更多信息,可以查看[这里](https://support.microsoft.com/en-us/help/909264/naming-conventions-in-active-directory-for-computers-domains-sites-and)和[这里](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.localaccounts/new-localuser?view=powershell-5.1)。
## {{% heading "whatsnext" %}}
<!--
* [Guide for scheduling Windows containers in Kubernetes](/docs/concepts/windows/user-guide/)
* [Managing Workload Identity with Group Managed Service Accounts (GMSA)](/docs/concepts/windows/user-guide/#managing-workload-identity-with-group-managed-service-accounts)
* [Configure GMSA for Windows pods and containers](/docs/tasks/configure-pod-container/configure-gmsa/)
-->
* [Kubernetes 中调度 Windows 容器的指南](/zh/docs/concepts/windows/user-guide/)
* [使用组托管服务帐户(GMSA)管理工作负载身份](/zh/docs/concepts/windows/user-guide/#managing-workload-identity-with-group-managed-service-accounts)
* [Windows 下 pod 和容器的 GMSA 配置](/zh/docs/tasks/configure-pod-container/configure-gmsa/)
@@ -0,0 +1,646 @@
---
title: 为 Pod 配置服务账户
content_type: task
weight: 90
---
<!--
reviewers:
- bprashanth
- liggitt
- thockin
title: Configure Service Accounts for Pods
content_type: task
weight: 90
-->
<!-- overview -->
<!--
A service account provides an identity for processes that run in a Pod.
This document is a user introduction to Service Accounts and describes how service accounts behave in a cluster set up
as recommended by the Kubernetes project. Your cluster administrator may have
customized the behavior in your cluster, in which case this documentation may
not apply.
-->
服务账户为 Pod 中运行的进程提供了一个标识。
{{< note >}}
本文是服务账户的用户使用介绍,描述服务账号在集群中如何起作用。
你的集群管理员可能已经对你的集群做了定制,因此导致本文中所讲述的内容并不适用。
{{< /note >}}
<!--
When you (a human) access the cluster (for example, using `kubectl`), you are
authenticated by the apiserver as a particular User Account (currently this is
usually `admin`, unless your cluster administrator has customized your
cluster). Processes in containers inside pods can also contact the apiserver.
When they do, they are authenticated as a particular Service Account (for example,
`default`).
-->
当你(自然人)访问集群时(例如,使用 `kubectl`),API 服务器将你的身份验证为
特定的用户帐户(当前这通常是 `admin`,除非你的集群管理员已经定制了你的集群配置)。
Pod 内的容器中的进程也可以与 api 服务器接触。
当它们进行身份验证时,它们被验证为特定的服务帐户(例如,`default`)。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Use the Default Service Account to access the API server.
When you create a pod, if you do not specify a service account, it is
automatically assigned the `default` service account in the same namespace.
If you get the raw json or yaml for a pod you have created (for example, `kubectl get pods/podname -o yaml`),
you can see the `spec.serviceAccountName` field has been
[automatically set](/docs/user-guide/working-with-resources/#resources-are-automatically-modified).
-->
## 使用默认的服务账户访问 API 服务器
当你创建 Pod 时,如果没有指定服务账户,Pod 会被指定给命名空间中的 `default` 服务账户。
如果你查看 Pod 的原始 JSON 或 YAML(例如:`kubectl get pods/podname -o yaml`),
你可以看到 `spec.serviceAccountName` 字段已经被自动设置了。
<!--
You can access the API from inside a pod using automatically mounted service account credentials,
as described in [Accessing the Cluster](/docs/tasks/accessing-application-cluster/access-cluster/).
The API permissions of the service account depend on the [authorization plugin and policy](/docs/reference/access-authn-authz/authorization/#authorization-modules) in use.
In version 1.6+, you can opt out of automounting API credentials for a service account by setting
`automountServiceAccountToken: false` on the service account:
-->
你可以使用自动挂载给 Pod 的服务账户凭据访问 API,
[访问集群](/zh/docs/tasks/access-application-cluster/access-cluster/)页面中有相关描述。
服务账户的 API 许可取决于你所使用的
[鉴权插件和策略](/zh/docs/reference/access-authn-authz/authorization/#authorization-modules)。
在 1.6 以上版本中,你可以通过在服务账户上设置 `automountServiceAccountToken: false`
来实现不给服务账号自动挂载 API 凭据:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false
...
```
<!--
In version 1.6+, you can also opt out of automounting API credentials for a particular pod:
-->
在 1.6 以上版本中,你也可以选择不给特定 Pod 自动挂载 API 凭据:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: build-robot
automountServiceAccountToken: false
...
```
<!--
The pod spec takes precedence over the service account if both specify a `automountServiceAccountToken` value.
-->
如果 Pod 和服务账户都指定了 `automountServiceAccountToken` 值,则 Pod 的 spec 优先于服务帐户。
<!--
## Use Multiple Service Accounts.
Every namespace has a default service account resource called `default`.
You can list this and any other serviceAccount resources in the namespace with this command:
-->
## 使用多个服务账户 {#use-multiple-service-accounts}
每个命名空间都有一个名为 `default` 的服务账户资源。
你可以用下面的命令查询这个服务账户以及命名空间中的其他 ServiceAccount 资源:
```shell
kubectl get serviceAccounts
```
<!--
The output is similar to this:
-->
输出类似于:
```
NAME SECRETS AGE
default 1 1d
```
<!--
You can create additional ServiceAccount objects like this:
-->
你可以像这样来创建额外的 ServiceAccount 对象:
```shell
kubectl create -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
```
<!--
The name of a ServiceAccount object must be a valid
[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
-->
ServiceAccount 对象的名字必须是一个有效的
[DNS 子域名](/zh/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
<!--
If you get a complete dump of the service account object, like this:
-->
如果你查询服务帐户对象的完整信息,如下所示:
```shell
kubectl get serviceaccounts/build-robot -o yaml
```
<!--
The output is similar to this:
-->
输出类似于:
```none
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-06-16T00:12:59Z
name: build-robot
namespace: default
resourceVersion: "272500"
uid: 721ab723-13bc-11e5-aec2-42010af0021e
secrets:
- name: build-robot-token-bvbk5
```
<!--
then you will see that a token has automatically been created and is referenced by the service account.
You may use authorization plugins to [set permissions on service accounts](/docs/reference/access-authn-authz/rbac/#service-account-permissions).
To use a non-default service account, set the `spec.serviceAccountName`
field of a pod to the name of the service account you wish to use.
-->
那么你就能看到系统已经自动创建了一个令牌并且被服务账户所引用。
你可以使用授权插件来
[设置服务账户的访问许可](/zh/docs/reference/access-authn-authz/rbac/#service-account-permissions)。
要使用非默认的服务账户,将 Pod 的 `spec.serviceAccountName` 字段设置为你想用的服务账户名称。
<!--
The service account has to exist at the time the pod is created, or it will be rejected.
You cannot update the service account of an already created pod.
You can clean up the service account from this example like this:
-->
Pod 被创建时服务账户必须存在,否则会被拒绝。
你不能更新已经创建好的 Pod 的服务账户。
你可以清除服务账户,如下所示:
```shell
kubectl delete serviceaccount/build-robot
```
<!--
## Manually create a service account API token.
Suppose we have an existing service account named "build-robot" as mentioned above, and we create
a new secret manually.
-->
## 手动创建服务账户 API 令牌
假设我们有一个上面提到的名为 "build-robot" 的服务账户,然后我们手动创建一个新的 Secret。
```shell
kubectl create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
```
<!--
Now you can confirm that the newly built secret is populated with an API token for the "build-robot" service account.
Any tokens for non-existent service accounts will be cleaned up by the token controller.
-->
现在,你可以确认新构建的 Secret 中填充了 "build-robot" 服务帐户的 API 令牌。
令牌控制器将清理不存在的服务帐户的所有令牌。
```shell
kubectl describe secrets/build-robot-secret
```
<!--
The output is similar to this:
-->
输出类似于:
```
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: build-robot
kubernetes.io/service-account.uid: da68f9c6-9d26-11e7-b84e-002dc52800da
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1338 bytes
namespace: 7 bytes
token: ...
```
<!--
The content of `token` is elided here.
-->
{{< note >}}
这里省略了 `token` 的内容。
{{< /note >}}
<!--
## Add ImagePullSecrets to a service account
### Create an imagePullSecret
- Create an imagePullSecret, as described in [Specifying ImagePullSecret on a Pod](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
-->
## 为服务账户添加 ImagePullSecrets {#add-imagepullsecrets-to-a-service-account}
### 创建 ImagePullSecret
- 创建一个 ImagePullSecret,如同[为 Pod 设置 ImagePullSecret](/zh/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod)所述。
```shell
kubectl create secret docker-registry myregistrykey --docker-server=DUMMY_SERVER \
--docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \
--docker-email=DUMMY_DOCKER_EMAIL
```
<!--
- Verify it has been created.
-->
- 确认创建成功:
```shell
kubectl get secrets myregistrykey
```
<!-- The output is similar to this: -->
输出类似于:
```
NAME TYPE DATA AGE
myregistrykey   kubernetes.io/.dockerconfigjson   1       1d
```
<!--
### Add image pull secret to service account
Next, modify the default service account for the namespace to use this secret as an imagePullSecret.
-->
### 将镜像拉取 Secret 添加到服务账号
接着修改命名空间的 `default` 服务帐户,以将该 Secret 用作 `imagePullSecret`。
```shell
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
```
<!--
You can instead use `kubectl edit`, or manually edit the YAML manifests as shown below:
-->
你也可以使用 `kubectl edit`,或者如下所示手动编辑 YAML 清单:
```shell
kubectl get serviceaccounts default -o yaml > ./sa.yaml
```
`sa.yaml` 文件的内容类似于:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
```
<!--
Using your editor of choice (for example `vi`), open the `sa.yaml` file, delete line with key `resourceVersion`, add lines with `imagePullSecrets:` and save.
The output of the `sa.yaml` file is similar to this:
-->
使用你常用的编辑器(例如 `vi`),打开 `sa.yaml` 文件,删除带有键名
`resourceVersion` 的行,添加带有 `imagePullSecrets:` 的行,最后保存文件。
所得到的 `sa.yaml` 文件类似于:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey
```
<!--
Finally replace the serviceaccount with the new updated `sa.yaml` file
-->
最后,用新的更新的 `sa.yaml` 文件替换服务账号。
```shell
kubectl replace serviceaccount default -f ./sa.yaml
```
<!--
### Verify imagePullSecrets was added to pod spec
Now, when a new Pod is created in the current namespace and using the default ServiceAccount, the new Pod has its `spec.imagePullSecrets` field set automatically:
-->
### 验证镜像拉取 Secret 已经被添加到 Pod 规约
现在,在当前命名空间中创建使用默认服务账号的新 Pod 时,新 Pod
会自动设置其 `.spec.imagePullSecrets` 字段:
```shell
kubectl run nginx --image=nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
```
<!-- The output is: -->
输出为:
```
myregistrykey
```
<!--
## Service Account Token Volume Projection
-->
## 服务帐户令牌卷投射 {#service-account-token-volume-projection}
{{< feature-state for_k8s_version="v1.20" state="stable" >}}
<!--
To enable and use token request projection, you must specify each of the following
command line arguments to `kube-apiserver`:
-->
为了启用令牌请求投射,你必须为 `kube-apiserver` 设置以下命令行参数:
<!--
* `--service-account-issuer`
It can be used as the Identifier of the service account token issuer. You can specify the
`--service-account-issuer` argument multiple times, this can be useful to enable a non-disruptive
change of the issuer. When this flag is specified multiple times, the first is used to generate
tokens and all are used to determine which issuers are accepted. You must be running Kubernetes
v1.22 or later to be able to specify `--service-account-issuer` multiple times.
-->
* `--service-account-issuer`
此参数可作为服务账户令牌发放者的身份标识(Identifier)。你可以多次指定
`--service-account-issuer` 参数,对于要变更发放者而又不想带来业务中断的场景,
这样做是有用的。如果这个参数被多次指定,则第一个参数值会被用来生成令牌,
而所有参数值都会被用来确定哪些发放者是可接受的。你所运行的 Kubernetes
集群必须是 v1.22 或更高版本,才能多次指定 `--service-account-issuer`。
<!--
* `--service-account-key-file`
File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify
ServiceAccount tokens. The specified file can contain multiple keys, and the flag can be specified
multiple times with different files. If specified multiple times, tokens signed by any of the
specified keys are considered valid by the Kubernetes API server.
-->
* `--service-account-key-file`
包含 PEM 编码的 x509 RSA 或 ECDSA 私钥或公钥,用来检查 ServiceAccount
的令牌。所指定的文件中可以包含多个秘钥,并且你可以多次使用此参数,
每次参数值为不同的文件。多次使用此参数时,由所给的秘钥之一签名的令牌会被
Kubernetes API 服务器认为是合法令牌。
<!--
* `--service-account-signing-key-file`
Path to the file that contains the current private key of the service account token issuer. The
issuer signs issued ID tokens with this private key.
-->
* `--service-account-signing-key-file`
指向包含当前服务账户令牌发放者的私钥的文件路径。
此发放者使用此私钥来签署所发放的 ID 令牌。
<!--
* `--api-audiences` (can be omitted)
The service account token authenticator validates that tokens used against the API are bound to
at least one of these audiences. If `api-audiences` is specified multiple times, tokens for any of
the specified audiences are considered valid by the Kubernetes API server. If the
`--service-account-issuer` flag is configured and this flag is not, this field defaults to a
single element list containing the issuer URL.
-->
* `--api-audiences` (can be omitted)
服务账号令牌身份检查组件会检查针对 API 访问所使用的令牌,
确认令牌至少是被绑定到这里所给的受众(audiences)之一。
如果此参数被多次指定,则针对所给的多个受众中任何目标的令牌都会被
Kubernetes API 服务器当做合法的令牌。如果 `--service-account-issuer`
参数被设置,而这个参数未指定,则这个参数的默认值为一个只有一个元素的列表,
且该元素为令牌发放者的 URL。
<!--
The kubelet can also project a service account token into a Pod. You can
specify desired properties of the token, such as the audience and the validity
duration. These properties are not configurable on the default service account
token. The service account token will also become invalid against the API when
the Pod or the ServiceAccount is deleted.
-->
kubelet 还可以将服务帐户令牌投射到 Pod 中。
你可以指定令牌的期望属性,例如受众和有效期限。
这些属性在 default 服务帐户令牌上无法配置。
当删除 Pod 或 ServiceAccount 时,服务帐户令牌也将对 API 无效。
<!--
This behavior is configured on a PodSpec using a ProjectedVolume type called
[ServiceAccountToken](/docs/concepts/storage/volumes/#projected). To provide a
pod with a token with an audience of "vault" and a validity duration of two
hours, you would configure the following in your PodSpec:
-->
使用名为 [ServiceAccountToken](/zh/docs/concepts/storage/volumes/#projected) 的
ProjectedVolume 类型在 PodSpec 上配置此功能。
要向 Pod 提供具有 "vault" 用户以及两个小时有效期的令牌,可以在 PodSpec 中配置以下内容:
{{< codenew file="pods/pod-projected-svc-token.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml
```
<!--
The kubelet will request and store the token on behalf of the pod, make the
token available to the pod at a configurable file path, and refresh the token as it approaches expiration.
The kubelet proactively rotates the token if it is older than 80% of its total TTL, or if the token is older than 24 hours.
The application is responsible for reloading the token when it rotates. Periodic reloading (e.g. once every 5 minutes) is sufficient for most use cases.
-->
`kubelet` 组件会替 Pod 请求令牌并将其保存起来,
通过将令牌存储到一个可配置的路径使之在 Pod 内可用,
并在令牌快要到期的时候刷新它。
`kubelet` 会在令牌存在期达到其 TTL 的 80% 的时候或者令牌生命期超过
24 小时的时候主动轮换它。
应用程序负责在令牌被轮换时重新加载其内容。对于大多数使用场景而言,
周期性地(例如,每隔 5 分钟)重新加载就足够了。
<!--
## Service Account Issuer Discovery
-->
## 发现服务账号分发者
{{< feature-state for_k8s_version="v1.21" state="stable" >}}
<!--
The Service Account Issuer Discovery feature is enabled when the Service Account
Token Projection feature is enabled, as described
[above](#service-account-token-volume-projection).
-->
当启用服务账号令牌投射时启用发现服务账号分发者(Service Account Issuer Discovery
这一功能特性,如[上文所述](#service-account-token-volume-projection)。
<!--
The issuer URL must comply with the
[OIDC Discovery Spec](https://openid.net/specs/openid-connect-discovery-1_0.html). In
practice, this means it must use the `https` scheme, and should serve an OpenID
provider configuration at `{service-account-issuer}/.well-known/openid-configuration`.
If the URL does not comply, the `ServiceAccountIssuerDiscovery` endpoints will
not be registered, even if the feature is enabled.
-->
分发者的 URL 必须遵从
[OIDC 发现规范](https://openid.net/specs/openid-connect-discovery-1_0.html)。
这意味着 URL 必须使用 `https` 模式,并且必须在
`{service-account-issuer}/.well-known/openid-configuration`
路径给出 OpenID 提供者(Provider)配置。
如果 URL 没有遵从这一规范,`ServiceAccountIssuerDiscovery` 末端就不会被注册,
即使该特性已经被启用。
<!--
The Service Account Issuer Discovery feature enables federation of Kubernetes
service account tokens issued by a cluster (the _identity provider_) with
external systems (_relying parties_).
When enabled, the Kubernetes API server provides an OpenID Provider
Configuration document at `/.well-known/openid-configuration` and the associated
JSON Web Key Set (JWKS) at `/openid/v1/jwks`. The OpenID Provider Configuration
is sometimes referred to as the _discovery document_.
-->
发现服务账号分发者这一功能使得用户能够用联邦的方式结合使用 Kubernetes
集群(“Identity Provider”,标识提供者)与外部系统(“Relying Parties”,
依赖方)所分发的服务账号令牌。
当此功能被启用时,Kubernetes API 服务器会在 `/.well-known/openid-configuration`
提供一个 OpenID 提供者配置文档,并在 `/openid/v1/jwks` 处提供与之关联的
JSON Web Key SetJWKS)。
这里的 OpenID 提供者配置有时候也被称作“发现文档(Discovery Document)”。
<!--
Clusters include a default RBAC ClusterRole called
`system:service-account-issuer-discovery`. A default RBAC ClusterRoleBinding
assigns this role to the `system:serviceaccounts` group, which all service
accounts implicitly belong to. This allows pods running on the cluster to access
the service account discovery document via their mounted service account token.
Administrators may, additionally, choose to bind the role to
`system:authenticated` or `system:unauthenticated` depending on their security
requirements and which external systems they intend to federate with.
-->
集群包括一个的默认 RBAC ClusterRole, 名为 `system:service-account-issuer-discovery`。
默认的 RBAC ClusterRoleBinding 将此角色分配给 `system:serviceaccounts` 组,
所有服务帐户隐式属于该组。这使得集群上运行的 Pod
能够通过它们所挂载的服务帐户令牌访问服务帐户发现文档。
此外,管理员可以根据其安全性需要以及期望集成的外部系统选择是否将该角色绑定到
`system:authenticated` 或 `system:unauthenticated`。
<!--
The responses served at `/.well-known/openid-configuration` and
`/openid/v1/jwks` are designed to be OIDC compatible, but not strictly OIDC
compliant. Those documents contain only the parameters necessary to perform
validation of Kubernetes service account tokens.
-->
对 `/.well-known/openid-configuration` 和 `/openid/v1/jwks` 路径请求的响应
被设计为与 OIDC 兼容,但不是完全与其一致。
返回的文档仅包含对 Kubernetes 服务账号令牌进行验证所必须的参数。
<!--
The JWKS response contains public keys that a relying party can use to validate
the Kubernetes service account tokens. Relying parties first query for the
OpenID Provider Configuration, and use the `jwks_uri` field in the response to
find the JWKS.
-->
JWKS 响应包含依赖方可以用来验证 Kubernetes 服务账号令牌的公钥数据。
依赖方先会查询 OpenID 提供者配置,之后使用返回响应中的 `jwks_uri` 来查找 JWKS。
<!--
In many cases, Kubernetes API servers are not available on the public internet,
but public endpoints that serve cached responses from the API server can be made
available by users or service providers. In these cases, it is possible to
override the `jwks_uri` in the OpenID Provider Configuration so that it points
to the public endpoint, rather than the API server's address, by passing the
`--service-account-jwks-uri` flag to the API server. Like the issuer URL, the
JWKS URI is required to use the `https` scheme.
-->
在很多场合,Kubernetes API 服务器都不会暴露在公网上,不过对于缓存并向外提供 API
服务器响应数据的公开末端而言,用户或者服务提供商可以选择将其暴露在公网上。
在这种环境中,可能会重载 OpenID 提供者配置中的
`jwks_uri`,使之指向公网上可用的末端地址,而不是 API 服务器的地址。
这时需要向 API 服务器传递 `--service-account-jwks-uri` 参数。
与分发者 URL 类似,此 JWKS URI 也需要使用 `https` 模式。
## {{% heading "whatsnext" %}}
<!--
See also:
- [Cluster Admin Guide to Service Accounts](/docs/reference/access-authn-authz/service-accounts-admin/)
- [Service Account Signing Key Retrieval KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1393-oidc-discovery)
- [OIDC Discovery Spec](https://openid.net/specs/openid-connect-discovery-1_0.html)
-->
另请参见:
- [服务账号的集群管理员指南](/zh/docs/reference/access-authn-authz/service-accounts-admin/)
- [服务账号签署密钥检索 KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1393-oidc-discovery)
- [OIDC 发现规范](https://openid.net/specs/openid-connect-discovery-1_0.html)
@@ -0,0 +1,197 @@
---
title: 配置 Pod 以使用卷进行存储
content_type: task
weight: 50
---
<!--
title: Configure a Pod to Use a Volume for Storage
content_type: task
weight: 50
-->
<!-- overview -->
<!--
This page shows how to configure a Pod to use a Volume for storage.
A Container's file system lives only as long as the Container does. So when a
Container terminates and restarts, filesystem changes are lost. For more
consistent storage that is independent of the Container, you can use a
[Volume](/docs/concepts/storage/volumes/). This is especially important for stateful
applications, such as key-value stores (such as Redis) and databases.
-->
此页面展示了如何配置 Pod 以使用卷进行存储。
只要容器存在,容器的文件系统就会存在,因此当一个容器终止并重新启动,对该容器的文件系统改动将丢失。
对于独立于容器的持久化存储,你可以使用[](/zh/docs/concepts/storage/volumes/)。
这对于有状态应用程序尤为重要,例如键值存储(如 Redis)和数据库。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Configure a volume for a Pod
In this exercise, you create a Pod that runs one Container. This Pod has a
Volume of type
[emptyDir](/docs/concepts/storage/volumes/#emptydir)
that lasts for the life of the Pod, even if the Container terminates and
restarts. Here is the configuration file for the Pod:
-->
## 为 Pod 配置卷 {#configure-a-volume-for-a-pod}
在本练习中,你将创建一个运行 Pod,该 Pod 仅运行一个容器并拥有一个类型为
[emptyDir](/zh/docs/concepts/storage/volumes/#emptydir) 的卷,
在整个 Pod 生命周期中一直存在,即使 Pod 中的容器被终止和重启。以下是 Pod 的配置:
{{< codenew file="pods/storage/redis.yaml" >}}
<!--
1.Create the Pod:
-->
1. 创建 Pod:
```shell
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
```
<!--
1.Verify that the Pod's Container is running, and then watch for changes to the Pod:
-->
2. 验证 Pod 中的容器是否正在运行,然后留意 Pod 的更改:
```shell
kubectl get pod redis --watch
```
输出如下:
```shell
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
```
<!--
1.In another terminal, get a shell to the running Container:
-->
3. 在另一个终端,用 shell 连接正在运行的容器:
```shell
kubectl exec -it redis -- /bin/bash
```
<!--
1.In your shell, go to `/data/redis`, and then create a file:
-->
4. 在你的 Shell中,切换到 `/data/redis` 目录下,然后创建一个文件:
```shell
root@redis:/data# cd /data/redis/
root@redis:/data/redis# echo Hello > test-file
```
<!--
1.In your shell, list the running processes:
-->
5. 在你的 Shell 中,列出正在运行的进程:
```shell
root@redis:/data/redis# apt-get update
root@redis:/data/redis# apt-get install procps
root@redis:/data/redis# ps aux
```
输出类似于:
```shell
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379
root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash
root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux
```
<!--
1.In your shell, kill the Redis process:
-->
6. 在你的 Shell 中,结束 Redis 进程:
```shell
root@redis:/data/redis# kill <pid>
```
其中 `<pid>` 是 Redis 进程的 ID (PID)。
<!--
1. In your original terminal, watch for changes to the Redis Pod. Eventually,
you will see something like this:
-->
7. 在你原先终端中,留意 Redis Pod 的更改。最终你将会看到和下面类似的输出:
```shell
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
redis 0/1 Completed 0 6m
redis 1/1 Running 1 6m
```
<!--
At this point, the Container has terminated and restarted. This is because the
Redis Pod has a
[restartPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)
of `Always`.
-->
此时,容器已经终止并重新启动。这是因为 Redis Pod 的
[restartPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)
为 `Always`。
<!--
1.Get a shell into the restarted Container:
-->
1. 用 Shell 进入重新启动的容器中:
```shell
kubectl exec -it redis -- /bin/bash
```
<!--
1.In your shell, goto `/data/redis`, and verify that `test-file` is still there.
-->
2. 在你的 Shell 中,进入到 `/data/redis` 目录下,并确认 `test-file` 文件是否仍然存在。
```shell
root@redis:/data/redis# cd /data/redis/
root@redis:/data/redis# ls
test-file
```
<!--
1.Delete the Pod that you created for this exercise:
-->
3. 删除为此练习所创建的 Pod
```shell
kubectl delete pod redis
```
## {{% heading "whatsnext" %}}
<!--
* See [Volume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#volume-v1-core).
* See [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core).
* In addition to the local disk storage provided by `emptyDir`, Kubernetes
supports many different network-attached storage solutions, including PD on
GCE and EBS on EC2, which are preferred for critical data and will handle
details such as mounting and unmounting the devices on the nodes. See
[Volumes](/docs/concepts/storage/volumes/) for more details.
-->
* 参阅 [Volume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#volume-v1-core)。
* 参阅 [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)。
* 除了 `emptyDir` 提供的本地磁盘存储外,Kubernetes 还支持许多不同的网络附加存储解决方案,
包括 GCE 上的 PD 和 EC2 上的 EBS,它们是关键数据的首选,并将处理节点上的一些细节,
例如安装和卸载设备。了解更多详情请参阅[](/zh/docs/concepts/storage/volumes/)。
@@ -0,0 +1,346 @@
---
title: 创建 Windows HostProcess Pod
content_type: task
weight: 20
min-kubernetes-server-version: 1.23
---
<!--
title: Create a Windows HostProcess Pod
content_type: task
weight: 20
min-kubernetes-server-version: 1.23
-->
<!-- overview -->
{{< feature-state for_k8s_version="v1.23" state="beta" >}}
<!--
Windows HostProcess containers enable you to run containerized
workloads on a Windows host. These containers operate as
normal processes but have access to the host network namespace,
storage, and devices when given the appropriate user privileges.
HostProcess containers can be used to deploy network plugins,
storage configurations, device plugins, kube-proxy, and other
components to Windows nodes without the need for dedicated proxies or
the direct installation of host services.
-->
Windows HostProcess 容器让你能够在 Windows 主机上运行容器化负载。
这类容器以普通的进程形式运行,但能够在具有合适用户特权的情况下,
访问主机网络名字空间、存储和设备。HostProcess 容器可用来在 Windows
节点上部署网络插件、存储配置、设备插件、kube-proxy 以及其他组件,
同时不需要配置专用的代理或者直接安装主机服务。
<!--
Administrative tasks such as installation of security patches, event
log collection, and more can be performed without requiring cluster operators to
log onto each Windows node. HostProcess containers can run as any user that is
available on the host or is in the domain of the host machine, allowing administrators
to restrict resource access through user permissions. While neither filesystem or process
isolation are supported, a new volume is created on the host upon starting the container
to give it a clean and consolidated workspace. HostProcess containers can also be built on
top of existing Windows base images and do not inherit the same
[compatibility requirements](https://docs.microsoft.com/virtualization/windowscontainers/deploy-containers/version-compatibility)
as Windows server containers, meaning that the version of the base images does not need
to match that of the host. It is, however, recommended that you use the same base image
version as your Windows Server container workloads to ensure you do not have any unused
images taking up space on the node. HostProcess containers also support
[volume mounts](#volume-mounts) within the container volume.
-->
类似于安装安全补丁、事件日志收集等这类管理性质的任务可以在不需要集群操作员登录到每个
Windows 节点的前提下执行。HostProcess 容器可以以主机上存在的任何用户账户来运行,
也可以以主机所在域中的用户账户运行,这样管理员可以通过用户许可权限来限制资源访问。
尽管文件系统和进程隔离都不支持,在启动容器时会在主机上创建一个新的卷,
为其提供一个干净的、整合的工作空间。HostProcess 容器也可以基于现有的 Windows
基础镜像来制作,并且不再有 Windows 服务器容器所带有的那些
[兼容性需求](https://docs.microsoft.com/virtualization/windowscontainers/deploy-containers/version-compatibility)
这意味着基础镜像的版本不必与主机操作系统的版本匹配。
不过,仍然建议你像使用 Windows 服务器容器负载那样,使用相同的基础镜像版本,
这样你就不会有一些未使用的镜像占用节点上的存储空间。HostProcess 容器也支持
在容器卷内执行[卷挂载](#volume-mounts)。
<!--
### When should I use a Windows HostProcess container?
- When you need to perform tasks which require the networking namespace of the host.
HostProcess containers have access to the host's network interfaces and IP addresses.
- You need access to resources on the host such as the filesystem, event logs, etc.
- Installation of specific device drivers or Windows services.
- Consolidation of administrative tasks and security policies. This reduces the degree of
privileges needed by Windows nodes.
-->
### 我何时该使用 Windows HostProcess 容器?
- 当你准备执行需要访问主机上网络名字空间的任务时,HostProcess
容器能够访问主机上的网络接口和 IP 地址。
- 当你需要访问主机上的资源,如文件系统、事件日志等等。
- 需要安装特定的设备驱动或者 Windows 服务时。
- 需要对管理任务和安全策略进行整合时。使用 HostProcess 容器能够缩小 Windows
节点上所需要的特权范围。
## {{% heading "prerequisites" %}}
<!-- change this when graduating to stable -->
<!--
This task guide is specific to Kubernetes v{{< skew currentVersion >}}.
If you are not running Kubernetes v{{< skew currentVersion >}}, check the documentation for
that version of Kubernetes.
In Kubernetes {{< skew currentVersion >}}, the HostProcess container feature is enabled by default. The kubelet will
communicate with containerd directly by passing the hostprocess flag via CRI. You can use the
latest version of containerd (v1.6+) to run HostProcess containers.
[How to install containerd.](/docs/setup/production-environment/container-runtimes/#containerd)
-->
本任务指南是特定于 Kubernetes v{{< skew currentVersion >}} 的。
如果你运行的不是 Kubernetes v{{< skew currentVersion >}},请移步访问正确
版本的 Kubernetes 文档。
在 Kubernetes v{{< skew currentVersion >}} 中,HostProcess 容器功能特性默认是启用的。
kubelet 会直接与 containerd 通信,通过 CRI 将主机进程标志传递过去。
你可以使用 containerd 的最新版本(v1.6+)来运行 HostProcess 容器。
参阅[如何安装 containerd](/zh/docs/setup/production-environment/container-runtimes/#containerd)。
<!--
To *disable* HostProcess containers you need to pass the following feature gate flag to the
**kubelet** and **kube-apiserver**:
-->
*禁用* HostProcess 容器特性,你需要为 **kubelet****kube-apiserver**
设置下面的特性门控标志:
```powershell
--feature-gates=WindowsHostProcessContainers=false
```
<!--
See [Features Gates](/docs/reference/command-line-tools-reference/feature-gates/#overview)
documentation for more details.
-->
进一步的细节可参阅[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/#overview)文档。
<!--
## Limitations
These limitations are relevant for Kubernetes v{{< skew currentVersion >}}:
-->
## 限制 {#limitations}
以下限制是与 Kubernetes v{{< skew currentVersion >}} 相关的:
<!--
- HostProcess containers require containerd 1.6 or higher
{{< glossary_tooltip text="container runtime" term_id="container-runtime" >}}.
- HostProcess pods can only contain HostProcess containers. This is a current limitation
of the Windows OS; non-privileged Windows containers cannot share a vNIC with the host IP namespace.
- HostProcess containers run as a process on the host and do not have any degree of
isolation other than resource constraints imposed on the HostProcess user account. Neither
filesystem or Hyper-V isolation are supported for HostProcess containers.
-->
- HostProcess 容器需要 containerd 1.6 或更高版本的
{{< glossary_tooltip text="容器运行时" term_id="container-runtime" >}}。
- HostProcess Pods 只能包含 HostProcess 容器。这是在 Windows 操作系统上的约束;
非特权的 Windows 容器不能与主机 IP 名字空间共享虚拟网卡(vNIC)。
- HostProcess 在主机上以一个进程的形式运行,除了通过 HostProcess
用户账号所实施的资源约束外,不提供任何形式的隔离。HostProcess 容器不支持文件系统或
Hyper-V 隔离。
<!--
- Volume mounts are supported and are mounted under the container volume. See
[Volume Mounts](#volume-mounts)
- A limited set of host user accounts are available for HostProcess containers by default.
See [Choosing a User Account](#choosing-a-user-account).
- Resource limits (disk, memory, cpu count) are supported in the same fashion as processes
on the host.
- Both Named pipe mounts and Unix domain sockets are **not** supported and should instead
be accessed via their path on the host (e.g. \\\\.\\pipe\\\*)
-->
- 卷挂载是被支持的,并且要花在到容器卷下。参见[卷挂载](#volume-mounts)。
- 默认情况下有一组主机用户账户可供 HostProcess 容器使用。
参见[选择用户账号](#choosing-a-user-account)。
- 对资源约束(磁盘、内存、CPU 个数)的支持与主机上进程相同。
- **不支持**命名管道或者 UNIX 域套接字形式的挂载,需要使用主机上的路径名来访问
(例如,\\\\.\\pipe\\\*)。
<!--
## HostProcess Pod configuration requirements
-->
## HostProcess Pod 配置需求 {#hostprocess-pod-configuration-requirements}
<!--
Enabling a Windows HostProcess pod requires setting the right configurations in the pod security
configuration. Of the policies defined in the [Pod Security Standards](/docs/concepts/security/pod-security-standards)
HostProcess pods are disallowed by the baseline and restricted policies. It is therefore recommended
that HostProcess pods run in alignment with the privileged profile.
When running under the privileged policy, here are
the configurations which need to be set to enable the creation of a HostProcess pod:
-->
启用 Windows HostProcess Pod 需要在 Pod 安全配置中设置合适的选项。
在 [Pod
安全标准](/zh/docs/concepts/security/pod-security-standards)中所定义的策略中,
HostProcess Pod 默认是不被 basline 和 restricted 策略支持的。因此建议
HostProcess 运行在与 privileged 模式相看齐的策略下。
当运行在 privileged 策略下时,下面是要启用 HostProcess Pod 创建所需要设置的选项:
<table>
<caption style="display: none"><!--Privileged policy specification-->privileged 策略规约</caption>
<thead>
<tr>
<th><!--Control-->控制</th>
<th><!--Policy-->策略</th>
</tr>
</thead>
<tbody>
<tr>
<td style="white-space: nowrap"><a href="/zh/docs/concepts/security/pod-security-standards"><tt>securityContext.windowsOptions.hostProcess</tt></a></td>
<td>
<p><!--Windows pods offer the ability to run <a href="/docs/tasks/configure-pod-container/create-hostprocess-pod">
HostProcess containers</a> which enables privileged access to the Windows node.-->
Windows Pods 提供运行<a href="/zh/docs/tasks/configure-pod-container/create-hostprocess-pod">
HostProcess 容器</a>的能力,这类容器能够具有对 Windows 节点的特权访问权限。</p>
<p><strong><!--Allowed Values-->可选值</strong></p>
<ul>
<li><code>true</code></li>
</ul>
</td>
</tr>
<tr>
<td style="white-space: nowrap"><a href="/zh/docs/concepts/security/pod-security-standards"><tt>hostNetwork</tt></a></td>
<td>
<p><!--Will be in host network by default initially. Support
to set network to a different compartment may be desirable in
the future.-->
初始时将默认位于主机网络中。在未来可能会希望将网络设置到不同的隔离环境中。
</p>
<p><strong><!--Allowed Values-->可选值</strong></p>
<ul>
<li><code>true</code></li>
</ul>
</td>
</tr>
<tr>
<td style="white-space: nowrap"><a href="/zh/docs/tasks/configure-pod-container/configure-runasusername/"><tt>securityContext.windowsOptions.runAsUsername</tt></a></td>
<td>
<p><!--Specification of which user the HostProcess container should run as is required for the pod spec.-->
关于 HostProcess 容器所要使用的用户的规约,需要设置在 Pod 的规约中。
</p>
<p><strong><!--Allowed Values-->可选值</strong></p>
<ul>
<li><code>NT AUTHORITY\SYSTEM</code></li>
<li><code>NT AUTHORITY\Local service</code></li>
<li><code>NT AUTHORITY\NetworkService</code></li>
</ul>
</td>
</tr>
<tr>
<td style="white-space: nowrap"><a href="/zh/docs/concepts/security/pod-security-standards"><tt>runAsNonRoot</tt></a></td>
<td>
<p><!--Because HostProcess containers have privileged access to the host, the <tt>runAsNonRoot</tt> field cannot be set to true.-->
因为 HostProcess 容器有访问主机的特权,<tt>runAsNonRoot</tt> 字段不可以设置为 true。
</p>
<p><strong><!--Allowed Values-->可选值</strong></p>
<ul>
<li><!--Undefined/Nil-->未定义/Nil</li>
<li><code>false</code></li>
</ul>
</td>
</tr>
</tbody>
</table>
<!--
### Example manifest (excerpt) {#manifest-example}
-->
### 配置清单示例(片段) {#manifest-example}
```yaml
spec:
securityContext:
windowsOptions:
hostProcess: true
runAsUserName: "NT AUTHORITY\\Local service"
hostNetwork: true
containers:
- name: test
image: image1:latest
command:
- ping
- -t
- 127.0.0.1
nodeSelector:
"kubernetes.io/os": windows
```
<!--
## Volume mounts
HostProcess containers support the ability to mount volumes within the container volume space.
Applications running inside the container can access volume mounts directly via relative or
absolute paths. An environment variable `$CONTAINER_SANDBOX_MOUNT_POINT` is set upon container
creation and provides the absolute host path to the container volume. Relative paths are based
upon the `.spec.containers.volumeMounts.mountPath` configuration.
-->
## 卷挂载 {#volume-mounts}
HostProcess 容器支持在容器卷空间中挂载卷的能力。
在容器内运行的应用能够通过相对或者绝对路径直接访问卷挂载。
环境变量 `$CONTAINER_SANDBOX_MOUNT_POINT` 在容器创建时被设置为指向容器卷的绝对主机路径。
相对路径是基于 `.spec.containers.volumeMounts.mountPath` 配置来推导的。
<!--
### Example {#volume-mount-example}
To access service account tokens the following path structures are supported within the container:
-->
### 示例 {#volume-mount-example}
容器内支持通过下面的路径结构来访问服务账好令牌:
`.\var\run\secrets\kubernetes.io\serviceaccount\`
`$CONTAINER_SANDBOX_MOUNT_POINT\var\run\secrets\kubernetes.io\serviceaccount\`
<!--
## Resource limits
Resource limits (disk, memory, cpu count) are applied to the job and are job wide.
For example, with a limit of 10MB set, the memory allocated for any HostProcess job object
will be capped at 10MB. This is the same behavior as other Windows container types.
These limits would be specified the same way they are currently for whatever orchestrator
or runtime is being used. The only difference is in the disk resource usage calculation
used for resource tracking due to the difference in how HostProcess containers are bootstrapped.
-->
## 资源约束 {#resource-limits}
资源约束(磁盘、内存、CPU 个数)作用到任务之上,并在整个任务上起作用。
例如,如果内存限制设置为 10MB,任何 HostProcess 任务对象所分配的内存不会超过 10MB。
这一行为与其他 Windows 容器类型相同。资源限制的设置方式与编排系统或容器运行时无关。
唯一的区别是用来跟踪资源所进行的磁盘资源用量的计算,出现差异的原因是因为
HostProcess 容器启动引导的方式造成的。
<!--
## Choosing a user account
HostProcess containers support the ability to run as one of three supported Windows service accounts:
-->
## 选择用户账号 {#choosing-a-user-account}
HostProcess 容器支持以三种被支持的 Windows 服务账号之一来运行:
- **[LocalSystem](https://docs.microsoft.com/windows/win32/services/localsystem-account)**
- **[LocalService](https://docs.microsoft.com/windows/win32/services/localservice-account)**
- **[NetworkService](https://docs.microsoft.com/windows/win32/services/networkservice-account)**
<!--
You should select an appropriate Windows service account for each HostProcess
container, aiming to limit the degree of privileges so as to avoid accidental (or even
malicious) damage to the host. The LocalSystem service account has the highest level
of privilege of the three and should be used only if absolutely necessary. Where possible,
use the LocalService service account as it is the least privileged of the three options.
-->
你应该为每个 HostProcess 容器选择一个合适的 Windows 服务账号,尝试限制特权范围,
避免给主机代理意外的(甚至是恶意的)伤害。LocalSystem 服务账号的特权级
在三者之中最高,只有在绝对需要的时候才应该使用。只要可能,应该使用
LocalService 服务账号,因为该账号在三者中特权最低。
@@ -0,0 +1,120 @@
---
title: 通过配置内置准入控制器实施 Pod 安全标准
content_type: task
min-kubernetes-server-version: v1.22
---
<!--
title: Enforce Pod Security Standards by Configuring the Built-in Admission Controller
reviewers:
- tallclair
- liggitt
content_type: task
min-kubernetes-server-version: v1.22
-->
<!--
As of v1.22, Kubernetes provides a built-in [admission controller](/docs/reference/access-authn-authz/admission-controllers/#podsecurity)
to enforce the [Pod Security Standards](/docs/concepts/security/pod-security-standards).
You can configure this admission controller to set cluster-wide defaults and [exemptions](/docs/concepts/security/pod-security-admission/#exemptions).
-->
在 v1.22 版本中,Kubernetes 提供一种内置的[准入控制器](/zh/docs/reference/access-authn-authz/admission-controllers/#podsecurity)
用来强制实施 [Pod 安全标准](/zh/docs/concepts/security/pod-security-standards)。
你可以配置此准入控制器来设置集群范围的默认值和[豁免选项](/zh/docs/concepts/security/pod-security-admission/#exemptions)。
## {{% heading "prerequisites" %}}
{{% version-check %}}
<!--
- Ensure the `PodSecurity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features) is enabled.
-->
- 确保 `PodSecurity` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features)已被启用。
<!--
## Configure the Admission Controller
-->
## 配置准入控制器 {#configure-the-admission-controller}
{{< tabs name="PodSecurityConfiguration_example_1" >}}
{{% tab name="pod-security.admission.config.k8s.io/v1beta1" %}}
```yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1beta1
kind: PodSecurityConfiguration
# 当未设置 mode 标签时会应用的默认设置
#
# level 标签必须是以下取值之一:
# - "privileged" (默认)
# - "baseline"
# - "restricted"
#
# version 标签必须是如下取值之一:
# - "latest" (默认)
# - 诸如 "v{{< skew latestVersion >}}" 这类版本号
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
# 要豁免的已认证用户名列表
usernames: []
# 要豁免的运行时类名称列表
runtimeClasses: []
# 要豁免的名字空间列表
namespaces: []
```
{{< note >}}
<!--
v1beta1 configuration requires v1.23+. For v1.22, use v1alpha1.
-->
v1beta1 配置结构需要使用 v1.23+ 版本;对于 v1.22 版本,可使用 v1alpha1。
{{< /note >}}
{{% /tab %}}
{{% tab name="pod-security.admission.config.k8s.io/v1alpha1" %}}
```yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1alpha1
kind: PodSecurityConfiguration
# 当未设置 mode 标签时会应用的默认设置
#
# level 标签必须是以下取值之一:
# - "privileged" (默认)
# - "baseline"
# - "restricted"
#
# version 标签必须是如下取值之一:
# - "latest" (默认)
# - 诸如 "v{{< skew latestVersion >}}" 这类版本号
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
# 要豁免的已认证用户名列表
usernames: []
# 要豁免的运行时类名称列表
runtimeClasses: []
# 要豁免的名字空间列表
namespaces: []
```
{{% /tab %}}
{{< /tabs >}}
@@ -0,0 +1,148 @@
---
title: 使用名字空间标签来实施 Pod 安全性标准
content_type: task
min-kubernetes-server-version: v1.22
---
<!--
title: Enforce Pod Security Standards with Namespace Labels
reviewers:
- tallclair
- liggitt
content_type: task
min-kubernetes-server-version: v1.22
-->
<!--
Namespaces can be labeled to enforce the [Pod Security Standards](/docs/concepts/security/pod-security-standards).The three policies
[privileged](/docs/concepts/security/pod-security-standards/#privileged), [baseline](/docs/concepts/security/pod-security-standards/#baseline)
and [restricted](/docs/concepts/security/pod-security-standards/#restricted) broadly cover the security spectrum
and are implemented by the [Pod Security](/docs/concepts/security/pod-security-admission/)
-->
[特权(privileged](/zh/docs/concepts/security/pod-security-standards/#privileged)、
[基线(baseline](/zh/docs/concepts/security/pod-security-standards/#baseline)和
[受限(restricted](/zh/docs/concepts/security/pod-security-standards/#restricted)
这三种策略涵盖了广泛安全范围,并由 [Pod 安全](/zh/docs/concepts/security/pod-security-admission/)
{{< glossary_tooltip text="准入控制器" term_id="admission-controller" >}}实现。
## {{% heading "prerequisites" %}}
{{% version-check %}}
<!--
- Ensure the `PodSecurity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features) is enabled.
-->
- 确保 `PodSecurity` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features)已被启用。
<!--
## Requiring the `baseline` Pod Security Standard with namespace labels
-->
## 通过名字空间标签来要求实施 `baseline` Pod 容器标准
<!--
This manifest defines a Namespace `my-baseline-namespace` that:
- _Blocks_ any pods that don't satisfy the `baseline` policy requirements.
- Generates a user-facing warning and adds an audit annotation to any created pod that does not
meet the `restricted` policy requirements.
- Pins the versions of the `baseline` and `restricted` policies to v{{< skew latestVersion >}}.
-->
下面的清单定义了一个 `my-baseline-namespace` 名字空间,其中
- *阻止*任何不满足 `baseline` 策略要求的 Pods
- 针对任何无法满足 `restricted` 策略要求的、已创建的 Pod 为用户生成警告信息,
并添加审计注解;
-`baseline``restricted` 策略的版本锁定到 v{{< skew latestVersion >}}。
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: my-baseline-namespace
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: v{{< skew latestVersion >}}
# 我们将这些标签设置为我们所 _期望_ 的 `enforce` 级别
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v{{< skew latestVersion >}}
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v{{< skew latestVersion >}}
```
<!--
## Add labels to existing namespaces with `kubectl label`
-->
## 使用 `kubectl label` 为现有名字空间添加标签
{{< note >}}
<!--
When an `enforce` policy (or version) label is added or changed, the admission plugin will test
each pod in the namespace against the new policy. Violations are returned to the user as warnings.
-->
在添加或变更 `enforce` 策略(或版本)标签时,准入插件会测试名字空间中的每个
Pod 以检查其是否满足新的策略。不符合策略的情况会被以警告的形式返回给用户。
{{< /note >}}
<!--
It is helpful to apply the `--dry-run` flag when initially evaluating security profile changes for
namespaces. The Pod Security Standard checks will still be run in _dry run_ mode, giving you
information about how the new policy would treat existing pods, without actually updating a policy.
-->
在刚开始为名字空间评估安全性策略变更时,使用 `--dry-run` 标志是很有用的。
Pod 安全性标准会在 _dry run(试运行)_
模式下运行,在这种模式下会生成新策略如何处理现有 Pod 的信息,
但不会真正更新策略。
```shell
kubectl label --dry-run=server --overwrite ns --all \
pod-security.kubernetes.io/enforce=baseline
```
<!--
### Applying to all namespaces
-->
### 应用到所有名字空间
<!--
If you're just getting started with the Pod Security Standards, a suitable first step would be to
configure all namespaces with audit annotations for a stricter level such as `baseline`:
-->
如果你是刚刚开始使用 Pod 安全性标准,一种比较合适的初始步骤是针对所有名字空间为类似
`baseline` 这种比较严格的安全级别配置审计注解。
```shell
kubectl label --overwrite ns --all \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/warn=baseline
```
<!--
Note that this is not setting an enforce level, so that namespaces that haven't been explicitly
evaluated can be distinguished. You can list namespaces without an explicitly set enforce level
using this command:
-->
注意,这里没有设置 enforce 级别,因而没有被显式评估的名字空间可以被识别出来。
你可以使用下面的命令列举那些没有显式设置 enforce 级别的名字空间:
```shell
kubectl get namespaces --selector='!pod-security.kubernetes.io/enforce'
```
<!--
### Applying to a single namespace
-->
### 应用到单个名字空间
<!--
You can update a specific namespace as well. This command adds the `enforce=restricted`
policy to `my-existing-namespace`, pinning the restricted policy version to v{{< skew latestVersion >}}.
-->
你也可以更新特定的名字空间。下面的命令将 `enforce=restricted` 策略应用到
`my-existing-namespace` 名字空间,将 restricted 策略的版本锁定到 v{{< skew latestVersion >}}。
```shell
kubectl label --overwrite ns my-existing-namespace \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=v{{< skew latestVersion >}}
```
@@ -0,0 +1,209 @@
---
title: 为容器分派扩展资源
content_type: task
weight: 40
---
<!--
title: Assign Extended Resources to a Container
content_type: task
weight: 40
-->
<!-- overview -->
{{< feature-state state="stable" >}}
<!--
This page shows how to assign extended resources to a Container.
-->
本文介绍如何为容器指定扩展资源。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!--
Before you do this exercise, do the exercise in
[Advertise Extended Resources for a Node](/docs/tasks/administer-cluster/extended-resource-node/).
That will configure one of your Nodes to advertise a dongle resource.
-->
在你开始此练习前,请先练习
[为节点广播扩展资源](/zh/docs/tasks/administer-cluster/extended-resource-node/)。
在那个练习中将配置你的一个节点来广播 dongle 资源。
<!-- steps -->
<!--
## Assign an extended resource to a Pod
To request an extended resource, include the `resources:requests` field in your
Container manifest. Extended resources are fully qualified with any domain outside of
`*.kubernetes.io/`. Valid extended resource names have the form `example.com/foo` where
`example.com` is replaced with your organization's domain and `foo` is a
descriptive resource name.
Here is the configuration file for a Pod that has one Container:
-->
## 给 Pod 分派扩展资源
要请求扩展资源,需要在你的容器清单中包括 `resources:requests` 字段。
扩展资源可以使用任何完全限定名称,只是不能使用 `*.kubernetes.io/`
有效的扩展资源名的格式为 `example.com/foo`,其中 `example.com` 应被替换为
你的组织的域名,而 `foo` 则是描述性的资源名称。
下面是包含一个容器的 Pod 配置文件:
{{< codenew file="pods/resource/extended-resource-pod.yaml" >}}
<!--
In the configuration file, you can see that the Container requests 3 dongles.
Create a Pod:
-->
在配置文件中,你可以看到容器请求了 3 个 dongles。
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod.yaml
```
<!--
Verify that the Pod is running:
-->
检查 Pod 是否运行正常:
```shell
kubectl get pod extended-resource-demo
```
<!--
Describe the Pod:
-->
描述 Pod:
```shell
kubectl describe pod extended-resource-demo
```
<!--
The output shows dongle requests:
-->
输出结果显示 dongle 请求如下:
```yaml
Limits:
example.com/dongle: 3
Requests:
example.com/dongle: 3
```
<!--
## Attempt to create a second Pod
Here is the configuration file for a Pod that has one Container. The Container requests
two dongles.
-->
## 尝试创建第二个 Pod
下面是包含一个容器的 Pod 配置文件,容器请求了 2 个 dongles。
{{< codenew file="pods/resource/extended-resource-pod-2.yaml" >}}
<!--
Kubernetes will not be able to satisfy the request for two dongles, because the first Pod
used three of the four available dongles.
Attempt to create a Pod:
-->
Kubernetes 将不能满足 2 个 dongles 的请求,因为第一个 Pod 已经使用了 4 个可用 dongles 中的 3 个。
尝试创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod-2.yaml
```
<!--
Describe the Pod
-->
描述 Pod
```shell
kubectl describe pod extended-resource-demo-2
```
<!--
The output shows that the Pod cannot be scheduled, because there is no Node that has
2 dongles available:
-->
输出结果表明 Pod 不能被调度,因为没有一个节点上存在两个可用的 dongles。
```
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (extended-resource-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient example.com/dongle (1)
```
<!--
View the Pod status:
-->
查看 Pod 的状态:
```shell
kubectl get pod extended-resource-demo-2
```
<!--
The output shows that the Pod was created, but not scheduled to run on a Node.
It has a status of Pending:
-->
输出结果表明 Pod 虽然被创建了,但没有被调度到节点上正常运行。Pod 的状态为 Pending
```
NAME READY STATUS RESTARTS AGE
extended-resource-demo-2 0/1 Pending 0 6m
```
<!--
## Clean up
Delete the Pods that you created for this exercise:
-->
## 清理
删除本练习中创建的 Pod
```shell
kubectl delete pod extended-resource-demo
kubectl delete pod extended-resource-demo-2
```
## {{% heading "whatsnext" %}}
<!--
### For application developers
* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)
-->
## 应用开发者参考
* [为容器和 Pod 分配内存资源](/zh/docs/tasks/configure-pod-container/assign-memory-resource/)
* [为容器和 Pod 分配 CPU 资源](/zh/docs/tasks/configure-pod-container/assign-cpu-resource/)
<!--
### For cluster administrators
* [Advertise Extended Resources for a Node](/docs/tasks/administer-cluster/extended-resource-node/)
-->
### 集群管理员参考
* [为节点广播扩展资源](/zh/docs/tasks/administer-cluster/extended-resource-node/)
@@ -0,0 +1,668 @@
---
title: 从 PodSecurityPolicy 迁移到内置的 PodSecurity 准入控制器
content_type: task
min-kubernetes-server-version: v1.22
---
<!--
title: Migrate from PodSecurityPolicy to the Built-In PodSecurity Admission Controller
reviewers:
- tallclair
- liggitt
content_type: task
min-kubernetes-server-version: v1.22
-->
<!-- overview -->
<!--
This page describes the process of migrating from PodSecurityPolicies to the built-in PodSecurity
admission controller. This can be done effectively using a combination of dry-run and `audit` and
`warn` modes, although this becomes harder if mutating PSPs are used.
-->
本页面描述从 PodSecurityPolicy 迁移到内置的 PodSecurity 准入控制器的过程。
这一迁移过程可以通过综合使用试运行、`audit``warn` 模式等来实现,
尽管在使用了变更式 PSP 时会变得有些困难。
## {{% heading "prerequisites" %}}
{{% version-check %}}
<!--
- Ensure the `PodSecurity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/#feature-gates-for-alpha-or-beta-features) is enabled.
-->
- 确保 `PodSecurity` [特性门控](/docs/reference/command-line-tools-reference/feature-gates/)被启用。
<!--
This page assumes you are already familiar with the basic [Pod Security Admission](/docs/concepts/security/pod-security-admission/)
concepts.
-->
本页面假定你已经熟悉 [Pod 安全性准入](/zh/docs/concepts/security/pod-security-admission/)的基本概念。
<!-- body -->
<!--
## Overall approach
There are multiple strategies you can take for migrating from PodSecurityPolicy to Pod Security
Admission. The following steps are one possible migration path, with a goal of minimizing both the
risks of a production outage and of a security gap.
-->
## 方法概览 {#overall-approach}
你可以采取多种策略来完成从 PodSecurityPolicy 到 Pod 安全性准入
Pod Security Admission)的迁移。
下面是一种可能的迁移路径,其目标是尽可能降低生产环境不可用的风险,
以及安全性仍然不足的风险。
<!-- Keep section header numbering in sync with this list. -->
<!--
0. Decide whether Pod Security Admission is the right fit for your use case.
1. Review namespace permissions
2. Simplify & standardize PodSecurityPolicies
3. Update namespaces
1. Identify an appropriate Pod Security level
2. Verify the Pod Security level
3. Enforce the Pod Security level
4. Bypass PodSecurityPolicy
4. Review namespace creation processes
5. Disable PodSecurityPolicy
-->
0. 确定 Pod 安全性准入是否对于你的使用场景而言比较合适。
1. 审查名字空间访问权限。
2. 简化、标准化 PodSecurityPolicy。
3. 更新名字空间:
1. 确定合适的 Pod 安全性级别;
2. 验证该 Pod 安全性级别可工作;
3. 实施该 Pod 安全性级别;
4. 绕过 PodSecurityPolicy。
4. 审阅名字空间创建过程。
5. 禁用 PodSecurityPolicy。
<!--
## 0. Decide whether Pod Security Admission is right for you {#is-psa-right-for-you}
-->
## 0. 确定是否 Pod 安全性准入适合你 {#is-psa-right-for-you}
<!--
Pod Security Admission was designed to meet the most common security needs out of the box, and to
provide a standard set of security levels across clusters. However, it is less flexible than
PodSecurityPolicy. Notably, the following features are supported by PodSecurityPolicy but not Pod
Security Admission:
-->
Pod 安全性准入被设计用来直接满足最常见的安全性需求,并提供一组可用于多个集群的安全性级别。
不过,这一机制比 PodSecurityPolicy 的灵活度要低。
值得注意的是,PodSecurityPolicy 所支持的以下特性是 Pod 安全性准入所不支持的:
<!--
- **Setting default security constraints** - Pod Security Admission is a non-mutating admission
controller, meaning it won't modify pods before validating them. If you were relying on this
aspect of PSP, you will need to either modify your workloads to meet the Pod Security constraints,
or use a [Mutating Admission Webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/)
to make those changes. See [Simplify & Standardize PodSecurityPolicies](#simplify-psps) below for more detail.
-->
- **设置默认的安全性约束** - Pod 安全性准入是一个非变更性质的准入控制器,
这就意味着它不会在对 Pod 进行合法性检查之前更改其配置。如果你之前依赖于 PSP 的这方面能力,
你或者需要更改你的负载以满足 Pod 安全性约束,或者需要使用一个
[变更性质的准入 Webhook](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/)
来执行相应的变更。进一步的细节可参见后文的[简化和标准化 PodSecurityPolicy](#simplify-psps)。
<!--
- **Fine-grained control over policy definition** - Pod Security Admission only supports
[3 standard levels](/docs/concepts/security/pod-security-standards/).
If you require more control over specific constraints, then you will need to use a
[Validating Admission Webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/)
to enforce those policies.
-->
- **对策略定义的细粒度控制** - Pod 安全性准入仅支持
[三种标准级别](/zh/docs/concepts/security/pod-security-standards/)。
如果你需要对特定的约束施加更多的控制,你就需要使用一个
[验证性质的准入 Webhook](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/)
以实施这列策略。
<!--
- **Sub-namespace policy granularity** - PodSecurityPolicy lets you bind different policies to
different Service Accounts or users, even within a single namespace. This approach has many
pitfalls and is not recommended, but if you require this feature anyway you will
need to use a 3rd party webhook instead. The exception to this is if you only need to completely exempt
specific users or [RuntimeClasses](/docs/concepts/containers/runtime-class/), in which case Pod
Security Admission does expose some
[static configuration for exemptions](/docs/concepts/security/pod-security-admission/#exemptions).
-->
- **粒度小于名字空间的策略** - PodSecurityPolicy 允许你为不同的服务账户或用户绑定不同策略,
即使这些服务账户或用户隶属于同一个名字空间。这一方法有很多缺陷,不建议使用。
不过如果你的确需要这种功能,你就需要使用第三方的 Webhook。
唯一的例外是当你只需要完全针对某用户或者
[RuntimeClasses](/zh/docs/concepts/containers/runtime-class/) 赋予豁免规则时,
Pod 安全性准入的确也为豁免规则暴露一些
[静态配置](/zh/docs/concepts/security/pod-security-admission/#exemptions)。
<!--
Even if Pod Security Admission does not meet all of your needs it was designed to be _complementary_
to other policy enforcement mechanisms, and can provide a useful fallback running alongside other
admission webhooks.
-->
即便 Pod 安全性准入无法满足你的所有需求,该机制也是设计用作其他策略实施机制的
_补充_,因此可以和其他准入 Webhook 一起运行,进而提供一种有用的兜底机制。
<!--
## 1. Review namespace permissions {#review-namespace-permissions}
-->
## 1. 审查名字空间访问权限 {#review-namespace-permissions}
<!--
Pod Security Admission is controlled by [labels on
namespaces](/docs/concepts/security/pod-security-admission/#pod-security-admission-labels-for-namespaces).
This means that anyone who can update (or patch or create) a namespace can also modify the Pod
Security level for that namespace, which could be used to bypass a more restrictive policy. Before
proceeding, ensure that only trusted, privileged users have these namespace permissions. It is not
recommended to grant these powerful permissions to users that shouldn't have elevated permissions,
but if you must you will need to use an
[admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/)
to place additional restrictions on setting Pod Security labels on Namespace objects.
-->
Pod 安全性准入是通过[名字空间上的标签](/zh/docs/concepts/security/pod-security-admission/#pod-security-admission-labels-for-namespaces)
来控制的。这也就是说,任何能够更新(或通过 patch 部分更新或创建)
名字空间的人都可以更改该名字空间的 Pod 安全性级别,而这可能会被利用来绕过约束性更强的策略。
在继续执行迁移操作之前,请确保只有被信任的、有特权的用户具有这类名字空间访问权限。
不建议将这类强大的访问权限授予不应获得权限提升的用户,不过如果你必须这样做,
你需要使用一个
[准入 Webhook](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/)
来针对为 Namespace 对象设置 Pod 安全性级别设置额外的约束。
<!--
## 2. Simplify & standardize PodSecurityPolicies {#simplify-psps}
-->
## 2. 简化、标准化 PodSecurityPolicy {#simplify-psps}
<!--
In this section, you will reduce mutating PodSecurityPolicies and remove options that are outside
the scope of the Pod Security Standards. You should make the changes recommended here to an offline
copy of the original PodSecurityPolicy being modified. The cloned PSP should have a different
name that is alphabetically before the original (for example, prepend a `0` to it). Do not create the
new policies in Kubernetes yet - that will be covered in the [Rollout the updated
policies](#psp-update-rollout) section below.
-->
在本节中,你会削减变更性质的 PodSecurityPolicy,去掉 Pod 安全性标准范畴之外的选项。
针对要修改的、已存在的 PodSecurityPolicy,你应该将这里所建议的更改写入到其离线副本中。
所克隆的 PSP 应该与原来的副本名字不同,并且按字母序要排到原副本之前
(例如,可以向 PSP 名字前加一个 `0`)。
先不要在 Kubernetes 中创建新的策略 - 这类操作会在后文的[推出更新的策略](#psp-update-rollout)
部分讨论。
<!--
### 2.a. Eliminate purely mutating fields {#eliminate-mutating-fields}
-->
### 2.a. 去掉纯粹变更性质的字段 {#eliminating-mutaging-fields}
<!--
If a PodSecurityPolicy is mutating pods, then you could end up with pods that don't meet the Pod
Security level requirements when you finally turn PodSecurityPolicy off. In order to avoid this, you
should eliminate all PSP mutation prior to switching over. Unfortunately PSP does not cleanly
separate mutating & validating fields, so this is not a straightforward migration.
-->
如果某个 PodSecurityPolicy 能够变更字段,你可能会在关掉 PodSecurityPolicy
时发现有些 Pod 无法满足 Pod 安全性级别。为避免这类状况,
你应该在执行切换操作之前去掉所有 PSP 的变更操作。
不幸的是,PSP 没有对变更性和验证性字段做清晰的区分,所以这一迁移操作也不够简单直接。
<!--
You can start by eliminating the fields that are purely mutating, and don't have any bearing on the
validating policy. These fields (also listed in the
[Mapping PodSecurityPolicies to Pod Security Standards](/docs/reference/access-authn-authz/psp-to-pod-security-standards/)
reference) are:
-->
你可以先去掉那些纯粹变更性质的字段,留下验证策略中的其他内容。
这些字段(也列举于[将 PodSecurityPolicy 映射到 Pod 安全性标准](/zh/docs/reference/access-authn-authz/psp-to-pod-security-standards/)参考中)
包括:
<!--
- `.spec.defaultAllowPrivilegeEscalation`
- `.spec.runtimeClass.defaultRuntimeClassName`
- `.metadata.annotations['seccomp.security.alpha.kubernetes.io/defaultProfileName']`
- `.metadata.annotations['apparmor.security.beta.kubernetes.io/defaultProfileName']`
- `.spec.defaultAddCapabilities` - Although technically a mutating & validating field, these should
be merged into `.spec.allowedCapabilities` which performs the same validation without mutation.
-->
- `.spec.defaultAllowPrivilegeEscalation`
- `.spec.runtimeClass.defaultRuntimeClassName`
- `.metadata.annotations['seccomp.security.alpha.kubernetes.io/defaultProfileName']`
- `.metadata.annotations['apparmor.security.beta.kubernetes.io/defaultProfileName']`
- `.spec.defaultAddCapabilities` - 尽管理论上是一个混合了变更性与验证性功能的字段,
这里的设置应该被合并到 `.spec.allowedCapabilities` 中,后者会执行相同的验证操作,
但不会执行任何变更动作。
{{< caution >}}
<!--
Removing these could result in workloads missing required configuration, and cause problems. See
[Rollout the updated policies](#psp-update-rollout) below for advice on how to roll these changes
out safely.
-->
删除这些字段可能导致负载缺少所需的配置信息,进而导致一些问题。
参见后文[退出更新的策略](#psp-update-rollout)以获得如何安全地将这些变更上线的建议。
{{< /caution >}}
<!--
### 2.b. Eliminate options not covered by the Pod Security Standards {#eliminate-non-standard-options}
-->
### 2.b. 去掉 Pod 安全性标准未涉及的选项 {#eliminate-non-standard-options}
<!--
There are several fields in PodSecurityPolicy that are not covered by the Pod Security Standards. If
you must enforce these options, you will need to supplement Pod Security Admission with an
[admission webhook](/docs/reference/access-authn-authz/extensible-admission-controllers/),
which is outside the scope of this guide.
-->
PodSecurityPolicy 中有一些字段未被 Pod 安全性准入机制覆盖。如果你必须使用这些选项,
你需要在 Pod 安全性准入之外部署
[准入 Webhook](/zh/docs/reference/access-authn-authz/extensible-admission-controllers/)
以补充这一能力,而这类操作不在本指南范围。
<!--
First, you can remove the purely validating fields that the Pod Security Standards do not cover.
These fields (also listed in the
[Mapping PodSecurityPolicies to Pod Security Standards](/docs/reference/access-authn-authz/psp-to-pod-security-standards/)
reference with "no opinion") are:
-->
首先,你可以去掉 Pod 安全性标准所未覆盖的那些验证性字段。这些字段(也列举于
[将 PodSecurityPolicy 映射到 Pod 安全性标准](/zh/docs/reference/access-authn-authz/psp-to-pod-security-standards/)参考中,标记为“无意见”)有:
- `.spec.allowedHostPaths`
- `.spec.allowedFlexVolumes`
- `.spec.allowedCSIDrivers`
- `.spec.forbiddenSysctls`
- `.spec.runtimeClass`
<!--
You can also remove the following fields, that are related to POSIX / UNIX group controls.
-->
你也可以去掉以下字段,这些字段与 POSIX/UNIX 用户组控制有关。
{{< caution >}}
<!--
If any of these use the `MustRunAs` strategy they may be mutating! Removing these could result in
workloads not setting the required groups, and cause problems. See
[Rollout the updated policies](#psp-update-rollout) below for advice on how to roll these changes
out safely.
-->
如果这些字段中存在使用 `MustRunAs` 策略的情况,则意味着对应字段是变更性质的。
去掉相应的字段可能导致负载无法设置所需的用户组,进而带来一些问题。
关于如何安全地将这类变更上线的相关建议,请参阅后文的[推出更新的策略](#psp-update-rollout)部分。
{{< /caution >}}
- `.spec.runAsGroup`
- `.spec.supplementalGroups`
- `.spec.fsGroup`
<!--
The remaining mutating fields are required to properly support the Pod Security Standards, and will
need to be handled on a case-by-case basis later:
-->
剩下的变更性字段是为了适当支持 Pod 安全性标准所需要的,因而需要逐个处理:
<!--
- `.spec.requiredDropCapabilities` - Required to drop `ALL` for the Restricted profile.
- `.spec.seLinux` - (Only mutating with the `MustRunAs` rule) required to enforce the SELinux
requirements of the Baseline & Restricted profiles.
- `.spec.runAsUser` - (Non-mutating with the `RunAsAny` rule) required to enforce `RunAsNonRoot` for
the Restricted profile.
- `.spec.allowPrivilegeEscalation` - (Only mutating if set to `false`) required for the Restricted
profile.
-->
- `.spec.requiredDropCapabilities` - 需要此字段来为 Restricted 配置去掉 `ALL` 设置。
- `.spec.seLinux` - (仅针对带有 `MustRunAs` 规则的变更性设置)需要此字段来满足
Baseline 和 Restricted 配置所需要的 SELinux 需求。
- `.spec.runAsUser` - (仅针对带有 `RunAsAny` 规则的非变更性设置)需要此字段来为
Restricted 配置保证 `RunAsNonRoot`
- `.spec.allowPrivilegeEscalation` - (如果设置为 `false` 则为变更性设置)
需要此字段来支持 Restricted 配置。
<!--
### 2.c. Rollout the updated PSPs {#psp-update-rollout}
-->
### 2.c. 推出更新的 PSP {#psp-update-rollout}
<!--
Next, you can rollout the updated policies to your cluster. You should proceed with caution, as
removing the mutating options may result in workloads missing required configuration.
For each updated PodSecurityPolicy:
-->
接下来,你可以将更新后的策略推出到你的集群上。在继续操作时,你要非常小心,
因为去掉变更性质的选项可能导致有些工作负载缺少必需的配置。
针对更新后的每个 PodSecurityPolicy
<!--
1. Identify pods running under the original PSP. This can be done using the `kubernetes.io/psp`
annotation. For example, using kubectl:
```sh
PSP_NAME="original" # Set the name of the PSP you're checking for
kubectl get pods --all-namespaces -o jsonpath="{range .items[?(@.metadata.annotations.kubernetes\.io\/psp=='$PSP_NAME')]}{.metadata.namespace} {.metadata.name}{'\n'}{end}"
```
-->
1. 识别运行于原 PSP 之下的 Pod。可以通过 `kubernetes.io/psp` 注解来完成。
例如,使用 kubectl
```shell
PSP_NAME="original" # 设置你要检查的 PSP 的名称
kubectl get pods --all-namespaces -o jsonpath="{range .items[?(@.metadata.annotations.kubernetes\.io\/psp=='$PSP_NAME')]}{.metadata.namespace} {.metadata.name}{'\n'}{end}"
```
<!--
2. Compare these running pods against the original pod spec to determine whether PodSecurityPolicy
has modified the pod. For pods created by a [workload resource](/docs/concepts/workloads/controllers/)
you can compare the pod with the PodTemplate in the controller resource. If any changes are
identified, the original Pod or PodTemplate should be updated with the desired configuration.
The fields to review are:
-->
2. 比较运行中的 Pod 与原来的 Pod 规约,确定 PodSecurityPolicy 是否更改过这些 Pod。
对于通过[工作负载资源](/zh/docs/concepts/workloads/controllers/)所创建的 Pod
你可以比较 Pod 和控制器资源中的 PodTemplate。如果发现任何变更,则原来的 Pod
或者 PodTemplate 需要被更新以加上所希望的配置。要审查的字段包括:
- `.metadata.annotations['container.apparmor.security.beta.kubernetes.io/*']`
(将 `*` 替换为每个容器的名称)
- `.spec.runtimeClassName`
- `.spec.securityContext.fsGroup`
- `.spec.securityContext.seccompProfile`
- `.spec.securityContext.seLinuxOptions`
- `.spec.securityContext.supplementalGroups`
<!--
- On containers, under `.spec.containers[*]` and `.spec.initContainers[*]`:
-->
- 对于容器,在 `.spec.containers[*]` 和 `.spec.initContainers[*]` 之下,检查下面字段:
- `.securityContext.allowPrivilegeEscalation`
- `.securityContext.capabilities.add`
- `.securityContext.capabilities.drop`
- `.securityContext.readOnlyRootFilesystem`
- `.securityContext.runAsGroup`
- `.securityContext.runAsNonRoot`
- `.securityContext.runAsUser`
- `.securityContext.seccompProfile`
- `.securityContext.seLinuxOptions`
<!--
3. Create the new PodSecurityPolicies. If any Roles or ClusterRoles are granting `use` on all PSPs
this could cause the new PSPs to be used instead of their mutating counter-parts.
4. Update your authorization to grant access to the new PSPs. In RBAC this means updating any Roles
or ClusterRoles that grant the `use` permision on the original PSP to also grant it to the
updated PSP.
-->
3. 创建新的 PodSecurityPolicy。如果存在 Role 或 ClusterRole 对象为用户授权了在所有 PSP
上使用 `use` 动词的权限,则所使用的的会是新创建的 PSP 而不是其变更性的副本。
4. 更新你的鉴权配置,为访问新的 PSP 授权。在 RBAC 机制下,这意味着需要更新所有为原 PSP
授予 `use` 访问权限的 Role 或 ClusterRole 对象,使之也对更新后的 PSP 授权。
<!--
5. Verify: after some soak time, rerun the command from step 1 to see if any pods are still using
the original PSPs. Note that pods need to be recreated after the new policies have been rolled
out before they can be fully verified.
6. (optional) Once you have verified that the original PSPs are no longer in use, you can delete
them.
-->
5. 验证:经过一段时间后,重新执行步骤 1 中所给的命令,查看是否有 Pod 仍在使用原来的 PSP。
注意,在新的策略被推出到集群之后,Pod 需要被重新创建才可以执行全面验证。
6. (可选)一旦你已经验证原来的 PSP 不再被使用,你就可以删除这些 PSP。
<!--
## 3. Update Namespaces {#update-namespaces}
-->
## 3. 更新名字空间 {#update-namespace}
<!--
The following steps will need to be performed on every namespace in the cluster. Commands referenced
in these steps use the `$NAMESPACE` variable to refer to the namespace being updated.
-->
下面的步骤需要在集群中的所有名字空间上执行。所列步骤中的命令使用变量
`$NAMESPACE` 来引用所更新的名字空间。
<!--
### 3.a. Identify an appropriate Pod Security level {#identify-appropriate-level}
-->
### 3.a. 识别合适的 Pod 安全级别 {#identify-appropriate-level}
<!--
Start reviewing the [Pod Security Standards](/docs/concepts/security/pod-security-standards/) and
familiarizing yourself with the 3 different levels.
There are several ways to choose a Pod Security level for your namespace:
-->
首先请回顾 [Pod 安全性标准](/zh/docs/concepts/security/pod-security-standards/)内容,
并了解三个安全级别。
为你的名字空间选择 Pod 安全性级别有几种方法:
<!--
1. **By security requirements for the namespace** - If you are familiar with the expected access
level for the namespace, you can choose an appropriate level based on those requirements, similar
to how one might approach this on a new cluster.
-->
1. **根据名字空间的安全性需求来确定** - 如果你熟悉某名字空间的预期访问级别,
你可以根据这类需求来选择合适的安全级别,就像大家在为新集群确定安全级别一样。
<!--
2. **By existing PodSecurityPolicies** - Using the
[Mapping PodSecurityPolicies to Pod Security Standards](/docs/reference/access-authn-authz/psp-to-pod-security-standards/)
reference you can map each
PSP to a Pod Security Standard level. If your PSPs aren't based on the Pod Security Standards, you
may need to decide between choosing a level that is at least as permissive as the PSP, and a
level that is at least as restrictive. You can see which PSPs are in use for pods in a given
namespace with this command:
-->
2. **根据现有的 PodSecurityPolicy 来确定** - 基于
[将 PodSecurityPolicy 映射到 Pod 安全性标准](/zh/docs/reference/access-authn-authz/psp-to-pod-security-standards/)
参考资料,你可以将各个 PSP 映射到某个 Pod 安全性标准级别。如果你的 PSP 不是基于
Pod 安全性标准的,你可能或者需要选择一个至少与该 PSP 一样宽松的级别,
或者选择一个至少与其一样严格的级别。使用下面的命令你可以查看被 Pod 使用的 PSP 有哪些:
```sh
kubectl get pods -n $NAMESPACE -o jsonpath="{.items[*].metadata.annotations.kubernetes\.io\/psp}" | tr " " "\n" | sort -u
```
<!--
3. **By existing pods** - Using the strategies under [Verify the Pod Security level](#verify-pss-level),
you can test out both the Baseline and Restricted levels to see
whether they are sufficiently permissive for existing workloads, and chose the least-privileged
valid level.
-->
3. **根据现有 Pod 来确定** - 使用[检查 Pod 安全性级别](#verify-pss-level)小节所述策略,
你可以测试 Baseline 和 Restricted 级别,检查它们是否对于现有负载而言足够宽松,
并选择二者之间特权级较低的合法级别。
{{< caution >}}
<!--
Options 2 & 3 above are based on _existing_ pods, and may miss workloads that aren't currently
running, such as CronJobs, scale-to-zero workloads, or other workloads that haven't rolled out.
-->
上面的第二和第三种方案是基于 _现有_ Pod 的,因此可能错失那些当前未处于运行状态的
Pod,例如 CronJobs、缩容到零的负载,或者其他尚未全面铺开的负载。
{{< /caution >}}
<!--
### 3.b. Verify the Pod Security level {#verify-pss-level}
-->
### 3.b. 检查 Pod 安全性级别 {#verify-pss-level}
<!--
Once you have selected a Pod Security level for the namespace (or if you're trying several), it's a
good idea to test it out first (you can skip this step if using the Privileged level). Pod Security
includes several tools to help test and safely roll out profiles.
-->
一旦你已经为名字空间选择了 Pod 安全性级别(或者你正在尝试多个不同级别),
先进行测试是个不错的主意(如果使用 Privileged 级别,则可略过此步骤)。
Pod 安全性包含若干工具可用来测试和安全地推出安全性配置。
<!--
First, you can dry-run the policy, which will evaluate pods currently running in the namespace
against the applied policy, without making the new policy take effect:
-->
首先,你可以试运行新策略,这个过程可以针对所应用的策略评估当前在名字空间中运行的
Pod,但不会令新策略马上生效:
```sh
# $LEVEL 是要试运行的级别,可以是 "baseline" 或 "restricted"
kubectl label --dry-run=server --overwrite ns $NAMESPACE pod-security.kubernetes.io/enforce=$LEVEL
```
<!--
This command will return a warning for any _existing_ pods that are not valid under the proposed
level.
-->
此命令会针对在所提议的级别下不再合法的所有 _现存_ Pod 返回警告信息。
<!--
The second option is better for catching workloads that are not currently running: audit mode. When
running under audit-mode (as opposed to enforcing), pods that violate the policy level are recorded
in the audit logs, which can be reviewed later after some soak time, but are not forbidden. Warning
mode works similarly, but returns the warning to the user immediately. You can set the audit level
on a namespace with this command:
-->
第二种办法在抓取当前未运行的负载方面表现的更好:audit 模式。
运行于 audit 模式(而非 enforcing 模式)下时,违反策略级别的 Pod 会被记录到审计日志中,
经过一段时间后可以在日志中查看到,但这些 Pod 不会被拒绝。
warning 模式的工作方式与此类似,不过会立即向用户返回告警信息。
你可以使用下面的命令为名字空间设置 audit 模式的级别:
```sh
kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/audit=$LEVEL
```
<!--
If either of these approaches yield unexpected violations, you will need to either update the
violating workloads to meet the policy requirements, or relax the namespace Pod Security level.
-->
当以上两种方法输出意料之外的违例状况时,你就需要或者更新发生违例的负载以满足策略需求,
或者放宽名字空间上的 Pod 安全性级别。
<!--
### 3.c. Enforce the Pod Security level {#enforce-pod-security-level}
-->
### 3.c. 实施 Pod 安全性级别 {#enforce-pod-security-level}
<!--
When you are satisfied that the chosen level can safely be enforced on the namespace, you can update
the namespace to enforce the desired level:
-->
当你对可以安全地在名字空间上实施的级别比较满意时,你可以更新名字空间来实施所期望的级别:
```sh
kubectl label --overwrite ns $NAMESPACE pod-security.kubernetes.io/enforce=$LEVEL
```
<!--
### 3.d. Bypass PodSecurityPolicy {#bypass-psp}
-->
### 3.d. 绕过 PodSecurityPolicy {#bypass-psp}
<!--
Finally, you can effectively bypass PodSecurityPolicy at the namespace level by binding the fully
{{< example file="policy/privileged-psp.yaml" >}}privileged PSP{{< /example >}} to all service
accounts in the namespace.
-->
最后,你可以通过将
{{< example file="policy/privileged-psp.yaml" >}}完全特权的 PSP{{< /example >}}
绑定到某名字空间中所有服务账户上,在名字空间层面绕过所有 PodSecurityPolicy。
```sh
# 下面集群范围的命令只需要执行一次
kubectl apply -f privileged-psp.yaml
kubectl create clusterrole privileged-psp --verb use --resource podsecuritypolicies.policy --resource-name privileged
# 逐个名字空间地禁用
kubectl create -n $NAMESPACE rolebinding disable-psp --clusterrole privileged-psp --group system:serviceaccounts:$NAMESPACE
```
<!--
Since the privileged PSP is non-mutating, and the PSP admission controller always
prefers non-mutating PSPs, this will ensure that pods in this namespace are no longer being modified
or restricted by PodSecurityPolicy.
-->
由于特权 PSP 是非变更性的,PSP 准入控制器总是优选非变更性的 PSP,
上面的操作会确保对应名字空间中的所有 Pod 不再会被 PodSecurityPolicy
所更改或限制。
<!--
The advantage to disabling PodSecurityPolicy on a per-namespace basis like this is if a problem
arises you can easily roll the change back by deleting the RoleBinding. Just make sure the
pre-existing PodSecurityPolicies are still in place!
-->
按上述操作逐个名字空间地禁用 PodSecurityPolicy 这种做法的好处是,
如果出现问题,你可以很方便地通过删除 RoleBinding 来回滚所作的更改。
你所要做的只是确保之前存在的 PodSecurityPolicy 还在。
```sh
# 撤销 PodSecurityPolicy 的禁用
kubectl delete -n $NAMESPACE rolebinding disable-psp
```
<!--
## 4. Review namespace creation processes {#review-namespace-creation-process}
-->
## 4. 审阅名字空间创建过程 {#review-namespace-creation-process}
<!--
Now that existing namespaces have been updated to enforce Pod Security Admission, you should ensure
that your processes and/or policies for creating new namespaces are updated to ensure that an
appropriate Pod Security profile is applied to new namespaces.
-->
现在,现有的名字空间都已被更新,强制实施 Pod 安全性准入,
你应该确保你用来管控新名字空间创建的流程与/或策略也被更新,这样合适的 Pod
安全性配置会被应用到新的名字空间上。
<!--
You can also statically configure the Pod Security admission controller to set a default enforce,
audit, and/or warn level for unlabeled namespaces. See
[Configure the Admission Controller](/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)
for more information.
-->
你也可以静态配置 Pod 安全性准入控制器,为尚未打标签的名字空间设置默认的
enforce、audit 与/或 warn 级别。详细信息可参阅
[配置准入控制器](/zh/docs/tasks/configure-pod-container/enforce-standards-admission-controller/#configure-the-admission-controller)
页面。
<!--
## 5. Disable PodSecurityPolicy {#disable-psp}
-->
## 5. 禁用 PodSecurityPolicy {#disable-psp}
<!--
Finally, you're ready to disable PodSecurityPolicy. To do so, you will need to modify the admission
configuration of the API server:
[How do I turn off an admission controller?](/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-off-an-admission-controller).
-->
最后,你已为禁用 PodSecurityPolicy 做好准备。要禁用 PodSecurityPolicy
你需要更改 API 服务器上的准入配置:
[我如何关闭某个准入控制器?](/zh/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-off-an-admission-controller)
<!--
To verify that the PodSecurityPolicy admission controller is no longer enabled, you can manually run
a test by impersonating a user without access to any PodSecurityPolicies (see the
[PodSecurityPolicy example](/docs/concepts/policy/pod-security-policy/#example)), or by verifying in
the API server logs. At startup, the API server outputs log lines listing the loaded admission
controller plugins:
-->
如果需要验证 PodSecurityPolicy 准入控制器不再被启用,你可以通过扮演某个无法访问任何
PodSecurityPolicy 的用户来执行测试(参见
[PodSecurityPolicy 示例](/zh/docs/concepts/policy/pod-security-policy/#example)),
或者通过检查 API 服务器的日志来进行验证。在启动期间,API
服务器会输出日志行,列举所挂载的准入控制器插件。
```
I0218 00:59:44.903329 13 plugins.go:158] Loaded 16 mutating admission controller(s) successfully in the following order: NamespaceLifecycle,LimitRanger,ServiceAccount,NodeRestriction,TaintNodesByCondition,Priority,DefaultTolerationSeconds,ExtendedResourceToleration,PersistentVolumeLabel,DefaultStorageClass,StorageObjectInUseProtection,RuntimeClass,DefaultIngressClass,MutatingAdmissionWebhook.
I0218 00:59:44.903350 13 plugins.go:161] Loaded 14 validating admission controller(s) successfully in the following order: LimitRanger,ServiceAccount,PodSecurity,Priority,PersistentVolumeClaimResize,RuntimeClass,CertificateApproval,CertificateSigning,CertificateSubjectRestriction,DenyServiceExternalIPs,ValidatingAdmissionWebhook,ResourceQuota.
```
<!--
You should see `PodSecurity` (in the validating admission controllers), and neither list should
contain `PodSecurityPolicy`.
-->
你应该会看到 `PodSecurity`(在 validating admission controllers 列表中),
并且两个列表中都不应该包含 `PodSecurityPolicy`。
<!--
Once you are certain the PSP admission controller is disabled (and after sufficient soak time to be
confident you won't need to roll back), you are free to delete your PodSecurityPolicies and any
associated Roles, ClusterRoles, RoleBindings and ClusterRoleBindings (just make sure they don't
grant any other unrelated permissions).
-->
一旦你确定 PSP 准入控制器已被禁用(并且这种状况已经持续了一段时间,
这样你才会比较确定不需要回滚),你就可以放心地删除你的 PodSecurityPolicy
以及所关联的所有 Role、ClusterRole、RoleBinding、ClusterRoleBinding 等对象
(仅需要确保他们不再授予其他不相关的访问权限)。
@@ -0,0 +1,356 @@
---
title: 从私有仓库拉取镜像
content_type: task
weight: 100
---
<!--
title: Pull an Image from a Private Registry
content_type: task
weight: 100
-->
<!-- overview -->
<!--
This page shows how to create a Pod that uses a
{{< glossary_tooltip text="Secret" term_id="secret" >}} to pull an image
from a private container image registry or repository. There are many private
registries in use. This task uses [Docker Hub](https://www.docker.com/products/docker-hub)
-->
本文介绍如何使用 {{< glossary_tooltip text="Secret" term_id="secret" >}}
从私有的镜像仓库或代码仓库拉取镜像来创建 Pod。
有很多私有镜像仓库正在使用中。这个任务使用的镜像仓库是
[Docker Hub](https://www.docker.com/products/docker-hub)
{{% thirdparty-content single="true" %}}
## {{% heading "prerequisites" %}}
* {{< include "task-tutorial-prereqs.md" >}}
<!--
* To do this exercise, you need the `docker` command line tool, and a
[Docker ID](https://docs.docker.com/docker-id/) for which you know the password.
* If you are using a different private container registry, you need the command
line tool for that registry and any login information for the registry.
-->
* 要进行此练习,你需要 `docker` 命令行工具和一个知道密码的
[Docker ID](https://docs.docker.com/docker-id/)。
* 如果你要使用不同的私有的镜像仓库,你需要有对应镜像仓库的命令行工具和登录信息。
<!-- steps -->
<!--
## Log in to Docker
On your laptop, you must authenticate with a registry in order to pull a private image:
-->
## 登录 Docker 镜像仓库 {#log-in-to-docker}
在个人电脑上,要想拉取私有镜像必须在镜像仓库上进行身份验证。
```shell
docker login
```
<!--
When prompted, enter your Docker ID, and then the credential you want to use (access token,
or the password for your Docker ID).
The login process creates or updates a `config.json` file that holds an authorization token. Review [how Kubernetes interprets this file](/docs/concepts/containers/images#config-json).
View the `config.json` file:
-->
当出现提示时,输入你的 Docker ID 和登录凭证(访问令牌、
或 Docker ID 的密码)。
登录过程会创建或更新保存有授权令牌的 `config.json` 文件。
查看 [Kubernetes 中如何解析这个文件](/zh/docs/concepts/containers/images#config-json)。
查看 `config.json` 文件:
```shell
cat ~/.docker/config.json
```
<!--
The output contains a section similar to this:
-->
输出结果包含类似于以下内容的部分:
```json
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "c3R...zE2"
}
}
}
```
<!--
If you use a Docker credentials store, you won't see that `auth` entry but a `credsStore` entry with the name of the store as value.
-->
{{< note >}}
如果使用 Docker 凭证仓库,则不会看到 `auth` 条目,看到的将是以仓库名称作为值的 `credsStore` 条目。
{{< /note >}}
<!--
## Create a Secret based on existing credentials {#registry-secret-existing-credentials}
A Kubernetes cluster uses the Secret of `kubernetes.io/dockerconfigjson` type to authenticate with
a container registry to pull a private image.
If you already ran `docker login`, you can copy
that credential into Kubernetes:
-->
## 创建一个基于现有凭证的 Secret {#registry-secret-existing-credentials}
Kubernetes 集群使用 `kubernetes.io/dockerconfigjson` 类型的
Secret 来通过镜像仓库的身份验证,进而提取私有镜像。
如果你已经运行了 `docker login` 命令,你可以复制该镜像仓库的凭证到 Kubernetes:
```shell
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=<path/to/.docker/config.json> \
--type=kubernetes.io/dockerconfigjson
```
<!--
If you need more control (for example, to set a namespace or a label on the new
secret) then you can customise the Secret before storing it.
Be sure to:
- set the name of the data item to `.dockerconfigjson`
- base64 encode the Docker configuration file and then paste that string, unbroken
as the value for field `data[".dockerconfigjson"]`
- set `type` to `kubernetes.io/dockerconfigjson`
Example:
-->
如果你需要更多的设置(例如,为新 Secret 设置名字空间或标签),
则可以在存储 Secret 之前对它进行自定义。
请务必:
- 将 data 项中的名称设置为 `.dockerconfigjson`
- 使用 base64 编码方法对 Docker 配置文件进行编码,然后粘贴该字符串的内容,作为字段
`data[".dockerconfigjson"]` 的值
-`type` 设置为 `kubernetes.io/dockerconfigjson`
示例:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: awesomeapps
data:
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
type: kubernetes.io/dockerconfigjson
```
<!--
If you get the error message `error: no objects passed to create`, it may mean the base64 encoded string is invalid.
If you get an error message like `Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...`, it means
the base64 encoded string in the data was successfully decoded, but could not be parsed as a `.docker/config.json` file.
-->
如果你收到错误消息:`error: no objects passed to create`
这可能意味着 base64 编码的字符串是无效的。 如果你收到类似
`Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...`
的错误消息,则表示数据中的 base64 编码字符串已成功解码,但无法解析为 `.docker/config.json` 文件。
<!--
## Create a Secret by providing credentials on the command line
Create this Secret, naming it `regcred`:
-->
## 在命令行上提供凭证来创建 Secret {#create-a-secret-by-providing-credentials-on-the-command-line}
创建 Secret,命名为 `regcred`
<!--
kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
-->
```shell
kubectl create secret docker-registry regcred \
--docker-server=<你的镜像仓库服务器> \
--docker-username=<你的用户名> \
--docker-password=<你的密码> \
--docker-email=<你的邮箱地址>
```
<!--
where:
* `<your-registry-server>` is your Private Docker Registry FQDN.
Use `https://index.docker.io/v1/` for DockerHub.
* `<your-name>` is your Docker username.
* `<your-pword>` is your Docker password.
* `<your-email>` is your Docker email.
You have successfully set your Docker credentials in the cluster as a Secret called `regcred`.
-->
在这里:
* `<your-registry-server>` 是你的私有 Docker 仓库全限定域名(FQDN)。
DockerHub 使用 `https://index.docker.io/v1/`
* `<your-name>` 是你的 Docker 用户名。
* `<your-pword>` 是你的 Docker 密码。
* `<your-email>` 是你的 Docker 邮箱。
这样你就成功地将集群中的 Docker 凭证设置为名为 `regcred` 的 Secret。
<!--
Typing secrets on the command line may store them in your shell history unprotected, and
those secrets might also be visible to other users on your PC during the time that
`kubectl` is running.
-->
{{< note >}}
在命令行上键入 Secret 可能会将它们存储在你的 shell 历史记录中而不受保护,
并且这些 Secret 信息也可能在 `kubectl` 运行期间对你 PC 上的其他用户可见。
{{< /note >}}
<!--
## Inspecting the Secret `regcred`
To understand the contents of the `regcred` Secret you created, start by viewing the Secret in YAML format:
-->
## 检查 Secret `regcred` {#inspecting-the-secret-regcred}
要了解你创建的 `regcred` Secret 的内容,可以用 YAML 格式进行查看:
```shell
kubectl get secret regcred --output=yaml
```
<!-- The output is similar to this: -->
输出和下面类似:
```yaml
apiVersion: v1
data:
.dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0=
kind: Secret
metadata:
...
name: regcred
...
type: kubernetes.io/dockerconfigjson
```
<!--
The value of the `.dockerconfigjson` field is a base64 representation of your Docker credentials.
To understand what is in the `.dockerconfigjson` field, convert the secret data to a
readable format:
-->
`.dockerconfigjson` 字段的值是 Docker 凭证的 base64 表示。
要了解 `dockerconfigjson` 字段中的内容,请将 Secret 数据转换为可读格式:
```shell
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
```
<!-- The output is similar to this: -->
输出和下面类似:
```json
{"auths":{"yourprivateregistry.com":{"username":"janedoe","password":"xxxxxxxxxxx","email":"jdoe@example.com","auth":"c3R...zE2"}}}
```
<!--
To understand what is in the `auth` field, convert the base64-encoded data to a readable format:
-->
要了解 `auth` 字段中的内容,请将 base64 编码过的数据转换为可读格式:
```shell
echo "c3R...zE2" | base64 --decode
```
<!--
The output, username and password concatenated with a `:`, is similar to this:
-->
输出结果中,用户名和密码用 `:` 链接,类似下面这样:
```none
janedoe:xxxxxxxxxxx
```
<!--
Notice that the Secret data contains the authorization token similar to your local `~/.docker/config.json` file.
You have successfully set your Docker credentials as a Secret called `regcred` in the cluster.
-->
注意,Secret 数据包含与本地 `~/.docker/config.json` 文件类似的授权令牌。
这样你就已经成功地将 Docker 凭证设置为集群中的名为 `regcred` 的 Secret。
<!--
## Create a Pod that uses your Secret
Here is a manifest for an example Pod that needs access to your Docker credentials in `regcred`:
-->
## 创建一个使用你的 Secret 的 Pod {#create-a-pod-that-uses-your-secret}
下面是一个 Pod 配置清单示例,该示例中 Pod 需要访问你的 Docker 凭证 `regcred`
{{< codenew file="pods/private-reg-pod.yaml" >}}
<!--
Download the above file onto your computer:
-->
将上述文件下载到你的计算机中:
```shell
curl -L -O my-private-reg-pod.yaml https://k8s.io/examples/pods/private-reg-pod.yaml
```
<!--
In file `my-private-reg-pod.yaml`, replace `<your-private-image>` with the path to an image in a private registry such as:
-->
`my-private-reg-pod.yaml` 文件中,使用私有仓库的镜像路径替换 `<your-private-image>`,例如:
```none
janedoe/jdoe-private:v1
```
<!--
To pull the image from the private registry, Kubernetes needs credentials.
The `imagePullSecrets` field in the configuration file specifies that
Kubernetes should get the credentials from a Secret named `regcred`.
Create a Pod that uses your Secret, and verify that the Pod is running:
-->
要从私有仓库拉取镜像,Kubernetes 需要凭证。
配置文件中的 `imagePullSecrets` 字段表明 Kubernetes 应该通过名为 `regcred` 的 Secret 获取凭证。
创建使用了你的 Secret 的 Pod,并检查它是否正常运行:
```shell
kubectl apply -f my-private-reg-pod.yaml
kubectl get pod private-reg
```
## {{% heading "whatsnext" %}}
<!--
* Learn more about [Secrets](/docs/concepts/configuration/secret/)
* or read the API reference for {{< api-reference page="config-and-storage-resources/secret-v1" >}}
* Learn more about [using a private registry](/docs/concepts/containers/images/#using-a-private-registry).
* Learn more about [adding image pull secrets to a service account](/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account).
* See [kubectl create secret docker-registry](/docs/reference/generated/kubectl/kubectl-commands/#-em-secret-docker-registry-em-).
* See the `imagePullSecrets` field within the [container definitions](/docs/reference/kubernetes-api/workload-resources/pod-v1/#containers) of a Pod
-->
* 进一步了解 [Secrets](/zh/docs/concepts/configuration/secret/)
* 或阅读 {{< api-reference page="config-and-storage-resources/secret-v1" >}} 的 API 参考
* 进一步了解 [使用私有仓库](/zh/docs/concepts/containers/images/#using-a-private-registry)
* 进一步了解 [为服务账户添加拉取镜像凭证](/zh/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account)
* 查看 [kubectl 创建 docker-registry 凭证](/docs/reference/generated/kubectl/kubectl-commands/#-em-secret-docker-registry-em-)
* 查看 Pod [容器定义](/docs/reference/kubernetes-api/workload-resources/pod-v1/#containers)中的 `imagePullSecrets` 字段。
@@ -0,0 +1,423 @@
---
title: 配置 Pod 的服务质量
content_type: task
weight: 30
---
<!--
title: Configure Quality of Service for Pods
content_type: task
weight: 30
-->
<!-- overview -->
<!--
This page shows how to configure Pods so that they will be assigned particular
Quality of Service (QoS) classes. Kubernetes uses QoS classes to make decisions about
scheduling and evicting Pods.
-->
本页介绍怎样配置 Pod 让其获得特定的服务质量(QoS)类。Kubernetes 使用 QoS 类来决定 Pod 的调度和驱逐策略。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## QoS classes
When Kubernetes creates a Pod it assigns one of these QoS classes to the Pod:
-->
## QoS 类 {#qos-classes}
Kubernetes 创建 Pod 时就给它指定了下列一种 QoS 类:
* Guaranteed
* Burstable
* BestEffort
<!--
## Create a namespace
Create a namespace so that the resources you create in this exercise are
isolated from the rest of your cluster.
-->
## 创建命名空间
创建一个命名空间,以便将本练习所创建的资源与集群的其余资源相隔离。
```shell
kubectl create namespace qos-example
```
<!--
## Create a Pod that gets assigned a QoS class of Guaranteed
For a Pod to be given a QoS class of Guaranteed:
* Every Container in the Pod must have a memory limit and a memory request.
* For every Container in the Pod, the memory limit must equal the memory request.
* Every Container in the Pod must have a CPU limit and a CPU request.
* For every Container in the Pod, the CPU limit must equal the CPU request.
These restrictions apply to init containers and app containers equally.
Here is the configuration file for a Pod that has one Container. The Container has a memory limit and a
memory request, both equal to 200 MiB. The Container has a CPU limit and a CPU request, both equal to 700 milliCPU:
-->
## 创建一个 QoS 类为 Guaranteed 的 Pod
对于 QoS 类为 Guaranteed 的 Pod
* Pod 中的每个容器都必须指定内存限制和内存请求。
* 对于 Pod 中的每个容器,内存限制必须等于内存请求。
* Pod 中的每个容器都必须指定 CPU 限制和 CPU 请求。
* 对于 Pod 中的每个容器,CPU 限制必须等于 CPU 请求。
这些限制同样适用于初始化容器和应用程序容器。
下面是包含一个容器的 Pod 配置文件。
容器设置了内存请求和内存限制,值都是 200 MiB。
容器设置了 CPU 请求和 CPU 限制,值都是 700 milliCPU
{{< codenew file="pods/qos/qos-pod.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example
```
<!--
View detailed information about the Pod:
-->
查看 Pod 详情:
```shell
kubectl get pod qos-demo --namespace=qos-example --output=yaml
```
<!--
The output shows that Kubernetes gave the Pod a QoS class of Guaranteed. The output also
verifies that the Pod Container has a memory request that matches its memory limit, and it has
a CPU request that matches its CPU limit.
-->
结果表明 Kubernetes 为 Pod 配置的 QoS 类为 Guaranteed。
结果也确认了 Pod 容器设置了与内存限制匹配的内存请求,设置了与 CPU 限制匹配的 CPU 请求。
```yaml
spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed
```
{{< note >}}
<!--
If a Container specifies its own memory limit, but does not specify a memory request, Kubernetes
automatically assigns a memory request that matches the limit. Similarly, if a Container specifies its own
CPU limit, but does not specify a CPU request, Kubernetes automatically assigns a CPU request that matches
the limit.
-->
如果容器指定了自己的内存限制,但没有指定内存请求,Kubernetes 会自动为它指定与内存限制匹配的内存请求。
同样,如果容器指定了自己的 CPU 限制,但没有指定 CPU 请求,Kubernetes 会自动为它指定与 CPU 限制匹配的 CPU 请求。
{{< /note >}}
<!--
Delete your Pod:
-->
删除 Pod
```shell
kubectl delete pod qos-demo --namespace=qos-example
```
<!--
## Create a Pod that gets assigned a QoS class of Burstable
A Pod is given a QoS class of Burstable if:
* The Pod does not meet the criteria for QoS class Guaranteed.
* At least one Container in the Pod has a memory or CPU request or limit.
Here is the configuration file for a Pod that has one Container. The Container has a memory limit of 200 MiB
and a memory request of 100 MiB.
-->
## 创建一个 QoS 类为 Burstable 的 Pod
如果满足下面条件,将会指定 Pod 的 QoS 类为 Burstable
* Pod 不符合 Guaranteed QoS 类的标准。
* Pod 中至少一个容器具有内存或 CPU 的请求或限制。
下面是包含一个容器的 Pod 配置文件。
容器设置了内存限制 200 MiB 和内存请求 100 MiB。
{{< codenew file="pods/qos/qos-pod-2.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example
```
<!--
View detailed information about the Pod:
-->
查看 Pod 详情:
```shell
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
```
<!--
The output shows that Kubernetes gave the Pod a QoS class of Burstable.
-->
结果表明 Kubernetes 为 Pod 配置的 QoS 类为 Burstable。
```yaml
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable
```
<!--
Delete your Pod:
-->
删除 Pod
```shell
kubectl delete pod qos-demo-2 --namespace=qos-example
```
<!--
## Create a Pod that gets assigned a QoS class of BestEffort
For a Pod to be given a QoS class of BestEffort, the Containers in the Pod must not
have any memory or CPU limits or requests.
Here is the configuration file for a Pod that has one Container. The Container has no memory or CPU
limits or requests:
-->
## 创建一个 QoS 类为 BestEffort 的 Pod
对于 QoS 类为 BestEffort 的 Pod,Pod 中的容器必须没有设置内存和 CPU 限制或请求。
下面是包含一个容器的 Pod 配置文件。
容器没有设置内存和 CPU 限制或请求。
{{< codenew file="pods/qos/qos-pod-3.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example
```
<!--
View detailed information about the Pod:
-->
查看 Pod 详情:
```shell
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
```
<!--
The output shows that Kubernetes gave the Pod a QoS class of BestEffort.
-->
结果表明 Kubernetes 为 Pod 配置的 QoS 类为 BestEffort。
```yaml
spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort
```
<!--
Delete your Pod:
-->
删除 Pod
```shell
kubectl delete pod qos-demo-3 --namespace=qos-example
```
<!--
## Create a Pod that has two Containers
Here is the configuration file for a Pod that has two Containers. One container specifies a memory
request of 200 MiB. The other Container does not specify any requests or limits.
-->
## 创建包含两个容器的 Pod
下面是包含两个容器的 Pod 配置文件。
一个容器指定了内存请求 200 MiB。
另外一个容器没有指定任何请求和限制。
{{< codenew file="pods/qos/qos-pod-4.yaml" >}}
<!--
Notice that this Pod meets the criteria for QoS class Burstable. That is, it does not meet the
criteria for QoS class Guaranteed, and one of its Containers has a memory request.
Create the Pod:
-->
注意此 Pod 满足 Burstable QoS 类的标准。
也就是说它不满足 Guaranteed QoS 类标准,因为它的一个容器设有内存请求。
创建 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example
```
<!--
View detailed information about the Pod:
-->
查看 Pod 详情:
```shell
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
```
<!--
The output shows that Kubernetes gave the Pod a QoS class of Burstable:
-->
结果表明 Kubernetes 为 Pod 配置的 QoS 类为 Burstable
```yaml
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
status:
qosClass: Burstable
```
<!--
Delete your Pod:
-->
删除 Pod
```shell
kubectl delete pod qos-demo-4 --namespace=qos-example
```
<!--
## Clean up
Delete your namespace:
-->
## 环境清理
删除命名空间:
```shell
kubectl delete namespace qos-example
```
## {{% heading "whatsnext" %}}
<!--
### For app developers
* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)
-->
### 应用开发者参考
* [为 Pod 和容器分配内存资源](/zh/docs/tasks/configure-pod-container/assign-memory-resource/)
* [为 Pod 和容器分配 CPU 资源](/zh/docs/tasks/configure-pod-container/assign-cpu-resource/)
<!--
### For cluster administrators
* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/memory-default-namespace/)
* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/cpu-default-namespace/)
* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/)
* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/)
* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)
* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/)
* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
* [Control Topology Management policies on a node](/docs/tasks/administer-cluster/topology-manager/)
-->
### 集群管理员参考
* [为命名空间配置默认的内存请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/)
* [为命名空间配置默认的 CPU 请求和限制](/zh/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace)
* [为命名空间配置最小和最大内存限制](/zh/docs/tasks/administer-cluster/manage-resources/memory-constraint-namespace/)
* [为命名空间配置最小和最大 CPU 限制](/zh/docs/tasks/administer-cluster/manage-resources/cpu-constraint-namespace/)
* [为命名空间配置内存和 CPU 配额](/zh/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)
* [为命名空间配置 Pod 配额](/zh/docs/tasks/administer-cluster/manage-resources/quota-pod-namespace/)
* [为 API 对象配置配额](/zh/docs/tasks/administer-cluster/quota-api-object/)
* [控制节点上的拓扑管理策略](/zh/docs/tasks/administer-cluster/topology-manager/)
@@ -0,0 +1,791 @@
---
title: 为 Pod 或容器配置安全上下文
content_type: task
weight: 80
---
<!--
reviewers:
- erictune
- mikedanese
- thockin
title: Configure a Security Context for a Pod or Container
content_type: task
weight: 80
-->
<!-- overview -->
<!--
A security context defines privilege and access control settings for
a Pod or Container. Security context settings include, but are not limited to:
* Discretionary Access Control: Permission to access an object, like a file, is based on
[user ID (UID) and group ID (GID)](https://wiki.archlinux.org/index.php/users_and_groups).
* [Security Enhanced Linux (SELinux)](https://en.wikipedia.org/wiki/Security-Enhanced_Linux):
Objects are assigned security labels.
* Running as privileged or unprivileged.
* [Linux Capabilities](https://linux-audit.com/linux-capabilities-hardening-linux-binaries-by-removing-setuid/):
Give a process some privileges, but not all the privileges of the root user.
-->
安全上下文(Security Context)定义 Pod 或 Container 的特权与访问控制设置。
安全上下文包括但不限于:
* 自主访问控制(Discretionary Access Control):
基于[用户 IDUID)和组 IDGID](https://wiki.archlinux.org/index.php/users_and_groups)
来判定对对象(例如文件)的访问权限。
* [安全性增强的 LinuxSELinux](https://zh.wikipedia.org/wiki/%E5%AE%89%E5%85%A8%E5%A2%9E%E5%BC%BA%E5%BC%8FLinux)
为对象赋予安全性标签。
* 以特权模式或者非特权模式运行。
* [Linux 权能](https://linux-audit.com/linux-capabilities-hardening-linux-binaries-by-removing-setuid/):
为进程赋予 root 用户的部分特权而非全部特权。
<!--
* [AppArmor](/docs/tutorials/security/apparmor/):
Use program profiles to restrict the capabilities of individual programs.
* [Seccomp](/docs/tutorials/security/seccomp/): Filter a process's system calls.
* `allowPrivilegeEscalation`: Controls whether a process can gain more privileges than
its parent process. This bool directly controls whether the
[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt)
flag gets set on the container process.
`allowPrivilegeEscalation` is always true
when the container:
- is run as privileged, or
- has `CAP_SYS_ADMIN`
* readOnlyRootFilesystem: Mounts the container's root filesystem as read-only.
-->
* [AppArmor](/zh/docs/tutorials/security/apparmor/):使用程序配置来限制个别程序的权能。
* [Seccomp](/zh/docs/tutorials/security/seccomp/):过滤进程的系统调用。
* `allowPrivilegeEscalation`:控制进程是否可以获得超出其父进程的特权。
此布尔值直接控制是否为容器进程设置
[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt)标志。
当容器满足一下条件之一时,`allowPrivilegeEscalation` 总是为 true
- 以特权模式运行,或者
- 具有 `CAP_SYS_ADMIN` 权能
* readOnlyRootFilesystem:以只读方式加载容器的根文件系统。
<!--
The above bullets are not a complete set of security context settings - please see
[SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
for a comprehensive list.
-->
以上条目不是安全上下文设置的完整列表 -- 请参阅
[SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
了解其完整列表。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Set the security context for a Pod
To specify security settings for a Pod, include the `securityContext` field
in the Pod specification. The `securityContext` field is a
[PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core) object.
The security settings that you specify for a Pod apply to all Containers in the Pod.
Here is a configuration file for a Pod that has a `securityContext` and an `emptyDir` volume:
-->
## 为 Pod 设置安全性上下文 {#set-the-security-context-for-a-pod}
要为 Pod 设置安全性设置,可在 Pod 规约中包含 `securityContext` 字段。`securityContext` 字段值是一个
[PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core)
对象。你为 Pod 所设置的安全性配置会应用到 Pod 中所有 Container 上。
下面是一个 Pod 的配置文件,该 Pod 定义了 `securityContext` 和一个 `emptyDir` 卷:
{{< codenew file="pods/security/security-context.yaml" >}}
<!--
In the configuration file, the `runAsUser` field specifies that for any Containers in
the Pod, all processes run with user ID 1000. The `runAsGroup` field specifies the primary group ID of 3000 for
all processes within any containers of the Pod. If this field is omitted, the primary group ID of the containers
will be root(0). Any files created will also be owned by user 1000 and group 3000 when `runAsGroup` is specified.
Since `fsGroup` field is specified, all processes of the container are also part of the supplementary group ID 2000.
The owner for volume `/data/demo` and any files created in that volume will be Group ID 2000.
Create the Pod:
-->
在配置文件中,`runAsUser` 字段指定 Pod 中的所有容器内的进程都使用用户 ID 1000
来运行。`runAsGroup` 字段指定所有容器中的进程都以主组 ID 3000 来运行。
如果忽略此字段,则容器的主组 ID 将是 root(0)。
`runAsGroup` 被设置时,所有创建的文件也会划归用户 1000 和组 3000。
由于 `fsGroup` 被设置,容器中所有进程也会是附组 ID 2000 的一部分。
`/data/demo` 及在该卷中创建的任何文件的属主都会是组 ID 2000。
创建该 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml
```
<!--
Verify that the Pod's Container is running:
-->
检查 Pod 的容器处于运行状态:
```shell
kubectl get pod security-context-demo
```
<!--
Get a shell to the running Container:
-->
开启一个 Shell 进入到运行中的容器:
```shell
kubectl exec -it security-context-demo -- sh
```
<!--
In your shell, list the running processes:
-->
在你的 Shell 中,列举运行中的进程:
```shell
ps
```
<!--
The output shows that the processes are running as user 1000, which is the value of `runAsUser`:
-->
输出显示进程以用户 1000 运行,即 `runAsUser` 所设置的值:
```shell
PID USER TIME COMMAND
1 1000 0:00 sleep 1h
6 1000 0:00 sh
...
```
<!--
In your shell, navigate to `/data`, and list the one directory:
-->
在你的 Shell 中,进入 `/data` 目录列举其内容:
```shell
cd /data
ls -l
```
<!--
The output shows that the `/data/demo` directory has group ID 2000, which is
the value of `fsGroup`.
-->
输出显示 `/data/demo` 目录的组 ID 为 2000,即 `fsGroup` 的设置值:
```shell
drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo
```
<!--
In your shell, navigate to `/data/demo`, and create a file:
-->
在你的 Shell 中,进入到 `/data/demo` 目录下创建一个文件:
```shell
cd demo
echo hello > testfile
```
<!--
List the file in the `/data/demo` directory:
-->
列举 `/data/demo` 目录下的文件:
```shell
ls -l
```
<!--
The output shows that `testfile` has group ID 2000, which is the value of `fsGroup`.
-->
输出显示 `testfile` 的组 ID 为 2000,也就是 `fsGroup` 所设置的值:
```shell
-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile
```
<!--
Run the following command:
-->
运行下面的命令:
```shell
id
```
<!--
The output is similar to this:
-->
输出类似于:
```none
uid=1000 gid=3000 groups=2000
```
<!--
From the output, you can see that `gid` is 3000 which is same as the `runAsGroup` field.
If the `runAsGroup` was omitted, the `gid` would remain as 0 (root) and the process will
be able to interact with files that are owned by the root(0) group and groups that have
the required group permissions for the root (0) group.
Exit your shell:
-->
从输出中你会看到 `gid` 值为 3000,也就是 `runAsGroup` 字段的值。
如果 `runAsGroup` 被忽略,则 `gid` 会取值 0(root),而进程就能够与 root
用户组所拥有以及要求 root 用户组访问权限的文件交互。
退出你的 Shell
```shell
exit
```
<!--
## Configure volume permission and ownership change policy for Pods
-->
## 为 Pod 配置卷访问权限和属主变更策略
{{< feature-state for_k8s_version="v1.23" state="stable" >}}
<!--
By default, Kubernetes recursively changes ownership and permissions for the contents of each
volume to match the `fsGroup` specified in a Pod's `securityContext` when that volume is
mounted.
For large volumes, checking and changing ownership and permissions can take a lot of time,
slowing Pod startup. You can use the `fsGroupChangePolicy` field inside a `securityContext`
to control the way that Kubernetes checks and manages ownership and permissions
for a volume.
-->
默认情况下,Kubernetes 在挂载一个卷时,会递归地更改每个卷中的内容的属主和访问权限,
使之与 Pod 的 `securityContext` 中指定的 `fsGroup` 匹配。
对于较大的数据卷,检查和变更属主与访问权限可能会花费很长时间,降低 Pod 启动速度。
你可以在 `securityContext` 中使用 `fsGroupChangePolicy` 字段来控制 Kubernetes
检查和管理卷属主和访问权限的方式。
<!--
**fsGroupChangePolicy** - `fsGroupChangePolicy` defines behavior for changing ownership
and permission of the volume before being exposed inside a Pod.
This field only applies to volume types that support `fsGroup` controlled ownership and permissions.
This field has two possible values:
* _OnRootMismatch_: Only change permissions and ownership if permission and ownership of
root directory does not match with expected permissions of the volume.
This could help shorten the time it takes to change ownership and permission of a volume.
* _Always_: Always change permission and ownership of the volume when volume is mounted.
For example:
-->
**fsGroupChangePolicy** - `fsGroupChangePolicy` 定义在卷被暴露给 Pod 内部之前对其
内容的属主和访问许可进行变更的行为。此字段仅适用于那些支持使用 `fsGroup`
控制属主与访问权限的卷类型。此字段的取值可以是:
* `OnRootMismatch`:只有根目录的属主与访问权限与卷所期望的权限不一致时,
才改变其中内容的属主和访问权限。这一设置有助于缩短更改卷的属主与访问
权限所需要的时间。
* `Always`:在挂载卷时总是更改卷中内容的属主和访问权限。
例如:
```yaml
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
fsGroupChangePolicy: "OnRootMismatch"
```
<!--
This field has no effect on ephemeral volume types such as
[`secret`](/docs/concepts/storage/volumes/#secret),
[`configMap`](/docs/concepts/storage/volumes/#configmap),
and [`emptydir`](/docs/concepts/storage/volumes/#emptydir).
-->
{{< note >}}
此字段对于 [`secret`](/zh/docs/concepts/storage/volumes/#secret)、
[`configMap`](/zh/docs/concepts/storage/volumes/#configmap)
和 [`emptydir`](/zh/docs/concepts/storage/volumes/#emptydir)
这类临时性存储无效。
{{< /note >}}
<!--
## Delegating volume permission and ownership change to CSI driver
-->
## 将卷权限和所有权更改委派给 CSI 驱动程序
{{< feature-state for_k8s_version="v1.23" state="beta" >}}
<!--
If you deploy a [Container Storage Interface (CSI)](https://github.com/container-storage-interface/spec/blob/master/spec.md)
driver which supports the `VOLUME_MOUNT_GROUP` `NodeServiceCapability`, the
process of setting file ownership and permissions based on the
`fsGroup` specified in the `securityContext` will be performed by the CSI driver
instead of Kubernetes, provided that the `DelegateFSGroupToCSIDriver` Kubernetes
feature gate is enabled. In this case, since Kubernetes doesn't perform any
ownership and permission change, `fsGroupChangePolicy` does not take effect, and
as specified by CSI, the driver is expected to mount the volume with the
provided `fsGroup`, resulting in a volume that is readable/writable by the
`fsGroup`.
-->
如果你部署了一个[容器存储接口 (CSI)](https://github.com/container-storage-interface/spec/blob/master/spec.md)
驱动,而该驱动支持 `VOLUME_MOUNT_GROUP` `NodeServiceCapability`
`securityContext` 中指定 `fsGroup` 来设置文件所有权和权限的过程将由 CSI
驱动而不是 Kubernetes 来执行,前提是 Kubernetes 的 `DelegateFSGroupToCSIDriver`
特性门控已启用。在这种情况下,由于 Kubernetes 不执行任何所有权和权限更改,
`fsGroupChangePolicy` 不会生效,并且按照 CSI 的规定,CSI 驱动应该使用所指定的
`fsGroup` 来挂载卷,从而生成了一个对 `fsGroup` 可读/可写的卷.
<!--
Please refer to the [KEP](https://github.com/gnufied/enhancements/blob/master/keps/sig-storage/2317-fsgroup-on-mount/README.md)
and the description of the `VolumeCapability.MountVolume.volume_mount_group`
field in the [CSI spec](https://github.com/container-storage-interface/spec/blob/master/spec.md#createvolume)
for more information.
-->
更多的信息请参考 [KEP](https://github.com/gnufied/enhancements/blob/master/keps/sig-storage/2317-fsgroup-on-mount/README.md)
和 [CSI 规范](https://github.com/container-storage-interface/spec/blob/master/spec.md#createvolume)
中的字段 `VolumeCapability.MountVolume.volume_mount_group` 的描述。
<!--
## Set the security context for a Container
To specify security settings for a Container, include the `securityContext` field
in the Container manifest. The `securityContext` field is a
[SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core) object.
Security settings that you specify for a Container apply only to
the individual Container, and they override settings made at the Pod level when
there is overlap. Container settings do not affect the Pod's Volumes.
Here is the configuration file for a Pod that has one Container. Both the Pod
and the Container have a `securityContext` field:
-->
## 为 Container 设置安全性上下文 {#set-the-security-context-for-a-container}
若要为 Container 设置安全性配置,可以在 Container 清单中包含 `securityContext`
字段。`securityContext` 字段的取值是一个
[SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
对象。你为 Container 设置的安全性配置仅适用于该容器本身,并且所指定的设置在与
Pod 层面设置的内容发生重叠时,会重载后者。Container 层面的设置不会影响到 Pod 的卷。
下面是一个 Pod 的配置文件,其中包含一个 Container。Pod 和 Container 都有
`securityContext` 字段:
{{< codenew file="pods/security/security-context-2.yaml" >}}
<!--
Create the Pod:
-->
创建该 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml
```
<!--
Verify that the Pod's Container is running:
-->
验证 Pod 中的容器处于运行状态:
```shell
kubectl get pod security-context-demo-2
```
<!--
Get a shell into the running Container:
-->
启动一个 Shell 进入到运行中的容器内:
```shell
kubectl exec -it security-context-demo-2 -- sh
```
<!--
In your shell, list the running processes:
-->
在你的 Shell 中,列举运行中的进程:
```shell
ps aux
```
<!--
The output shows that the processes are running as user 2000. This is the value
of `runAsUser` specified for the Container. It overrides the value 1000 that is
specified for the Pod.
-->
输出显示进程以用户 2000 运行。该值是在 Container 的 `runAsUser` 中设置的。
该设置值重载了 Pod 层面所设置的值 1000。
```
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js
2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js
...
```
<!--
Exit your shell:
-->
退出你的 Shell
```shell
exit
```
<!--
## Set capabilities for a Container
With [Linux capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html),
you can grant certain privileges to a process without granting all the privileges
of the root user. To add or remove Linux capabilities for a Container, include the
`capabilities` field in the `securityContext` section of the Container manifest.
First, see what happens when you don't include a `capabilities` field.
Here is configuration file that does not add or remove any Container capabilities:
-->
## 为 Container 设置权能 {#set-capabilities-for-a-container}
使用 [Linux 权能](https://man7.org/linux/man-pages/man7/capabilities.7.html)
你可以赋予进程 root 用户所拥有的某些特权,但不必赋予其全部特权。
要为 Container 添加或移除 Linux 权能,可以在 Container 清单的 `securityContext`
节包含 `capabilities` 字段。
首先,看一下不包含 `capabilities` 字段时候会发生什么。
下面是一个配置文件,其中没有添加或移除容器的权能:
{{< codenew file="pods/security/security-context-3.yaml" >}}
<!--
Create the Pod:
-->
创建该 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml
```
<!--
Verify that the Pod's Container is running:
-->
验证 Pod 的容器处于运行状态:
```shell
kubectl get pod security-context-demo-3
```
<!--
Get a shell into the running Container:
-->
启动一个 Shell 进入到运行中的容器:
```shell
kubectl exec -it security-context-demo-3 -- sh
```
<!--
In your shell, list the running processes:
-->
在你的 Shell 中,列举运行中的进程:
```shell
ps aux
```
<!--
The output shows the process IDs (PIDs) for the Container:
-->
输出显示容器中进程 ID(PIDs):
```shell
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
```
<!--
In your shell, view the status for process 1:
-->
在你的 Shell 中,查看进程 1 的状态:
```shell
cd /proc/1
cat status
```
<!--
The output shows the capabilities bitmap for the process:
-->
输出显示进程的权能位图:
```
...
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
...
```
<!--
Make a note of the capabilities bitmap, and then exit your shell:
-->
记下进程权能位图,之后退出你的 Shell:
```shell
exit
```
<!--
Next, run a Container that is the same as the preceding container, except
that it has additional capabilities set.
Here is the configuration file for a Pod that runs one Container. The configuration
adds the `CAP_NET_ADMIN` and `CAP_SYS_TIME` capabilities:
-->
接下来运行一个与前例中容器相同的容器,只是这个容器有一些额外的权能设置。
下面是一个 Pod 的配置,其中运行一个容器。配置为容器添加 `CAP_NET_ADMIN`
`CAP_SYS_TIME` 权能:
{{< codenew file="pods/security/security-context-4.yaml" >}}
<!--
Create the Pod:
-->
创建 Pod
```shell
kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml
```
<!--
Get a shell into the running Container:
-->
启动一个 Shell,进入到运行中的容器:
```shell
kubectl exec -it security-context-demo-4 -- sh
```
<!--
In your shell, view the capabilities for process 1:
-->
在你的 Shell 中,查看进程 1 的权能:
```shell
cd /proc/1
cat status
```
<!--
The output shows capabilities bitmap for the process:
-->
输出显示的是进程的权能位图:
```shell
...
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
...
```
<!--
Compare the capabilities of the two Containers:
-->
比较两个容器的权能位图:
```
00000000a80425fb
00000000aa0435fb
```
<!--
In the capability bitmap of the first container, bits 12 and 25 are clear. In the second container,
bits 12 and 25 are set. Bit 12 is `CAP_NET_ADMIN`, and bit 25 is `CAP_SYS_TIME`.
See [capability.h](https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h)
for definitions of the capability constants.
-->
在第一个容器的权能位图中,位 12 和 25 是没有设置的。在第二个容器中,位 12
和 25 是设置了的。位 12 是 `CAP_NET_ADMIN` 而位 25 则是 `CAP_SYS_TIME`
参见 [capability.h](https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h)
了解权能常数的定义。
<!--
Linux capability constants have the form `CAP_XXX`.
But when you list capabilities in your Container manifest, you must
omit the `CAP_` portion of the constant.
For example, to add `CAP_SYS_TIME`, include `SYS_TIME` in your list of capabilities.
-->
{{< note >}}
Linux 权能常数定义的形式为 `CAP_XXX`。但是你在 Container 清单中列举权能时,
要将权能名称中的 `CAP_` 部分去掉。例如,要添加 `CAP_SYS_TIME`
可在权能列表中添加 `SYS_TIME`
{{< /note >}}
<!--
## Set the Seccomp Profile for a Container
To set the Seccomp profile for a Container, include the `seccompProfile` field
in the `securityContext` section of your Pod or Container manifest. The
`seccompProfile` field is a
[SeccompProfile](/docs/reference/generated/kubernetes-api/{{< param "version"
>}}/#seccompprofile-v1-core) object consisting of `type` and `localhostProfile`.
Valid options for `type` include `RuntimeDefault`, `Unconfined`, and
`Localhost`. `localhostProfile` must only be set if `type: Localhost`. It
indicates the path of the pre-configured profile on the node, relative to the
kubelet's configured Seccomp profile location (configured with the `-root-dir`
flag).
Here is an example that sets the Seccomp profile to the node's container runtime
default profile:
-->
## 为容器设置 Seccomp 配置
若要为容器设置 Seccomp 配置(Profile),可在你的 Pod 或 Container 清单的
`securityContext` 节中包含 `seccompProfile` 字段。该字段是一个
[SeccompProfile](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#seccompprofile-v1-core)
对象,包含 `type``localhostProfile` 属性。
`type` 的合法选项包括 `RuntimeDefault``Unconfined``Localhost`
`localhostProfile` 只能在 `type: Localhost` 配置下才可以设置。
该字段标明节点上预先设定的配置的路径,路径是相对于 kubelet 所配置的
Seccomp 配置路径(使用 `--root-dir` 设置)而言的。
下面是一个例子,设置容器使用节点上容器运行时的默认配置作为 Seccomp 配置:
```yaml
...
securityContext:
seccompProfile:
type: RuntimeDefault
```
<!--
Here is an example that sets the Seccomp profile to a pre-configured file at
`<kubelet-root-dir>/seccomp/my-profiles/profile-allow.json`:
-->
下面是另一个例子,将 Seccomp 的样板设置为位于
`<kubelet-根目录>/seccomp/my-profiles/profile-allow.json`
的一个预先配置的文件。
```yaml
...
securityContext:
seccompProfile:
type: Localhost
localhostProfile: my-profiles/profile-allow.json
```
<!--
## Assign SELinux labels to a Container
To assign SELinux labels to a Container, include the `seLinuxOptions` field in
the `securityContext` section of your Pod or Container manifest. The
`seLinuxOptions` field is an
[SELinuxOptions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#selinuxoptions-v1-core)
object. Here's an example that applies an SELinux level:
-->
## 为 Container 赋予 SELinux 标签
若要给 Container 设置 SELinux 标签,可以在 Pod 或 Container 清单的
`securityContext` 节包含 `seLinuxOptions` 字段。
`seLinuxOptions` 字段的取值是一个
[SELinuxOptions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#selinuxoptions-v1-core)
对象。下面是一个应用 SELinux 标签的例子:
```yaml
...
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
```
<!--
To assign SELinux labels, the SELinux security module must be loaded on the host operating system.
-->
{{< note >}}
要指定 SELinux,需要在宿主操作系统中装载 SELinux 安全性模块。
{{< /note >}}
<!--
## Discussion
The security context for a Pod applies to the Pod's Containers and also to
the Pod's Volumes when applicable. Specifically `fsGroup` and `seLinuxOptions` are
applied to Volumes as follows:
-->
## 讨论 {#discussion}
Pod 的安全上下文适用于 Pod 中的容器,也适用于 Pod 所挂载的卷(如果有的话)。
尤其是,`fsGroup``seLinuxOptions` 按下面的方式应用到挂载卷上:
<!--
* `fsGroup`: Volumes that support ownership management are modified to be owned
and writable by the GID specified in `fsGroup`. See the
[Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
for more details.
* `seLinuxOptions`: Volumes that support SELinux labeling are relabeled to be accessible
by the label specified under `seLinuxOptions`. Usually you only
need to set the `level` section. This sets the
[Multi-Category Security (MCS)](https://selinuxproject.org/page/NB_MLS)
label given to all Containers in the Pod as well as the Volumes.
-->
* `fsGroup`:支持属主管理的卷会被修改,将其属主变更为 `fsGroup` 所指定的 GID
并且对该 GID 可写。进一步的细节可参阅
[属主变更设计文档](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)。
* `seLinuxOptions`:支持 SELinux 标签的卷会被重新打标签,以便可被 `seLinuxOptions`
下所设置的标签访问。通常你只需要设置 `level` 部分。
该部分设置的是赋予 Pod 中所有容器及卷的
[多类别安全性(Multi-Category SecurityMCS)](https://selinuxproject.org/page/NB_MLS)标签。
<!--
After you specify an MCS label for a Pod, all Pods with the same label can
access the Volume. If you need inter-Pod protection, you must assign a unique
MCS label to each Pod.
-->
{{< warning >}}
在为 Pod 设置 MCS 标签之后,所有带有相同标签的 Pod 可以访问该卷。
如果你需要跨 Pod 的保护,你必须为每个 Pod 赋予独特的 MCS 标签。
{{< /warning >}}
<!--
## Clean up
Delete the Pod:
-->
## 清理
删除之前创建的所有 Pod
```shell
kubectl delete pod security-context-demo
kubectl delete pod security-context-demo-2
kubectl delete pod security-context-demo-3
kubectl delete pod security-context-demo-4
```
## {{% heading "whatsnext" %}}
<!--
* [PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core)
* [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
* [Tuning Docker with the newest security enhancements](https://github.com/containerd/containerd/blob/main/docs/cri/config.md)
* [Security Contexts design document](https://git.k8s.io/community/contributors/design-proposals/auth/security_context.md)
* [Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
* [Pod Security Policies](/docs/concepts/security/pod-security-policy/)
* [AllowPrivilegeEscalation design
document](https://git.k8s.io/community/contributors/design-proposals/auth/no-new-privs.md)
* For more information about security mechanisms in Linux, see
[Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features)
-->
* [PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core) API 定义
* [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core) API 定义
* [使用最新的安全性增强来调优 Docker(英文)](https://github.com/containerd/containerd/blob/main/docs/cri/config.md)
* [安全上下文的设计文档(英文)](https://git.k8s.io/community/contributors/design-proposals/auth/security_context.md)
* [属主管理的设计文档(英文)](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
* [Pod 安全策略](/zh/docs/concepts/security/pod-security-policy/)
* [AllowPrivilegeEscalation 的设计文档(英文)](https://git.k8s.io/community/contributors/design-proposals/auth/no-new-privs.md)
* 关于在 Linux 系统中的安全机制的更多信息,可参阅
[Linux 内核安全性能力概述](https://www.linux.com/learn/overview-linux-kernel-security-features)。
@@ -0,0 +1,187 @@
---
title: 在 Pod 中的容器之间共享进程命名空间
min-kubernetes-server-version: v1.10
content_type: task
weight: 160
---
<!--
---
title: Share Process Namespace between Containers in a Pod
min-kubernetes-server-version: v1.10
reviewers:
- verb
- yujuhong
- dchen1107
content_type: task
weight: 160
---
-->
<!-- overview -->
{{< feature-state state="stable" for_k8s_version="v1.17" >}}
<!--
This page shows how to configure process namespace sharing for a pod. When
process namespace sharing is enabled, processes in a container are visible
to all other containers in that pod.
-->
此页面展示如何为 pod 配置进程命名空间共享。
当启用进程命名空间共享时,容器中的进程对该 pod 中的所有其他容器都是可见的。
<!--
You can use this feature to configure cooperating containers, such as a log
handler sidecar container, or to troubleshoot container images that don't
include debugging utilities like a shell.
-->
你可以使用此功能来配置协作容器,比如日志处理 sidecar 容器,或者对那些不包含诸如 shell 等调试实用工具的镜像进行故障排查。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Configure a Pod
-->
## 配置 Pod
<!--
Process Namespace Sharing is enabled using the `ShareProcessNamespace` field of
`v1.PodSpec`. For example:
-->
进程命名空间共享使用 `v1.PodSpec` 中的 `ShareProcessNamespace` 字段启用。例如:
{{< codenew file="pods/share-process-namespace.yaml" >}}
<!--
1. Create the pod `nginx` on your cluster:
```shell
kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
```
1. Attach to the `shell` container and run `ps`:
```shell
kubectl attach -it nginx -c shell
```
If you don't see a command prompt, try pressing enter.
```
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
14 101 0:00 nginx: worker process
15 root 0:00 sh
21 root 0:00 ps ax
```
-->
1. 在集群中创建 `nginx` pod
```shell
kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
```
1. 获取容器 `shell`,执行 `ps`
```shell
kubectl attach -it nginx -c shell
```
如果没有看到命令提示符,请按 enter 回车键。
```
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
14 101 0:00 nginx: worker process
15 root 0:00 sh
21 root 0:00 ps ax
```
<!--
You can signal processes in other containers. For example, send `SIGHUP` to
nginx to restart the worker process. This requires the `SYS_PTRACE` capability.
-->
你可以在其他容器中对进程发出信号。例如,发送 `SIGHUP` 到 nginx 以重启工作进程。这需要 `SYS_PTRACE` 功能。
```
/ # kill -HUP 8
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
```
<!--
It's even possible to access another container image using the
`/proc/$pid/root` link.
-->
甚至可以使用 `/proc/$pid/root` 链接访问另一个容器镜像。
```
/ # head /proc/8/root/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
```
<!-- discussion -->
<!--
## Understanding Process Namespace Sharing
-->
## 理解进程命名空间共享
<!--
Pods share many resources so it makes sense they would also share a process
namespace. Some container images may expect to be isolated from other
containers, though, so it's important to understand these differences:
-->
Pod 共享许多资源,因此它们共享进程命名空间是很有意义的。
不过,有些容器镜像可能希望与其他容器隔离,因此了解这些差异很重要:
<!--
1. **The container process no longer has PID 1.** Some container images refuse
to start without PID 1 (for example, containers using `systemd`) or run
commands like `kill -HUP 1` to signal the container process. In pods with a
shared process namespace, `kill -HUP 1` will signal the pod sandbox.
(`/pause` in the above example.)
1. **Processes are visible to other containers in the pod.** This includes all
information visible in `/proc`, such as passwords that were passed as arguments
or environment variables. These are protected only by regular Unix permissions.
1. **Container filesystems are visible to other containers in the pod through the
`/proc/$pid/root` link.** This makes debugging easier, but it also means
that filesystem secrets are protected only by filesystem permissions.
-->
1. **容器进程不再具有 PID 1。** 在没有 PID 1 的情况下,一些容器镜像拒绝启动(例如,使用 `systemd` 的容器),或者拒绝执行 `kill -HUP 1` 之类的命令来通知容器进程。在具有共享进程命名空间的 pod 中,`kill -HUP 1` 将通知 pod 沙箱(在上面的例子中是 `/pause`)。
2. **进程对 pod 中的其他容器可见。** 这包括 `/proc` 中可见的所有信息,例如作为参数或环境变量传递的密码。这些仅受常规 Unix 权限的保护。
3. **容器文件系统通过 `/proc/$pid/root` 链接对 pod 中的其他容器可见。** 这使调试更加容易,但也意味着文件系统安全性只受文件系统权限的保护。
@@ -0,0 +1,439 @@
---
title: 创建静态 Pod
weight: 170
content_type: task
---
<!-- overview -->
<!--
*Static Pods* are managed directly by the kubelet daemon on a specific node,
without the {{< glossary_tooltip text="API server" term_id="kube-apiserver" >}}
observing them.
Unlike Pods that are managed by the control plane (for example, a
{{< glossary_tooltip text="Deployment" term_id="deployment" >}});
instead, the kubelet watches each static Pod (and restarts it if it crashes).
-->
*静态 Pod* 在指定的节点上由 kubelet 守护进程直接管理,不需要
{{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}} 监管。
与由控制面管理的 Pod(例如,{{< glossary_tooltip text="Deployment" term_id="deployment" >}}
不同;kubelet 监视每个静态 Pod(在它崩溃之后重新启动)。
<!--
Static Pods are always bound to one {{< glossary_tooltip term_id="kubelet" >}} on a specific node.
The kubelet automatically tries to create a {{< glossary_tooltip text="mirror Pod" term_id="mirror-pod" >}}
on the Kubernetes API server for each static Pod.
This means that the Pods running on a node are visible on the API server,
but cannot be controlled from there.
The Pod names will be suffixed with the node hostname with a leading hyphen.
{{< note >}}
If you are running clustered Kubernetes and are using static
Pods to run a Pod on every node, you should probably be using a
{{< glossary_tooltip text="DaemonSet" term_id="daemonset" >}}
instead.
{{< /note >}}
-->
静态 Pod 永远都会绑定到一个指定节点上的 {{< glossary_tooltip term_id="kubelet" >}}。
kubelet 会尝试通过 Kubernetes API 服务器为每个静态 Pod 自动创建一个
{{< glossary_tooltip text="镜像 Pod" term_id="mirror-pod" >}}。
这意味着节点上运行的静态 Pod 对 API 服务来说是可见的,但是不能通过 API 服务器来控制。
Pod 名称将把以连字符开头的节点主机名作为后缀。
{{< note >}}
如果你在运行一个 Kubernetes 集群,并且在每个节点上都运行一个静态 Pod,
就可能需要考虑使用 {{< glossary_tooltip text="DaemonSet" term_id="daemonset" >}} 替代这种方式。
{{< /note >}}
<!--
The `spec` of a static Pod cannot refer to other API objects
(e.g., {{< glossary_tooltip text="ServiceAccount" term_id="service-account" >}},
{{< glossary_tooltip text="ConfigMap" term_id="configmap" >}},
{{< glossary_tooltip text="Secret" term_id="secret" >}}, etc).
-->
{{< note >}}
静态 Pod 的 `spec` 不能引用其他 API 对象
(如:{{< glossary_tooltip text="ServiceAccount" term_id="service-account" >}}、
{{< glossary_tooltip text="ConfigMap" term_id="configmap" >}}、
{{< glossary_tooltip text="Secret" term_id="secret" >}} 等)。
{{< /note >}}
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!--
This page assumes you're using {{< glossary_tooltip term_id="cri-o" >}} to run Pods,
and that your nodes are running the Fedora operating system.
Instructions for other distributions or Kubernetes installations may vary.
-->
本文假定你在使用 {{< glossary_tooltip term_id="docker" >}} 来运行 Pod
并且你的节点是运行着 Fedora 操作系统。
其它发行版或者 Kubernetes 部署版本上操作方式可能不一样。
<!-- steps -->
<!--
## Create a static pod {#static-pod-creation}
You can configure a static Pod with either a [file system hosted configuration file](/docs/tasks/configure-pod-container/static-pod/#configuration-files) or a [web hosted configuration file](/docs/tasks/configure-pod-container/static-pod/#pods-created-via-http).
-->
## 创建静态 Pod {#static-pod-creation}
可以通过[文件系统上的配置文件](/zh/docs/tasks/configure-pod-container/static-pod/#configuration-files)
或者 [web 网络上的配置文件](/zh/docs/tasks/configure-pod-container/static-pod/#pods-created-via-http)
来配置静态 Pod。
<!--
### Filesystem-hosted static Pod manifest {#configuration-files}
Manifests are standard Pod definitions in JSON or YAML format in a specific directory. Use the `staticPodPath: <the directory>` field in the
[kubelet configuration file](/docs/reference/config-api/kubelet-config.v1beta1/),
which periodically scans the directory and creates/deletes static Pods as YAML/JSON files appear/disappear there.
Note that the kubelet will ignore files starting with dots when scanning the specified directory.
For example, this is how to start a simple web server as a static Pod:
-->
### 文件系统上的静态 Pod 声明文件 {#configuration-files}
声明文件是标准的 Pod 定义文件,以 JSON 或者 YAML 格式存储在指定目录。路径设置在
[Kubelet 配置文件](/zh/docs/reference/config-api/kubelet-config.v1beta1/)
`staticPodPath: <目录>` 字段,kubelet 会定期的扫描这个文件夹下的 YAML/JSON
文件来创建/删除静态 Pod。
注意 kubelet 扫描目录的时候会忽略以点开头的文件。
例如:下面是如何以静态 Pod 的方式启动一个简单 web 服务:
<!--
1. Choose a node where you want to run the static Pod. In this example, it's `my-node1`.
-->
1. 选择一个要运行静态 Pod 的节点。在这个例子中选择 `my-node1`
```shell
ssh my-node1
```
<!--
2. Choose a directory, say `/etc/kubelet.d` and place a web server Pod definition there, e.g. `/etc/kubelet.d/static-web.yaml`:
```shell
# Run this command on the node where kubelet is running
mkdir /etc/kubelet.d/
cat <<EOF >/etc/kubelet.d/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
-->
2. 选择一个目录,比如在 `/etc/kubelet.d` 目录来保存 web 服务 Pod 的定义文件,
`/etc/kubelet.d/static-web.yaml`
```shell
# 在 kubelet 运行的节点上执行以下命令
mkdir /etc/kubelet.d/
cat <<EOF >/etc/kubelet.d/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
```
<!--
3. Configure your kubelet on the node to use this directory by running it with `--pod-manifest-path=/etc/kubelet.d/` argument. On Fedora edit `/etc/kubernetes/kubelet` to include this line:
```
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubelet.d/"
```
or add the `staticPodPath: <the directory>` field in the
[kubelet configuration file](/docs/reference/config-api/kubelet-config.v1beta1/).
-->
3. 配置这个节点上的 kubelet,使用这个参数执行 `--pod-manifest-path=/etc/kubelet.d/`
在 Fedora 上编辑 `/etc/kubernetes/kubelet` 以包含下行:
```
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubelet.d/"
```
或者在 [Kubelet 配置文件](/zh/docs/reference/config-api/kubelet-config.v1beta1/)
中添加 `staticPodPath: <目录>`字段。
<!--
4. Restart the kubelet. On Fedora, you would run:
```shell
# Run this command on the node where the kubelet is running
systemctl restart kubelet
```
-->
4. 重启 kubelet。Fedora 上使用下面的命令:
```shell
# 在 kubelet 运行的节点上执行以下命令
systemctl restart kubelet
```
<!--
### Web-hosted static pod manifest {#pods-created-via-http}
Kubelet periodically downloads a file specified by `--manifest-url=<URL>` argument
and interprets it as a JSON/YAML file that contains Pod definitions.
Similar to how [filesystem-hosted manifests](#configuration-files) work, the kubelet
refetches the manifest on a schedule. If there are changes to the list of static
Pods, the kubelet applies them.
To use this approach:
-->
### Web 网上的静态 Pod 声明文件 {#pods-created-via-http}
Kubelet 根据 `--manifest-url=<URL>` 参数的配置定期的下载指定文件,并且转换成
JSON/YAML 格式的 Pod 定义文件。
与[文件系统上的清单文件](#configuration-files)使用方式类似,kubelet 调度获取清单文件。
如果静态 Pod 的清单文件有改变,kubelet 会应用这些改变。
按照下面的方式来:
<!--
1. Create a YAML file and store it on a web server so that you can pass the URL of that file to the kubelet.
-->
1. 创建一个 YAML 文件,并保存在 web 服务上,为 kubelet 生成一个 URL。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
```
<!--
2. Configure the kubelet on your selected node to use this web manifest by running it with `--manifest-url=<manifest-url>`. On Fedora, edit `/etc/kubernetes/kubelet` to include this line:
-->
2. 通过在选择的节点上使用 `--manifest-url=<manifest-url>` 配置运行 kubelet。
在 Fedora 添加下面这行到 `/etc/kubernetes/kubelet`
```
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<manifest-url>"
```
<!--
3. Restart the kubelet. On Fedora, you would run:
```shell
# Run this command on the node where the kubelet is running
systemctl restart kubelet
```
-->
3. 重启 kubelet。在 Fedora 上运行如下命令:
```shell
# 在 kubelet 运行的节点上执行以下命令
systemctl restart kubelet
```
<!--
## Observe static pod behavior {#behavior-of-static-pods}
When the kubelet starts, it automatically starts all defined static Pods. As you have
defined a static Pod and restarted the kubelet, the new static Pod should
already be running.
You can view running containers (including static Pods) by running (on the node):
```shell
# Run this command on the node where kubelet is running
crictl ps
```
The output might be something like:
-->
## 观察静态 pod 的行为 {#behavior-of-static-pods}
当 kubelet 启动时,会自动启动所有定义的静态 Pod。
当定义了一个静态 Pod 并重新启动 kubelet 时,新的静态 Pod 就应该已经在运行了。
可以在节点上运行下面的命令来查看正在运行的容器(包括静态 Pod):
```shell
# 在 kubelet 运行的节点上执行以下命令
crictl ps
```
<!--
The output might be something like:
-->
输出可能会像这样:
```console
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
129fd7d382018 docker.io/library/nginx@sha256:... 11 minutes ago Running web 0 34533c6729106
```
<!--
`crictl` outputs the image URI and SHA-256 checksum. `NAME` will look more like:
`docker.io/library/nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31`.
-->
{{< note >}}
`crictl` 会输出镜像 URI 和 SHA-256 校验和。 `NAME` 看起来像:
`docker.io/library/nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31`
{{< /note >}}
<!--
You can see the mirror Pod on the API server:
-->
可以在 API 服务上看到镜像 Pod:
```shell
kubectl get pods
```
```
NAME READY STATUS RESTARTS AGE
static-web 1/1 Running 0 2m
```
<!--
Make sure the kubelet has permission to create the mirror Pod in the API server. If not, the creation request is rejected by the API server. See
[Pod Security admission](/docs/concepts/security/pod-security-admission) and [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/).
-->
{{< note >}}
要确保 kubelet 在 API 服务上有创建镜像 Pod 的权限。如果没有,创建请求会被 API 服务拒绝。
可以看 [Pod 安全性准入](/zh/docs/concepts/security/pod-security-admission/)和 [Pod 安全策略](/zh/docs/concepts/security/pod-security-policy/)。
{{< /note >}}
<!--
{{< glossary_tooltip term_id="label" text="Labels" >}} from the static Pod are
propagated into the mirror Pod. You can use those labels as normal via
{{< glossary_tooltip term_id="selector" text="selectors" >}}, etc.
-->
静态 Pod 上的{{< glossary_tooltip term_id="label" text="标签" >}} 被传到镜像 Pod。
你可以通过 {{< glossary_tooltip term_id="selector" text="选择算符" >}} 使用这些标签。
<!--
If you try to use `kubectl` to delete the mirror Pod from the API server,
the kubelet _doesn't_ remove the static Pod:
-->
如果你用 `kubectl` 从 API 服务上删除镜像 Podkubelet _不会_ 移除静态 Pod
```shell
kubectl delete pod static-web
```
```
pod "static-web" deleted
```
<!--
You can see that the Pod is still running:
-->
可以看到 Pod 还在运行:
```shell
kubectl get pods
```
```
NAME READY STATUS RESTARTS AGE
static-web 1/1 Running 0 4s
```
<!--
Back on your node where the kubelet is running, you can try to stop the container manually.
You'll see that, after a time, the kubelet will notice and will restart the Pod
automatically:
```shell
# Run these commands on the node where the kubelet is running
crictl stop 129fd7d382018 # replace with the ID of your container
sleep 20
crictl ps
```
-->
回到 kubelet 运行的节点上,你可以手动停止容器。
可以看到过了一段时间后 kubelet 会发现容器停止了并且会自动重启 Pod:
```shell
# 在 kubelet 运行的节点上执行以下命令
# 把 ID 换为你的容器的 ID
crictl stop 129fd7d382018
sleep 20
crictl ps
```
```console
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
89db4553e1eeb docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
```
<!--
## Dynamic addition and removal of static pods
The running kubelet periodically scans the configured directory (`/etc/kubelet.d` in our example) for changes and adds/removes Pods as files appear/disappear in this directory.
```shell
# This assumes you are using filesystem-hosted static Pod configuration
# Run these commands on the node where the kubelet is running
#
mv /etc/kubelet.d/static-web.yaml /tmp
sleep 20
crictl ps
# You see that no nginx container is running
mv /tmp/static-web.yaml /etc/kubelet.d/
sleep 20
crictl ps
```
-->
## 动态增加和删除静态 pod
运行中的 kubelet 会定期扫描配置的目录(比如例子中的 `/etc/kubelet.d` 目录)中的变化,
并且根据文件中出现/消失的 Pod 来添加/删除 Pod。
```shell
# 前提是你在用主机文件系统上的静态 Pod 配置文件
# 在 kubelet 运行的节点上执行以下命令
mv /etc/kubelet.d/static-web.yaml /tmp
sleep 20
crictl ps
# 可以看到没有 nginx 容器在运行
mv /tmp/static-web.yaml /etc/kubelet.d/
sleep 20
crictl ps
```
```console
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
f427638871c35 docker.io/library/nginx@sha256:... 19 seconds ago Running web 1 34533c6729106
```
@@ -0,0 +1,713 @@
---
title: 将 Docker Compose 文件转换为 Kubernetes 资源
content_type: task
weight: 200
---
<!--
reviewers:
- cdrage
title: Translate a Docker Compose File to Kubernetes Resources
content_type: task
weight: 200
-->
<!-- overview -->
<!--
What's Kompose? It's a conversion tool for all things compose (namely Docker Compose) to container orchestrators (Kubernetes or OpenShift).
-->
Kompose 是什么?它是个转换工具,可将 compose(即 Docker Compose)所组装的所有内容
转换成容器编排器(Kubernetes 或 OpenShift)可识别的形式。
<!--
More information can be found on the Kompose website at [http://kompose.io](http://kompose.io).
-->
更多信息请参考 Kompose 官网 [http://kompose.io](http://kompose.io)。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
<!--
## Install Kompose
We have multiple ways to install Kompose. Our preferred method is downloading the binary from the latest GitHub release.
-->
## 安装 Kompose {#install-kompose}
我们有很多种方式安装 Kompose。首选方式是从最新的 GitHub 发布页面下载二进制文件。
{{< tabs name="install_ways" >}}
{{% tab name="GitHub 下载" %}}
<!--
Kompose is released via GitHub on a three-week cycle, you can see all current releases on the [GitHub release page](https://github.com/kubernetes/kompose/releases).
-->
Kompose 通过 GitHub 发布,发布周期为三星期。
你可以在 [GitHub 发布页面](https://github.com/kubernetes/kompose/releases)
上看到所有当前版本。
```shell
# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.24.0/kompose-linux-amd64 -o kompose
# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.24.0/kompose-darwin-amd64 -o kompose
# Windows
curl -L https://github.com/kubernetes/kompose/releases/download/v1.24.0/kompose-windows-amd64.exe -o kompose.exe
chmod +x kompose
sudo mv ./kompose /usr/local/bin/kompose
```
<!--
Alternatively, you can download the [tarball](https://github.com/kubernetes/kompose/releases).
-->
或者,你可以下载 [tar 包](https://github.com/kubernetes/kompose/releases)。
{{% /tab %}}
{{% tab name="基于源代码构建" %}}
<!--
Installing using `go get` pulls from the master branch with the latest development changes.
-->
`go get` 命令从主分支拉取最新的开发变更的方法安装 Kompose。
```shell
go get -u github.com/kubernetes/kompose
```
{{% /tab %}}
{{% tab name="CentOS 包" %}}
<!--
Kompose is in [EPEL](https://fedoraproject.org/wiki/EPEL) CentOS repository.
If you don't have [EPEL](https://fedoraproject.org/wiki/EPEL) repository already installed and enabled you can do it by running `sudo yum install epel-release`
-->
Kompose 位于 [EPEL](https://fedoraproject.org/wiki/EPEL) CentOS 代码仓库。
如果你还没有安装启用 [EPEL](https://fedoraproject.org/wiki/EPEL) 代码仓库,
请运行命令 `sudo yum install epel-release`
<!--
If you have [EPEL](https://fedoraproject.org/wiki/EPEL) enabled in your system, you can install Kompose like any other package.
-->
如果你的系统中已经启用了 [EPEL](https://fedoraproject.org/wiki/EPEL)
你就可以像安装其他软件包一样安装 Kompose。
```shell
sudo yum -y install kompose
```
{{% /tab %}}
{{% tab name="Fedora package" %}}
<!--
Kompose is in Fedora 24, 25 and 26 repositories. You can install it like any other package.
-->
Kompose 位于 Fedora 24、25 和 26 的代码仓库。你可以像安装其他软件包一样安装 Kompose。
```shell
sudo dnf -y install kompose
```
{{% /tab %}}
{{% tab name="Homebrew (macOS)" %}}
<!--
On macOS you can install latest release via [Homebrew](https://brew.sh):
-->
在 macOS 上你可以通过 [Homebrew](https://brew.sh) 安装 Kompose 的最新版本:
```shell
brew install kompose
```
{{% /tab %}}
{{< /tabs >}}
<!--
## Use Kompose
-->
## 使用 Kompose {#use-kompose}
<!--
In a few steps, we'll take you from Docker Compose to Kubernetes. All
you need is an existing `docker-compose.yml` file.
-->
再需几步,我们就把你从 Docker Compose 带到 Kubernetes。
你只需要一个现有的 `docker-compose.yml` 文件。
<!--
1. Go to the directory containing your `docker-compose.yml` file. If you don't have one, test using this one.
-->
1. 进入 `docker-compose.yml` 文件所在的目录。如果没有,请使用下面这个进行测试。
```yaml
version: "2"
services:
redis-master:
image: k8s.gcr.io/redis:e2e
ports:
- "6379"
redis-slave:
image: gcr.io/google_samples/gb-redisslave:v3
ports:
- "6379"
environment:
- GET_HOSTS_FROM=dns
frontend:
image: gcr.io/google-samples/gb-frontend:v4
ports:
- "80:80"
environment:
- GET_HOSTS_FROM=dns
labels:
kompose.service.type: LoadBalancer
```
<!--
2. To convert the `docker-compose.yml` file to files that you can use with
`kubectl`, run `kompose convert` and then `kubectl apply -f <output file>`.
-->
2. 要将 `docker-compose.yml` 转换为 `kubectl` 可用的文件,请运行 `kompose convert`
命令进行转换,然后运行 `kubectl apply -f <output file>` 进行创建。
```shell
kompose convert
```
```none
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
```
```bash
kubectl apply -f frontend-service.yaml,redis-master-service.yaml,redis-slave-service.yaml,frontend-deployment.yaml,
```
<!--
The output is similar to:
-->
输出类似于:
```none
service/frontend created
service/redis-master created
service/redis-slave created
deployment.apps/frontend created
deployment.apps/redis-master created
deployment.apps/redis-slave created
```
<!--
Your deployments are running in Kubernetes.
-->
你部署的应用在 Kubernetes 中运行起来了。
<!--
3. Access your application.
-->
3. 访问你的应用
<!--
If you're already using `minikube` for your development process:
-->
如果你在开发过程中使用 `minikube`,请执行:
```shell
minikube service frontend
```
<!--
Otherwise, let's look up what IP your service is using!
-->
否则,我们要查看一下你的服务使用了什么 IP!
```shell
kubectl describe svc frontend
```
```none
Name: frontend
Namespace: default
Labels: service=frontend
Selector: service=frontend
Type: LoadBalancer
IP: 10.0.0.183
LoadBalancer Ingress: 192.0.2.89
Port: 80 80/TCP
NodePort: 80 31144/TCP
Endpoints: 172.17.0.4:80
Session Affinity: None
No events.
```
<!--
If you're using a cloud provider, your IP will be listed next to `LoadBalancer Ingress`.
-->
如果你使用的是云提供商,你的 IP 将在 `LoadBalancer Ingress` 字段给出。
```shell
curl http://192.0.2.89
```
<!-- discussion -->
<!--
## User Guide
-->
## 用户指南 {#user-guide}
<!--
- CLI
- [`kompose convert`](#kompose-convert)
- Documentation
- [Alternative Conversions](#alternative-conversions)
- [Labels](#labels)
- [Restart](#restart)
- [Docker Compose Versions](#docker-compose-versions)
-->
- CLI
- [`kompose convert`](#kompose-convert)
- 文档
- [其他转换方式](#其他转换方式)
- [标签](#labels)
- [重启](#restart)
- [Docker Compose 版本](#docker-compose-versions)
<!--
Kompose has support for two providers: OpenShift and Kubernetes.
You can choose a targeted provider using global option `--provider`. If no provider is specified, Kubernetes is set by default.
-->
Kompose 支持两种驱动:OpenShift 和 Kubernetes。
你可以通过全局选项 `--provider` 选择驱动。如果没有指定,
会将 Kubernetes 作为默认驱动。
## `kompose convert`
<!--
Kompose supports conversion of V1, V2, and V3 Docker Compose files into Kubernetes and OpenShift objects.
-->
Kompose 支持将 V1、V2 和 V3 版本的 Docker Compose 文件转换为 Kubernetes 和 OpenShift 资源对象。
<!--
### Kubernetes `kompose convert` example
-->
### Kubernetes `kompose convert` 示例 {#kubernetes-kompose-convert-example}
```shell
kompose --file docker-voting.yml convert
```
```none
WARN Unsupported key networks - ignoring
WARN Unsupported key build - ignoring
INFO Kubernetes file "worker-svc.yaml" created
INFO Kubernetes file "db-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "result-svc.yaml" created
INFO Kubernetes file "vote-svc.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
INFO Kubernetes file "result-deployment.yaml" created
INFO Kubernetes file "vote-deployment.yaml" created
INFO Kubernetes file "worker-deployment.yaml" created
INFO Kubernetes file "db-deployment.yaml" created
```
```shell
ls
```
```none
db-deployment.yaml docker-compose.yml docker-gitlab.yml redis-deployment.yaml result-deployment.yaml vote-deployment.yaml worker-deployment.yaml
db-svc.yaml docker-voting.yml redis-svc.yaml result-svc.yaml vote-svc.yaml worker-svc.yaml
```
<!--
You can also provide multiple docker-compose files at the same time:
-->
你也可以同时提供多个 docker-compose 文件进行转换:
```shell
kompose -f docker-compose.yml -f docker-guestbook.yml convert
```
```none
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "mlbparks-service.yaml" created
INFO Kubernetes file "mongodb-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "mlbparks-deployment.yaml" created
INFO Kubernetes file "mongodb-deployment.yaml" created
INFO Kubernetes file "mongodb-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
```
```shell
ls
```
```
mlbparks-deployment.yaml mongodb-service.yaml redis-slave-service.jsonmlbparks-service.yaml
frontend-deployment.yaml mongodb-claim0-persistentvolumeclaim.yaml redis-master-service.yaml
frontend-service.yaml mongodb-deployment.yaml redis-slave-deployment.yaml
redis-master-deployment.yaml
```
<!--
When multiple docker-compose files are provided the configuration is merged. Any configuration that is common will be over ridden by subsequent file.
-->
当提供多个 docker-compose 文件时,配置将会合并。任何通用的配置都将被后续文件覆盖。
<!--
### OpenShift `kompose convert` example
-->
### OpenShift `kompose convert` 示例 {#openshift-kompose-convert-example}
```shell
kompose --provider openshift --file docker-voting.yml convert
```
```
WARN [worker] Service cannot be created because of missing port.
INFO OpenShift file "vote-service.yaml" created
INFO OpenShift file "db-service.yaml" created
INFO OpenShift file "redis-service.yaml" created
INFO OpenShift file "result-service.yaml" created
INFO OpenShift file "vote-deploymentconfig.yaml" created
INFO OpenShift file "vote-imagestream.yaml" created
INFO OpenShift file "worker-deploymentconfig.yaml" created
INFO OpenShift file "worker-imagestream.yaml" created
INFO OpenShift file "db-deploymentconfig.yaml" created
INFO OpenShift file "db-imagestream.yaml" created
INFO OpenShift file "redis-deploymentconfig.yaml" created
INFO OpenShift file "redis-imagestream.yaml" created
INFO OpenShift file "result-deploymentconfig.yaml" created
INFO OpenShift file "result-imagestream.yaml" created
```
<!--
It also supports creating buildconfig for build directive in a service. By default, it uses the remote repo for the current git branch as the source repo, and the current branch as the source branch for the build. You can specify a different source repo and branch using ``--build-repo`` and ``--build-branch`` options respectively.
-->
kompose 还支持为服务中的构建指令创建 buildconfig。
默认情况下,它使用当前 git 分支的 remote 仓库作为源仓库,使用当前分支作为构建的源分支。
你可以分别使用 ``--build-repo`` 和 ``--build-branch`` 选项指定不同的源仓库和分支。
```shell
kompose --provider openshift --file buildconfig/docker-compose.yml convert
```
```none
WARN [foo] Service cannot be created because of missing port.
INFO OpenShift Buildconfig using git@github.com:rtnpro/kompose.git::master as source.
INFO OpenShift file "foo-deploymentconfig.yaml" created
INFO OpenShift file "foo-imagestream.yaml" created
INFO OpenShift file "foo-buildconfig.yaml" created
```
<!--
If you are manually pushing the Openshift artifacts using ``oc create -f``, you need to ensure that you push the imagestream artifact before the buildconfig artifact, to workaround this Openshift issue: https://github.com/openshift/origin/issues/4518 .
-->
{{< note >}}
如果使用 ``oc create -f`` 手动推送 Openshift 工件,则需要确保在构建配置工件之前推送
imagestream 工件,以解决 Openshift 的这个问题: https://github.com/openshift/origin/issues/4518 。
{{< /note >}}
<!--
## Alternative Conversions
The default `kompose` transformation will generate Kubernetes [Deployments](/docs/concepts/workloads/controllers/deployment/) and [Services](/docs/concepts/services-networking/service/), in yaml format. You have alternative option to generate json with `-j`. Also, you can alternatively generate [Replication Controllers](/docs/concepts/workloads/controllers/replicationcontroller/) objects, [Daemon Sets](/docs/concepts/workloads/controllers/daemonset/), or [Helm](https://github.com/helm/helm) charts.
-->
## 其他转换方式 {#alternative-conversions}
默认的 `kompose` 转换会生成 yaml 格式的 Kubernetes
[Deployment](/zh/docs/concepts/workloads/controllers/deployment/) 和
[Service](/zh/docs/concepts/services-networking/service/) 对象。
你可以选择通过 `-j` 参数生成 json 格式的对象。
你也可以替换生成 [Replication Controllers](/zh/docs/concepts/workloads/controllers/replicationcontroller/) 对象、
[Daemon Sets](/zh/docs/concepts/workloads/controllers/daemonset/) 或
[Helm](https://github.com/helm/helm) charts。
```shell
kompose convert -j
```
```none
INFO Kubernetes file "redis-svc.json" created
INFO Kubernetes file "web-svc.json" created
INFO Kubernetes file "redis-deployment.json" created
INFO Kubernetes file "web-deployment.json" created
```
<!--
The `*-deployment.json` files contain the Deployment objects.
-->
`*-deployment.json` 文件中包含 Deployment 对象。
```shell
kompose convert --replication-controller
```
```none
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-replicationcontroller.yaml" created
INFO Kubernetes file "web-replicationcontroller.yaml" created
```
<!--
The `*-replicationcontroller.yaml` files contain the Replication Controller objects. If you want to specify replicas (default is 1), use `--replicas` flag: `$ kompose convert --replication-controller --replicas 3`
-->
`*-replicationcontroller.yaml` 文件包含 Replication Controller 对象。
如果你想指定副本数(默认为 1),可以使用 `--replicas` 参数:
`kompose convert --replication-controller --replicas 3`
```shell
kompose convert --daemon-set
```
```none
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-daemonset.yaml" created
INFO Kubernetes file "web-daemonset.yaml" created
```
<!--
The `*-daemonset.yaml` files contain the DaemonSet objects
If you want to generate a Chart to be used with [Helm](https://github.com/kubernetes/helm) simply do:
-->
`*-daemonset.yaml` 文件包含 DaemonSet 对象。
如果你想生成 [Helm](https://github.com/kubernetes/helm) 可用的 Chart
只需简单的执行下面的命令:
```shell
kompose convert -c
```
```none
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-deployment.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
chart created in "./docker-compose/"
```
```shell
tree docker-compose/
```
```
docker-compose
├── Chart.yaml
├── README.md
└── templates
├── redis-deployment.yaml
├── redis-svc.yaml
├── web-deployment.yaml
└── web-svc.yaml
```
<!--
The chart structure is aimed at providing a skeleton for building your Helm charts.
-->
这个 Chart 结构旨在为构建 Helm Chart 提供框架。
<!--
## Labels
`kompose` supports Kompose-specific labels within the `docker-compose.yml` file in order to explicitly define a service's behavior upon conversion.
- `kompose.service.type` defines the type of service to be created.
For example:
-->
## 标签 {#labels}
`kompose` 支持 `docker-compose.yml` 文件中用于 Kompose 的标签,以便
在转换时明确定义 Service 的行为。
- `kompose.service.type` 定义要创建的 Service 类型。例如:
```yaml
version: "2"
services:
nginx:
image: nginx
dockerfile: foobar
build: ./foobar
cap_add:
- ALL
container_name: foobar
labels:
kompose.service.type: nodeport
```
<!--
- `kompose.service.expose` defines if the service needs to be made accessible from outside the cluster or not. If the value is set to "true", the provider sets the endpoint automatically, and for any other value, the value is set as the hostname. If multiple ports are defined in a service, the first one is chosen to be the exposed.
- For the Kubernetes provider, an ingress resource is created and it is assumed that an ingress controller has already been configured.
- For the OpenShift provider, a route is created.
For example:
-->
- `kompose.service.expose` 定义是否允许从集群外部访问 Service。
如果该值被设置为 "true",提供程序将自动设置端点,
对于任何其他值,该值将被设置为主机名。
如果在 Service 中定义了多个端口,则选择第一个端口作为公开端口。
- 如果使用 Kubernetes 驱动,会有一个 Ingress 资源被创建,并且假定
已经配置了相应的 Ingress 控制器。
- 如果使用 OpenShift 驱动,则会有一个 route 被创建。
例如:
```yaml
version: "2"
services:
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: "counter.example.com"
redis:
image: redis:3.0
ports:
- "6379"
```
<!--
The currently supported options are:
| Key | Value |
|----------------------|-------------------------------------|
| kompose.service.type | nodeport / clusterip / loadbalancer |
| kompose.service.expose| true / hostname |
-->
当前支持的选项有:
| 键 | 值 |
|------------------------|-------------------------------------|
| kompose.service.type | nodeport / clusterip / loadbalancer |
| kompose.service.expose | true / hostname |
{{< note >}}
<!--
The `kompose.service.type` label should be defined with `ports` only, otherwise `kompose` will fail.
-->
`kompose.service.type` 标签应该只用 `ports` 来定义,否则 `kompose` 会失败。
{{< /note >}}
<!--
## Restart
If you want to create normal pods without controllers you can use `restart` construct of docker-compose to define that. Follow table below to see what happens on the `restart` value.
-->
## 重启 {#restart}
如果你想创建没有控制器的普通 Pod,可以使用 docker-compose 的 `restart`
结构来指定这一行为。请参考下表了解 `restart` 的不同参数。
<!--
| `docker-compose` `restart` | object created | Pod `restartPolicy` |
|----------------------------|-------------------|---------------------|
| `""` | controller object | `Always` |
| `always` | controller object | `Always` |
| `on-failure` | Pod | `OnFailure` |
| `no` | Pod | `Never` |
-->
| `docker-compose` `restart` | 创建的对象 | Pod `restartPolicy` |
|----------------------------|-------------------|---------------------|
| `""` | 控制器对象 | `Always` |
| `always` | 控制器对象 | `Always` |
| `on-failure` | Pod | `OnFailure` |
| `no` | Pod | `Never` |
<!--
The controller object could be `deployment` or `replicationcontroller`, etc.
-->
{{< note >}}
控制器对象可以是 `deployment``replicationcontroller` 等。
{{< /note >}}
<!--
For example, the `pival` service will become pod down here. This container calculated value of `pi`.
-->
例如,`pival` Service 将在这里变成 Pod。这个容器计算 `pi` 的取值。
```yaml
version: '2'
services:
pival:
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restart: "on-failure"
```
<!--
### Warning about Deployment Configurations
If the Docker Compose file has a volume specified for a service, the Deployment (Kubernetes) or DeploymentConfig (OpenShift) strategy is changed to "Recreate" instead of "RollingUpdate" (default). This is done to avoid multiple instances of a service from accessing a volume at the same time.
-->
### 关于 Deployment Config 的提醒 {#warning-about-deployment-configurations}
如果 Docker Compose 文件中为服务声明了卷,DeploymentKubernetes)或
DeploymentConfigOpenShift)策略会从 “RollingUpdate”(默认)变为 “Recreate”。
这样做的目的是为了避免服务的多个实例同时访问卷。
<!--
If the Docker Compose file has service name with `_` in it (eg.`web_service`), then it will be replaced by `-` and the service name will be renamed accordingly (eg.`web-service`). Kompose does this because "Kubernetes" doesn't allow `_` in object name.
Please note that changing service name might break some `docker-compose` files.
-->
如果 Docker Compose 文件中的服务名包含 `_`(例如 `web_service`),
那么将会被替换为 `-`,服务也相应的会重命名(例如 `web-service`)。
Kompose 这样做的原因是 “Kubernetes” 不允许对象名称中包含 `_`
请注意,更改服务名称可能会破坏一些 `docker-compose` 文件。
<!--
## Docker Compose Versions
Kompose supports Docker Compose versions: 1, 2 and 3. We have limited support on versions 2.1 and 3.2 due to their experimental nature.
A full list on compatibility between all three versions is listed in our [conversion document](https://github.com/kubernetes/kompose/blob/master/docs/conversion.md) including a list of all incompatible Docker Compose keys.
-->
## Docker Compose 版本 {#docker-compose-versions}
Kompose 支持的 Docker Compose 版本包括:1、2 和 3。
对 2.1 和 3.2 版本的支持还有限,因为它们还在实验阶段。
所有三个版本的兼容性列表请查看我们的
[转换文档](https://github.com/kubernetes/kompose/blob/master/docs/conversion.md)
文档中列出了所有不兼容的 Docker Compose 关键字。