在k8s中除了使用secret和configMap向容器注入配置和敏感信息外,应用程序有时还需要基于其所运行的外在环境(如运行在哪个宿主机之上,宿主机的IP地址等)来了解自己的运行特性。

downwardAPI存储卷类型,从严格意义上来说,downwardAPI不是存储卷,它自身就存在。原因在于,它引用的是Pod自身的运行环境信息,这些信息在Pod启动后就存在。

类似于ConfigMap或Secret资源,容器能够在环境变量中在valueFrom字段中嵌套fieldRef或resourceFieldRef字段来引用其所属Pod对象的元数据信息。不过,通常只有常量类型的属性才能够通过环境变量注入到容器中,毕竟,在进程启动完成后无法再向其告知变量值的变动,于是,环境变量也就不支持中途的更新操作。

DownwardAPI引用

DownwardAPI的引用分为两类

第一类

容器规范中可在环境变量配置中的valueFrom通过内嵌字段fieldRef引用的信息包括如下这些:

1
2
3
4
5
metadata.name:Pod对象的名称;
metadata.namespace:Pod对象隶属的名称空间;
metadata.uid:Pod对象的UID;
metadata.labels['<KEY>']:Pod对象标签中的指定键的值,例如metadata.labels['mylabel'],仅Kubernetes 1.9及之后的版本才支持;
metadata.annotations['<KEY>']:Pod对象注解信息中的指定键的值,仅Kubernetes 1.9及之后的版本才支持。

第二类

容器上的计算资源需求和资源限制相关的信息,以及临时存储资源需求和资源限制相关的信息可通过容器规范中的resourceFieldRef字段引用,相关字段包括requests.cpu、limits.cpu、requests.memory和limits.memory等。另外,可通过环境变量引用的信息有如下几个:

1
2
3
4
status.podIP:Pod对象的IP地址
spec.serviceAccountName:Pod对象使用的ServiceAccount资源名称
spec.nodeName:节点名称
status.hostIP:节点IP地址

另外,还可以通过resourceFieldRef字段引用当前容器的资源请求及资源限额的定义,因此它们包括requests.cpu、requests.memory、requests.ephemeral-storage、limits.cpu、limits.memory和limits.ephemeral-storage这6项.

使用downwardAPI变量示例

1.编写资源清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
root@k8s-master01:~/yaml/chapter06# vim downwardapi-env-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: downwardapi-env-demo
labels:
app: demoapp
spec:
containers:
- name: demoapp
image: ikubernetes/demoapp:v1.0
command: ["/bin/sh","-c","env"]
resources:
requests:
memory: "32Mi"
cpu: "250m"
limits:
memory: "64Mi"
cpu: "500m"
env:
- name: THIS_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: THIS_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: THIS_APP_LABEL
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: THIS_CPU_LIMIT
valueFrom:
resourceFieldRef:
resource: limits.cpu # 此为container中定义的limits下的cpu
- name: THIS_MEM_REQUEST
valueFrom:
resourceFieldRef:
resource: requests.memory # 此为containers中定义的requests下的memory
divisor: 1Mi # 默认为字节数,此处除以1000
restartPolicy: Never

2.应用资源清单

1
2
3
4
5
6
7
root@k8s-master01:~/yaml/chapter06# kubectl apply -f downwardapi-env-demo.yaml
pod/downwardapi-env-demo created

root@k8s-master01:~/yaml/chapter06# kubectl get pods downwardapi-env-demo -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
downwardapi-env-demo 0/1 Completed 0 40m 10.244.1.15 k8s-node01 <none> <none>
# 此容器为答应完env就退出。

3.查看容器日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@k8s-master01:~/yaml/chapter06# kubectl logs downwardapi-env-demo
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=downwardapi-env-demo
THIS_CPU_LIMIT=1 # 此为downwardapi导入的变量
THIS_APP_LABEL=demoapp # 此为downwardapi导入的变量
SHLVL=1
HOME=/root
THIS_MEM_REQUEST=32 # 此为downwardapi导入的变量
PS1=[\u@\h \w]\$
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
THIS_POD_NAME=downwardapi-env-demo # 此为downwardapi导入的变量
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
DEPLOYENV=Production
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
RELEASE=Stable
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
THIS_POD_NAMESPACE=default # 此为downwardapi导入的变量

