Docker 與 K8S學習筆記(二十)—— 使用Downward API向容器注入Pod資訊

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 特性門控

  • 容器的臨時存儲約束值

  • 容器的臨時存儲請求值