此页面描述 Pod 如何使用 DownwardAPIVolumeFile把自己的信息呈现给 Pod 中运行的容器。 DownwardAPIVolumeFile
可以呈现 Pod 和容器的字段。
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
要获知版本信息,请输入 kubectl version
。
有两种方式可以将 Pod 和 Container 字段呈现给运行中的容器:
这两种呈现 Pod 和 Container 字段的方式都称为 "Downward API"。
在这个练习中,你将创建一个包含一个容器的 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 '\n\n'; cat /etc/podinfo/labels; fi;
if [[ -e /etc/podinfo/annotations ]]; then
echo -en '\n\n'; 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
类型的卷,并且挂载到容器中的 /etc/podinfo
目录。
查看 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/podinfo/labels
输出显示 Pod 的所有标签都已写入 labels
文件。
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"
同样,查看 annotations
文件:
/# cat /etc/podinfo/annotations
查看 /etc/podinfo
目录下的文件:
/# ls -laR /etc/podinfo
在输出中可以看到,labels
和 annotations
文件都在一个临时子目录中。 在这个例子,..2982_06_02_21_47_53.299460680
。 在 /etc/podinfo
目录中,..data
是一个指向临时子目录 的符号链接。/etc/podinfo
目录中,labels
和 annotations
也是符号链接。
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
用符号链接可实现元数据的动态原子性刷新;更新将写入一个新的临时目录, 然后通过使用 rename(2)完成 ..data
符号链接的原子性更新。
说明: 如果容器以 subPath卷挂载方式来使用 Downward API,则该容器无法收到更新事件。
退出 Shell:
/# exit
前面的练习中,你将 Pod 字段保存到 DownwardAPIVolumeFile
中。 接下来这个练习,你将存储 Container 字段。这里是包含一个容器的 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 '\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
在这个配置文件中,你可以看到 Pod 有一个 downwardAPI
卷, 并且挂载到容器的 /etc/podinfo
目录。
查看 downwardAPI
下面的 items
数组。每个数组元素都是一个 DownwardAPIVolumeFile。
第一个元素指定在名为 client-container
的容器中, 以 1m
所指定格式的 limits.cpu
字段的值应保存在名为 cpu_limit
的文件中。 divisor
字段是可选的,默认值为 1,表示 CPU 的核心和内存的字节。
创建Pod:
kubectl apply -f https://k8s.io/examples/pods/inject/dapi-volume-resources.yaml
打开一个 Shell,进入 Pod 中运行的容器:
kubectl exec -it kubernetes-downwardapi-volume-example-2 -- sh
在 Shell 中,查看 cpu_limit
文件:
/# cat /etc/podinfo/cpu_limit
你可以使用同样的命令查看 cpu_request
、mem_limit
和 mem_request
文件.
下面这些信息可以通过环境变量和 downwardAPI
卷提供给容器:
能通过 fieldRef
获得的:
metadata.name
- Pod 名称 metadata.namespace
- Pod 名字空间 metadata.uid
- Pod 的 UID metadata.labels['<KEY>']
- Pod 标签 <KEY>
的值 (例如:metadata.labels['mylabel']
) metadata.annotations['<KEY>']
- Pod 的注解 <KEY>
的值 (例如:metadata.annotations['myannotation']
) 能通过 resourceFieldRef
获得的:
DownwardAPIHugePages
特性门控) DownwardAPIHugePages
特性门控) 此外,以下信息可通过 downwardAPI
卷从 fieldRef
获得:
metadata.labels
- Pod 的所有标签,以 label-key="escaped-label-value"
格式显示,每行显示一个标签 metadata.annotations
- Pod 的所有注解,以 annotation-key="escaped-annotation-value"
格式显示,每行显示一个标签 以下信息可通过环境变量获得:
status.podIP
- Pod IP 地址 spec.serviceAccountName
- Pod 服务帐号名称 spec.nodeName
- 调度器总是尝试将 Pod 调度到的节点的名称 status.hostIP
- Pod 分配到的节点的 IP说明: 如果容器未指定 CPU 和内存限制,则 Downward API 默认将节点可分配值 视为容器的 CPU 和内存限制。
你可以将键名投射到指定路径并且指定每个文件的访问权限。
对于容器来说,有时候拥有自己的信息是很有用的,可避免与 Kubernetes 过度耦合。 Downward API 使得容器使用自己或者集群的信息,而不必通过 Kubernetes 客户端或 API 服务器来获得。
一个例子是有一个现有的应用假定要用一个非常熟悉的环境变量来保存一个唯一标识。 一种可能是给应用增加处理层,但这样是冗余和易出错的,而且它违反了低耦合的目标。 更好的选择是使用 Pod 名称作为标识,把 Pod 名称注入这个环境变量中。