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 特性門控)
-
容器的臨時儲存約束值
-
容器的臨時儲存請求值