我们都知道,Pod的逻辑概念在容器之上,K8s 在成功创建Pod之后,会为Pod和容器设置一些额外的信息,例如Pod级别的Pod 名称,Pod IP ,Label,Annotation,容器级别的资源限制等。

在很多应用场景中,这些信息对容器内的应用来说都很有用,例如使用Pod名称作为日志记录的一个字段用于标识日志来源,为了在容器内获取Pod级别的这些信息,k8s 提供了Downward API 机制来将Pod 和容器的某些元数据信息注入容器环境内,供容器应用方便地使用。

Downward API 可以通过以下两种方式将Pod 和容器的元数据信息注入容器内部。
(1)环境变量:将Pod或Container信息设置为容器内的环境变量。
(2)Volume挂载:将Pod或Container信息以文件的形式挂载到容器内部。

下面通过例子对Downward API 的用法进行说明。

一. 环境变量方式
通过环境变量的方式可以将Pod 信息或Container 信息注入容器运行环境中,下面通过两个例子进行说明。

  1. 将Pod 信息设置为容器内的环境变量
    下面的例子通过Downward API 将Pod 的IP,名称和所在命名空间注入容器的环境变量中,Pod 的yaml 文件如下:
# dapi-envars-pod.yaml
apiVersion: v1
kind: Pod
metadata: 
  name: dapi-envars-fieldref
spec: 
  containers:
   - name: test-container
     image: busybox
     command: ["sh","-c"]
     args:
     - while true; do
        echo -en '\n';
        printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
        printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
        sleep 10;
       done;
     env: 
      - name: MY_NODE_NAME
        valueFrom: 
          fieldRef: 
            fieldPath: spec.nodeName
      - name: MY_POD_NAME
        valueFrom: 
          fieldRef: 
            fieldPath: metadata.name
      - name: MY_POD_NAMESPACE
        valueFrom: 
          fieldRef: 
            fieldPath: metadata.namespace
      - name: MY_POD_IP
        valueFrom: 
          fieldRef: 
            fieldPath: status.podIP
      - name: MY_POD_SERVICE_ACCOUNT
        valueFrom: 
          fieldRef: 
            fieldPath: spec.serviceAccountName
  restartPolicy: Never

注意,环境变量不直接设置value,而是设置valueFrom 对Pod 的元数据进行引用。
在本例中通过会Downward API 的设置使用了以下Pod 的元数据信息设置环境变量。
(1) spec.nodeName: Pod 所在Node 的名称。
(2)metadata.name: Pod 名称。
(3)metadata.namespace:Pod所在命名空间的名称。
(4)status.podIP:Pod的IP地址。
(5)spec.serviceAccountName:Pod 使用的ServiceAccount名称。

运行kubectl create 命令创建这个Pod:

[root@k8s-master ~]# kubectl create -f dapi-envars-pod.yaml 
pod/dapi-envars-fieldref created

查看Pod的日志,可以看到容器启动命令将环境变量的值打印出来:

[root@k8s-master ~]# kubectl logs dapi-envars-fieldref

k8s-node-1
dapi-envars-fieldref
default
10.244.109.86
default
.......

我们从日志中可以看到Pod 的Node IP ,Pod名称,命名空间名称,Pod IP ServiceAccount 名称等信息都被正确设置到了容器的环境变量中。

也可以通过kubectl exec 命令登陆容器查看环境变量的设置:

[root@k8s-master ~]# kubectl  exec -it dapi-envars-fieldref -- sh
/ # printenv | grep MY
MY_POD_SERVICE_ACCOUNT=default
MY_POD_NAMESPACE=default
MY_POD_IP=10.244.109.86
MY_NODE_NAME=k8s-node-1
MY_POD_NAME=dapi-envars-fieldref
......其pod的环境变量
  1. 将Container 信息设置为容器内的环境变量
    下面的例子通过Downward API 将Container 的资源请求和资源限制信息设置为容器内的环境变量,Pod 的yaml文件内容如下:
# dapi-envars-container.yaml

