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

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

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

要获知版本信息,请输入 kubectl version.

Downward API

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

这两种呈现Pod和Container字段的方式都称为*Downward API*。

存储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: k8s.gcr.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有一个downwardAPI类型的Volume,并且挂载到容器中的/etc

查看downwardAPI下面的items数组。每个数组元素都是一个DownwardAPIVolumeFile。 第一个元素指示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

输出显示 labelsannotations 文件的内容:

  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/labels

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

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

同样,查看annotations文件:

  1. /# cat /etc/annotations

查看/etc目录下的文件:

  1. /# ls -laR /etc

在输出中可以看到,labelsannotations文件都在一个临时子目录中:这个例子,..2019_12_05_07_00_34.813117769。在/etc目录中,..data是一个指向临时子目录 的符号链接。/etc目录中,labelsannotations也是符号链接。

  1. /etc/podinfo # ls -alRL
  2. .:
  3. total 8
  4. drwxrwxrwt 3 root root 120 Dec 5 07:00 .
  5. drwxr-xr-x 1 root root 21 Dec 5 07:00 ..
  6. drwxr-xr-x 2 root root 80 Dec 5 07:00 ..2019_12_05_07_00_34.813117769
  7. drwxr-xr-x 2 root root 80 Dec 5 07:00 ..data
  8. -rw-r--r-- 1 root root 1123 Dec 5 07:00 annotations
  9. -rw-r--r-- 1 root root 39 Dec 5 07:00 labels
  10. ./..2019_12_05_07_00_34.813117769:
  11. total 8
  12. drwxr-xr-x 2 root root 80 Dec 5 07:00 .
  13. drwxrwxrwt 3 root root 120 Dec 5 07:00 ..
  14. -rw-r--r-- 1 root root 1123 Dec 5 07:00 annotations
  15. -rw-r--r-- 1 root root 39 Dec 5 07:00 labels
  16. ./..data:
  17. total 8
  18. drwxr-xr-x 2 root root 80 Dec 5 07:00 .
  19. drwxrwxrwt 3 root root 120 Dec 5 07:00 ..
  20. -rw-r--r-- 1 root root 1123 Dec 5 07:00 annotations
  21. -rw-r--r-- 1 root root 39 Dec 5 07:00 labels

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

退出shell:

  1. /# exit

存储容器字段

前面的练习中,你将Pod字段保存到DownwardAPIVolumeFile中。接下来这个练习,你将存储容器字段。这里是包含一个容器的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: k8s.gcr.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类型的Volume,并且挂载到容器的/etc目录。

查看downwardAPI下面的items数组。每个数组元素都是一个DownwardAPIVolumeFile。

第一个元素指定名为client-container的容器中limits.cpu字段的值应保存在名为cpu_limit的文件中。

创建Pod:

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

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

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

在shell中,查看cpu_limit文件:

  1. /# cat /etc/cpu_limit

你可以使用同样的命令查看cpu_request, mem_limitmem_request 文件.

Capabilities of the Downward API

下面这些信息可以通过环境变量和DownwardAPIVolumeFiles提供给容器:

能通过fieldRef获得的: * metadata.name - Pod名称 * metadata.namespace - Pod名字空间 * metadata.uid - Pod的UID, 版本要求 v1.8.0-alpha.2 * metadata.labels['<KEY>'] - 单个 pod 标签值 <KEY> (例如, metadata.labels['mylabel']); 版本要求 Kubernetes 1.9+ * metadata.annotations['<KEY>'] - 单个 pod 的标注值 <KEY> (例如, metadata.annotations['myannotation']); 版本要求 Kubernetes 1.9+

能通过resourceFieldRef获得的: * 容器的CPU约束值 * 容器的CPU请求值 * 容器的内存约束值 * 容器的内存请求值 * 容器的临时存储约束值, 版本要求 v1.8.0-beta.0 * 容器的临时存储请求值, 版本要求 v1.8.0-beta.0

此外,以下信息可通过DownwardAPIVolumeFiles从fieldRef获得:

  • metadata.labels - all of the pod’s labels, formatted as label-key="escaped-label-value" with one label per line
  • metadata.annotations - all of the pod’s annotations, formatted as annotation-key="escaped-annotation-value" with one annotation per line
  • metadata.labels - 所有Pod的标签,以label-key="escaped-label-value"格式显示,每行显示一个label
  • metadata.annotations - Pod的注释,以annotation-key="escaped-annotation-value"格式显示,每行显示一个标签

以下信息可通过环境变量从fieldRef获得:

  • 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

注意: 如果容器未指定CPU和memory limits,则Downward API默认为节点可分配值。

投射密钥到指定路径并且指定文件权限

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

Downward API的动机

对于容器来说,有时候拥有自己的信息是很有用的,可避免与Kubernetes过度耦合。Downward API使得容器使用自己或者集群的信息,而不必通过Kubernetes客户端或API服务器。

一个例子是有一个现有的应用假定要用一个非常熟悉的环境变量来保存一个唯一标识。一种可能是给应用增加处理层,但这样是冗余和易出错的,而且它违反了低耦合的目标。更好的选择是使用Pod名称作为标识,把Pod名称注入这个环境变量中。

接下来