3-10-3-使用Downward API向容器注入Pod信息

熊 0 阅读 容器

Kubernetes在创建Pod时 , 会为Pod和容器设置一些额外的信息 , 比如Pod名称、Pod IP、Node IP、Label、Annotation、资源限制等 , 我们经常会在应用程序中使用到这些数据 , 比如利用Pod名称作为应用日志的字段 , 方便分析日志。为了能在容器内获取这些信息 , 我们可以使用Downward API机制来实现。

Downward API可以通过环境变量和Volume挂载这两种方式将Pod信息注入容器 , 我们分别来看一下:

1. 可用字段

只有部分 Kubernetes API 字段可以通过 Downward API 使用。本节列出了你可以使用的字段。

你可以使用 fieldRef 传递来自可用的 Pod 级字段的信息。在 API 层面 , 一个 Pod 的 spec 总是定义了至少一个 Container。 你可以使用 resourceFieldRef 传递来自可用的 Container 级字段的信息。

1.1 可通过fieldRef获得的信息

对于大多数 Pod 级别的字段 , 你可以将它们作为环境变量或使用 downwardAPI 卷提供给容器。 通过这两种机制可用的字段有:

  • metadata.name : Pod的名称

  • metadata.namespace : Pod的命名空间

  • metadata.uid : Pod的唯一ID

  • metadata.annotations['<KEY>'] : Pod 的注解 <KEY> 的值(例如:metadata.annotations['myannotation'])

  • metadata.labels['<KEY>'] : Pod的标签<KEY> 的值 ( 例如:metadata.labels['mylabel'])

  • spec.serviceAccountName : Pod的服务账号名称

  • spec.nodeName : Pod运行时所处的节点名称

  • status.hostIP : Pod所在节点的主IP地址

  • status.podIP : Pod的主IP地址 ( 通常是其IPv4地址)

此外 , 以下信息可以通过 downwardAPI 卷 fieldRef 获得 , 但不能作为环境变量获得:

  • metadata.labels : Pod 的所有标签 , 格式为 标签键名="转义后的标签值" , 每行一个标签

  • metadata.annotations : Pod 的全部注解 , 格式为 注解键名="转义后的注解值" , 每行一个注解

1.2 可通过 resourceFieldRef 获得的信息

  • resource: limits.cpu : 容器的 CPU 限制值

  • resource: requests.cpu : 容器的 CPU 请求值

  • resource: limits.memory : 容器的内存限制值

  • resource: requests.memory : 容器的内存请求值

  • resource: limits.hugepages-* : 容器的巨页限制值 ( 前提是启用了 DownwardAPIHugePages 特性门控)

  • resource: requests.hugepages-* : 容器的巨页请求值 ( 前提是启用了 DownwardAPIHugePages 特性门控)

  • resource: limits.ephemeral-storage : 容器的临时存储的限制值

  • resource: requests.ephemeral-storage : 容器的临时存储的请求值

资源限制的后备信息

如果没有为容器指定 CPU 和内存限制时尝试使用 Downward API 暴露该信息 , 那么 kubelet 默认会根据 节点可分配资源计算并暴露 CPU 和内存的最大可分配值

2. 使用方式

2.1 环境变量方式

我们还是以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命令打印下输出:

root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl apply -f ./
pod/busybox-pod created
​
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl get pods 
NAME          READY   STATUS      RESTARTS   AGE
busybox-pod   0/1     Completed   0          36s
nginx-demo    1/1     Running     0          4h35m
nginx-demo2   1/1     Running     0          3h58m
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl logs busybox-pod 
VAR_MEM_REQUEST=16777216
VAR_NODE_NAME=k8s-node02.cbear.top
VAR_SERVICE_ACCOUNT=default
VAR_CPU_REQUEST=1
VAR_POD_NAME=busybox-pod
VAR_MEM_LIMIT=33554432
VAR_POD_NAMESPACE=default
VAR_POD_IP=172.20.4.56
VAR_CPU_LIMIT=1
​

2.2 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查看输出:

root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl apply -f busybox-pod-volume.yaml
pod/busybox-pod created
​
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl get pods 
NAME          READY   STATUS    RESTARTS   AGE
busybox-pod   1/1     Running   0          20s
nginx-demo    1/1     Running   0          4h42m
nginx-demo2   1/1     Running   0          4h5m
root@k8s-master01:/opt/k8s-data/yaml/downward# 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="2024-06-04T10:56:28.369423144Z"
kubernetes.io/config.source="api"
​
250
​
125
​
32
​
16
​

我们进入容器查看挂载的文件

root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl exec -it busybox-pod -- sh
​
/ # ls /etc/podinfo/
annotations  cpu_limit    cpu_request  labels       mem_limit    mem_request
​


参考链接

Downward API | Kubernetes (aluopy.cn)

Docker 与 K8S学习笔记(二十)—— 使用Downward API向容器注入Pod信息 (qq.com)