apiVersion: v1
kind: Pod
metadata: 
  name: dapi-envars-resourcefieldref
spec: 
  containers: 
    - name: test-container
      image: busybox
      imagePullPolicy: Never
      command: ["sh","-c"]
      args: 
      - while true; do
         echo -en '\n';
         printenv MY_CPU_REQUEST MY_CPU_LIMIT;
         printenv MY_MEM_REQUEST MY_MEM_LIMIT;
         sleep 10;
        done;
      args: 
      - while true; do
         echo -en '\n';
         printenv MY_CPU_REQUEST MY_CPU_LIMIT;
         printenv MY_MEM_REQUEST MY_MEM_LIMIT;
         sleep 3600;
        done;
      resources: 
        requests: 
           memory: "32Mi"
           cpu: "125m"
        limits: 
           memory: "64Mi"
           cpu: "250m"
      env: 
        - name: MY_CPU_REQUEST
          valueFrom: 
            resourceFieldRef: 
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom: 
            resourceFieldRef: 
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom: 
            resourceFieldRef: 
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom: 
            resourceFieldRef: 
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never   

在本例中通过Downward API 将以下Container 的资源限制信息设置为环境变量。
(1)requests.cpu: 容器的cpu请求值。
(2)limits.cpu: 容器的cpu限制值。
(3)requests.memory: 容器的内存请求值。
(4)limits.memory: 容器的内存限制值。

运行kubectl create 命令创建Pod:

[root@k8s-master ~]# kubectl create -f dapi-envars-container.yaml
pod/dapi-envars-resourcefieldref created

查看Pod日志:

[root@k8s-master ~]# kubectl  logs dapi-envars-resourcefieldref

1
1
33554432
67108864

我们从日志中可以看到 Container 的 requests.cpu,limits,cpu,requests.memory,limits.memory 等信息都被正确保存到了容器的环境变量中。

二. Volume挂载方式
通过Volume 挂载方式可以将Pod 信息或Container 信息挂载为容器内的文件,下面通过例子进行说明。

  1. 将Pod信息挂载为容器内的文件
    下面的例子通过Downward API 将Pod 的Label,Annotation 信息通过Volume挂载为容器中的文件:
# dapi-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example
  labels: 
    zone: us-est-coast
    cluster: test-cluster
    rack: rack-22
  annotations:
    build: two
    builder: john-doe
spec: 
  containers:
    - name: client-container
      image: busybox
      command: ["sh","-c"]
      args: 
      - while true; do
          if [[ -e /etc/podinfo/labels ]]; then
             echo -en '\n\n'; /etc/podinfo/labels; fi;
          if [[ -e /etc/podinfo/annotations ]]; then
             echo -en '\n\n'; /etc/podinfo/annotations; fi;
          sleep 5;
        done;
      volumeMounts: 
      - name: podinfo
        mountPath: /etc/podinfo
  volumes: 
    - name: podinfo
      downwardAPI: 
        items: 
          - path: "labels"
            fieldRef: 
              fieldPath: metadata.labels
          - path: "annotations"
            fieldRef: 
              fieldPath: metadata.annotations

在Pod 的 volumes 字段中使用Downward API 的方法: 通过fieldRef 字段设置需要引用Pod 的元数据信息,将其设置到volume 的items 中,在本例中使用了以下Pod 元数据信息:
(1)metadata.labels: Pod 的Label 列表。
(2)metadata.annotations: Pod 的Annotation 列表。

然后,通过容器级别volumeMounts 的设置,系统会基于volume 中item 的path 名称生成文件。根据上面的设置,系统将在容器内的/etc/podinfo,目录下生成labels 和annotations两个文件,在labels 文件中将包含Pod 的全部Label 列表,在annotations文件中将包含Pod 的全部Annotation 列表。

运行kubectl create 命令创建Pod:

[root@k8s-master ~]# kubectl create -f dapi-volume.yaml 
pod/kubernetes-downwardapi-volume-example created

进入容器查看挂载的文件:

