通过文件将 Pod 信息呈现给容器

此页面描述 Pod 如何使用 downwardAPI 卷 把自己的信息呈现给 Pod 中运行的容器。 downwardAPI 卷可以呈现 Pod 和容器的字段。

在 Kubernetes 中,有两种方式可以将 Pod 和容器字段呈现给运行中的容器:

这两种呈现 Pod 和容器字段的方式都称为 downward API

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

存储 Pod 字段

在这部分的练习中,你将创建一个包含一个容器的 Pod,并将 Pod 级别的字段作为文件投射到正在运行的容器中。 Pod 的清单如下:

pods/inject/dapi-volume.yaml 通过文件将 Pod 信息呈现给容器 - 图1

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: kubernetes-downwardapi-volume-example
  5. labels:
  6. zone: us-est-coast
  7. cluster: test-cluster1
  8. rack: rack-22
  9. annotations:
  10. build: two
  11. builder: john-doe
  12. spec:
  13. containers:
  14. - name: client-container
  15. image: registry.k8s.io/busybox
  16. command: ["sh", "-c"]
  17. args:
  18. - while true; do
  19. if [[ -e /etc/podinfo/labels ]]; then
  20. echo -en '\n\n'; cat /etc/podinfo/labels; fi;
  21. if [[ -e /etc/podinfo/annotations ]]; then
  22. echo -en '\n\n'; cat /etc/podinfo/annotations; fi;
  23. sleep 5;
  24. done;
  25. volumeMounts:
  26. - name: podinfo
  27. mountPath: /etc/podinfo
  28. volumes:
  29. - name: podinfo
  30. downwardAPI:
  31. items:
  32. - path: "labels"
  33. fieldRef:
  34. fieldPath: metadata.labels
  35. - path: "annotations"
  36. fieldRef:
  37. fieldPath: metadata.annotations

在 Pod 清单中,你可以看到 Pod 有一个 downwardAPI 类型的卷,并且挂载到容器中的 /etc/podinfo 目录。

查看 downwardAPI 下面的 items 数组。 数组的每个元素定义一个 downwardAPI 卷。 第一个元素指示 Pod 的 metadata.labels 字段的值保存在名为 labels 的文件中。 第二个元素指示 Pod 的 annotations 字段的值保存在名为 annotations 的文件中。

说明:

本示例中的字段是 Pod 字段,不是 Pod 中容器的字段。

创建 Pod:

  1. kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume.yaml

验证 Pod 中的容器运行正常:

  1. kubectl get pods

查看容器的日志:

  1. kubectl logs kubernetes-downwardapi-volume-example

输出显示 labels 文件和 annotations 文件的内容:

  1. cluster="test-cluster1"
  2. rack="rack-22"
  3. zone="us-est-coast"
  4. build="two"
  5. builder="john-doe"

进入 Pod 中运行的容器,打开一个 Shell:

  1. kubectl exec -it kubernetes-downwardapi-volume-example -- sh

在该 Shell中,查看 labels 文件:

  1. /# cat /etc/podinfo/labels

输出显示 Pod 的所有标签都已写入 labels 文件。

  1. cluster="test-cluster1"
  2. rack="rack-22"
  3. zone="us-est-coast"

同样,查看 annotations 文件:

  1. /# cat /etc/podinfo/annotations

查看 /etc/podinfo 目录下的文件:

  1. /# ls -laR /etc/podinfo

在输出中可以看到,labelsannotations 文件都在一个临时子目录中。 在这个例子中,这个临时子目录为 ..2982_06_02_21_47_53.299460680。 在 /etc/podinfo 目录中,..data 是指向该临时子目录的符号链接。 另外在 /etc/podinfo 目录中,labelsannotations 也是符号链接。

  1. drwxr-xr-x ... Feb 6 21:47 ..2982_06_02_21_47_53.299460680
  2. lrwxrwxrwx ... Feb 6 21:47 ..data -> ..2982_06_02_21_47_53.299460680
  3. lrwxrwxrwx ... Feb 6 21:47 annotations -> ..data/annotations
  4. lrwxrwxrwx ... Feb 6 21:47 labels -> ..data/labels
  5. /etc/..2982_06_02_21_47_53.299460680:
  6. total 8
  7. -rw-r--r-- ... Feb 6 21:47 annotations
  8. -rw-r--r-- ... Feb 6 21:47 labels

用符号链接可实现元数据的动态原子性刷新;更新将写入一个新的临时目录, 然后通过使用 rename(2) 完成 ..data 符号链接的原子性更新。

