Kubernetes权威指南:从Docker到Kubernetes实践全接触(第4版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.6 在容器内获取Pod信息(Downward API)

我们知道,每个Pod在被成功创建出来之后,都会被系统分配唯一的名字、IP地址,并且处于某个Namespace中,那么我们如何在Pod的容器内获取Pod的这些重要信息呢?答案就是使用Downward API。

Downward API可以通过以下两种方式将Pod信息注入容器内部。

(1)环境变量:用于单个变量,可以将Pod信息和Container信息注入容器内部。

(2)Volume挂载:将数组类信息生成为文件并挂载到容器内部。

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

3.6.1 环境变量方式:将Pod信息注入为环境变量

下面的例子通过Downward API将Pod的IP、名称和所在Namespace注入容器的环境变量中,容器应用使用env命令将全部环境变量打印到标准输出中:

        dapi-test-pod.yaml
        apiVersion: v1
        kind: Pod
        metadata:
          name: dapi-test-pod
        spec:
          containers:
            - name: test-container
              image: busybox
              command: [ "/bin/sh", "-c", "env" ]
              env:
                - 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
          restartPolicy: Never

注意到上面valueFrom这种特殊的语法是Downward API的写法。目前Downward API提供了以下变量。

◎ metadata.name:Pod的名称,当Pod通过RC生成时,其名称是RC随机产生的唯一名称。

◎ status.podIP:Pod的IP地址,之所以叫作status.podIP而非metadata.IP,是因为Pod的IP属于状态数据,而非元数据。

◎ metadata.namespace:Pod所在的Namespace。

运行kubectl create命令创建Pod:

        # kubectl create -f dapi-test-pod.yaml
        pod "dapi-test-pod" created

查看dapi-test-pod的日志:

        # kubectl logs dapi-test-pod
        ......
        MY_POD_NAMESPACE=default
        MY_POD_IP=172.17.1.2
        MY_POD_NAME=dapi-test-pod
        ......

从日志中我们可以看到Pod的IP、Name及Namespace等信息都被正确保存到了Pod的环境变量中。

3.6.2 环境变量方式:将容器资源信息注入为环境变量

下面的例子通过Downward API将Container的资源请求和限制信息注入容器的环境变量中,容器应用使用printenv命令将设置的资源请求和资源限制环境变量打印到标准输出中:

        dapi-test-pod-container-vars.yaml
        apiVersion: v1
        kind: Pod
        metadata:
          name: dapi-test-pod-container-vars
        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 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

注意valueFrom这种特殊的Downward API语法,目前resourceFieldRef可以将容器的资源请求和资源限制等配置设置为容器内部的环境变量。

◎ requests.cpu:容器的CPU请求值。

◎ limits.cpu:容器的CPU限制值。

◎ requests.memory:容器的内存请求值。

◎ limits.memory:容器的内存限制值。

运行kubectl create命令来创建Pod:

        # kubectl create -f dapi-test-pod-container-vars.yaml
        pod "dapi-test-pod-container-vars" created

        # kubectl get pods
        NAME                           READY     STATUS    RESTARTS   AGE
        dapi-test-pod-container-vars   1/1       Running   0          36s

查看dapi-test-pod-container-vars的日志:

        # kubectl logs dapi-test-pod-container-vars
        11
        33554432
        67108864

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

3.6.3 Volume挂载方式

下面的例子通过Downward API将Pod的Label、Annotation列表通过Volume挂载为容器中的一个文件,容器应用使用echo命令将文件的内容打印到标准输出中:

        dapi-test-pod-volume.yaml
        apiVersion: v1
        kind: Pod
        metadata:
          name: dapi-test-pod-volume
          labels:
            zone: us-est-coast
            cluster: test-cluster1
            rack: rack-22
          annotations:
            build: two
            builder: john-doe
        spec:
          containers:
            - name: test-container
              image: busybox
              imagePullPolicy: Never
              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 3600;
              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

这里要注意“volumes”字段中downwardAPI的特殊语法,通过items的设置,系统会根据path的名称生成文件。根据上例的设置,系统将在容器内生成/etc/labels和/etc/annotations两个文件。在/etc/labels文件中将包含metadata.labels的全部Label列表,在/etc/annotations文件中将包含metadata.annotations的全部Label列表。

运行kubectl create命令创建Pod:

        # kubectl create -f dapi-test-pod-volume.yaml
        pod "dapi-test-pod-volume" created

        # kubectl get pods
        NAME                   READY     STATUS    RESTARTS   AGE
        dapi-test-pod-volume   1/1       Running   0          1m

查看dapi-test-pod-volume的日志:

        # k logs dapi-test-pod-volume
        cluster="test-cluster1"
        rack="rack-22"
        zone="us-est-coast"

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

从日志中我们看到Pod的Label和Annotation信息都被保存到了容器内的/etc/labels和/etc/annotations文件中。

那么,Downward API有什么价值呢?

在某些集群中,集群中的每个节点都需要将自身的标识(ID)及进程绑定的IP地址等信息事先写入配置文件中,进程在启动时会读取这些信息,然后将这些信息发布到某个类似服务注册中心的地方,以实现集群节点的自动发现功能。此时Downward API就可以派上用场了,具体做法是先编写一个预启动脚本或Init Container,通过环境变量或文件方式获取Pod自身的名称、IP地址等信息,然后将这些信息写入主程序的配置文件中,最后启动主程序。