Kubernetes在创建Pod时,会为Pod和容器设置一些额外的信息,比如Pod名称、Pod IP、Node IP、Label、Annotation、资源限制等,我们经常会在应用程序中使用到这些数据,比如利用Pod名称作为应用日志的字段,方便分析日志。为了能在容器内获取这些信息,我们可以使用Downward API机制来实现。
Downward API可以通过环境变量和Volume挂载这两种方式将Pod信息注入容器,我们分别来看一下:
一、环境变量方式
我们还是以Busybox为例进行演示,我们将Pod信息和Container信息以环境变量方式注入容器,在容器启动后通过env命令打印出来,我们Yaml文件内容如下:
apiVersion: v1 kind: Pod metadata: name: busybox-pod spec: containers: - name: busybox image: busybox command: ["/bin/sh", "-c", "env | grep VAR_"] resources: requests: memory: "16Mi" cpu: "125m" limits: memory: "32Mi" cpu: "250m" env: - name: VAR_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName - name: VAR_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: VAR_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: VAR_POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: VAR_SERVICE_ACCOUNT valueFrom: fieldRef: fieldPath: spec.serviceAccountName - name: VAR_CPU_REQUEST valueFrom: resourceFieldRef: containerName: busybox resource: requests.cpu - name: VAR_CPU_LIMIT valueFrom: resourceFieldRef: containerName: busybox resource: limits.cpu - name: VAR_MEM_REQUEST valueFrom: resourceFieldRef: containerName: busybox resource: requests.memory - name: VAR_MEM_LIMIT valueFrom: resourceFieldRef: containerName: busybox resource: limits.memory restartPolicy: Never
我们创建Pod并使用kubtctl logs命令打印下输出:
$ sudo kubectl apply -f busy_pod.yaml pod/busybox-pod created $ sudo kubectl logs busybox-pod VAR_MEM_REQUEST=16777216 # 容器内存请求值 VAR_NODE_NAME=ayato # 节点名称 VAR_SERVICE_ACCOUNT=default # Pod使用的ServiceAccount名称 VAR_CPU_REQUEST=1 # 容器cpu请求值 VAR_POD_NAME=busybox-pod # pod名称 VAR_MEM_LIMIT=33554432 # 容器内存限制值 VAR_POD_NAMESPACE=default # Pod所在命名空间 VAR_POD_IP=172.17.0.6 # Pod ip地址 VAR_CPU_LIMIT=1 # 容器cpu请求值
二、Volume挂载方式
我们接下来尝试使用Volume挂载方式,将Pod信息注入容器。还是以Busybox为例,由于Pod信息都是以文件方式注入容器,所以我们修改容器启动后执行命令:我们使用cat不断打印注入的文件,修改后的Yaml文件如下:
apiVersion: v1 kind: Pod metadata: name: busybox-pod labels: cluster: demo-cluster type: tool-pod annotations: builder: alalazy spec: containers: - name: busybox image: busybox command: ["/bin/sh", "-c"] args: - while true; do if [[ -e /etc/podinfo/labels ]]; then echo -en '\n\n'; cat /etc/podinfo/labels; fi; if [[ -e /etc/podinfo/annotations ]]; then echo -en '\n\n'; cat /etc/podinfo/annotations; fi; if [[ -e /etc/podinfo/cpu_limit ]]; then echo -en '\n\n'; cat /etc/podinfo/cpu_limit; fi; if [[ -e /etc/podinfo/cpu_request ]]; then echo -en '\n\n'; cat /etc/podinfo/cpu_request; fi; if [[ -e /etc/podinfo/mem_limit ]]; then echo -en '\n\n'; cat /etc/podinfo/mem_limit; fi; if [[ -e /etc/podinfo/mem_request ]]; then echo -en '\n\n'; cat /etc/podinfo/mem_request; fi; sleep 5; done; volumeMounts: - name: podinfo mountPath: /etc/podinfo resources: requests: memory: "16Mi" cpu: "125m" limits: memory: "32Mi" cpu: "250m" volumes: - name: podinfo downwardAPI: items: - path: "labels" fieldRef: fieldPath: metadata.labels - path: "annotations" fieldRef: fieldPath: metadata.annotations - path: "cpu_limit" resourceFieldRef: containerName: busybox resource: limits.cpu divisor: 1m - path: "cpu_request" resourceFieldRef: containerName: busybox resource: requests.cpu divisor: 1m - path: "mem_limit" resourceFieldRef: containerName: busybox resource: limits.memory divisor: 1Mi - path: "mem_request" resourceFieldRef: containerName: busybox resource: requests.memory divisor: 1Mi
我们创建此Pod,并通过kubectl logs查看输出:
$ sudo kubectl apply -f busy_pod.yaml pod/busybox-pod created $ sudo kubectl logs busybox-pod cluster="demo-cluster" type="tool-pod" builder="alalazy" kubectl.kubernetes.io/last-applied-configuration="{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"builder\":\"alalazy\"},\"labels\":{\"cluster\":\"demo-cluster\",\"type\":\"tool-pod\"},\"name\":\"busybox-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"while true; do if [[ -e /etc/podinfo/labels ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/labels; fi; if [[ -e /etc/podinfo/annotations ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/annotations; fi; if [[ -e /etc/podinfo/cpu_limit ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/cpu_limit; fi; if [[ -e /etc/podinfo/cpu_request ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/cpu_request; fi; if [[ -e /etc/podinfo/mem_limit ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/mem_limit; fi; if [[ -e /etc/podinfo/mem_request ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/mem_request; fi; sleep 5; done;\"],\"command\":[\"/bin/sh\",\"-c\"],\"image\":\"busybox\",\"name\":\"busybox\",\"resources\":{\"limits\":{\"cpu\":\"250m\",\"memory\":\"32Mi\"},\"requests\":{\"cpu\":\"125m\",\"memory\":\"16Mi\"}},\"volumeMounts\":[{\"mountPath\":\"/etc/podinfo\",\"name\":\"podinfo\"}]}],\"volumes\":[{\"downwardAPI\":{\"items\":[{\"fieldRef\":{\"fieldPath\":\"metadata.labels\"},\"path\":\"labels\"},{\"fieldRef\":{\"fieldPath\":\"metadata.annotations\"},\"path\":\"annotations\"},{\"path\":\"cpu_limit\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1m\",\"resource\":\"limits.cpu\"}},{\"path\":\"cpu_request\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1m\",\"resource\":\"requests.cpu\"}},{\"path\":\"mem_limit\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1Mi\",\"resource\":\"limits.memory\"}},{\"path\":\"mem_request\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1Mi\",\"resource\":\"requests.memory\"}}]},\"name\":\"podinfo\"}]}}\n" kubernetes.io/config.seen="2022-01-15T05:33:53.379386410Z" kubernetes.io/config.source="api" 250 125 32 16
我们进入容器查看下挂载的文件:
$ sudo kubectl exec -it busybox-pod -- sh / # cd /etc/podinfo/ /etc/podinfo # ls annotations cpu_limit cpu_request labels mem_limit mem_request
三、Downward API的能力
我们可以通过Downward API向容器注入如下信息:
1)可通过fieldRef获得的信息:
-
metadata.name:Pod 名称
-
metadata.namespace:Pod 名字空间
-
metadata.uid:Pod 的 UID
-
metadata.labels['<KEY>']:Pod标签 <KEY> 的值 (例如, metadata.labels['mylabel'])
-
metadata.annotations['<KEY>']:Pod 的注解 <KEY> 的值(例如, metadata.annotations['myannotation'])
-
metadata.labels:获取所有标签
-
metadata.annotations:获取所有注解
-
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
2)可通过 resourceFieldRef 获得的信息:
-
容器的 CPU 约束值
-
容器的 CPU 请求值
-
容器的内存约束值
-
容器的内存请求值
-
容器的巨页限制值(前提是启用了DownwardAPIHugePages 特性门控)
-
容器的巨页请求值(前提是启用了DownwardAPIHugePages 特性门控)
-
容器的临时存储约束值
-
容器的临时存储请求值