说明:

如果容器以 subPath 卷挂载方式来使用 Downward API,则该容器无法收到更新事件。

退出 Shell:

  1. /# exit

存储容器字段

前面的练习中,你使用 downward API 使 Pod 级别的字段可以被 Pod 内正在运行的容器访问。 接下来这个练习,你将只传递由 Pod 定义的部分的字段到 Pod 内正在运行的容器中, 但这些字段取自特定容器而不是整个 Pod。 下面是一个同样只有一个容器的 Pod 的清单:

pods/inject/dapi-volume-resources.yaml 通过文件将 Pod 信息呈现给容器 - 图2

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: kubernetes-downwardapi-volume-example-2
  5. spec:
  6. containers:
  7. - name: client-container
  8. image: registry.k8s.io/busybox:1.24
  9. command: ["sh", "-c"]
  10. args:
  11. - while true; do
  12. echo -en '\n';
  13. if [[ -e /etc/podinfo/cpu_limit ]]; then
  14. echo -en '\n'; cat /etc/podinfo/cpu_limit; fi;
  15. if [[ -e /etc/podinfo/cpu_request ]]; then
  16. echo -en '\n'; cat /etc/podinfo/cpu_request; fi;
  17. if [[ -e /etc/podinfo/mem_limit ]]; then
  18. echo -en '\n'; cat /etc/podinfo/mem_limit; fi;
  19. if [[ -e /etc/podinfo/mem_request ]]; then
  20. echo -en '\n'; cat /etc/podinfo/mem_request; fi;
  21. sleep 5;
  22. done;
  23. resources:
  24. requests:
  25. memory: "32Mi"
  26. cpu: "125m"
  27. limits:
  28. memory: "64Mi"
  29. cpu: "250m"
  30. volumeMounts:
  31. - name: podinfo
  32. mountPath: /etc/podinfo
  33. volumes:
  34. - name: podinfo
  35. downwardAPI:
  36. items:
  37. - path: "cpu_limit"
  38. resourceFieldRef:
  39. containerName: client-container
  40. resource: limits.cpu
  41. divisor: 1m
  42. - path: "cpu_request"
  43. resourceFieldRef:
  44. containerName: client-container
  45. resource: requests.cpu
  46. divisor: 1m
  47. - path: "mem_limit"
  48. resourceFieldRef:
  49. containerName: client-container
  50. resource: limits.memory
  51. divisor: 1Mi
  52. - path: "mem_request"
  53. resourceFieldRef:
  54. containerName: client-container
  55. resource: requests.memory
  56. divisor: 1Mi

在这个清单中,你可以看到 Pod 有一个 downwardAPI 卷, 并且这个卷会挂载到 Pod 内的单个容器的 /etc/podinfo 目录。

查看 downwardAPI 下面的 items 数组。 数组的每个元素定义一个 downwardAPI 卷。

第一个元素指定在名为 client-container 的容器中, 以 1m 所指定格式的 limits.cpu 字段的值应推送到名为 cpu_limit 的文件中。 divisor 字段是可选的,默认值为 1。1 的除数表示 CPU 资源的核数或内存资源的字节数。

创建 Pod:

  1. kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume-resources.yaml

打开一个 Shell,进入 Pod 中运行的容器:

  1. kubectl exec -it kubernetes-downwardapi-volume-example-2 -- sh

在 Shell 中,查看 cpu_limit 文件:

  1. # 在容器内的 Shell 中运行
  2. cat /etc/podinfo/cpu_limit

你可以使用同样的命令查看 cpu_requestmem_limitmem_request 文件。

投射键名到指定路径并且指定文件权限

你可以将键名投射到指定路径并且指定每个文件的访问权限。 更多信息,请参阅 Secret

接下来

  • 参阅 Pod spec API 的定义,其中包括了容器(Pod 的一部分)的定义。
  • 参阅你可以使用 downward API 公开的可用字段列表。

阅读旧版的 API 参考中关于卷的内容:

  • 参阅 Volume API 定义,该 API 在 Pod 中定义通用卷以供容器访问。
  • 参阅 DownwardAPIVolumeSource API 定义,该 API 定义包含 Downward API 信息的卷。
  • 参阅 DownwardAPIVolumeFile API 定义,该 API 包含对对象或资源字段的引用,用于在 Downward API 卷中填充文件。
  • 参阅 ResourceFieldSelector API 定义,该 API 指定容器资源及其输出格式。