[root@k8s-master ~]# kubectl exec -it kubernetes-downwardapi-volume-example  -- sh
/ # ls -l /etc/podinfo/
total 0
lrwxrwxrwx    1 root     root            18 Feb 19 05:49 annotations -> ..data/annotations
lrwxrwxrwx    1 root     root            13 Feb 19 05:49 labels -> ..data/labels
/ # cat /etc/podinfo/labels 
cluster="test-cluster"
rack="rack-22"
/ # cat /etc/podinfo/annotations
build="two"
builder="john-doe"
cni.projectcalico.org/containerID="81d9ae3d027ad163683db9580053106270e8d7cce5ef19214620f39ecc4c2cd9"
cni.projectcalico.org/podIP="10.244.140.87/32"
cni.projectcalico.org/podIPs="10.244.140.87/32"
kubernetes.io/config.seen="2022-02-19T13:49:48.645023277+08:00"
kubernetes.io/config.source="api"
  1. 将Container信息挂载为容器内的文件
    下面的例子通过DownWard API 将Container 的资源限制信息通过Volume挂载为容器中的文件:
#  dapi-volume-resources.yaml
apiVersion: v1
kind: Pod
metadata: 
  name: kubernetes-downwardapi-volume-example-2
spec: 
  containers: 
    - name: client-container
      image: busybox
      command: ["sh","-c"]
      args: 
      - while true; do
          echo -en '\n';
          if [[ -e /etc/podinfo/cpu_limit ]]; then
            echo -en '\n'; cat /etc/podinfo/cpu_limit; fi;
          if [[ -e /etc/podinfo/cpu_request ]]; then
            echo -en '\n'; cat /etc/podinfo/cpu_request; fi;
          if [[ -e /etc/podinfo/mem_limit ]]; then
            echo -en '\n'; cat /etc/podinfo/mem_limit; fi;
          if [[ -e /etc/podinfo/mem_request ]]; then
            echo -en '\n'; cat /etc/podinfo/mem_request; fi;  
          sleep 5;
        done;
      resources: 
        requests: 
          memory: "32Mi"
          cpu: "125m"
        limits: 
          memory: "64Mi"
          cpu: "250m"
      volumeMounts: 
      - name: podinfo
        mountPath: /etc/podinfo
  volumes: 
    - name: podinfo
      downwardAPI: 
        items: 
          - path: "cpu_limit"
            resourceFieldRef: 
              containerName: client-container
              resource: limits.cpu
              divisor: 1m
          - path: "cpu_request"
            resourceFieldRef: 
              containerName: client-container
              resource: requests.cpu
              divisor: 1m 
          - path: "mem_limit"
            resourceFieldRef: 
              containerName: client-container
              resource: limits.memory
              divisor: 1Mi
          - path: "mem_request"
            resourceFieldRef: 
              containerName: client-container
              resource: requests.memory
              divisor: 1Mi

在本例中通过Downward API 设置将以下Container的资源限制信息设置到Volume中。
(1)requests.cpu : 容器的cpu请求值。
(2)limits.cpu: 容器的cpu限制值。
(3)requests.memory: 容器的内存请求值。
(4)limits.memory: 容器的内存限制值。

运行kubectl create 命令创建Pod:

[root@k8s-master ~]# kubectl create -f dapi-volume-resources.yaml
pod/kubernetes-downwardapi-volume-example-2 created

进入容器,查看挂载的文件:

[root@k8s-master ~]# kubectl exec -it kubernetes-downwardapi-volume-example-2 -- sh
/ # ls -l /etc/podinfo
total 0
lrwxrwxrwx    1 root     root            16 Feb 19 06:13 cpu_limit -> ..data/cpu_limit
lrwxrwxrwx    1 root     root            18 Feb 19 06:13 cpu_request -> ..data/cpu_request
lrwxrwxrwx    1 root     root            16 Feb 19 06:13 mem_limit -> ..data/mem_limit
lrwxrwxrwx    1 root     root            18 Feb 19 06:13 mem_request -> ..data/mem_request
/ # cat /etc/podinfo/cpu_limit
250
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