downwardAPI存储卷示例

1.编写配置清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
root@k8s-master01:~/yaml/chapter06# vim downwardapi-volume-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: downwardapi-volume-demo
labels:
zone: zone1
rack: rack100
app: demoapp
annotations:
region: ease-cn
spec:
containers:
- name: demoapp
image: ikubernetes/demoapp:v1.0
resources:
requests:
memory: "32Mi"
cpu: "250m"
limits:
memory: "64Mi"
cpu: "500m"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
readOnly: false
volumes:
- name: podinfo
downwardAPI: # 没有引用downwardAPI,事实上是引用了当前pod的信息,从apiServer中查询的
defaultMode: 420
items:
- fieldRef:
fieldPath: metadata.namespace
path: pod_namespace
- fieldRef:
fieldPath: metadata.labels
path: pod_labels
- fieldRef:
fieldPath: metadata.annotations
path: pod_annotations
- resourceFieldRef:
containerName: demoapp
resource: limits.cpu
path: "cpu_limit"
- resourceFieldRef:
containerName: demoapp
resource: requests.memory
divisor: "1Mi"
path: "mem_request"

2.应用配置清单

1
2
3
4
5
root@k8s-master01:~/yaml/chapter06# kubectl apply -f downwardapi-volume-demo.yaml
pod/downwardapi-volume-demo created
root@k8s-master01:~/yaml/chapter06# kubectl get pods downwardapi-volume-demo
NAME READY STATUS RESTARTS AGE
downwardapi-volume-demo 1/1 Running 0 19s

3.查看downwardAPI在/etc/podinfo所挂载的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@k8s-master01:~/yaml/chapter06# kubectl exec -it downwardapi-volume-demo -- /bin/sh
[root@downwardapi-volume-demo /]# cd /etc/podinfo/
[root@downwardapi-volume-demo /etc/podinfo]# ls -l
total 0
lrwxrwxrwx 1 root root 16 Jul 19 09:17 cpu_limit -> ..data/cpu_limit
lrwxrwxrwx 1 root root 18 Jul 19 09:17 mem_request -> ..data/mem_request
lrwxrwxrwx 1 root root 22 Jul 19 09:17 pod_annotations -> ..data/pod_annotations
lrwxrwxrwx 1 root root 17 Jul 19 09:17 pod_labels -> ..data/pod_labels
lrwxrwxrwx 1 root root 20 Jul 19 09:17 pod_namespace -> ..data/pod_namespace

[root@downwardapi-volume-demo /etc/podinfo]# cat ./*
1

32

kubectl.kubernetes.io/last-applied-configuration="{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"region\":\"ease-cn\"},\"labels\":{\"app\":\"demoapp\",\"rack\":\"rack100\",\"zone\":\"zone1\"},\"name\":\"downwardapi-volume-demo\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"ikubernetes/demoapp:v1.0\",\"name\":\"demoapp\",\"resources\":{\"limits\":{\"cpu\":\"500m\",\"memory\":\"64Mi\"},\"requests\":{\"cpu\":\"250m\",\"memory\":\"32Mi\"}},\"volumeMounts\":[{\"mountPath\":\"/etc/podinfo\",\"name\":\"podinfo\",\"readOnly\":false}]}],\"volumes\":[{\"downwardAPI\":{\"defaultMode\":420,\"items\":[{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"},\"path\":\"pod_namespace\"},{\"fieldRef\":{\"fieldPath\":\"metadata.labels\"},\"path\":\"pod_labels\"},{\"fieldRef\":{\"fieldPath\":\"metadata.annotations\"},\"path\":\"pod_annotations\"},{\"path\":\"cpu_limit\",\"resourceFieldRef\":{\"containerName\":\"demoapp\",\"resource\":\"limits.cpu\"}},{\"path\":\"mem_request\",\"resourceFieldRef\":{\"containerName\":\"demoapp\",\"divisor\":\"1Mi\",\"resource\":\"requests.memory\"}}]},\"name\":\"podinfo\"}]}}\n"
kubernetes.io/config.seen="2021-07-19T09:17:04.392801370Z"
kubernetes.io/config.source="api"

region="ease-cn"app="demoapp"
rack="rack100"