k8s Downward API

Downward API

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

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

用Pod字段作为环境变量的值

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

kind: Pod
metadata:
  name: dapi-envars-fieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '
';
          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

这个配置文件中,你可以看到五个环境变量。env字段是一个EnvVars类型的数组。 数组中第一个元素指定MY_NODE_NAME这个环境变量从Pod的spec.nodeName字段获取变量值。同样,其它环境变量也是从Pod的字段获取它们的变量值。

说明: 本示例中的字段是Pod字段,不是Pod中容器的字段。

创建Pod:

kubectl apply -f https://k8s.io/examples/pods/inject/dapi-envars-pod.yaml

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

kubectl get pods

查看容器日志:

kubectl logs dapi-envars-fieldref

输出信息显示了所选择的环境变量的值:

minikube
dapi-envars-fieldref
default
172.17.0.4
default

要了解为什么这些值在日志中,请查看配置文件中的command 和 args字段。 当容器启动时,它将五个环境变量的值写入stdout。每十秒重复执行一次。

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

kubectl exec -it dapi-envars-fieldref -- sh

在shell中,查看环境变量:

/# printenv

输出信息显示环境变量已经指定为Pod的字段的值。

MY_POD_SERVICE_ACCOUNT=default
...
MY_POD_NAMESPACE=default
MY_POD_IP=172.17.0.4
...
MY_NODE_NAME=minikube
...
MY_POD_NAME=dapi-envars-fieldref

用容器字段作为环境变量的值

前面的练习中,你将Pod字段作为环境变量的值。接下来这个练习,你将用容器字段作为环境变量的值。这里是包含一个容器的pod的配置文件:


apiVersion: v1 kind: Pod metadata: name: dapi
-envars-resourcefieldref spec: containers: - name: test-container image: k8s.gcr.io/busybox:1.24 command: [ "sh", "-c"] args: - while true; do echo -en ' '; printenv MY_CPU_REQUEST MY_CPU_LIMIT; printenv MY_MEM_REQUEST MY_MEM_LIMIT; sleep 10; 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

这个配置文件中,你可以看到四个环境变量。env字段是一个EnvVars 类型的数组。数组中第一个元素指定MY_CPU_REQUEST这个环境变量从容器的requests.cpu字段获取变量值。同样,其它环境变量也是从容器的字段获取它们的变量值。

创建Pod:

kubectl apply -f https://k8s.io/examples/pods/inject/dapi-envars-container.yaml

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

kubectl get pods

查看容器日志:

kubectl logs dapi-envars-resourcefieldref

输出信息显示了所选择的环境变量的值:

1
1
33554432
67108864

 

存储Pod字段

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


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: k8s.gcr.io/busybox command: ["sh", "-c"] args: - while true; do if [[ -e /etc/podinfo/labels ]]; then echo -en ' '; cat /etc/podinfo/labels; fi; if [[ -e /etc/podinfo/annotations ]]; then echo -en ' '; cat /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有一个downwardAPI类型的Volume,并且挂载到容器中的/etc

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

说明: 本示例中的字段是Pod字段,不是Pod中容器的字段。

创建 Pod:

kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume.yaml

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

kubectl get pods

查看容器的日志:

kubectl logs kubernetes-downwardapi-volume-example

输出显示 labels 和 annotations 文件的内容:

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

在输出中可以看到,labels 和 annotations文件都在一个临时子目录中:这个例子,..2019_12_05_07_00_34.813117769。在/etc目录中,..data是一个指向临时子目录 的符号链接。/etc目录中,labels 和 annotations也是符号链接。

/etc/podinfo # ls -alRL 
.:
total 8
drwxrwxrwt    3 root     root           120 Dec  5 07:00 .
drwxr-xr-x    1 root     root            21 Dec  5 07:00 ..
drwxr-xr-x    2 root     root            80 Dec  5 07:00 ..2019_12_05_07_00_34.813117769
drwxr-xr-x    2 root     root            80 Dec  5 07:00 ..data
-rw-r--r--    1 root     root          1123 Dec  5 07:00 annotations
-rw-r--r--    1 root     root            39 Dec  5 07:00 labels

./..2019_12_05_07_00_34.813117769:
total 8
drwxr-xr-x    2 root     root            80 Dec  5 07:00 .
drwxrwxrwt    3 root     root           120 Dec  5 07:00 ..
-rw-r--r--    1 root     root          1123 Dec  5 07:00 annotations
-rw-r--r--    1 root     root            39 Dec  5 07:00 labels

./..data:
total 8
drwxr-xr-x    2 root     root            80 Dec  5 07:00 .
drwxrwxrwt    3 root     root           120 Dec  5 07:00 ..
-rw-r--r--    1 root     root          1123 Dec  5 07:00 annotations
-rw-r--r--    1 root     root            39 Dec  5 07:00 labels

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

退出shell:

/# exit

存储容器字段

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


apiVersion: v1 kind: Pod metadata: name: kubernetes
-downwardapi-volume-example-2 spec: containers: - name: client-container image: k8s.gcr.io/busybox:1.24 command: ["sh", "-c"] args: - while true; do echo -en ' '; if [[ -e /etc/podinfo/cpu_limit ]]; then echo -en ' '; cat /etc/podinfo/cpu_limit; fi; if [[ -e /etc/podinfo/cpu_request ]]; then echo -en ' '; cat /etc/podinfo/cpu_request; fi; if [[ -e /etc/podinfo/mem_limit ]]; then echo -en ' '; cat /etc/podinfo/mem_limit; fi; if [[ -e /etc/podinfo/mem_request ]]; then echo -en ' '; 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

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

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

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

创建Pod:

kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume-resources.yaml

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

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

在shell中,查看cpu_limit文件:

/# cat /etc/cpu_limit

你可以使用同样的命令查看cpu_requestmem_limit 和mem_request 文件.

Capabilities of the Downward API

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

能通过fieldRef获得的:

  • metadata.name - Pod名称
  • metadata.namespace - Pod名字空间
  • metadata.uid - Pod的UID, 版本要求 v1.8.0-alpha.2
  • metadata.labels['<KEY>'] - 单个 pod 标签值 <KEY> (例如, metadata.labels['mylabel']); 版本要求 Kubernetes 1.9+
  • metadata.annotations['<KEY>'] - 单个 pod 的标注值 <KEY> (例如, metadata.annotations['myannotation']); 版本要求 Kubernetes 1.9+

能通过resourceFieldRef获得的:

  • 容器的CPU约束值
  • 容器的CPU请求值
  • 容器的内存约束值
  • 容器的内存请求值
  • 容器的临时存储约束值, 版本要求 v1.8.0-beta.0
  • 容器的临时存储请求值, 版本要求 v1.8.0-beta.0

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

  • metadata.labels - all of the pod’s labels, formatted as label-key="escaped-label-value" with one label per line
  • metadata.annotations - all of the pod’s annotations, formatted as annotation-key="escaped-annotation-value" with one annotation per line
  • metadata.labels - 所有Pod的标签,以label-key="escaped-label-value"格式显示,每行显示一个label
  • metadata.annotations - Pod的注释,以annotation-key="escaped-annotation-value"格式显示,每行显示一个标签

以下信息可通过环境变量从fieldRef获得:

  • 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
说明: 如果容器未指定CPU和memory limits,则Downward API默认为节点可分配值。

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

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

Downward API的动机

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

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

摘自:

https://kubernetes.io/zh/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/

https://kubernetes.io/zh/docs/tasks/inject-data-application/environment-variable-expose-pod-information/

原文地址:https://www.cnblogs.com/fengjian2016/p/13337686.html