3-10-3-使用Downward API向容器注入Pod信息
Kubernetes在创建Pod时 , 会为Pod和容器设置一些额外的信息 , 比如Pod名称、Pod IP、Node IP、Label、Annotation、资源限制等 , 我们经常会在应用程序中使用到这些数据 , 比如利用Pod名称作为应用日志的字段 , 方便分析日志。为了能在容器内获取这些信息 , 我们可以使用Downward API机制来实现。
Downward API可以通过环境变量和Volume挂载这两种方式将Pod信息注入容器 , 我们分别来看一下:
1. 可用字段
只有部分 Kubernetes API 字段可以通过 Downward API 使用。本节列出了你可以使用的字段。
你可以使用 fieldRef 传递来自可用的 Pod 级字段的信息。在 API 层面 , 一个 Pod 的 spec 总是定义了至少一个 Container。 你可以使用 resourceFieldRef 传递来自可用的 Container 级字段的信息。
1.1 可通过fieldRef获得的信息
对于大多数 Pod 级别的字段 , 你可以将它们作为环境变量或使用 downwardAPI 卷提供给容器。 通过这两种机制可用的字段有:
metadata.name:Pod的名称metadata.namespace:Pod的命名空间metadata.uid:Pod的唯一IDmetadata.annotations['<KEY>']:Pod的注解<KEY>的值(例如:metadata.annotations['myannotation'])metadata.labels['<KEY>']:Pod的标签<KEY>的值 ( 例如:metadata.labels['mylabel'])spec.serviceAccountName:Pod的服务账号名称spec.nodeName:Pod运行时所处的节点名称status.hostIP:Pod所在节点的主IP地址status.podIP:Pod的主IP地址 ( 通常是其IPv4地址)
此外 , 以下信息可以通过 downwardAPI 卷 fieldRef 获得 , 但不能作为环境变量获得:
metadata.labels:Pod的所有标签 , 格式为标签键名="转义后的标签值", 每行一个标签metadata.annotations:Pod的全部注解 , 格式为注解键名="转义后的注解值", 每行一个注解
1.2 可通过 resourceFieldRef 获得的信息
resource: limits.cpu: 容器的CPU限制值resource: requests.cpu: 容器的CPU请求值resource: limits.memory: 容器的内存限制值resource: requests.memory: 容器的内存请求值resource: limits.hugepages-*: 容器的巨页限制值 ( 前提是启用了DownwardAPIHugePages特性门控)resource: requests.hugepages-*: 容器的巨页请求值 ( 前提是启用了DownwardAPIHugePages特性门控)resource: limits.ephemeral-storage: 容器的临时存储的限制值resource: requests.ephemeral-storage: 容器的临时存储的请求值
资源限制的后备信息
如果没有为容器指定 CPU 和内存限制时尝试使用 Downward API 暴露该信息 , 那么 kubelet 默认会根据 节点可分配资源计算并暴露 CPU 和内存的最大可分配值
2. 使用方式
2.1 环境变量方式
我们还是以Busybox为例进行演示 , 我们将Pod信息和Container信息以环境变量方式注入容器 , 在容器启动后通过env命令打印出来 , 我们Yaml文件内容如下 :
apiVersion: v1
kind: Pod
metadata:
name: busybox-pod
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh", "-c", "env | grep VAR_"]
resources:
requests:
memory: "16Mi"
cpu: "125m"
limits:
memory: "32Mi"
cpu: "250m"
env:
- name: VAR_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: VAR_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: VAR_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: VAR_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: VAR_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: VAR_CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: busybox
resource: requests.cpu
- name: VAR_CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: busybox
resource: limits.cpu
- name: VAR_MEM_REQUEST
valueFrom:
resourceFieldRef:
containerName: busybox
resource: requests.memory
- name: VAR_MEM_LIMIT
valueFrom:
resourceFieldRef:
containerName: busybox
resource: limits.memory
restartPolicy: Never我们创建Pod并使用kubtctl logs命令打印下输出:
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl apply -f ./
pod/busybox-pod created
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox-pod 0/1 Completed 0 36s
nginx-demo 1/1 Running 0 4h35m
nginx-demo2 1/1 Running 0 3h58m
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl logs busybox-pod
VAR_MEM_REQUEST=16777216
VAR_NODE_NAME=k8s-node02.cbear.top
VAR_SERVICE_ACCOUNT=default
VAR_CPU_REQUEST=1
VAR_POD_NAME=busybox-pod
VAR_MEM_LIMIT=33554432
VAR_POD_NAMESPACE=default
VAR_POD_IP=172.20.4.56
VAR_CPU_LIMIT=1
2.2 Volume挂载方式
我们接下来尝试使用Volume挂载方式 , 将Pod信息注入容器。还是以Busybox为例 , 由于Pod信息都是以文件方式注入容器 , 所以我们修改容器启动后执行命令:我们使用cat不断打印注入的文件 , 修改后的Yaml文件如下:
apiVersion: v1
kind: Pod
metadata:
name: busybox-pod
labels:
cluster: demo-cluster
type: tool-pod
annotations:
builder: alalazy
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/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;
if [[ -e /etc/podinfo/cpu_limit ]]; then
echo -en '\n\n'; cat /etc/podinfo/cpu_limit; fi;
if [[ -e /etc/podinfo/cpu_request ]]; then
echo -en '\n\n'; cat /etc/podinfo/cpu_request; fi;
if [[ -e /etc/podinfo/mem_limit ]]; then
echo -en '\n\n'; cat /etc/podinfo/mem_limit; fi;
if [[ -e /etc/podinfo/mem_request ]]; then
echo -en '\n\n'; cat /etc/podinfo/mem_request; fi;
sleep 5;
done;
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
resources:
requests:
memory: "16Mi"
cpu: "125m"
limits:
memory: "32Mi"
cpu: "250m"
volumes:
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
- path: "cpu_limit"
resourceFieldRef:
containerName: busybox
resource: limits.cpu
divisor: 1m
- path: "cpu_request"
resourceFieldRef:
containerName: busybox
resource: requests.cpu
divisor: 1m
- path: "mem_limit"
resourceFieldRef:
containerName: busybox
resource: limits.memory
divisor: 1Mi
- path: "mem_request"
resourceFieldRef:
containerName: busybox
resource: requests.memory
divisor: 1Mi我们创建此pod , 并通过kubectl logs查看输出:
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl apply -f busybox-pod-volume.yaml
pod/busybox-pod created
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox-pod 1/1 Running 0 20s
nginx-demo 1/1 Running 0 4h42m
nginx-demo2 1/1 Running 0 4h5m
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl logs busybox-pod
cluster="demo-cluster"
type="tool-pod"
builder="alalazy"
kubectl.kubernetes.io/last-applied-configuration="{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"builder\":\"alalazy\"},\"labels\":{\"cluster\":\"demo-cluster\",\"type\":\"tool-pod\"},\"name\":\"busybox-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"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; if [[ -e /etc/podinfo/cpu_limit ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/cpu_limit; fi; if [[ -e /etc/podinfo/cpu_request ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/cpu_request; fi; if [[ -e /etc/podinfo/mem_limit ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/mem_limit; fi; if [[ -e /etc/podinfo/mem_request ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/mem_request; fi; sleep 5; done;\"],\"command\":[\"/bin/sh\",\"-c\"],\"image\":\"busybox\",\"name\":\"busybox\",\"resources\":{\"limits\":{\"cpu\":\"250m\",\"memory\":\"32Mi\"},\"requests\":{\"cpu\":\"125m\",\"memory\":\"16Mi\"}},\"volumeMounts\":[{\"mountPath\":\"/etc/podinfo\",\"name\":\"podinfo\"}]}],\"volumes\":[{\"downwardAPI\":{\"items\":[{\"fieldRef\":{\"fieldPath\":\"metadata.labels\"},\"path\":\"labels\"},{\"fieldRef\":{\"fieldPath\":\"metadata.annotations\"},\"path\":\"annotations\"},{\"path\":\"cpu_limit\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1m\",\"resource\":\"limits.cpu\"}},{\"path\":\"cpu_request\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1m\",\"resource\":\"requests.cpu\"}},{\"path\":\"mem_limit\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1Mi\",\"resource\":\"limits.memory\"}},{\"path\":\"mem_request\",\"resourceFieldRef\":{\"containerName\":\"busybox\",\"divisor\":\"1Mi\",\"resource\":\"requests.memory\"}}]},\"name\":\"podinfo\"}]}}\n"
kubernetes.io/config.seen="2024-06-04T10:56:28.369423144Z"
kubernetes.io/config.source="api"
250
125
32
16
我们进入容器查看挂载的文件
root@k8s-master01:/opt/k8s-data/yaml/downward# kubectl exec -it busybox-pod -- sh
/ # ls /etc/podinfo/
annotations cpu_limit cpu_request labels mem_limit mem_request
参考链接
Downward API | Kubernetes (aluopy.cn)
Docker 与 K8S学习笔记(二十)—— 使用Downward API向容器注入Pod信息 (qq.com)