0%

k8s-downwardAPI

downwardAPI存储卷

– 摘自 《kubernetes进阶实战》

很多时候,应⽤程序需要基于其所在的环境信息设定运⾏特性等,这类环境信息包括节点及集群的部分详细属性信息等,例如,Nginx进程可根据节点的CPU核⼼数量⾃动设定要启动的worker进程数,JVM虚拟机可根据节点内存资源⾃动设定其堆内存⼤⼩。类似地,托管运⾏于Kubernetes的Pod对象中的容器化应⽤偶尔也需要获取其所属Pod对象的IP、主机名、标签、注解、UID、请求的CPU及内存资源量及其限额,甚⾄是Pod所在的节点名称等,容器可以通过环境变量或downwardAPI存储卷访问此类信息,不过,标签和注解仅⽀持通过存储卷暴露给容器。

环境变量式元数据注⼊

引⽤downwardAPI元数据信息的常⽤⽅式之⼀是使⽤容器的环境变量,它通过在valueFrom字段中嵌套fieldRef或resourceFieldRef字段来引⽤相应的数据源。不过,通常只有常量类的属性才能够通过环境变量注⼊到容器中,毕竟,在进程启动完成后将⽆法再向其告知变量值的变动,于是,环境变量也就不⽀持中途的更新操作。

可通过fieldRef字段引⽤的信息具体如下。

·spec.nodeName:节点名称。
·status.hostIP:节点IP地址。
·metadata.name:Pod对象的名称。
·metadata.namespace:Pod对象⾪属的名称空间。
·status.podIP:Pod对象的IP地址。
·spec.serviceAccountName:Pod对象使⽤的ServiceAccount资源的名称。
·metadata.uid:Pod对象的UID。
·metadata.labels[‘‘] :Pod对象标签中的指定键的值,例如
metadata.labels[‘mylabel’],仅Kubernetes 1.9及之后的版本才⽀持。
·metadata.annotations[‘‘] :Pod对象注解信息中的指定键的值,仅Kubernetes 1.9及之后的版本才⽀持。

另外,可通过resourceFieldRef字段引⽤的信息是指当前容器的资源请求及资源限额的定义,因此它们包括requests.cpu、limits.cpu、requests.memory和limits.memory四项。

下⾯的资源配置清单⽰例(downwardAPI-env.yaml)中定义的Pod对象通过环境变量向容器env-test-container中注⼊了Pod对象的名称、⾪属的名称空间、标签app的值以及容器⾃⾝的CPU资源限额和内存资源请求等信息:

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
apiVersion: v1
kind: Pod
metadata:
name: env-test-pod
labels:
app: env-test-pod
spec:
containers:
- name: env-test-container
image: busybox
command: [ "/bin/sh", "-c", "env" ]
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
env:
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: MY_APP_LABEL
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: MY_CPU_LIMIT
valueFrom:
resourceFieldRef:
resource: limits.cpu
- name: MY_MEM_REQUEST
valueFrom:
resourceFieldRef:
resource: requests.memory
divisor: 1Mi
restartPolicy: Never

此Pod对象创建完成后,向控制台打印所有的环境变量即可终⽌运⾏,它仅⽤于测试通过环境变量注⼊信息到容器的使⽤效果:

1
2
3
4
5
~]$	kubectl	create	-f	downwardAPI-env.yaml
pod "env-test-pod" created
$ kubectl get pods -l app=env-test-pod
NAME READY STATUS RESTARTS AGE
env-test-pod 0/1 Completed 0 1m

⽽后即可通过控制台⽇志获取注⼊的环境变量:

1
2
3
4
5
6
~]$	kubectl logs env-test-pod | grep "^MY_"
MY_POD_NAMESPACE=default
MY_CPU_LIMIT=1
MY_APP_LABEL=env-test-pod
MY_MEM_REQUEST=32
MY_POD_NAME=env-test-pod

