--- title: 通过文件将 Pod 信息呈现给容器 content_type: task weight: 40 --- 此页面描述 Pod 如何使用 DownwardAPIVolumeFile 把自己的信息呈现给 Pod 中运行的容器。 DownwardAPIVolumeFile 可以呈现 Pod 的字段和容器字段。 ## {{% heading "prerequisites" %}} {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} ## Downward API 有两种方式可以将 Pod 和 Container 字段呈现给运行中的容器: * [环境变量](/zh/docs/tasks/inject-data-application/environment-variable-expose-pod-information/#the-downward-api) * 卷文件 这两种呈现 Pod 和 Container 字段的方式都称为 *Downward API*。 ## 存储 Pod 字段 在这个练习中,你将创建一个包含一个容器的 Pod。Pod 的配置文件如下: {{< codenew file="pods/inject/dapi-volume.yaml" >}} 在配置文件中,你可以看到 Pod 有一个 `downwardAPI` 类型的卷,并且挂载到容器中的 `/etc/podinfo` 目录。 查看 `downwardAPI` 下面的 `items` 数组。 每个数组元素都是一个 [DownwardAPIVolumeFile](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#downwardapivolumefile-v1-core) 对象。 第一个元素指示 Pod 的 `metadata.labels` 字段的值保存在名为 `labels` 的文件中。 第二个元素指示 Pod 的 `annotations` 字段的值保存在名为 `annotations` 的文件中。 {{< note >}} 本示例中的字段是Pod字段,不是Pod中容器的字段。 {{< /note >}} 创建 Pod: ```shell kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume.yaml ``` 验证Pod中的容器运行正常: ```shell kubectl get pods ``` 查看容器的日志: ```shell kubectl logs kubernetes-downwardapi-volume-example ``` 输出显示 `labels` 和 `annotations` 文件的内容: ``` cluster="test-cluster1" rack="rack-22" zone="us-est-coast" build="two" builder="john-doe" ``` 进入 Pod 中运行的容器,打开一个 Shell: ```shell kubectl exec -it kubernetes-downwardapi-volume-example -- sh ``` 在该 Shell中,查看 `labels` 文件: ```shell /# cat /etc/podinfo/labels ``` 输出显示 Pod 的所有标签都已写入 `labels` 文件。 ``` cluster="test-cluster1" rack="rack-22" zone="us-est-coast" ``` 同样,查看`annotations`文件: ```shell /# cat /etc/podinfo/annotations ``` 查看`/etc/podinfo`目录下的文件: ```shell /# ls -laR /etc/podinfo ``` 在输出中可以看到,`labels` 和 `annotations` 文件都在一个临时子目录中。 在这个例子,`..2982_06_02_21_47_53.299460680`。 在 `/etc/podinfo` 目录中,`..data` 是一个指向临时子目录 的符号链接。`/etc/podinfo` 目录中,`labels` 和 `annotations` 也是符号链接。 ``` drwxr-xr-x ... Feb 6 21:47 ..2982_06_02_21_47_53.299460680 lrwxrwxrwx ... Feb 6 21:47 ..data -> ..2982_06_02_21_47_53.299460680 lrwxrwxrwx ... Feb 6 21:47 annotations -> ..data/annotations lrwxrwxrwx ... Feb 6 21:47 labels -> ..data/labels /etc/podinfo/..2982_06_02_21_47_53.299460680: total 8 -rw-r--r-- ... Feb 6 21:47 annotations -rw-r--r-- ... Feb 6 21:47 labels ``` 用符号链接可实现元数据的动态原子性刷新;更新将写入一个新的临时目录, 然后通过使用[rename(2)](http://man7.org/linux/man-pages/man2/rename.2.html) 完成 `..data` 符号链接的原子性更新。 {{< note >}} 如果容器以 [subPath](/zh/docs/concepts/storage/volumes/#using-subpath)卷挂载方式来使用 Downward API,则该容器无法收到更新事件。 {{< /note >}} 退出 Shell: ```shell /# exit ``` ## 存储容器字段 前面的练习中,你将 Pod 字段保存到 DownwardAPIVolumeFile 中。 接下来这个练习,你将存储 Container 字段。这里是包含一个容器的 Pod 的配置文件: {{< codenew file="pods/inject/dapi-volume-resources.yaml" >}} 在这个配置文件中,你可以看到 Pod 有一个 `downwardAPI` 类型的卷,并且挂载到容器的 `/etc/podinfo` 目录。 查看 `downwardAPI` 下面的 `items` 数组。每个数组元素都是一个 DownwardAPIVolumeFile。 第一个元素指定名为 `client-container` 的容器中 `limits.cpu` 字段的值应保存在名为 `cpu_limit` 的文件中。 创建Pod: ```shell kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume-resources.yaml ``` 打开一个 Shell,进入 Pod 中运行的容器: ``` kubectl exec -it kubernetes-downwardapi-volume-example-2 -- sh ``` 在 Shell 中,查看 `cpu_limit` 文件: ```shell /# cat /etc/podinfo/cpu_limit ``` 你可以使用同样的命令查看 `cpu_request`、`mem_limit` 和 `mem_request` 文件. ## Downward API 的能力 下面这些信息可以通过环境变量和 `downwardAPI` 卷提供给容器: * 能通过 `fieldRef` 获得的: * `metadata.name` - Pod 名称 * `metadata.namespace` - Pod 名字空间 * `metadata.uid` - Pod 的 UID * `metadata.labels['']` - Pod 标签 `` 的值 (例如, `metadata.labels['mylabel']`) * `metadata.annotations['']` - Pod 的注解 `` 的值(例如, `metadata.annotations['myannotation']`) * 能通过 `resourceFieldRef` 获得的: * 容器的 CPU 约束值 * 容器的 CPU 请求值 * 容器的内存约束值 * 容器的内存请求值 * 容器的巨页限制值(前提是启用了 `DownwardAPIHugePages` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)) * 容器的巨页请求值(前提是启用了 `DownwardAPIHugePages` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)) * 容器的临时存储约束值 * 容器的临时存储请求值 此外,以下信息可通过 `downwardAPI` 卷从 `fieldRef` 获得: * `metadata.labels` - Pod 的所有标签,以 `label-key="escaped-label-value"` 格式显示,每行显示一个标签 * `metadata.annotations` - Pod 的所有注解,以 `annotation-key="escaped-annotation-value"` 格式显示,每行显示一个标签 以下信息可通过环境变量获得: * `status.podIP` - 节点 IP * `spec.serviceAccountName` - Pod 服务帐号名称, 版本要求 v1.4.0-alpha.3 * `spec.nodeName` - 节点名称, 版本要求 v1.4.0-alpha.3 * `status.hostIP` - 节点 IP, 版本要求 v1.7.0-alpha.1 {{< note >}} 如果容器未指定 CPU 和内存限制,则 Downward API 默认将节点可分配值 视为容器的 CPU 和内存限制。 {{< /note >}} ## 投射键名到指定路径并且指定文件权限 你可以将键名投射到指定路径并且指定每个文件的访问权限。 更多信息,请参阅[Secrets](/zh/docs/concepts/configuration/secret/). ## Downward API的动机 对于容器来说,有时候拥有自己的信息是很有用的,可避免与 Kubernetes 过度耦合。 Downward API 使得容器使用自己或者集群的信息,而不必通过 Kubernetes 客户端或 API 服务器来获得。 一个例子是有一个现有的应用假定要用一个非常熟悉的环境变量来保存一个唯一标识。 一种可能是给应用增加处理层,但这样是冗余和易出错的,而且它违反了低耦合的目标。 更好的选择是使用 Pod 名称作为标识,把 Pod 名称注入这个环境变量中。 ## {{% heading "whatsnext" %}} * [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core) * [Volume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#volume-v1-core) * [DownwardAPIVolumeSource](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#downwardapivolumesource-v1-core) * [DownwardAPIVolumeFile](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#downwardapivolumefile-v1-core) * [ResourceFieldSelector](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#resourcefieldselector-v1-core)