此页面描述Pod如何使用DownwardAPIVolumeFile把自己的信息呈现给pod中运行的容器。DownwardAPIVolumeFile可以呈现pod的字段和容器字段。

Before you begin

You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using Minikube, or you can use one of these Kubernetes playgrounds:

To check the version, enter kubectl version.

Downward API

有两种方式可以将Pod和Container字段呈现给运行中的容器:

这两种呈现Pod和Container字段的方式都称为Downward API

存储Pod字段

在这个练习中,你将创建一个包含一个容器的pod。这是该pod的配置文件:

dapi-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example
  labels:
    zone: us-est-coast
    cluster: test-cluster1
    rack: rack-22
  annotations:
    build: two
    builder: john-doe
spec:
  containers:
    - name: client-container
      image: gcr.io/google_containers/busybox
      command: ["sh", "-c"]
      args:
      - while true; do
          if [[ -e /etc/labels ]]; then 
            echo -en '\n\n'; cat /etc/labels; fi;
          if [[ -e /etc/annotations ]]; then
            echo -en '\n\n'; cat /etc/annotations; fi;
          sleep 5;
        done;
      volumeMounts:
        - name: podinfo
          mountPath: /etc
          readOnly: false
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "labels"
            fieldRef:
              fieldPath: metadata.labels
          - path: "annotations"
            fieldRef:
              fieldPath: metadata.annotations

在配置文件中,你可以看到Pod有一个downwardAPI类型的Volume,并且挂载到容器中的/etc

查看downwardAPI下面的items数组。每个数组元素都是一个DownwardAPIVolumeFile。 第一个元素指示Pod的metadata.labels字段的值保存在名为labels的文件中。 第二个元素指示Pod的annotations字段的值保存在名为annotations的文件中。

注意: 本示例中的字段是Pod字段,不是Pod中容器的字段。

创建Pod:

kubectl create -f https://k8s.io/cn/docs/tasks/inject-data-application/dapi-volume.yaml

验证Pod中的容器运行正常:

kubectl get pods

查看容器的日志:

kubectl logs kubernetes-downwardapi-volume-example

输出显示labelsannotations文件的内容:

cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"

build="two"
builder="john-doe"

进入Pod中运行的容器,打开一个shell:

kubectl exec -it kubernetes-downwardapi-volume-example -- sh

在该shell中,查看labels文件:

/# cat /etc/labels

输出显示Pod的所有labels都已写入labels文件。

cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"

同样,查看annotations文件:

/# cat /etc/annotations

查看/etc目录下的文件:

/# ls -laR /etc

在输出中可以看到,labelsannotations文件都在一个临时子目录中:这个例子,..2982_06_02_21_47_53.299460680。在/etc目录中,..data是一个指向临时子目录 的符号链接。/etc目录中,labelsannotations也是符号链接。

drwxr-xr-x  ... Feb 6 21:47 ..2982_06_02_21_47_53.299460680
lrwxrwxrwx  ... Feb 6 21:47 ..data -> ..2982_06_02_21_47_53.299460680
lrwxrwxrwx  ... Feb 6 21:47 annotations -> ..data/annotations
lrwxrwxrwx  ... Feb 6 21:47 labels -> ..data/labels

/etc/..2982_06_02_21_47_53.299460680:
total 8
-rw-r--r--  ... Feb  6 21:47 annotations
-rw-r--r--  ... Feb  6 21:47 labels

用符号链接可实现元数据的动态原子刷新;更新将写入一个新的临时目录,然后..data符号链接完成原子更新,通过使用rename(2)

退出shell:

/# exit

存储容器字段

前面的练习中,你将Pod字段保存到DownwardAPIVolumeFile中。接下来这个练习,你将存储容器字段。这里是包含一个容器的pod的配置文件:

dapi-volume-resources.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubernetes-downwardapi-volume-example-2
spec:
  containers:
    - name: client-container
      image: gcr.io/google_containers/busybox:1.24
      command: ["sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          if [[ -e /etc/cpu_limit ]]; then
            echo -en '\n'; cat /etc/cpu_limit; fi;
          if [[ -e /etc/cpu_request ]]; then
            echo -en '\n'; cat /etc/cpu_request; fi;
          if [[ -e /etc/mem_limit ]]; then
            echo -en '\n'; cat /etc/mem_limit; fi;
          if [[ -e /etc/mem_request ]]; then
            echo -en '\n'; cat /etc/mem_request; fi;
          sleep 5;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      volumeMounts:
        - name: podinfo
          mountPath: /etc
          readOnly: false
  volumes:
    - name: podinfo
      downwardAPI:
        items:
          - path: "cpu_limit"
            resourceFieldRef:
              containerName: client-container
              resource: limits.cpu
          - path: "cpu_request"
            resourceFieldRef:
              containerName: client-container
              resource: requests.cpu
          - path: "mem_limit"
            resourceFieldRef:
              containerName: client-container
              resource: limits.memory
          - path: "mem_request"
            resourceFieldRef:
              containerName: client-container
              resource: requests.memory

在这个配置文件中,你可以看到Pod有一个downwardAPI类型的Volume,并且挂载到容器的/etc目录。

查看downwardAPI下面的items数组。每个数组元素都是一个DownwardAPIVolumeFile。

第一个元素指定名为client-container的容器中limits.cpu字段的值应保存在名为cpu_limit的文件中。

创建Pod:

kubectl create -f https://k8s.io/cn/docs/tasks/inject-data-application/dapi-volume-resources.yaml

进入Pod中运行的容器,打开一个shell:

kubectl exec -it kubernetes-downwardapi-volume-example-2 -- sh

在shell中,查看cpu_limit文件:

/# cat /etc/cpu_limit

你可以使用同样的命令查看cpu_request, mem_limitmem_request 文件.

Capabilities of the Downward API

下面这些信息可以通过环境变量和DownwardAPIVolumeFiles提供给容器:

此外,以下信息可通过DownwardAPIVolumeFiles获得:

Note: 如果容器未指定CPU和memory limits,则Downward API默认为节点可分配值。

投射密钥到指定路径并且指定文件权限

你可以将密钥投射到指定路径并且指定每个文件的访问权限。更多信息,请参阅Secrets.

Downward API的动机

对于容器来说,有时候拥有自己的信息是很有用的,可避免与Kubernetes过度耦合。Downward API使得容器使用自己或者集群的信息,而不必通过Kubernetes客户端或API服务器。

一个例子是有一个现有的应用假定要用一个非常熟悉的环境变量来保存一个唯一标识。一种可能是给应用增加处理层,但这样是冗余和易出错的,而且它违反了低耦合的目标。更好的选择是使用Pod名称作为标识,把Pod名称注入这个环境变量中。

What’s next