如⽰例中的最后⼀个环境变量所⽰,在定义资源请求或资源限制时还可额外指定⼀个“divisor”字段,⽤于为引⽤的值指定⼀个除数以实现所引⽤的相关值的单位换算。CPU资源的divisor字段其默认值为1,表⽰为1个核⼼,相除的结果不⾜1个单位时则向上圆整(例如,0.25向上圆整的结果为1),它的另⼀个可⽤单位为1m,即表⽰1个微核⼼。内存资源的divisor字段其默认值为也是1,不过,它意指1个字节,此时,32Mi的内存资源则要换算为33554432的结果予以输出。其他可⽤的单位还有1Ki、1Mi、1Gi等,于是,在将divisor字段的值设置为1Mi时,32Mi的内存资源的换算结果即为32。

注意: 未为容器定义资源请求及资源限额时,downwardAPI引⽤的值即默认为节点的可分配CPU及内存资源量。

存储卷式元数据注⼊

向容器注⼊元数据信息的另⼀种⽅式是使⽤downwardAPI存储卷,它将配置的字段数据映射为⽂件并可通过容器中的挂载点进⾏访问。7.2.5节中能够通过环境变量的⽅式注⼊的元数据信息也都可以使⽤存储卷的⽅式进⾏信息暴露,除此之外,还可以在downwardAPI存储卷中使⽤fieldRef引⽤如下两个数据源。

·metadata.labels:Pod对象的所有标签信息,每⾏⼀个,格式为label-key=”escaped-label-value”。
·metadata.annotations:Pod对象的所有注解信息,每⾏⼀个,格式为annotation-key=”escaped-annotation-value”。

下⾯的资源配置清单⽰例(downwardAPI-vol.yaml)中定义的Pod对象通过downwardAPI存储卷向容器volume-test-container中注⼊了Pod对象⾪属的名称空间、标签、注解以及容器⾃⾝的CPU资源限额和内存资源请求等信息。存储卷在容器中的挂载点为/etc/podinfo⽬录,因此,注⼊的每⼀项信息均会映射为此路径下的⼀个⽂件:

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
kind: Pod
apiVersion: v1
metadata:
labels:
zone: east-china
rack: rack-101
app: dapi-vol-pod
name: dapi-vol-pod
annotations:
annotation1: "test-value-1"
spec:
containers:
- name: volume-test-container
image: busybox
command: ["sh", "-c", "sleep 864000"]
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
readOnly: false
volumes:
- name: podinfo
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
- resourceFieldRef:
containerName: volume-test-container
resource: limits.cpu
path: "cpu_limit"
- resourceFieldRef:
containerName: volume-test-container
resource: requests.memory
divisor: "1Mi"
path: "mem_request"

创建资源配置清单中定义的Pod对象后即可测试访问由downwardAPI存储卷映射的⽂件pod_namespace、pod_labels、pod_annotations、limits_cpu和mem_request等:

1
2
~]$	kubectl	create	-f	downwardAPI-vol.yaml
pod "dapi-vol-pod" created

接下来即可测试访问上述的映射⽂件,例如,查看Pod对象的标签列表:

1
2
3
4
~]$	kubectl	exec	dapi-vol-pod	--	cat	/etc/podinfo/pod_labels
app="dapi-vol-pod"
rack="rack-101"
zone="east-china"

如命令结果所⽰,Pod对象的标签信息每⾏⼀个地映射于⾃定义的路径/etc/podinfo/pod_labels⽂件中,类似地,注解信息也以这种⽅式进⾏处理。如前⾯的章节中所述,标签和注解⽀持运⾏时修改,其改动的结果也会实时映射进downwardAPI⽣成的⽂件中。例如,为dapi-vol-pod添加新的标签:

1
2
~]$	kubectl	label	pods	dapi-vol-pod	env="test"
pod "dapi-vol-pod" labeled

⽽后再次查看容器内的pod_labels⽂件的内容,由如下的命令结果可知新的标签已经能够通过相关的⽂件获取到:

1
2
3
4
5
~]$	kubectl	exec	dapi-vol-pod	--	cat	/etc/podinfo/pod_labels
app="dapi-vol-pod"
env="test"
rack="rack-101"
zone="east-china"

downwardAPI存储卷为Kubernetes上运⾏容器化应⽤提供了获取外部环境信息的有效途径,这⼀点对那些⾮为云原⽣开发的应⽤程序在不进⾏代码重构的前提下,获取环境信息进⾏⾃⾝配置等操作时尤为有⽤。