diff --git a/content/zh/docs/concepts/_index.md b/content/zh/docs/concepts/_index.md index 6059a0544e..a2b1991cd9 100644 --- a/content/zh/docs/concepts/_index.md +++ b/content/zh/docs/concepts/_index.md @@ -14,7 +14,9 @@ weight: 40 {{% capture overview %}} - + 概念部分可以帮助你了解 Kubernetes 的各个组成部分以及 Kubernetes 用来表示集群的一些抽象概念,并帮助你更加深入的理解 Kubernetes 是如何工作的。 @@ -22,37 +24,51 @@ weight: 40 {{% capture body %}} - + ## 概述 - + -要使用 Kubernetes,你需要用 *Kubernetes API 对象* 来描述集群的*预期状态(desired state)* :包括你需要运行的应用或者负载,它们使用的镜像、副本数,以及所需网络和磁盘资源等等。你可以使用命令行工具 `kubectl` 来调用 Kubernetes API 创建对象,通过所创建的这些对象来配置预期状态。你也可以直接调用 Kubernetes API 和集群进行交互,设置或者修改预期状态。 +要使用 Kubernetes,你需要用 *Kubernetes API 对象* 来描述集群的 *预期状态(desired state)* :包括你需要运行的应用或者负载,它们使用的镜像、副本数,以及所需网络和磁盘资源等等。你可以使用命令行工具 `kubectl` 来调用 Kubernetes API 创建对象,通过所创建的这些对象来配置预期状态。你也可以直接调用 Kubernetes API 和集群进行交互,设置或者修改预期状态。 - + -一旦你设置了你所需的目标状态,*Kubernetes 控制面(control plane)* 会促成集群的当前状态符合其预期状态。为此,Kubernetes 会自动执行各类任务,比如运行或者重启容器、调整给定应用的副本数等等。Kubernetes 控制面由一组运行在集群上的进程组成: +一旦你设置了你所需的目标状态,*Kubernetes 控制面(control plane)* 会通过 Pod 生命周期事件生成器( PLEG ),促成集群的当前状态符合其预期状态。为此,Kubernetes 会自动执行各类任务,比如运行或者重启容器、调整给定应用的副本数等等。Kubernetes 控制面由一组运行在集群上的进程组成: - + * **[kube-proxy](/docs/admin/kube-proxy/)**, a network proxy which reflects Kubernetes networking services on each node. +--> -* **Kubernetes 主控组件(Master)** 包含三个进程,都运行在集群中的某个节上,通常这个节点被称为 master 节点。这些进程包括:[kube-apiserver](/docs/admin/kube-apiserver/)、[kube-controller-manager](/docs/admin/kube-controller-manager/)和[kube-scheduler](/docs/admin/kube-scheduler/)。 +* **Kubernetes 主控组件(Master)** 包含三个进程,都运行在集群中的某个节上,通常这个节点被称为 master 节点。这些进程包括:[kube-apiserver](/docs/admin/kube-apiserver/)、[kube-controller-manager](/docs/admin/kube-controller-manager/) 和 [kube-scheduler](/docs/admin/kube-scheduler/)。 * 集群中的每个非 master 节点都运行两个进程: * **[kubelet](/docs/admin/kubelet/)**,和 master 节点进行通信。 * **[kube-proxy](/docs/admin/kube-proxy/)**,一种网络代理,将 Kubernetes 的网络服务代理到每个节点上。 - + ## Kubernetes 对象 - + -Kubernetes 包含若干抽象用来表示系统状态,包括:已部署的容器化应用和负载、与它们相关的网络和磁盘资源以及有关集群正在运行的其他操作的信息。这些抽象使用 Kubernetes API 对象来表示。参阅 [Kubernetes对象概述](/docs/concepts/abstractions/overview/)以了解详细信息。 +Kubernetes 包含若干抽象用来表示系统状态,包括:已部署的容器化应用和负载、与它们相关的网络和磁盘资源以及有关集群正在运行的其他操作的信息。这些抽象使用 Kubernetes API 对象来表示。参阅 [Kubernetes 对象概述](/docs/concepts/abstractions/overview/)以了解详细信息。 - + 基本的 Kubernetes 对象包括: @@ -61,7 +77,9 @@ Kubernetes 包含若干抽象用来表示系统状态,包括:已部署的容 * [Volume](/docs/concepts/storage/volumes/) * [Namespace](/docs/concepts/overview/working-with-objects/namespaces/) - + 另外,Kubernetes 包含大量的被称作*控制器(controllers)* 的高级抽象。控制器基于基本对象构建并提供额外的功能和方便使用的特性。具体包括: @@ -71,52 +89,75 @@ Kubernetes 包含若干抽象用来表示系统状态,包括:已部署的容 * [DaemonSet](/docs/concepts/workloads/controllers/daemonset/) * [Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/) - + ## Kubernetes 控制面 - + -关于 Kubernetes 控制平面的各个部分,(如 Kubernetes 主控组件和 kubelet 进程,管理着 Kubernetes 如何与你的集群进行通信。控制平面维护着系统中所有的 Kubernetes 对象的状态记录,并且通过连续的控制循环来管理这些对象的状态。在任一的给定时间点,控制面的控制环都能响应集群中的变化,并且让系统中所有对象的实际状态与你提供的预期状态相匹配。 +关于 Kubernetes 控制平面的各个部分,(如 Kubernetes 主控组件和 kubelet 进程),管理着 Kubernetes 如何与你的集群进行通信。控制平面维护着系统中所有的 Kubernetes 对象的状态记录,并且通过连续的控制循环来管理这些对象的状态。在任意的给定时间点,控制面的控制环都能响应集群中的变化,并且让系统中所有对象的实际状态与你提供的预期状态相匹配。 - + 比如, 当你通过 Kubernetes API 创建一个 Deployment 对象,你就为系统增加了一个新的目标状态。Kubernetes 控制平面记录着对象的创建,并启动必要的应用然后将它们调度至集群某个节点上来执行你的指令,以此来保持集群的实际状态和目标状态的匹配。 - + ### Kubernetes Master 节点 - + Kubernetes master 节点负责维护集群的目标状态。当你要与 Kubernetes 通信时,使用如 `kubectl` 的命令行工具,就可以直接与 Kubernetes master 节点进行通信。 - + -> "master" 是指管理集群状态的一组进程的集合。通常这些进程都跑在集群中一个单独的节点上,并且这个节点被称为 master 节点。master 节点也可以扩展副本数,来获取更好的性能及冗余。 +> "master" 是指管理集群状态的一组进程的集合。通常这些进程都跑在集群中一个单独的节点上,并且这个节点被称为 master 节点。master 节点也可以扩展副本数,来获取更好的可用性及冗余。 - + ### Kubernetes Node 节点 - + 集群中的 node 节点(虚拟机、物理机等等)都是用来运行你的应用和云工作流的机器。Kubernetes master 节点控制所有 node 节点;你很少需要和 node 节点进行直接通信。 - + #### 对象元数据 -* [注释](/docs/concepts/overview/working-with-objects/annotations/) +* [注解](/docs/concepts/overview/working-with-objects/annotations/) {{% /capture %}} {{% capture whatsnext %}} - +for information about the concept page type and the concept template. +--> 如果你想编写一个概念页面,请参阅[使用页面模板](/docs/home/contribute/page-templates/)获取更多有关概念页面类型和概念模板的信息。 diff --git a/content/zh/docs/concepts/configuration/_index.md b/content/zh/docs/concepts/configuration/_index.md new file mode 100644 index 0000000000..265da88a94 --- /dev/null +++ b/content/zh/docs/concepts/configuration/_index.md @@ -0,0 +1,4 @@ +--- +title: "配置" +weight: 70 +--- \ No newline at end of file diff --git a/content/zh/docs/concepts/configuration/manage-compute-resources-container.md b/content/zh/docs/concepts/configuration/manage-compute-resources-container.md index 0d798d058b..c8424c2d6f 100644 --- a/content/zh/docs/concepts/configuration/manage-compute-resources-container.md +++ b/content/zh/docs/concepts/configuration/manage-compute-resources-container.md @@ -1,22 +1,67 @@ --- -title: Managing Compute Resources for Containers +title: 为容器管理计算资源 content_template: templates/concept +weight: 20 +feature: + title: 自动装箱 + description: > + 根据资源需求和其他约束自动放置容器,同时不会牺牲可用性,将任务关键工作负载和尽力服务工作负载进行混合放置,以提高资源利用率并节省更多资源。 --- {{% capture overview %}} -当您定义 [Pod](/docs/user-guide/pods) 的时候可以选择为每个容器指定需要的 CPU 和内存(RAM)大小。当为容器指定了资源请求后,调度器就能够更好的判断出将容器调度到哪个节点上。如果您还为容器指定了资源限制,节点上的资源就可以按照指定的方式做竞争。关于资源请求和限制的不同点和更多资料请参考 [Resource QoS](https://git.k8s.io/community/contributors/design-proposals/resource-qos.md)。 + +当您定义 [Pod](/docs/user-guide/pods) 的时候可以选择为每个容器指定需要的 CPU 和内存(RAM)大小。当为容器指定了资源请求后,调度器就能够更好的判断出将容器调度到哪个节点上。如果您还为容器指定了资源限制,Kubernetes 就可以按照指定的方式来处理节点上的资源竞争。关于资源请求和限制的不同点和更多资料请参考 [Resource QoS](https://git.k8s.io/community/contributors/design-proposals/resource-qos.md)。 {{% /capture %}} {{% capture body %}} + + ## 资源类型 -*CPU* 和 *内存* 都是 *资源类型* 。资源类型具有基本单位。CPU 的单位是 core,内存的单位是 byte。 +*CPU* 和*内存*都是*资源类型*。资源类型具有基本单位。CPU 的单位是核心数,内存的单位是字节。 -CPU和内存统称为*计算资源* ,也可以称为*资源* 。计算资源的数量是可以被请求、分配、消耗和可测量的。它们与 [API 资源](/docs/api/) 不同。 API 资源(如 Pod 和 [Service](/docs/user-guide/services))是可通过 Kubernetes API server 读取和修改的对象。 +CPU和内存统称为*计算资源*,也可以称为*资源*。计算资源的数量是可以被请求、分配、消耗和可测量的。它们与 [API 资源](/docs/concepts/overview/kubernetes-api/) 不同。 API 资源(如 Pod 和 [Service](/docs/concepts/services-networking/service/))是可通过 Kubernetes API server 读取和修改的对象。 + + ## Pod 和 容器的资源请求和限制 @@ -29,6 +74,31 @@ Pod 中的每个容器都可以指定以下的一个或者多个值: 尽管只能在个别容器上指定请求和限制,但是我们可以方便地计算出 Pod 资源请求和限制。特定资源类型的Pod 资源请求/限制是 Pod 中每个容器的该类型的资源请求/限制的总和。 + + ## CPU 的含义 CPU 资源的限制和请求以 *cpu* 为单位。 @@ -44,6 +114,15 @@ Kubernetes 中的一个 cpu 等于: CPU 总是要用绝对数量,不可以使用相对数量;0.1 的 CPU 在单核、双核、48核的机器中的意义是一样的。 + + ## 内存的含义 内存的限制和请求以字节为单位。您可以使用以下后缀之一作为平均整数或定点整数表示内存:E,P,T,G,M,K。您还可以使用两个字母的等效的幂数:Ei,Pi,Ti ,Gi,Mi,Ki。例如,以下代表大致相同的值: @@ -52,6 +131,14 @@ CPU 总是要用绝对数量,不可以使用相对数量;0.1 的 CPU 在单 128974848, 129e6, 129M, 123Mi ``` + + 下面是个例子。 以下 Pod 有两个容器。每个容器的请求为 0.25 cpu 和 64MiB(226 字节)内存,每个容器的限制为 0.5 cpu 和 128MiB 内存。您可以说该 Pod 请求 0.5 cpu 和 128 MiB 的内存,限制为 1 cpu 和 256MiB 的内存。 @@ -65,6 +152,9 @@ spec: containers: - name: db image: mysql + env: + - name: MYSQL_ROOT_PASSWORD + value: "password" resources: requests: memory: "64Mi" @@ -83,27 +173,107 @@ spec: cpu: "500m" ``` + + ## 具有资源请求的 Pod 如何调度 当您创建一个 Pod 时,Kubernetes 调度程序将为 Pod 选择一个节点。每个节点具有每种资源类型的最大容量:可为 Pod 提供的 CPU 和内存量。调度程序确保对于每种资源类型,调度的容器的资源请求的总和小于节点的容量。请注意,尽管节点上的实际内存或 CPU 资源使用量非常低,但如果容量检查失败,则调度程序仍然拒绝在该节点上放置 Pod。当资源使用量稍后增加时,例如在请求率的每日峰值期间,这可以防止节点上的资源短缺。 + + ## 具有资源限制的 Pod 如何运行 当 kubelet 启动一个 Pod 的容器时,它会将 CPU 和内存限制传递到容器运行时。 当使用 Docker 时: -- `spec.containers[].resources.requests.cpu` 的值将转换成 millicore 值,这是个浮点数,并乘以1024,这个数字中的较大者或2用作 `docker run` 命令中的[ `--cpu-shares`](https://docs.docker.com/engine/reference/run/#/cpu-share-constraint) 标志的值。 + + +- `spec.containers[].resources.requests.cpu` 的值将转换成 millicore 值,这是个浮点数,并乘以 1024,这个数字中的较大者或 2 用作 `docker run` 命令中的[ `--cpu-shares`](https://docs.docker.com/engine/reference/run/#/cpu-share-constraint) 标志的值。 + - `spec.containers[].resources.limits.cpu` 被转换成 millicore 值。被乘以 100000 然后 除以 1000。这个数字用作 `docker run` 命令中的 [`--cpu-quota`](https://docs.docker.com/engine/reference/run/#/cpu-quota-constraint) 标志的值。[`--cpu-quota` ] 标志被设置成了 100000,表示测量配额使用的默认100ms 周期。如果 [`--cpu-cfs-quota`] 标志设置为 true,则 kubelet 会强制执行 cpu 限制。从 Kubernetes 1.2 版本起,此标志默认为 true。 + + + + {{< note >}} + 默认配额限制为 100 毫秒。 CPU配额的最小单位为 1 毫秒。 + {{}} + + + - `spec.containers[].resources.limits.memory` 被转换为整型,作为 `docker run` 命令中的 [`--memory`](https://docs.docker.com/engine/reference/run/#/user-memory-constraints) 标志的值。 + + 如果容器超过其内存限制,则可能会被终止。如果可重新启动,则与所有其他类型的运行时故障一样,kubelet 将重新启动它。 如果一个容器超过其内存请求,那么当节点内存不足时,它的 Pod 可能被逐出。 容器可能被允许也可能不被允许超过其 CPU 限制时间。但是,由于 CPU 使用率过高,不会被杀死。 -要确定容器是否由于资源限制而无法安排或被杀死,请参阅 [疑难解答](#troubleshooting) 部分。 +要确定容器是否由于资源限制而无法安排或被杀死,请参阅[疑难解答](#troubleshooting) 部分。 + + ## 监控计算资源使用 @@ -111,6 +281,16 @@ Pod 的资源使用情况被报告为 Pod 状态的一部分。 如果为集群配置了 [可选监控](http://releases.k8s.io/{{< param "githubbranch" >}}/cluster/addons/cluster-monitoring/README.md),则可以从监控系统检索 Pod 资源的使用情况。 + + ## 疑难解答 ### 我的 Pod 处于 pending 状态且事件信息显示 failedScheduling @@ -118,25 +298,50 @@ Pod 的资源使用情况被报告为 Pod 状态的一部分。 如果调度器找不到任何该 Pod 可以匹配的节点,则该 Pod 将保持不可调度状态,直到找到一个可以被调度到的位置。每当调度器找不到 Pod 可以调度的地方时,会产生一个事件,如下所示: ```shell -$ kubectl describe pod frontend | grep -A 3 Events +kubectl describe pod frontend | grep -A 3 Events +``` +``` Events: FirstSeen LastSeen Count From Subobject PathReason Message 36s 5s 6 {scheduler } FailedScheduling Failed for reason PodExceedsFreeCPU and possibly others ``` + + 在上述示例中,由于节点上的 CPU 资源不足,名为 “frontend” 的 Pod 将无法调度。由于内存不足(PodExceedsFreeMemory),类似的错误消息也可能会导致失败。一般来说,如果有这种类型的消息而处于 pending 状态,您可以尝试如下几件事情: +- 向集群添加更多节点。 +- 终止不需要的 Pod,为待处理的 Pod 腾出空间。 +- 检查 Pod 所需的资源是否大于所有节点的资源。 例如,如果全部节点的容量为`cpu:1`,那么一个请求为 `cpu:1.1`的 Pod 永远不会被调度。 + +您可以使用 `kubectl describe nodes` 命令检查节点容量和分配的数量。 例如: + + ```shell -$ kubectl describe nodes e2e-test-minion-group-4lw4 -Name: e2e-test-minion-group-4lw4 +kubectl describe nodes e2e-test-node-pool-4lw4 +``` +``` +Name: e2e-test-node-pool-4lw4 [ ... lines removed for clarity ...] Capacity: - alpha.kubernetes.io/nvidia-gpu: 0 cpu: 2 memory: 7679792Ki pods: 110 Allocatable: - alpha.kubernetes.io/nvidia-gpu: 0 cpu: 1800m memory: 7474992Ki pods: 110 @@ -156,20 +361,50 @@ Allocated resources: 680m (34%) 400m (20%) 920Mi (12%) 1070Mi (14%) ``` + + 在上面的输出中,您可以看到如果 Pod 请求超过 1120m CPU 或者 6.23Gi 内存,节点将无法满足。 通过查看 `Pods` 部分,您将看到哪些 Pod 占用的节点上的资源。 -Pod 可用的资源量小于节点容量,因为系统守护程序使用一部分可用资源。 [NodeStatus](/docs/resources-reference/{{< param "version" >}}/#nodestatus-v1-core) 的 `allocatable` 字段给出了可用于 Pod 的资源量。有关更多信息,请参阅 [节点可分配资源](https://git.k8s.io/community/contributors/design-proposals/node-allocatable.md)。 +Pod 可用的资源量小于节点容量,因为系统守护程序使用一部分可用资源。 +[NodeStatus](/docs/resources-reference/{{< param "version" >}}/#nodestatus-v1-core) 的 `allocatable` 字段给出了可用于 Pod 的资源量。 +有关更多信息,请参阅 [节点可分配资源](https://git.k8s.io/community/contributors/design-proposals/node-allocatable.md)。 可以将 [资源配额](/docs/concepts/policy/resource-quotas/) 功能配置为限制可以使用的资源总量。如果与 namespace 配合一起使用,就可以防止一个团队占用所有资源。 + + ## 我的容器被终止了 您的容器可能因为资源枯竭而被终止了。要查看容器是否因为遇到资源限制而被杀死,请在相关的 Pod 上调用 `kubectl describe pod`: ```shell -[12:54:41] $ kubectl describe pod simmemleak-hra99 +kubectl describe pod simmemleak-hra99 +``` +``` Name: simmemleak-hra99 Namespace: default Image(s): saadali/simmemleak @@ -206,59 +441,466 @@ Events: Tue, 07 Jul 2015 12:53:51 -0700 Tue, 07 Jul 2015 12:53:51 -0700 1 {kubelet kubernetes-node-tf0f} spec.containers{simmemleak} created Created with docker id 87348f12526a ``` + + 在上面的例子中,`Restart Count: 5` 意味着 Pod 中的 `simmemleak` 容器被终止并重启了五次。 您可以使用 `kubectl get pod` 命令加上 `-o go-template=...` 选项来获取之前终止容器的状态。 + ```shell -[13:59:01] $ kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-60xbc +kubectl get pod -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-hra99 +``` +``` Container Name: simmemleak LastState: map[terminated:map[exitCode:137 reason:OOM Killed startedAt:2015-07-07T20:58:43Z finishedAt:2015-07-07T20:58:43Z containerID:docker://0e4095bba1feccdfe7ef9fb6ebffe972b4b14285d5acdec6f0d3ae8a22fad8b2]] ``` + + 您可以看到容器因为 `reason:OOM killed` 被终止,`OOM` 表示 Out Of Memory。 -## 不透明整型资源(Alpha功能) + -不透明整型资源是以 `pod.alpha.kubernetes.io/opaque-int-resource-` 为前缀的资源。API server 将限制这些资源的数量为整数。*有效* 数量的例子有 `3`、`3000m` 和 `3Ki`。*无效* 数量的例子有 `0.5` 和 `1500m`。 +## 本地临时存储 -申请使用不透明整型资源需要两步。首先,集群运维人员必须在一个或多个节点上通告每个节点不透明的资源。然后,用户必须在 Pod 中请求不透明资源。 +Kubernetes版本1.8引入了新资源_ephemeral-storage_,用于管理本地临时存储。 +在每个Kubernetes节点中,kubelet的根目录(默认为 /var/lib/kubelet)和日志目录( /var/log )存储在节点的根分区上。 +Pods还通过emptyDir卷,容器日志,镜像层和容器可写层共享和使用此分区。 -要发布新的不透明整型资源,集群运维人员应向 API server 提交 `PATCH` HTTP请求,以指定集群中节点的`status.capacity` 的可用数量。在此操作之后,节点的 `status.capacity` 将包括一个新的资源。 `status.allocatable` 字段由 kubelet 异步地使用新资源自动更新。请注意,由于调度器在评估 Pod 适应度时使用节点 `status.allocatable` 值,所以在使用新资源修补节点容量和请求在该节点上调度资源的第一个 pod 之间可能会有短暂的延迟。 +该分区是“临时”分区,应用程序无法从该分区获得任何性能SLA(例如磁盘IOPS)。 本地临时存储管理仅适用于根分区。 图像层和可写层的可选分区超出范围。 -**示例** +{{< note >}} +如果使用可选的运行时分区,则根分区将不保存任何镜像层或可写层。 +{{< /note >}} -这是一个 HTTP 请求,master 节点是 k8s-master,在 k8s-node-1 节点上通告 5 个 “foo” 资源。 + -```http -PATCH /api/v1/nodes/k8s-node-1/status HTTP/1.1 -Accept: application/json -Content-Type: application/json-patch+json -Host: k8s-master:8080 +### 本地临时存储的请求和限制设置 +Pod 的每个容器可以指定以下一项或多项: -[ - { - "op": "add", - "path": "/status/capacity/pod.alpha.kubernetes.io~1opaque-int-resource-foo", - "value": "5" - } -] +* `spec.containers[].resources.limits.ephemeral-storage` +* `spec.containers[].resources.requests.ephemeral-storage` + + + +对“临时存储”的限制和请求以字节为单位。您可以使用以下后缀之一将存储表示为纯整数或小数形式:E,P,T,G,M,K。您还可以使用2的幂次方:Ei,Pi,Ti,Gi,Mi,Ki。例如,以下内容表示的值其实大致相同: + +```shell +128974848, 129e6, 129M, 123Mi ``` + + +例如,以下Pod具有两个容器。每个容器都有一个2GiB的本地临时存储请求。每个容器的本地临时存储限制为4GiB。因此,该Pod要求本地临时存储空间为4GiB,存储空间限制为8GiB。 + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: frontend +spec: + containers: + - name: db + image: mysql + env: + - name: MYSQL_ROOT_PASSWORD + value: "password" + resources: + requests: + ephemeral-storage: "2Gi" + limits: + ephemeral-storage: "4Gi" + - name: wp + image: wordpress + resources: + requests: + ephemeral-storage: "2Gi" + limits: + ephemeral-storage: "4Gi" +``` + + + +### 如何调度临时存储请求的 Pod + +创建Pod时,Kubernetes调度程序会选择一个节点来运行Pod。每个节点都可以为Pod提供最大数量的本地临时存储。 +有关更多信息,请参见[节点可分配](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)。 + +调度程序会确保调度的容器的资源请求的总和小于节点的容量。 + + + +### 具有临时存储限制的 Pod 如何运行 + +对于容器级隔离,如果容器的可写层和日志使用量超出其存储限制,则将驱逐Pod。对于 pod 级别的隔离,如果来自所有容器的本地临时存储使用量以及 Pod 的 emptyDir 卷的总和超过限制,则将驱逐Pod。 + + + +### 监控临时存储消耗 + +使用本地临时存储时,kubelet 会持续对本地临时存储时进行监视。 +通过定期扫描,来监视每个 emptyDir 卷,日志目录和可写层。 +从Kubernetes 1.15开始,作为集群操作员的一个选项,可以通过[项目配额](http://xfs.org/docs/xfsdocs-xml-dev/XFS_User_Guide/tmp/en-US/html/xfs-quotas.html) 来管理 emptyDir 卷(但是不包括日志目录或可写层)。 +项目配额最初是在XFS中实现的,最近又被移植到ext4fs中。 项目配额可用于监视和执行; 从Kubernetes 1.15开始,它们可用作Alpha功能仅用于监视。 + + + +配额比目录扫描更快,更准确。 +将目录分配给项目时,在该目录下创建的所有文件都将在该项目中创建,内核仅需跟踪该项目中的文件正在使用多少块。 +如果创建并删除了文件,但是文件描述符已打开,它将继续占用空间。 该空间将由配额跟踪,但目录扫描不会检查。 + + + +Kubernetes使用从1048576开始的项目ID。正在使用的ID注册于 `/etc/projects` 和 `/etc/projid`。 +如果此范围内的项目ID用于系统上的其他目的,则这些项目ID必须在 `/etc/projects` 和 `/etc/projid` 中注册,以防止Kubernetes使用它们。 + + + +要启用项目配额,集群操作员必须执行以下操作: + +* 在kubelet配置中启用 `LocalStorageCapacityIsolationFSQuotaMonitoring = true` 功能。 在Kubernetes 1.15中默认为 false,因此必须显式设置为 true。 + +* 确保根分区(或可选的运行时分区)是在启用项目配额的情况下构建的。 所有 XFS 文件系统都支持项目配额,但是 ext4 文件系统必须专门构建。 + +* 确保在启用了项目配额的情况下挂载了根分区(或可选的运行时分区)。 + + + +#### 在启用项目配额的情况下构建和挂载文件系统 + +XFS文件系统在构建时不需要任何特殊操作; 它们是在启用项目配额的情况下自动构建的。 + +Ext4fs文件系统必须在启用了配额的情况下构建,然后必须在文件系统中启用它们: + +``` +% sudo mkfs.ext4 other_ext4fs_args... -E quotatype=prjquota /dev/block_device +% sudo tune2fs -O project -Q prjquota /dev/block_device + +``` + + + +要挂载文件系统,ext4fs 和 XFS 都需要在 `/etc/fstab` 中设置 `prjquota` 选项: + +``` +/dev/block_device /var/kubernetes_data defaults,prjquota 0 0 +``` + + + + +## 拓展资源 + +拓展资源是 `kubernetes.io` 域名之外的标准资源名称。它们允许集群管理员做分发,而且用户可以使用非Kubernetes内置资源。 +使用扩展资源需要两个步骤。 首先,集群管理员必须分发拓展资源。 其次,用户必须在 Pod 中请求拓展资源。 + ```shell curl --header "Content-Type: application/json-patch+json" \ --request PATCH \ ---data '[{"op": "add", "path": "/status/capacity/pod.alpha.kubernetes.io~1opaque-int-resource-foo", "value": "5"}]' \ +--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \ http://k8s-master:8080/api/v1/nodes/k8s-node-1/status ``` -**注意:** 在前面的请求中,`~1` 是 patch 路径中 `/` 字符的编码。JSON-Patch 中的操作路径值被解释为 JSON-Pointer。更多详细信息请参阅 [IETF RFC 6901, section 3](https://tools.ietf.org/html/rfc6901#section-3)。 + + +### 管理拓展资源 + +#### 节点级拓展资源 + +节点级拓展资源绑定到节点。 + + + +##### 设备插件托管资源 + +有关如何在每个节点上分发设备插件托管资源的信息,请参阅[设备插件](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/)。 + + + +##### 其他资源 +为了发布新的节点级拓展资源,集群操作员可以向API服务器提交 `PATCH` HTTP 请求, +以在 `status.capacity` 中为集群中的节点指定可用数量。 +完成此操作后,节点的 `status.capacity` 将包含新资源。 +由kubelet异步使用新资源自动更新 `status.allocatable` 字段。 +请注意,由于调度程序在评估Pod适合性时使用节点的状态 `status.allocatable` 值, +因此在用新资源修补节点容量和请求在该节点上调度资源的第一个Pod之间可能会有短暂的延迟。 + + + +**示例:** + +这是一个示例,显示了如何使用 `curl` 进行HTTP请求,该请求在主节点为 `k8s-master` 的子节点 `k8s-node-1` +上通告五个 `example.com/foo` 资源。 + +```shell +curl --header "Content-Type: application/json-patch+json" \ +--request PATCH \ +--data '[{"op": "add", "path": "/status/capacity/example.com~1foo", "value": "5"}]' \ +http://k8s-master:8080/api/v1/nodes/k8s-node-1/status +``` + +{{< note >}} + + + +在前面的请求中,`~1` 是 Patch 路径中字符 `/` 的编码。 JSON-Patch中的操作路径值被解释为JSON-Pointer。 +有关更多详细信息,请参见 +[IETF RFC 6901, section 3](https://tools.ietf.org/html/rfc6901#section-3). +{{< /note >}} + + + +#### 集群级扩展资源 + +群集级扩展资源不绑定到节点。 它们通常由调度程序扩展程序管理,这些程序处理资源消耗和资源配额。 + +您可以在[调度程序策略配置](https://github.com/kubernetes/kubernetes/blob/release-1.10/pkg/scheduler/api/v1/types.go#L31)中指定由调度程序扩展程序处理的扩展资源。 + + + +**示例:** + +通过调度程序策略的以下配置,指示群集级扩展资源 "example.com/foo" 由调度程序扩展程序处理。 + +- 仅当Pod请求 "example.com/foo" 时,调度程序才会将 Pod 发送到调度程序扩展程序。 +- `ignoredByScheduler` 字段指定调度程序不在其 `PodFitsResources` 字段中检查 "example.com/foo" 资源。 + +```json +{ + "kind": "Policy", + "apiVersion": "v1", + "extenders": [ + { + "urlPrefix":"", + "bindVerb": "bind", + "managedResources": [ + { + "name": "example.com/foo", + "ignoredByScheduler": true + } + ] + } + ] +} +``` + + + +### 消耗扩展资源 + +就像 CPU 和内存一样,用户可以使用 Pod 的扩展资源。 +调度程序负责核算资源,因此不会同时将过多的可用资源分配给 Pod。 + +{{< note >}} + + + +扩展资源取代了 Opaque 整数资源。 用户可以使用保留字 `kubernetes.io` 以外的任何域名前缀。 + +{{< /note >}} + + + +要在Pod中使用扩展资源,请在容器规范的 `spec.containers[].resources.limits` 映射中包含资源名称作为键。 + +{{< note >}} + + + +扩展资源不能过量使用,因此如果容器规范中存在请求和限制,则它们必须一致。 + +{{< /note >}} + + + +仅当满足所有资源请求(包括 CPU ,内存和任何扩展资源)时,才能调度 Pod。 只要资源请求无法满足,则 Pod 保持在 `PENDING` 状态。 + +**示例:** + +下面的 Pod 请求2个 CPU 和1个"example.com/foo"(扩展资源)。 ```yaml apiVersion: v1 @@ -272,14 +914,42 @@ spec: resources: requests: cpu: 2 - pod.alpha.kubernetes.io/opaque-int-resource-foo: 1 + example.com/foo: 1 + limits: + example.com/foo: 1 ``` + + ## 计划改进 -在 kubernetes 1.5 版本中仅允许在容器上指定资源量。计划改进对所有容器在 Pod 中共享资源的计量,如 [emptyDir volume](/docs/concepts/storage/volumes/#emptydir)。 +在 kubernetes 1.5 版本中仅允许在容器上指定资源量。计划改进对所有容器在 Pod 中共享资源的计量, +如 [emptyDir volume](/docs/concepts/storage/volumes/#emptydir)。 -在 kubernetes 1.5 版本中仅支持容器对 CPU 和内存的申请和限制。计划增加新的资源类型,包括节点磁盘空间资源和一个可支持自定义 [资源类型](https://github.com/kubernetes/community/blob/{{< param "githubbranch" >}}/contributors/design-proposals/resources.md) 的框架。 +在 kubernetes 1.5 版本中仅支持容器对 CPU 和内存的申请和限制。计划增加新的资源类型,包括节点磁盘空间资源和一个可支持自定义 +[资源类型](https://github.com/kubernetes/community/blob/{{< param "githubbranch" >}}/contributors/design-proposals/resources.md) 的框架。 Kubernetes 通过支持通过多级别的 [服务质量](http://issue.k8s.io/168) 来支持资源的过度使用。 @@ -287,13 +957,25 @@ Kubernetes 通过支持通过多级别的 [服务质量](http://issue.k8s.io/168 {{% /capture %}} + {{% capture whatsnext %}} -- 获取将 [CPU 和内存资源分配给容器](/docs/tasks/configure-pod-container/assign-cpu-ram-container/) 的实践经验 -- [容器](/docs/api-reference/{{< param "version" >}}/#container-v1-core) -- [ResourceRequirements](/docs/resources-reference/{{< param "version" >}}/#resourcerequirements-v1-core) + + +* 获取将 [分配内存资源给容器和 Pod ](/docs/tasks/configure-pod-container/assign-memory-resource/) 的实践经验 + +* 获取将 [分配 CPU 资源给容器和 Pod ](/docs/tasks/configure-pod-container/assign-cpu-resource/) 的实践经验 + +* [容器](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core) + +* [资源需求](/docs/resources-reference/{{< param "version" >}}/#resourcerequirements-v1-core) {{% /capture %}} - - - diff --git a/content/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig.md b/content/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig.md new file mode 100644 index 0000000000..5d5757ba5c --- /dev/null +++ b/content/zh/docs/concepts/configuration/organize-cluster-access-kubeconfig.md @@ -0,0 +1,275 @@ +--- +title: 使用 kubeconfig 文件组织集群访问 +content_template: templates/concept +weight: 60 +--- + +{{% capture overview %}} + + +使用 kubeconfig 文件来组织有关集群、用户、命名空间和身份认证机制的信息。`kubectl` 命令行工具使用 kubeconfig 文件来查找选择集群所需的信息,并与集群的 API 服务器进行通信。 + + +{{< note >}} +注意:用于配置集群访问的文件称为 *kubeconfig 文件*。这是引用配置文件的通用方法。这并不意味着有一个名为 `kubeconfig` 的文件 +{{< /note >}} + + +默认情况下,`kubectl` 在 `$HOME/.kube` 目录下查找名为 `config` 的文件。您可以通过设置 `KUBECONFIG` 环境变量或者设置[`--kubeconfig`](/docs/reference/generated/kubectl/kubectl/)参数来指定其他 kubeconfig 文件。 + + +有关创建和指定 kubeconfig 文件的分步说明,请参阅[配置对多集群的访问](/docs/tasks/access-application-cluster/configure-access-multiple-clusters)。 + +{{% /capture %}} + + +{{% capture body %}} + + +## 支持多集群、用户和身份认证机制 + + +假设您有多个集群,并且您的用户和组件以多种方式进行身份认证。比如: + + +- 正在运行的 kubelet 可能使用证书在进行认证。 +- 用户可能通过令牌进行认证。 +- 管理员可能拥有多个证书集合提供给各用户。 + + +使用 kubeconfig 文件,您可以组织集群、用户和命名空间。您还可以定义上下文,以便在集群和命名空间之间快速轻松地切换。 + + +## 上下文(Context) + + +通过 kubeconfig 文件中的 *context* 元素,使用简便的名称来对访问参数进行分组。每个上下文都有三个参数:cluster、namespace 和 user。默认情况下,`kubectl` 命令行工具使用 *当前上下文* 中的参数与集群进行通信。 + + +选择当前上下文 +``` +kubectl config use-context +``` + + +## KUBECONFIG 环境变量 + + +`KUBECONFIG` 环境变量包含一个 kubeconfig 文件列表。对于 Linux 和 Mac,列表以冒号分隔。对于 Windows,列表以分号分隔。`KUBECONFIG` 环境变量不是必要的。如果 `KUBECONFIG` 环境变量不存在,`kubectl` 使用默认的 kubeconfig 文件,`$HOME/.kube/config`。 + + +如果 `KUBECONFIG` 环境变量存在,`kubectl` 使用 `KUBECONFIG` 环境变量中列举的文件合并后的有效配置。 + + +## 合并 kubeconfig 文件 + + + +要查看配置,输入以下命令: +```shell +kubectl config view +``` + + +如前所述,输出可能来自 kubeconfig 文件,也可能是合并多个 kubeconfig 文件的结果。 + + +以下是 `kubectl` 在合并 kubeconfig 文件时使用的规则。 + + +1. 如果设置了 `--kubeconfig` 参数,则仅使用指定的文件。不进行合并。此参数只能使用一次。 + + 否则,如果设置了 `KUBECONFIG` 环境变量,将它用作应合并的文件列表。根据以下规则合并 `KUBECONFIG` 环境变量中列出的文件: + + * 忽略空文件名。 + * 对于内容无法反序列化的文件,产生错误信息。 + * 第一个设置特定值或者映射键的文件将生效。 + * 永远不会更改值或者映射键。示例:保留第一个文件的上下文以设置 `current-context`。示例:如果两个文件都指定了 `red-user`,则仅使用第一个文件的 `red-user` 中的值。即使第二个文件在 `red-user` 下有非冲突条目,也要丢弃它们。 + + + 有关设置 `KUBECONFIG` 环境变量的示例,请参阅[设置 KUBECONFIG 环境变量](/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#set-the-kubeconfig-environment-variable)。 + + + 否则,使用默认的 kubeconfig 文件, `$HOME/.kube/config`,不进行合并。 + + +1. 根据此链中的第一个匹配确定要使用的上下文。 + + 1. 如果存在,使用 `--context` 命令行参数。 + 1. 使用合并的 kubeconfig 文件中的 `current-context`。 + + + 这种场景下允许空上下文。 + + +1. 确定集群和用户。此时,可能有也可能没有上下文。根据此链中的第一个匹配确定集群和用户,这将运行两次:一次用于用户,一次用于集群。 + + 1. 如果存在,使用命令行参数:`--user` 或者 `--cluster`。 + 1. 如果上下文非空,从上下文中获取用户或集群。 + + + 这种场景下用户和集群可以为空。 + + +1. 确定要使用的实际集群信息。此时,可能有也可能没有集群信息。基于此链构建每个集群信息;第一个匹配项会被采用: + + 1. 如果存在:`--server`、`--certificate-authority` 和 `--insecure-skip-tls-verify`,使用命令行参数。 + 1. 如果合并的 kubeconfig 文件中存在集群信息属性,则使用它们。 + 1. 如果没有 server 配置,则配置无效。 + + +1. 确定要使用的实际用户信息。使用与集群信息相同的规则构建用户信息,但每个用户只允许一种身份认证技术: + + 1. 如果存在:`--client-certificate`、`--client-key`、`--username`、`--password` 和 `--token`,使用命令行参数。 + 1. 使用合并的 kubeconfig 文件中的 `user` 字段。 + 1. 如果存在两种冲突技术,则配置无效。 + + +1. 对于仍然缺失的任何信息,使用其对应的默认值,并可能提示输入身份认证信息。 + + +## 文件引用 + + +kubeconfig 文件中的文件和路径引用是相对于 kubeconfig 文件的位置。命令行上的文件引用是相当对于当前工作目录的。在 `$HOME/.kube/config` 中,相对路径按相对路径存储,绝对路径按绝对路径存储。 + +{{% /capture %}} + + +{{% capture whatsnext %}} + + +* [配置对多集群的访问](/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) +* [`kubectl config`](/docs/reference/generated/kubectl/kubectl-commands#config) + +{{% /capture %}} + + diff --git a/content/zh/docs/concepts/configuration/overview.md b/content/zh/docs/concepts/configuration/overview.md new file mode 100644 index 0000000000..abb90bde09 --- /dev/null +++ b/content/zh/docs/concepts/configuration/overview.md @@ -0,0 +1,263 @@ +--- +reviewers: +- mikedanese +title: 配置最佳实践 +content_template: templates/concept +weight: 10 +--- + +{{% capture overview %}} + +本文档重点介绍并整合了整个用户指南、入门文档和示例中介绍的配置最佳实践。 + + +这是一份活文件。 +如果您认为某些内容不在此列表中但可能对其他人有用,请不要犹豫,提交问题或提交 PR。 +{{% /capture %}} + +{{% capture body %}} + +## 一般配置提示 + + +- 定义配置时,请指定最新的稳定 API 版本。 + + +- 在推送到集群之前,配置文件应存储在版本控制中。 + 这允许您在必要时快速回滚配置更改。 + 它还有助于集群重新创建和恢复。 + + +- 使用 YAML 而不是 JSON 编写配置文件。虽然这些格式几乎可以在所有场景中互换使用,但 YAML 往往更加用户友好。 + + +- 只要有意义,就将相关对象分组到一个文件中。 + 一个文件通常比几个文件更容易管理。 + 请参阅[guestbook-all-in-one.yaml](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/guestbook/all-in-one/guestbook-all-in-one.yaml) 文件作为此语法的示例。 + + +- 另请注意,可以在目录上调用许多`kubectl`命令。 + 例如,你可以在配置文件的目录中调用`kubectl apply`。 + + +- 不要不必要地指定默认值:简单的最小配置会降低错误的可能性。 + + +- 将对象描述放在注释中,以便更好地进行内省。 + + + +## “Naked”Pods 与 ReplicaSet,Deployment 和 Jobs + + +- 如果您能避免,不要使用 naked Pods(即,Pod 未绑定到[ReplicaSet](/docs/concepts/workloads/controllers/replicaset/) 或[Deployment](/docs/concepts/workloads/controllers/deployment/))。 + 如果节点发生故障,将不会重新安排 Naked Pods。 + + + 部署,它创建一个 ReplicaSet 以确保所需数量的 Pod 始终可用,并指定替换 Pod 的策略(例如 [RollingUpdate](/docs/concepts/workloads/controllers/deployment/#rolling-update-deployment)),除了一些显式的[`restartPolicy: Never`](/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy)场景之外,几乎总是优先考虑直接创建 Pod。 +[Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/) 也可能是合适的。 + + + +## 服务 + + +- 在其相应的后端工作负载(Deployment 或 ReplicaSet)之前,以及在需要访问它的任何工作负载之前创建[服务](/docs/concepts/services-networking/service/)。 + 当 Kubernetes 启动容器时,它提供指向启动容器时正在运行的所有服务的环境变量。 + 例如,如果存在名为`foo`当服务,则所有容器将在其初始环境中获取以下变量。 + + ```shell + FOO_SERVICE_HOST= + FOO_SERVICE_PORT= + ``` + + + *这确实意味着订购要求* - 必须在`Pod`本身之前创建`Pod`想要访问的任何`Service`,否则将不会填充环境变量。 + DNS没有此限制。 + + +- 一个可选(尽管强烈推荐)[cluster add-on](/docs/concepts/cluster-administration/addons/)是 DNS 服务器。DNS 服务器为新的`Services`监视 Kubernetes API,并为每个创建一组 DNS 记录。 + 如果在整个集群中启用了 DNS,则所有`Pods`应该能够自动对`Services`进行名称解析。 + + +- 除非绝对必要,否则不要为 Pod 指定`hostPort`。 + 将 Pod 绑定到`hostPort`时,它会限制 Pod 可以调度的位置数,因为每个<`hostIP`, `hostPort`, `protocol`>组合必须是唯一的。如果您没有明确指定`hostIP`和`protocol`,Kubernetes将使用`0.0.0.0`作为默认`hostIP`和`TCP`作为默认`protocol`。 + + + 如果您只需要访问端口以进行调试,则可以使用[apiserver proxy](/docs/tasks/access-application-cluster/access-cluster/#manually-constructing-apiserver-proxy-urls)或[`kubectl port-forward`](/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)。 + + + 如果您明确需要在节点上公开 Pod 的端口,请在使用`hostPort`之前考虑使用[NodePort](/docs/concepts/services-networking/service/#nodeport) 服务。 + + +- 避免使用`hostNetwork`,原因与`hostPort`相同。 + + +- 当您不需要`kube-proxy`负载平衡时,使用 [无头服务](/docs/concepts/services-networking/service/#headless- +services) (具有`None`的`ClusterIP`)以便于服务发现。 + + +## 使用标签 + + +- 定义并使用[标签](/docs/concepts/overview/working-with-objects/labels/)来识别应用程序或部署的__semantic attributes__,例如`{ app: myapp, tier: frontend, phase: test, deployment: v3 }`。 + 您可以使用这些标签为其他资源选择合适的 Pod;例如,一个选择所有`tier: frontend` Pod 的服务,或者`app: myapp`的所有`phase: test`组件。 + 有关此方法的示例,请参阅[留言板](https://github.com/kubernetes/examples/tree/{{< param "githubbranch" >}}/guestbook/) 。 + + +通过从选择器中省略特定发行版的标签,可以使服务跨越多个部署。 +[部署](/docs/concepts/workloads/controllers/deployment/)可以在不停机的情况下轻松更新正在运行的服务。 + + +部署描述了对象的期望状态,并且如果对该规范的更改是_applied_,则部署控制器以受控速率将实际状态改变为期望状态。 + + +- 您可以操纵标签进行调试。 +- 由于 Kubernetes 控制器(例如 ReplicaSet)和服务使用选择器标签与 Pod 匹配,因此从 Pod 中删除相关标签将阻止其被控制器考虑或由服务提供服务流量。 + 如果删除现有 Pod 的标签,其控制器将创建一个新的 Pod 来取代它。 + 这是在"隔离"环境中调试先前"实时"Pod 的有用方法。 + 要以交互方式删除或添加标签,请使用[`kubectl label`](/docs/reference/generated/kubectl/kubectl-commands#label)。 + + +## 容器镜像 + + +当 [kubelet](/docs/admin/kubelet/)尝试拉取指定的镜像时,[imagePullPolicy](/ docs / concepts / containers / images / #updating-images)和镜像的标签会生效。 + + +- `imagePullPolicy: IfNotPresent`:仅当镜像在本地不存在时镜像才被拉取。 + + +- `imagePullPolicy: Always`:每次启动 pod 的时候都会拉取镜像。 + + +- 省略`imagePullPolicy`,镜像标签为`:latest`或被省略,`Always`被应用。 + + +- `imagePullPolicy`被省略,并且镜像的标签被指定且不是`:latest`,`IfNotPresent`被应用。 + + +- `imagePullPolicy: Never`:镜像被假设存在于本地。 + 没有尝试拉取镜像。 + +{{< note >}} + + +要确保容器始终使用相同版本的镜像,你可以指定其 [摘要](https://docs.docker.com/engine/reference/commandline/pull/#pull-an-image-by-digest-immutable-identifier), 例如`sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2`。 +摘要唯一地标识出镜像的指定版本,因此除非您更改摘要值,否则 Kubernetes 永远不会更新它。 +{{< /note >}} + +{{< note >}} + + +在生产中部署容器时应避免使用 `:latest` 标记,因为更难跟踪正在运行的镜像版本,并且更难以正确回滚。 +{{< /note >}} + +{{< note >}} + +底层镜像提供程序的缓存语义甚至使 `imagePullPolicy: Always`变得高效。 +例如,对于 Docker,如果镜像已经存在,则拉取尝试很快,因为镜像层都被缓存并且不需要镜像下载。 +{{< /note >}} + + +## 使用 kubectl + + +- 使用`kubectl apply -f `。 + 它在``中的所有`.yaml`,`.yml`和`.json`文件中查找 Kubernetes 配置,并将其传递给`apply`。 + + +- 使用标签选择器进行`get`和`delete`操作,而不是特定的对象名称。 +- 请参阅[标签选择器](/docs/concepts/overview/working-with-objects/labels/#label-selectors)和[有效使用标签](/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively)部分。 + + +- 使用`kubectl run`和`kubectl expose`来快速创建单容器部署和服务。 + 有关示例,请参阅[使用服务访问集群中的应用程序](/docs/tasks/access-application-cluster/service-access-application-cluster/)。 + +{{% /capture %}} + + diff --git a/content/zh/docs/concepts/configuration/secret.md b/content/zh/docs/concepts/configuration/secret.md index a415bd5e00..9e55499449 100644 --- a/content/zh/docs/concepts/configuration/secret.md +++ b/content/zh/docs/concepts/configuration/secret.md @@ -1,19 +1,62 @@ --- -approvers: -- mikedanese title: Secret +content_template: templates/concept +weight: 50 --- -`Secret` 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。将这些信息放在 `secret` 中比放在 `pod` 的定义或者 docker 镜像中来说更加安全和灵活。参阅 [Secret 设计文档](https://git.k8s.io/community/contributors/design-proposals/secrets.md) 获取更多详细信息。 -{{< toc >}} +{{% capture overview %}} + + + +`Secret` 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。 +将这些信息放在 `secret` 中比放在 {{< glossary_tooltip term_id="pod" >}} 的定义或者 {{< glossary_tooltip text="容器镜像" term_id="image" >}} 中来说更加安全和灵活。 +参阅 [Secret 设计文档](https://git.k8s.io/community/contributors/design-proposals/auth/secrets.md) 获取更多详细信息。 + +{{% /capture %}} + +{{% capture body %}} + + + ## Secret 概览 Secret 是一种包含少量敏感信息例如密码、token 或 key 的对象。这样的信息可能会被放在 Pod spec 中或者镜像中;将其放在一个 secret 对象中可以更好地控制它的用途,并降低意外暴露的风险。 + + 用户可以创建 secret,同时系统也创建了一些 secret。 -要使用 secret,pod 需要引用 secret。Pod 可以用两种方式使用 secret:作为 [volume](/docs/concepts/storage/volumes/) 中的文件被挂载到 pod 中的一个或者多个容器里,或者当 kubelet 为 pod 拉取镜像时使用。 +要使用 secret,pod 需要引用 secret。Pod 可以用两种方式使用 secret:作为 {{< glossary_tooltip text="volume" term_id="volume" >}} 中的文件被挂载到 pod 中的一个或者多个容器里,或者当 kubelet 为 pod 拉取镜像时使用。 + + ### 内置 secret @@ -21,10 +64,28 @@ Secret 是一种包含少量敏感信息例如密码、token 或 key 的对象 Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改您的 pod 以使用此类型的 secret。 + + 如果需要,可以禁用或覆盖自动创建和使用API凭据。但是,如果您需要的只是安全地访问 apiserver,我们推荐这样的工作流程。 -参阅 [Service Account](/docs/user-guide/service-accounts) 文档获取关于 Service Account 如何工作的更多信息。 +参阅 [Service Account](/docs/tasks/configure-pod-container/configure-service-account/) 文档获取关于 Service Account 如何工作的更多信息。 + ### 创建您自己的 Secret #### 使用 kubectl 创建 Secret @@ -33,25 +94,57 @@ Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改您的 ```shell # Create files needed for rest of example. -$ echo -n "admin" > ./username.txt -$ echo -n "1f2d1e2e67df" > ./password.txt +echo -n 'admin' > ./username.txt +echo -n '1f2d1e2e67df' > ./password.txt ``` + + `kubectl create secret` 命令将这些文件打包到一个 Secret 中并在 API server 中创建了一个对象。 + ```shell -$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt +kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt +``` +``` secret "db-user-pass" created ``` +{{< note >}} + + + +特殊字符(例如 `$`, `\*` 和 `!` )需要转义。 +如果您使用的密码具有特殊字符,则需要使用 `\\` 字符对其进行转义。 例如,如果您的实际密码是 `S!B\*d$zDsb` ,则应通过以下方式执行命令: + kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password=S\\!B\\\\*d\\$zDsb +您无需从文件中转义密码中的特殊字符( `--from-file` )。 +{{< /note >}} + + 您可以这样检查刚创建的 secret: ```shell -$ kubectl get secrets +kubectl get secrets +``` +``` NAME TYPE DATA AGE db-user-pass Opaque 2 51s - -$ kubectl describe secrets/db-user-pass +``` +```shell +kubectl describe secrets/db-user-pass +``` +``` Name: db-user-pass Namespace: default Labels: @@ -65,23 +158,60 @@ password.txt: 12 bytes username.txt: 5 bytes ``` -请注意,默认情况下,`get` 和 `describe` 命令都不会显示文件的内容。这是为了防止将 secret 中的内容被意外暴露给从终端日志记录中刻意寻找它们的人。 +{{< note >}} + + + +{{< /note >}} + +默认情况下,`kubectl get`和`kubectl describe`避免显示密码的内容。 这是为了防止机密被意外地暴露给旁观者或存储在终端日志中。 + + 请参阅 [解码 secret](#解码-secret) 了解如何查看它们的内容。 + + #### 手动创建 Secret 您也可以先以 json 或 yaml 格式在文件中创建一个 secret 对象,然后创建该对象。 +[密码](/docs/reference/generated/kubernetes-api/v1.12/#secret-v1-core)包含两中类型,数据和字符串数据。 +数据字段用于存储使用base64编码的任意数据。 提供stringData字段是为了方便起见,它允许您将机密数据作为未编码的字符串提供。 -每一项必须是 base64 编码: + + +例如,要使用数据字段将两个字符串存储在 Secret 中,请按如下所示将它们转换为 base64: ```shell -$ echo -n "admin" | base64 +echo -n 'admin' | base64 YWRtaW4= -$ echo -n "1f2d1e2e67df" | base64 +echo -n '1f2d1e2e67df' | base64 MWYyZDFlMmU2N2Rm ``` + + 现在可以像这样写一个 secret 对象: ```yaml @@ -95,27 +225,277 @@ data: password: MWYyZDFlMmU2N2Rm ``` -数据字段是一个映射。它的键必须匹配 [`DNS_SUBDOMAIN`](https://git.k8s.io/community/contributors/design-proposals/identifiers.md),前导点也是可以的。这些值可以是任意数据,使用 base64 进行编码。 + -使用 [`kubectl create`](/docs/user-guide/kubectl/v1.7/#create) 创建 secret: +使用 [`kubectl apply`](/docs/reference/generated/kubectl/kubectl-commands#apply) 创建 secret: ```shell -$ kubectl create -f ./secret.yaml +kubectl apply -f ./secret.yaml +``` +``` secret "mysecret" created ``` -**编码注意:** secret 数据的序列化 JSON 和 YAML 值使用 base64 编码成字符串。换行符在这些字符串中无效,必须省略。当在 Darwin/OS X 上使用 `base64` 实用程序时,用户应避免使用 `-b` 选项来拆分长行。另外,对于 Linux 用户如果 `-w` 选项不可用的话,应该添加选项 `-w 0` 到 `base64` 命令或管道 `base64 | tr -d '\n' ` 。 + + +对于某些情况,您可能希望改用 stringData 字段。 此字段允许您将非 base64 编码的字符串直接放入 Secret 中, +并且在创建或更新 Secret 时将为您编码该字符串。 + +下面的一个实践示例提供了一个参考,您正在部署使用密钥存储配置文件的应用程序,并希望在部署过程中填补齐配置文件的部分内容。 + +如果您的应用程序使用以下配置文件: + +```yaml +apiUrl: "https://my.api.com/api/v1" +username: "user" +password: "password" +``` + + + +您可以使用以下方法将其存储在Secret中: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +stringData: + config.yaml: |- + apiUrl: "https://my.api.com/api/v1" + username: {{username}} + password: {{password}} +``` + + + +然后,您的部署工具可以在执行 `kubectl apply` 之前替换模板的 `{{username}}` 和 `{{password}}` 变量。 +stringData 是只写的便利字段。 检索 Secrets 时永远不会被输出。 例如,如果您运行以下命令: + +```shell +kubectl get secret mysecret -o yaml +``` + + + +输出将类似于: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + creationTimestamp: 2018-11-15T20:40:59Z + name: mysecret + namespace: default + resourceVersion: "7225" + uid: c280ad2e-e916-11e8-98f2-025000000001 +type: Opaque +data: + config.yaml: YXBpVXJsOiAiaHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MSIKdXNlcm5hbWU6IHt7dXNlcm5hbWV9fQpwYXNzd29yZDoge3twYXNzd29yZH19 +``` + + + +如果在 data 和 stringData 中都指定了字段,则使用 stringData 中的值。 例如,以下是 Secret 定义: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +data: + username: YWRtaW4= +stringData: + username: administrator +``` + + + +secret 中的生成结果: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + creationTimestamp: 2018-11-15T20:46:46Z + name: mysecret + namespace: default + resourceVersion: "7579" + uid: 91460ecb-e917-11e8-98f2-025000000001 +type: Opaque +data: + username: YWRtaW5pc3RyYXRvcg== +``` + + + +`YWRtaW5pc3RyYXRvcg==` 转换成了 `administrator`。 + + + +data和stringData的键必须由字母数字字符 '-', '_' 或者 '.' 组成。 + +** 编码注意:** 秘密数据的序列化 JSON 和 YAML 值被编码为base64字符串。 +换行符在这些字符串中无效,因此必须省略。 +在 Darwin / macOS 上使用 `base64` 实用程序时,用户应避免使用 `-b` 选项来分隔长行。 +相反,Linux用户 *应该* 在 `base64` 命令中添加选项 `-w 0`, 或者,如果`-w`选项不可用的情况下, +执行 `base64 | tr -d '\n'`。 + + + +#### 从生成器创建 Secret +Kubectl 从1.14版本开始支持 [使用 Kustomize 管理对象](/docs/tasks/manage-kubernetes-objects/kustomization/) +使用此新功能,您还可以从生成器创建一个 Secret,然后将其应用于在 Apiserver 上创建对象。 +生成器应在目录内的“ kustomization.yaml”中指定。 + +例如,从文件 `./username.txt` 和 `./password.txt` 生成一个 Secret。 + +```shell +# Create a kustomization.yaml file with SecretGenerator +cat <./kustomization.yaml +secretGenerator: +- name: db-user-pass + files: + - username.txt + - password.txt +EOF +``` + + + +应用 kustomization 目录创建 Secret 对象。 + +```shell +$ kubectl apply -k . +secret/db-user-pass-96mffmfh4k created +``` + + + +您可以检查 secret 是否是这样创建的: + +```shell +$ kubectl get secrets +NAME TYPE DATA AGE +db-user-pass-96mffmfh4k Opaque 2 51s + +$ kubectl describe secrets/db-user-pass-96mffmfh4k +Name: db-user-pass +Namespace: default +Labels: +Annotations: + +Type: Opaque + +Data +==== +password.txt: 12 bytes +username.txt: 5 bytes +``` + + + +例如,要从文字 `username=admin` 和 `password=secret` 生成秘密,可以在 `kustomization.yaml` 中将秘密生成器指定为 + +```shell +# Create a kustomization.yaml file with SecretGenerator +$ cat <./kustomization.yaml +secretGenerator: +- name: db-user-pass + literals: + - username=admin + - password=secret +EOF +``` +Apply the kustomization directory to create the Secret object. +```shell +$ kubectl apply -k . +secret/db-user-pass-dddghtt9b5 created +``` +{{< note >}} + + + +通过对内容进行序列化后,生成一个后缀作为 Secrets 的名称。 +这样可以确保每次修改内容时都会生成一个新的Secret。 + +{{< /note >}} + + #### 解码 Secret 可以使用 `kubectl get secret` 命令获取 secret。例如,获取在上一节中创建的 secret: ```shell -$ kubectl get secret mysecret -o yaml +kubectl get secret mysecret -o yaml +``` +``` apiVersion: v1 -data: - username: YWRtaW4= - password: MWYyZDFlMmU2N2Rm kind: Secret metadata: creationTimestamp: 2016-01-22T18:41:56Z @@ -124,27 +504,103 @@ metadata: resourceVersion: "164619" uid: cfee02d6-c137-11e5-8d73-42010af00002 type: Opaque +data: + username: YWRtaW4= + password: MWYyZDFlMmU2N2Rm ``` + + 解码密码字段: ```shell -$ echo "MWYyZDFlMmU2N2Rm" | base64 --decode +echo 'MWYyZDFlMmU2N2Rm' | base64 --decode +``` +``` 1f2d1e2e67df ``` -### 使用 Secret + -#### 在 Pod 中使用 Secret 文件 +#### 编辑 Secret + +可以通过下面的命令编辑一个已经存在的 secret 。 + +```shell +kubectl edit secrets mysecret +``` + + + +这将打开默认配置的编辑器,并允许更新 `data` 字段中的base64编码的 secret: + +``` +# Please edit the object below. Lines beginning with a '#' will be ignored, +# and an empty file will abort the edit. If an error occurs while saving this file will be +# reopened with the relevant failures. +# +apiVersion: v1 +data: + username: YWRtaW4= + password: MWYyZDFlMmU2N2Rm +kind: Secret +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: { ... } + creationTimestamp: 2016-01-22T18:41:56Z + name: mysecret + namespace: default + resourceVersion: "164619" + uid: cfee02d6-c137-11e5-8d73-42010af00002 +type: Opaque +``` + + + +## 使用 Secret + +Secret 可以作为数据卷被挂载,或作为{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}} +暴露出来以供 pod 中的容器使用。它们也可以被系统的其他部分使用,而不直接暴露在 pod 内。 +例如,它们可以保存凭据,系统的其他部分应该用它来代表您与外部系统进行交互。 + + + +### 在 Pod 中使用 Secret 文件 在 Pod 中的 volume 里使用 Secret: 1. 创建一个 secret 或者使用已有的 secret。多个 pod 可以引用同一个 secret。 -2. 修改您的 pod 的定义在 `spec.volumes[]` 下增加一个 volume。可以给这个 volume 随意命名,它的 `spec.volumes[].secret.secretName` 必须等于 secret 对象的名字。 -3. 将 `spec.containers[].volumeMounts[]` 加到需要用到该 secret 的容器中。指定 `spec.containers[].volumeMounts[].readOnly = true` 和 `spec.containers[].volumeMounts[].mountPath` 为您想要该 secret 出现的尚未使用的目录。 -4. 修改您的镜像并且/或者命令行让程序从该目录下寻找文件。Secret 的 `data` 映射中的每一个键都成为了 `mountPath` 下的一个文件名。 +1. 修改您的 pod 的定义在 `spec.volumes[]` 下增加一个 volume。可以给这个 volume 随意命名,它的 `spec.volumes[].secret.secretName` 必须等于 secret 对象的名字。 +1. 将 `spec.containers[].volumeMounts[]` 加到需要用到该 secret 的容器中。指定 `spec.containers[].volumeMounts[].readOnly = true` 和 `spec.containers[].volumeMounts[].mountPath` 为您想要该 secret 出现的尚未使用的目录。 +1. 修改您的镜像并且/或者命令行让程序从该目录下寻找文件。Secret 的 `data` 映射中的每一个键都成为了 `mountPath` 下的一个文件名。 这是一个在 pod 中使用 volume 挂在 secret 的例子: @@ -167,6 +623,20 @@ spec: secretName: mysecret ``` + + 您想要用的每个 secret 都需要在 `spec.volumes` 中指明。 如果 pod 中有多个容器,每个容器都需要自己的 `volumeMounts` 配置块,但是每个 secret 只需要一个 `spec.volumes`。 @@ -199,6 +669,25 @@ spec: path: my-group/my-username ``` + + 将会发生什么呢: - `username` secret 存储在 `/etc/foo/my-group/my-username` 文件中而不是 `/etc/foo/username` 中。 @@ -210,6 +699,8 @@ spec: 您还可以指定 secret 将拥有的权限模式位文件。如果不指定,默认使用 `0644`。您可以为整个保密卷指定默认模式,如果需要,可以覆盖每个密钥。 +例如,您可以指定如下默认模式: + ```yaml apiVersion: v1 kind: Pod @@ -229,6 +720,18 @@ spec: defaultMode: 256 ``` + + 然后,secret 将被挂载到 `/etc/foo` 目录,所有通过该 secret volume 挂载创建的文件的权限都是 `0400`。 请注意,JSON 规范不支持八进制符号,因此使用 256 值作为 0400 权限。如果您使用 yaml 而不是 json 作为 pod,则可以使用八进制符号以更自然的方式指定权限。 @@ -257,6 +760,22 @@ spec: mode: 511 ``` + + 在这种情况下,导致 `/etc/foo/my-group/my-username` 的文件的权限值为 `0777`。由于 JSON 限制,必须以十进制格式指定模式。 请注意,如果稍后阅读此权限值可能会以十进制格式显示。 @@ -266,30 +785,96 @@ spec: 在挂载的 secret volume 的容器内,secret key 将作为文件,并且 secret 的值使用 base-64 解码并存储在这些文件中。这是在上面的示例容器内执行的命令的结果: ```shell -$ ls /etc/foo/ +ls /etc/foo/ +``` +``` username password -$ cat /etc/foo/username +``` + +```shell +cat /etc/foo/username +``` +``` admin -$ cat /etc/foo/password +``` + + +```shell +cat /etc/foo/password +``` +``` 1f2d1e2e67df ``` + + 容器中的程序负责从文件中读取 secret。 **挂载的 secret 被自动更新** -当已经在 volume 中被消费的 secret 被更新时,被映射的 key 也将被更新。 + +当已经在 volume 中被消费的 secret 被更新时,被映射的 key 也将被更新。 +Kubelet 在周期性同步时检查被挂载的 secret 是不是最新的。 +但是,它正在使用其本地缓存来获取 Secret 的当前值。 + +缓存的类型可以使用 (`ConfigMapAndSecretChangeDetectionStrategy` 中的 [KubeletConfiguration 结构](https://github.com/kubernetes/kubernetes/blob/{{< param "docsbranch" >}}/staging/src/k8s.io/kubelet/config/v1beta1/types.go)). +它可以通过基于 ttl 的 watch(默认)传播,也可以将所有请求直接重定向到直接kube-apiserver。 +结果,从更新密钥到将新密钥投射到 Pod 的那一刻的总延迟可能与 kubelet 同步周期 + 缓存传播延迟一样长,其中缓存传播延迟取决于所选的缓存类型。 +(它等于观察传播延迟,缓存的ttl或相应为0) + +{{< note >}} + + + +使用 Secret 作为[子路径](/docs/concepts/storage/volumes#using-subpath)卷安装的容器将不会收到 Secret 更新。 + +{{< /note >}} + + #### Secret 作为环境变量 -将 secret 作为 pod 中的环境变量使用: +将 secret 作为 pod 中的{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}}使用: 1. 创建一个 secret 或者使用一个已存在的 secret。多个 pod 可以引用同一个 secret。 -2. 修改 Pod 定义,为每个要使用 secret 的容器添加对应 secret key 的环境变量。消费secret key 的环境变量应填充 secret 的名称,并键入 `env[x].valueFrom.secretKeyRef`。 -3. 修改镜像并/或者命令行,以便程序在指定的环境变量中查找值。 +1. 修改 Pod 定义,为每个要使用 secret 的容器添加对应 secret key 的环境变量。消费secret key 的环境变量应填充 secret 的名称,并键入 `env[x].valueFrom.secretKeyRef`。 +1. 修改镜像并/或者命令行,以便程序在指定的环境变量中查找值。 + +这是一个使用 Secret 作为环境变量的示例: ```yaml apiVersion: v1 @@ -314,17 +899,42 @@ spec: restartPolicy: Never ``` + **消费环境变量里的 Secret 值** 在一个消耗环境变量 secret 的容器中,secret key 作为包含 secret 数据的 base-64 解码值的常规环境变量。这是从上面的示例在容器内执行的命令的结果: ```shell -$ echo $SECRET_USERNAME +echo $SECRET_USERNAME +``` +``` admin -$ echo $SECRET_PASSWORD +``` +```shell +echo $SECRET_PASSWORD +``` +``` 1f2d1e2e67df ``` + + #### 使用 imagePullSecret imagePullSecret 是将包含 Docker(或其他)镜像注册表密码的 secret 传递给 Kubelet 的一种方式,因此可以代表您的 pod 拉取私有镜像。 @@ -333,14 +943,46 @@ imagePullSecret 是将包含 Docker(或其他)镜像注册表密码的 secre imagePullSecret 的使用在 [镜像文档](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod) 中说明。 + + ### 安排 imagePullSecrets 自动附加 您可以手动创建 imagePullSecret,并从 serviceAccount 引用它。使用该 serviceAccount 创建的任何 pod 和默认使用该 serviceAccount 的 pod 将会将其的 imagePullSecret 字段设置为服务帐户的 imagePullSecret 字段。有关该过程的详细说明,请参阅 [将 ImagePullSecrets 添加到服务帐户](/docs/tasks/configure-pod-container/configure-service-account/#adding-imagepullsecrets-to-a-service-account)。 + + #### 自动挂载手动创建的 Secret 手动创建的 secret(例如包含用于访问 github 帐户的令牌)可以根据其服务帐户自动附加到 pod。请参阅 [使用 PodPreset 向 Pod 中注入信息](/docs/tasks/run-application/podpreset/) 以获取该进程的详细说明。 + + ## 详细 ### 限制 @@ -349,10 +991,39 @@ imagePullSecret 的使用在 [镜像文档](/docs/concepts/containers/images/#sp Secret API 对象驻留在命名空间中。它们只能由同一命名空间中的 pod 引用。 + + 每个 secret 的大小限制为1MB。这是为了防止创建非常大的 secret 会耗尽 apiserver 和 kubelet 的内存。然而,创建许多较小的 secret 也可能耗尽内存。更全面得限制 secret 对内存使用的功能还在计划中。 Kubelet 仅支持从 API server 获取的 Pod 使用 secret。这包括使用 kubectl 创建的任何 pod,或间接通过 replication controller 创建的 pod。它不包括通过 kubelet `--manifest-url` 标志,其 `--config` 标志或其 REST API 创建的pod(这些不是创建 pod 的常用方法)。 + + 必须先创建 secret,除非将它们标记为可选项,否则必须在将其作为环境变量在 pod 中使用之前创建 secret。对不存在的 secret 的引用将阻止其启动。 使用 `secretKeyRef` ,引用指定的 secret 中的不存在的 key ,这会阻止 pod 的启动。 @@ -360,15 +1031,37 @@ Kubelet 仅支持从 API server 获取的 Pod 使用 secret。这包括使用 ku 对于通过 `envFrom` 填充环境变量的 secret,这些环境变量具有被认为是无效环境变量名称的 key 将跳过这些键。该 pod 将被允许启动。将会有一个事件,其原因是 `InvalidVariableNames`,该消息将包含被跳过的无效键的列表。该示例显示一个 pod,它指的是包含2个无效键,1badkey 和 2alsobad 的默认/mysecret ConfigMap。 ```shell -$ kubectl get events +kubectl get events +``` +``` LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON 0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. ``` + ### Secret 与 Pod 生命周期的联系 通过 API 创建 Pod 时,不会检查应用的 secret 是否存在。一旦 Pod 被调度,kubelet 就会尝试获取该 secret 的值。如果获取不到该 secret,或者暂时无法与 API server 建立连接,kubelet 将会定期重试。Kubelet 将会报告关于 pod 的事件,并解释它无法启动的原因。一旦获取到 secret,kubelet将创建并装载一个包含它的卷。在所有 pod 的卷被挂载之前,都不会启动 pod 的容器。 + + ## 使用案例 ### 使用案例:包含 ssh 密钥的 pod @@ -376,16 +1069,31 @@ LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT 创建一个包含 ssh key 的 secret: ```shell -$ kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub +kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub ``` -**安全性注意事项**:发送自己的 ssh 密钥之前要仔细思考:集群的其他用户可能有权访问该密钥。使用您想要共享 Kubernetes 群集的所有用户可以访问的服务帐户,如果它们遭到入侵,可以撤销。 +``` +secret "ssh-key-secret" created +``` +{{< caution >}} + + +发送自己的 ssh 密钥之前要仔细思考:集群的其他用户可能有权访问该密钥。使用您想要共享 Kubernetes 群集的所有用户可以访问的服务帐户,如果它们遭到入侵,可以撤销。 +{{< /caution >}} + + + 现在我们可以创建一个使用 ssh 密钥引用 secret 的pod,并在一个卷中使用它: ```yaml -kind: Pod apiVersion: v1 +kind: Pod metadata: name: secret-test-pod labels: @@ -404,6 +1112,10 @@ spec: mountPath: "/etc/secret-volume" ``` + + 当容器中的命令运行时,密钥的片段将可在以下目录: ```shell @@ -411,24 +1123,64 @@ spec: /etc/secret-volume/ssh-privatekey ``` + 然后容器可以自由使用密钥数据建立一个 ssh 连接。 + ### 使用案例:包含 prod/test 凭据的 pod 下面的例子说明一个 pod 消费一个包含 prod 凭据的 secret,另一个 pod 使用测试环境凭据消费 secret。 -创建 secret: +通过秘钥生成器制作 kustomization.yaml ```shell -$ kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 +kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11 +``` +``` secret "prod-db-secret" created -$ kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests -secret "test-db-secret" created ``` +```shell +kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests +``` +``` +secret "test-db-secret" created +``` +{{< note >}} + + +特殊字符(例如 `$`, `\*`, 和 `!`)需要转义。 如果您使用的密码具有特殊字符,则需要使用 `\\` 字符对其进行转义。 例如,如果您的实际密码是 `S!B\*d$zDsb`,则应通过以下方式执行命令: + +```shell +kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password=S\\!B\\\*d\\$zDsb +``` + + +您无需从文件中转义密码中的特殊字符( `--from-file` )。 +{{< /note >}} + + 创建 pod : -```yaml +```shell +$ cat < pod.yaml apiVersion: v1 kind: List items: @@ -468,8 +1220,34 @@ items: - name: secret-volume readOnly: true mountPath: "/etc/secret-volume" +EOF ``` + + +加入 Pod 到同样的 kustomization.yaml 文件 + +```shell +$ cat <> kustomization.yaml +resources: +- pod.yaml +EOF +``` + + +部署所有的对象通过下面的命令 + +```shell +kubectl apply -k . +``` + + 这两个容器将在其文件系统上显示以下文件,其中包含每个容器环境的值: ```shell @@ -477,11 +1255,22 @@ items: /etc/secret-volume/password ``` -请注意,两个 pod 的 spec 配置中仅有一个字段有所不同;这有助于使用普通的 pod 配置模板创建具有不同功能的 pod。您可以使用两个 service account 进一步简化基本 pod spec:一个名为 `prod-user` 拥有 `prod-db-secret` ,另一个称为 `test-user` 拥有 `test-db-secret` 。然后,pod spec 可以缩短为,例如: + + +请注意,两个 pod 的 spec 配置中仅有一个字段有所不同;这有助于使用普通的 pod 配置模板创建具有不同功能的 pod。 + +您可以使用两个 service account 进一步简化基本 pod spec:一个名为 `prod-user` 拥有 `prod-db-secret` ,另一个称为 `test-user` 拥有 `test-db-secret` 。然后,pod spec 可以缩短为,例如: ```yaml -kind: Pod apiVersion: v1 +kind: Pod metadata: name: prod-db-client-pod labels: @@ -493,20 +1282,26 @@ spec: image: myClientImage ``` + ### 使用案例:Secret 卷中以点号开头的文件 为了将数据“隐藏”起来(即文件名以点号开头的文件),简单地说让该键以一个点开始。例如,当如下 secret 被挂载到卷中: ```yaml -kind: Secret apiVersion: v1 +kind: Secret metadata: name: dotfile-secret data: .secret-file: dmFsdWUtMg0KDQo= --- -kind: Pod apiVersion: v1 +kind: Pod metadata: name: secret-dotfiles-pod spec: @@ -527,35 +1322,122 @@ spec: mountPath: "/etc/secret-volume" ``` + + `Secret-volume` 将包含一个单独的文件,叫做 `.secret-file`,`dotfile-test-container` 的 `/etc/secret-volume/.secret-file` 路径下将有该文件。 -**注意** +{{< note >}} + + 以点号开头的文件在 `ls -l` 的输出中被隐藏起来了;列出目录内容时,必须使用 `ls -la` 才能查看它们。 +{{< /note >}} + + ### 使用案例:Secret 仅对 pod 中的一个容器可见 考虑以下一个需要处理 HTTP 请求的程序,执行一些复杂的业务逻辑,然后使用 HMAC 签署一些消息。因为它具有复杂的应用程序逻辑,所以在服务器中可能会出现一个未被注意的远程文件读取漏洞,这可能会将私钥暴露给攻击者。 + + 这可以在两个容器中分为两个进程:前端容器,用于处理用户交互和业务逻辑,但无法看到私钥;以及可以看到私钥的签名者容器,并且响应来自前端的简单签名请求(例如通过本地主机网络)。 使用这种分割方法,攻击者现在必须欺骗应用程序服务器才能进行任意的操作,这可能比使其读取文件更难。 + + ## 最佳实践 ### 客户端使用 Secret API -当部署与 secret API 交互的应用程序时,应使用诸如 [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/) 之类的 [授权策略](https://kubernetes.io/docs/admin/authorization/) 来限制访问。 +当部署与 secret API 交互的应用程序时,应使用 [授权策略](/docs/reference/access-authn-authz/authorization/), 例如 [RBAC](/docs/reference/access-authn-authz/rbac/) 来限制访问。 + + Secret 中的值对于不同的环境来说重要性可能不同,例如对于 Kubernetes 集群内部(例如 service account 令牌)和集群外部来说就不一样。即使一个应用程序可以理解其期望的与之交互的 secret 有多大的能力,但是同一命名空间中的其他应用程序却可能不这样认为。 由于这些原因,在命名空间中 `watch` 和 `list` secret 的请求是非常强大的功能,应该避免这样的行为,因为列出 secret 可以让客户端检查所有 secret 是否在该命名空间中。在群集中`watch` 和 `list` 所有 secret 的能力应该只保留给最有特权的系统级组件。 -需要访问 secrets API 的应用程序应该根据他们需要的 secret 执行 `get` 请求。这允许管理员限制对所有 secret 的访问,同时设置 [白名单访问](https://kubernetes.io/docs/admin/authorization/rbac/#referring-to-resources) 应用程序需要的各个实例。 + + +需要访问 secrets API 的应用程序应该根据他们需要的 secret 执行 `get` 请求。这允许管理员限制对所有 secret 的访问, +同时设置 [白名单访问](/docs/reference/access-authn-authz/rbac/#referring-to-resources) 应用程序需要的各个实例。 + +为了提高循环获取的性能,客户端可以设计引用 secret 的资源,然后 `watch` 资源,在引用更改时重新请求 secret。 +此外,还提出了一种 [”批量监控“ API](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/bulk_watch.md) 来让客户端 `watch` 每个资源,该功能可能会在将来的 Kubernetes 版本中提供。 + + ## 安全属性 @@ -563,23 +1445,82 @@ Secret 中的值对于不同的环境来说重要性可能不同,例如对于 因为 `secret` 对象可以独立于使用它们的 `pod` 而创建,所以在创建、查看和编辑 pod 的流程中 secret 被暴露的风险较小。系统还可以对 `secret` 对象采取额外的预防措施,例如避免将其写入到磁盘中可能的位置。 + + 只有当节点上的 pod 需要用到该 secret 时,该 secret 才会被发送到该节点上。它不会被写入磁盘,而是存储在 tmpfs 中。一旦依赖于它的 pod 被删除,它就被删除。 -在大多数 Kubernetes 项目维护的发行版中,用户与 API server 之间的通信以及从 API server 到 kubelet 的通信都受到 SSL/TLS 的保护。通过这些通道传输时,secret 受到保护。 - -节点上的 secret 数据存储在 tmpfs 卷中,因此不会传到节点上的其他磁盘。 - 同一节点上的很多个 pod 可能拥有多个 secret。但是,只有 pod 请求的 secret 在其容器中才是可见的。因此,一个 pod 不能访问另一个 Pod 的 secret。 -Pod 中有多个容器。但是,pod 中的每个容器必须请求其挂载卷中的 secret 卷才能在容器内可见。这可以用于 [在 Pod 级别构建安全分区](#使用案例secret-仅对-pod-中的一个容器可见)。 + +Pod 中有多个容器。但是,pod 中的每个容器必须请求其挂载卷中的 secret 卷才能在容器内可见。 +这可以用于 [在 Pod 级别构建安全分区](#使用案例secret-仅对-pod-中的一个容器可见)。 + +在大多数 Kubernetes 项目维护的发行版中,用户与 API server 之间的通信以及从 API server 到 kubelet 的通信都受到 SSL/TLS 的保护。通过这些通道传输时,secret 受到保护。 + +{{< feature-state for_k8s_version="v1.13" state="beta" >}} + + +你可以为 secret 数据开启[静态加密](/docs/tasks/administer-cluster/encrypt-data/),这样秘密信息就不会以明文形式存储到{{< glossary_tooltip term_id="etcd" >}}。 + + + ### 风险 - API server 的 secret 数据以纯文本的方式存储在 etcd 中,因此: + - 管理员应该为集群数据开启静态加密(需求 v1.13 或者更新)。 - 管理员应该限制 admin 用户访问 etcd; - API server 中的 secret 数据位于 etcd 使用的磁盘上;管理员可能希望在不再使用时擦除/粉碎 etcd 使用的磁盘 + - 如果 etcd 运行在集群内,管理员应该确保 etcd 之间的通信使用 SSL/TLS 进行加密。 - 如果您将 secret 数据编码为 base64 的清单(JSON 或 YAML)文件,共享该文件或将其检入代码库,这样的话该密码将会被泄露。 Base64 编码不是一种加密方式,一样也是纯文本。 - 应用程序在从卷中读取 secret 后仍然需要保护 secret 的值,例如不会意外记录或发送给不信任方。 - 可以创建和使用 secret 的 pod 的用户也可以看到该 secret 的值。即使 API server 策略不允许用户读取 secret 对象,用户也可以运行暴露 secret 的 pod。 -- 如果运行了多个副本,那么这些 secret 将在它们之间共享。默认情况下,etcd 不能保证与 SSL/TLS 的对等通信,尽管可以进行配置。 - 目前,任何节点的 root 用户都可以通过模拟 kubelet 来读取 API server 中的任何 secret。只有向实际需要它们的节点发送 secret 才能限制单个节点的根漏洞的影响,该功能还在计划中。 + +{{% capture whatsnext %}} + +{{% /capture %}} diff --git a/content/zh/docs/concepts/configuration/taint-and-toleration.md b/content/zh/docs/concepts/configuration/taint-and-toleration.md index 388bb057c0..af4e054fe1 100755 --- a/content/zh/docs/concepts/configuration/taint-and-toleration.md +++ b/content/zh/docs/concepts/configuration/taint-and-toleration.md @@ -1,28 +1,9 @@ --- -approvers: -- davidopp -- kevin-wangzefeng -- bsalamat -cn-approvers: -- linyouchong title: Taint 和 Toleration content_template: templates/concept weight: 40 --- - - -{{< toc >}} {{% capture overview %}} 想删除上述命令添加的 taint ,您可以运行: ```shell -kubectl taint nodes kube11 key:NoSchedule- +kubectl taint nodes node1 key:NoSchedule- ``` + + +您可以在PodSpec中为容器设定容忍标签。以下两个容忍标签都与上面的 `kubectl taint` 创建的污点“匹配”, +因此具有任一容忍标签的Pod都可以将其调度到“ node1”上: + ```yaml tolerations: - key: "key" @@ -111,13 +101,13 @@ A toleration "matches" a taint if the keys are the same and the effects are the {{< note >}} +will tolerate everything. +--> -**注意:** 存在两种特殊情况: +存在两种特殊情况: * 如果一个 toleration 的 `key` 为空且 operator 为 `Exists` ,表示这个 toleration 与任意的 key 、 value 和 effect 都匹配,即这个 toleration 能容忍任意 taint。 @@ -127,9 +117,8 @@ tolerations: ``` +--> * 如果一个 toleration 的 `effect` 为空,则 `key` 值与之相同的相匹配 taint 的 `effect` 可以是任意值。 ```yaml @@ -158,13 +147,13 @@ remaining un-ignored taints have the indicated effects on the pod. In particular +the node (if it is already running on the node), and will not be +scheduled onto the node (if it is not yet running on the node). +--> * 如果未被过滤的 taint 中存在一个以上 effect 值为 `NoSchedule` 的 taint,则 Kubernetes 不会将 pod 分配到该节点。 * 如果未被过滤的 taint 中不存在 effect 值为 `NoSchedule` 的 taint,但是存在 effect 值为 `PreferNoSchedule` 的 taint,则 Kubernetes 会*尝试*将 pod 分配到该节点。 * 如果未被过滤的 taint 中存在一个以上 effect 值为 `NoExecute` 的 taint,则 Kubernetes 不会将 pod 分配到该节点(如果 pod 还未在节点上运行),或者将 pod 从该节点驱逐(如果 pod 已经在节点上运行)。 @@ -247,52 +236,52 @@ pods that shouldn't be running. A few of the use cases are +a particular set of users, you can add a taint to those nodes (say, +`kubectl taint nodes nodename dedicated=groupName:NoSchedule`) and then add a corresponding +toleration to their pods (this would be done most easily by writing a custom +[admission controller](/docs/reference/access-authn-authz/admission-controllers/)). +The pods with the tolerations will then be allowed to use the tainted (dedicated) nodes as +well as any other nodes in the cluster. If you want to dedicate the nodes to them *and* +ensure they *only* use the dedicated nodes, then you should additionally add a label similar +to the taint to the same set of nodes (e.g. `dedicated=groupName`), and the admission +controller should additionally add a node affinity to require that the pods can only schedule +onto nodes labeled with `dedicated=groupName`. +--> * **专用节点**:如果您想将某些节点专门分配给特定的一组用户使用,您可以给这些节点添加一个 taint(即, `kubectl taint nodes nodename dedicated=groupName:NoSchedule`),然后给这组用户的 pod 添加一个相对应的 toleration(通过编写一个自定义的[admission controller](/docs/admin/admission-controllers/),很容易就能做到)。拥有上述 toleration 的 pod 就能够被分配到上述专用节点,同时也能够被分配到集群中的其它节点。如果您希望这些 pod 只能被分配到上述专用节点,那么您还需要给这些专用节点另外添加一个和上述 taint 类似的 label (例如:`dedicated=groupName`),同时 还要在上述 admission controller 中给 pod 增加节点亲和性要求上述 pod 只能被分配到添加了 `dedicated=groupName` 标签的节点上。 +hardware (for example GPUs), it is desirable to keep pods that don't need the specialized +hardware off of those nodes, thus leaving room for later-arriving pods that do need the +specialized hardware. This can be done by tainting the nodes that have the specialized +hardware (e.g. `kubectl taint nodes nodename special=true:NoSchedule` or +`kubectl taint nodes nodename special=true:PreferNoSchedule`) and adding a corresponding +toleration to pods that use the special hardware. As in the dedicated nodes use case, +it is probably easiest to apply the tolerations using a custom +[admission controller](/docs/reference/access-authn-authz/admission-controllers/). +For example, it is recommended to use [Extended +Resources](/docs/concepts/configuration/manage-compute-resources-container/#extended-resources) +to represent the special hardware, taint your special hardware nodes with the +extended resource name and run the +[ExtendedResourceToleration](/docs/reference/access-authn-authz/admission-controllers/#extendedresourcetoleration) +admission controller. Now, because the nodes are tainted, no pods without the +toleration will schedule on them. But when you submit a pod that requests the +extended resource, the `ExtendedResourceToleration` admission controller will +automatically add the correct toleration to the pod and that pod will schedule +on the special hardware nodes. This will make sure that these special hardware +nodes are dedicated for pods requesting such hardware and you don't have to +manually add tolerations to your pods. +--> * **配备了特殊硬件的节点**:在部分节点配备了特殊硬件(比如 GPU)的集群中,我们希望不需要这类硬件的 pod 不要被分配到这些特殊节点,以便为后继需要这类硬件的 pod 保留资源。要达到这个目的,可以先给配备了特殊硬件的节点添加 taint(例如 `kubectl taint nodes nodename special=true:NoSchedule` or `kubectl taint nodes nodename special=true:PreferNoSchedule`),然后给使用了这类特殊硬件的 pod 添加一个相匹配的 toleration。和专用节点的例子类似,添加这个 toleration 的最简单的方法是使用自定义 [admission controller](/docs/reference/access-authn-authz/admission-controllers/)。比如,我们推荐使用 [Extended Resources](/docs/concepts/configuration/manage-compute-resources-container/#extended-resources) 来表示特殊硬件,给配置了特殊硬件的节点添加 taint 时包含 extended resource 名称,然后运行一个 [ExtendedResourceToleration](/docs/reference/access-authn-authz/admission-controllers/#extendedresourcetoleration) admission controller。此时,因为节点已经被 taint 了,没有对应 toleration 的 Pod 会被调度到这些节点。但当你创建一个使用了 extended resource 的 Pod 时,`ExtendedResourceToleration` admission controller 会自动给 Pod 加上正确的 toleration ,这样 Pod 就会被自动调度到这些配置了特殊硬件件的节点上。这样就能够确保这些配置了特殊硬件的节点专门用于运行 需要使用这些硬件的 Pod,并且您无需手动给这些 Pod 添加 toleration。 -* **基于 taint 的驱逐 (alpha 特性)**: 这是在每个 pod 中配置的在节点出现问题时的驱逐行为,接下来的章节会描述这个特性 +* **Taint based Evictions (beta feature)**: A per-pod-configurable eviction behavior +when there are node problems, which is described in the next section. +--> +* **基于 taint 的驱逐 (beta 特性)**: 这是在每个 pod 中配置的在节点出现问题时的驱逐行为,接下来的章节会描述这个特性 +--> 前文我们提到过 taint 的 effect 值 `NoExecute` ,它会影响已经在节点上运行的 pod * 如果 pod 不能忍受effect 值为 `NoExecute` 的 taint,那么 pod 将马上被驱逐 * 如果 pod 能够忍受effect 值为 `NoExecute` 的 taint,但是在 toleration 定义中没有指定 `tolerationSeconds`,则 pod 还会一直在这个节点上运行。 @@ -337,6 +326,7 @@ certain condition is true. The following taints are built in: this node, the kubelet removes this taint. --> 此外,Kubernetes 1.6 已经支持(alpha阶段)节点问题的表示。换句话说,当某种条件为真时,node controller会自动给节点添加一个 taint。当前内置的 taint 包括: + * `node.kubernetes.io/not-ready`:节点未准备好。这相当于节点状态 `Ready` 的值为 "`False`"。 * `node.kubernetes.io/unreachable`:node controller 访问不到节点. 这相当于节点状态 `Ready` 的值为 "`Unknown`"。 * `node.kubernetes.io/out-of-disk`:节点磁盘耗尽。 @@ -347,13 +337,11 @@ certain condition is true. The following taints are built in: * `node.cloudprovider.kubernetes.io/uninitialized`:如果 kubelet 启动时指定了一个 "外部" cloud provider,它将给当前节点添加一个 taint 将其标志为不可用。在 cloud-controller-manager 的一个 controller 初始化这个节点后,kubelet 将删除这个 taint。 -在启用了 `TaintBasedEvictions` 这个 alpha 功能特性后(在 Kubernetes controller manager 的 `--feature-gates` 参数中包含`TaintBasedEvictions=true` 开启这个功能特性,例如:`--feature-gates=FooBar=true,TaintBasedEvictions=true`),NodeController (或 kubelet)会自动给节点添加这类 taint,上述基于节点状态 Ready 对 pod 进行驱逐的逻辑会被禁用。 +在版本1.13中,`TaintBasedEvictions` 功能已升级为Beta,并且默认启用,因此污点会自动给节点添加这类 taint,上述基于节点状态 Ready 对 pod 进行驱逐的逻辑会被禁用。 {{< note >}} -使用这个 alpha 功能特性,结合 `tolerationSeconds` ,pod 就可以指定当节点出现一个或全部上述问题时还将在这个节点上运行多长的时间。 +使用这个 beta 功能特性,结合 `tolerationSeconds` ,pod 就可以指定当节点出现一个或全部上述问题时还将在这个节点上运行多长的时间。 注意,Kubernetes 会自动给 pod 添加一个 key 为 `node.kubernetes.io/not-ready` 的 toleration 并配置 `tolerationSeconds=300`,除非用户提供的 pod 配置中已经已存在了 key 为 `node.kubernetes.io/not-ready` 的 toleration。同样,Kubernetes 会给 pod 添加一个 key 为 `node.kubernetes.io/unreachable` 的 toleration 并配置 `tolerationSeconds=300`,除非用户提供的 pod 配置中已经已存在了 key 为 `node.kubernetes.io/unreachable` 的 toleration。 @@ -413,7 +401,7 @@ admission controller](https://git.k8s.io/kubernetes/plugin/pkg/admission/default [DaemonSet](/docs/concepts/workloads/controllers/daemonset/) pods are created with `NoExecute` tolerations for the following taints with no `tolerationSeconds`: - * `node.alpha.kubernetes.io/unreachable` + * `node.kubernetes.io/unreachable` * `node.kubernetes.io/not-ready` This ensures that DaemonSet pods are never evicted due to these problems, @@ -421,23 +409,22 @@ which matches the behavior when this feature is disabled. --> [DaemonSet](/docs/concepts/workloads/controllers/daemonset/) 中的 pod 被创建时,针对以下 taint 自动添加的 `NoExecute` 的 toleration 将不会指定 `tolerationSeconds`: - * `node.alpha.kubernetes.io/unreachable` + * `node.kubernetes.io/unreachable` * `node.kubernetes.io/not-ready` 这保证了出现上述问题时 DaemonSet 中的 pod 永远不会被驱逐,这和 `TaintBasedEvictions` 这个特性被禁用后的行为是一样的。 ## 基于节点状态添加 taint -1.8 版本引入了一个 alpha 特性,让 node controller 根据节点的状态创建 taint。当开启了这个特性时(通过给 scheduler 的 `--feature-gates` 添加 `TaintNodesByCondition=true` 参数,例如:`--feature-gates=FooBar=true,TaintNodesByCondition=true`),scheduler不会去检查节点的状态,而是检查节点的 taint。这确保了节点的状态不影响应该调度哪些 Pod 到节点上。用户可以通过给 Pod 添加 toleration 来选择忽略节点的一些问题(节点状态的形式表示)。 -从 Kubernetes 1.8 开始,DaemonSet controller 会自动添加如下 `NoSchedule` toleration,以防止 DaemonSet 中断。 +--> +在版本1.12中,`TaintNodesByCondition` 功能已升级为Beta,因此节点生命周期控制器会自动创建与Node条件相对应的污点。 +同样,调度程序不检查节点条件。 而是调度程序检查污点。 这确保了节点条件不会影响调度到节点上的内容。 用户可以通过添加适当的 Pod 容忍来选择忽略某些Node的问题(表示为 Node 的调度条件)。 +注意,`TaintNodesByCondition` 只会污染具有 `NoSchedule` 设定的节点。 `NoExecute` 效应由 `TaintBasedEviction` 控制, +`TaintBasedEviction` 是 Beta 版功能,自1.13版起默认启用。 + * `node.kubernetes.io/memory-pressure` * `node.kubernetes.io/disk-pressure` * `node.kubernetes.io/out-of-disk` (*只适合 critical pod*) @@ -461,4 +451,5 @@ breaking. Adding these tolerations ensures backward compatibility. You can also add arbitrary tolerations to DaemonSets. --> + 添加上述 toleration 确保了向后兼容,您也可以选择自由的向 DaemonSet 添加 toleration。 diff --git a/content/zh/docs/reference/glossary/index.md b/content/zh/docs/reference/glossary/index.md new file mode 100755 index 0000000000..ecd4541c0b --- /dev/null +++ b/content/zh/docs/reference/glossary/index.md @@ -0,0 +1,12 @@ +--- +title: 标准化词汇表 +layout: glossary +noedit: true +default_active_tag: fundamental +weight: 5 +card: + name: 参考 + weight: 10 + title: 词汇表 +--- +