downwardAPI存储卷
每个Pod在被成功创建出来以后,都会被系统分配唯一的名字,IP地址,并且处在某个namespace中,我们如何在Pod的容器内获取Pod的这些重要信息呢,答案就是使用DownwardAPI Downward API可用通过两种方式将Pod信息注入容器内部
- 环境变量:用于单个变量,可用将Pod信息和container信息注入容器内部
- Volume挂载: 将数组类信息生成为文件并挂载到容器内
很多时候,应用程序需要基于其所在的环境信息设定运行特性等,这类环境信息包括节点及集群的部分详细属性信息等,例如,Nginx进程可根据节点的CPU核心数量自动设定要启动的worker进程数,JVM虚拟机可根据节点内存资源自动设定其堆内存大小。类似的,托管运行于K8S的Pod对象中的容器化应用偶尔也需要获取其所属Pod对象的IP,主机名,标签,注解,UID,请求的CPU及内存资源量及其限额,甚至是Pod所在的节点名称等,容器可以通过环境变量或downwardAPI存储卷访问此类信息,不过,标签和注解仅支持通过存储卷暴露给容器
环境变量式元数据注入
引用downwardAPI元数据信息的常用方式之一是使用容器的环境变量,它通过在
.spec.containers.env.valueFrom字段中嵌套fieldRef或resourceFieldRef字段来引用相应的数据源。不过,通常只有常量类型的属性才能够通过环境变量注入到容器中,毕竟,在进程启动完成后将无法再向其告知变量值的变动,于是,环境变量也就不支持中途的更新操作.spec.containers.env.valueFrom.fieldRef可引用的字段信息如下
.spec.nodeName: 节点名称.status.hostIP: 节点IP.metadata.name:: Pod对象的名称metadata.namespace: Pod对象隶属的名称空间status.podIP: Pod对象的IP地址spec.serviceAccountName: Pod对象使用的ServiceAccount资源的名称metadata.uid: Pod对象的UIDmetadata.labels['<KEY>']: Pod对象标签中指定键的值,例如,metadata.labels[‘mylabel’]metadata.annotations['<KEY>']: Pod对象注解信息中的指定键的值另外,可通过resourceFieldRef字段引用的信息是指当前容器的资源请求及资源限额的定义,因此它们包括
requests.cpu、limits.cpu、requests.memory和limits.memory四项下面的资源配置清单示例(downwardAPI-env.yaml)中定义的Pod对象通过环境变量向容器myweb-nginx中注入了Pod对象的名称,隶属的名称空间,标签app的值以及容器自身的CPU资源限额和内存资源请求等信息
apiVersion: apps/v1kind: Deploymentmetadata:name: env-test-wardspec:replicas: 1selector:matchLabels:app: mywebtemplate:metadata:labels:app: mywebspec:containers:- name: myweb-nginximage: docker.io/ikubernetes/myapp:v2ports:- containerPort: 80name: httpimagePullPolicy: IfNotPresentresources:requests:cpu: "125m"memory: "200Mi"limits:cpu: "250m"memory: "512Mi"command: ["/bin/sh","-c","env"]env:#注入节点名称- name: MY_NODE_NAMEvalueFrom:fieldRef:fieldPath: spec.nodeName#注入节点IP- name: MY_NODE_IPvalueFrom:fieldRef:fieldPath: status.hostIP#注入Pod名称- name: MY_POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name#注入名称空间- name: MY_POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespace#注入PodIP- name: MY_POD_IPvalueFrom:fieldRef:fieldPath: status.podIP#注入标签信息- name: MY_APP_LABELvalueFrom:fieldRef:fieldPath: metadata.labels['app']#注入CPU资源最大限额信息- name: MY_CPU_LIMITvalueFrom:resourceFieldRef:resource: limits.cpudivisor: 1m#注入内存资源最大限额信息- name: MY_MEMORY_LIMITvalueFrom:resourceFieldRef:resource: limits.memorydivisor: 1Mi#注入内存资源信息- name: MY_MEMORY_REQUESTvalueFrom:resourceFieldRef:resource: requests.memorydivisor: 1Mi#注入CPU资源请求信息- name: MY_CPU_REQUESTvalueFrom:resourceFieldRef:resource: requests.cpudivisor: 1m
资源清单文件配置完成之后,即可创建Pod资源,该Pod资源创建完成之后,向控制台打印所有的环境变量就会终止运行,它仅用于测试通过环境变量注入信息到容器的使用效果
[root@k8s-master01 pv]# kubectl apply -f downwardAPI-env.yamldeployment.apps/env-test-ward configured[root@k8s-master01 pv]#[root@k8s-master01 pv]# kubectl get pods -l app=mywebNAME READY STATUS RESTARTS AGEenv-test-ward-568f44db9b-ckg97 0/1 Completed 0 3s[root@k8s-master01 pv]#
而后可通过控制台日志获取注入的环境变量
[root@k8s-master01 pv]# kubectl logs env-test-ward-568f44db9b-ckg97 |grep "^MY"MY_MEMORY_REQUEST=200MY_NODE_IP=172.18.15.113MY_POD_NAMESPACE=defaultMY_POD_IP=10.244.59.2MY_CPU_LIMIT=1MY_APP_LABEL=mywebMY_MEMORY_LIMIT=512MY_NODE_NAME=172.18.15.113MY_CPU_REQUEST=1MY_POD_NAME=env-test-ward-568f44db9b-ckg97[root@k8s-master01 pv]#
如示例中类似硬件资源的环境表里所示,在定义资源请求或资源限制时还可以额外指定一个”divisor”字段,用于为音容的值指定一个除数以事先所引用的相关值的单位换算。CPU资源的divisor字段其默认值为1,表示为1个核心,相除的结果不足1个单位时则向上圆整(例如,0.25向上圆整的结果为1),它的另外一个可用单位为1m,即表示1个微核心。内存资源的divisor字段其默认值为也是1,不过,它意指1个字节。其他可用的单位还有1Ki,1Mi,1Gi等,于是,在将divisor字段的值设置为1Mi时,200Mi的内存资源的换结果为200
如果没有未容器定义资源请求及资源限额时,downwardAPI引用的值即默认为节点的可分配CPU及内存资源量
存储卷式元数据注入(volume挂载)
向容器注入元数据信息的另一种方式是使用downwardAPI存储卷,它将配置的字段数据映射为文件并可通过容器中的挂载点进行访问。之前章节中通过环境变量的方式注入的元数据信息也都可用使用存储卷的方式进行信息暴漏,初次之外,还可用在downwardAPI存储卷中使用fieldRef引用如下两个数据源
.metadata.labels: Pod对象的所有标签信息,每行一个,格式为label-key=”escaped-label-value”.metadata.annotations: Pod对象的所有注解信息,每行一个,格式为annotations-key=”escaped-annotations-value”下面的资源清单配置示例(downwardAPI-vol.yaml)中定义的Pod对象通过downwardAPI存储卷向容器dapi-nginx中注入了Pod对象隶属的名称空间,标签,注解以及容器自身的CPU资源限额和内存资源请求等信息。存储卷在容器中的挂载点为/etc/podinfo目录,因此,注入的每一项信息均会映射为此路径下的一个文件
apiVersion: apps/v1kind: Deploymentmetadata:name: vol-downwardspec:replicas: 1selector:matchLabels:app: dapi-vol-webzone: east-chinaenv: stabletemplate:metadata:labels:app: dapi-vol-webzone: east-chinaenv: stableannotations:annotation1: "test-volumes1"spec:containers:- name: dapi-nginximage: docker.io/ikubernetes/myapp:v2ports:- containerPort: 80name: httpimagePullPolicy: IfNotPresentresources:requests:cpu: "100m"memory: "200Mi"limits:cpu: "200m"memory: "400Mi"volumeMounts:- name: podinfomountPath: /etc/podinforeadOnly: falsevolumes:- name: podinfodownwardAPI:defaultMode: 420items:- path: pod_namespacefieldRef:fieldPath: metadata.namespace- path: pod_labelsfieldRef:fieldPath: metadata.labels- path: pod_annotationsfieldRef:fieldPath: metadata.annotations- path: cpu_limitresourceFieldRef:containerName: dapi-nginxresource: limits.cpu- path: memory_limitresourceFieldRef:containerName: dapi-nginxresource: limits.memorydivisor: 1Mi- path: cpu_requestresourceFieldRef:containerName: dapi-nginxresource: requests.cpu- path: memory_requestresourceFieldRef:containerName: dapi-nginxresource: requests.memorydivisor: 1Mi
创建完资源配置清单中定义的Pod对象后即可测试访问由downwardAPI存储卷映射的文件pod_namespace、pod_labels、pod_annotations、cpu_limit和memory_request等
[root@k8s-master01 pv]# kubectl apply -f downwardAPI-vol.yamldeployment.apps/vol-downward created[root@k8s-master01 pv]#[root@k8s-master01 pv]# kubectl get pods -l "env=stable"NAME READY STATUS RESTARTS AGEvol-downward-556f6948cc-zq79w 1/1 Running 0 4m52s[root@k8s-master01 pv]#
Pod处于running状态之后,即可测试访问上述的映射文件
[root@k8s-master01 pv]# kubectl exec vol-downward-556f6948cc-zq79w -- cat /etc/podinfo/pod_labelsapp="dapi-vol-web"env="stable"pod-template-hash="556f6948cc"zone="east-china"[root@k8s-master01 pv]#[root@k8s-master01 pv]# kubectl exec vol-downward-556f6948cc-zq79w -- cat /etc/podinfo/memory_request200[root@k8s-master01 pv]#[root@k8s-master01 pv]# kubectl exec vol-downward-556f6948cc-zq79w -- cat /etc/podinfo/memory_limit400[root@k8s-master01 pv]#[root@k8s-master01 pv]# kubectl exec vol-downward-556f6948cc-zq79w -- cat /etc/podinfo/cpu_limit1[root@k8s-master01 pv]#
如命令结果所示,Pod对象的标签信息每行一个的映射于自定义的路径/etc/podinfo/pod_labels文件中,类似的,注解信息也以这种方式进行处理。如前面的文章中所述,标签和注解支持运行时修改,其改动的结果也会实时映射进downwardAPI生成的文件中。例如,为vol-downward-556f6948cc-zq79w添加新的标签
[root@k8s-master01 pv]# kubectl label pod vol-downward-556f6948cc-zq79w idc="sh"pod/vol-downward-556f6948cc-zq79w labeled[root@k8s-master01 pv]#
而后再次查看容器内的pod_labels文件的内容,由如下的命令结果可知新的标签已经能够通过相关的文件获取到
[root@k8s-master01 pv]# kubectl exec vol-downward-556f6948cc-zq79w -- cat /etc/podinfo/pod_labelsapp="dapi-vol-web"env="stable"idc="sh"pod-template-hash="556f6948cc"zone="east-china"[root@k8s-master01 pv]#
downwardAPI存储卷为K8S上运行容器化应用提供了获取额外环境信息的有效途径,这一点对那些非为云原生开发的应用程序在不进行代码重构的前提下,获取环境信息进行自身配置等操作时尤为有用
