Kubernetes通过downwardAPI传递元数据
应用往往需要获取所运行环境的一些信息,包括应用自身以及集群中其他组件的信息。Kubernetes可以通过环境变量以及DNS进行服务发现,但其他信息如何处理呢?下面将介绍特定pod和容器元数据如何被传递到容器,了解在容器中运行的应用如何便捷地与Kubernetes API服务器进行交互,从而获取在集群中部署资源的信息,并且进一步了解如何创建和修改这些资源。
1.通过Downward API传递元数据
Kubernetes可以环境变量或者configMap和secret卷向应用传递配置数据。这对于pod调度、运行前预设的数据是可行的。但是对于那些不能预先知道的数据,比如pod的IP、主机名或者是pod自身的名称(当名称被生成,比如当pod通过ReplicaSet或类似的控制器生成时)呢?此外,对于那些己经在别处定义的数据,比如pod的标签和注解呢?不想在多个地方重复保留同样的数据。
对于此类问题,可以通过使用Kubernetes Downward API解决。Downward API允许通过环境变量或者文件(在downwardAPI卷中)的传递pod的元数据。不要对这个名称产生困惑,Downward API的方式并不像REST endpoint那样需要通过访问的方式获取数据。这种方式主要是将在pod的定义和状态中取得的数据作为环境变量和文件的值。
1.1 了解可用元数据
Downward API可以给在pod中运行的进程暴露pod的元数据。目前可以给容器传递以下数据:
- pod的名称
- pod的IP
- pod所在的命名空间
- pod运行节点的名称
- pod运行所归属的服务账户的名称 •每个容器请求的CPU和内存的使用量
- 每个容器可以使用的CPU和内存的限制
- pod的标签
- pod的注解
这个清单中所列举的大部分项目,除了服务账户、CPU和内存的请求和限制概念,其他都无须进一步解释。其它篇章讲解。现在需了解,服务账户是pod访问API服务器时用来进行身份验证的账户。
列表中的大部分项目既可以通过环境变量也可以通过downwardAPI卷传递给容器,但是标签和注解只可以通过卷暴露。部分数据可以通过其他方式获取(例如,可以直接从操作系统获取),但是DownwardAPI提供了一种更加便捷的方式。
来看一个向容器化的进程传递元数据的例子。
1.2 通过环境变量暴露元数据
首先了解如何通过环境变量的方式将pod和容器的元数据传递到容器中。根据如下列出的manifest创建一个简单的单容器。
代码8.1 在环境变量中使用downwardAPI: downward-api-env.yaml
apiVersion: v1
kind: Pod
metadata:
name: downward
spec:
containers:
- name: main
image: busybox
command: ["sleep", "9999999"]
resources:
requests:
cpu: 15m
memory: 100Ki
limits:
cpu: 100m
memory: 4Mi
env:
- name: POD_NAME #引用pod manifest中的元数据名称字段,而不是设定一个具体的值
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
- name: CONTAINER_CPU_REQUEST_MILLICORES #容器请求的CPU和内存使用量是引用resourceFieldRef字段,而不是fieldRef字段
valueFrom:
resourceFieldRef:
resource: requests.cpu
divisor: 1m #对于资源相关的字段,定义一个基数单位,从而生成每一部分的值
- name: CONTAINER_MEMORY_LIMIT_KIBIBYTES
valueFrom:
resourceFieldRef:
resource: limits.memory
divisor: 1Ki
当进程在运行时,它可以获取所有在pod的定义文件中设定的环境变量。图8-2展示了所有的环境变量以及变量值的来源。pod的名称、IP和命名空间可以通过pod_NAME、pod_IP和pod_NAMESPACE这几个环境变量分别暴露。容器运行的节点的名称可以通过NODE_NAME变量暴露。同样,服务账户可以使用环境变量SERVICE_ACCOUNT。也可以创建两个环境变量来保存容器请求使用的CPU的数量,以及容器被最大允许使用的内存数量。
对于暴露资源请求和使用限制的环境变量,可以会设定一个基数单位。实际的资源请求直和限制直除以这个基数单位,所得的结果通过环境变量暴露出去。在前面的例子中,设定CPU请求的基数为1m(即1 millicore,也就是千分之一核CPU)。当设置资源请求15m时,环境变量CONTAINER_CPU_REQUEST_MILLICORES的值就是15。同样,我们设定内存的使用限制为4Mi(4 mebibytes),设定基数为1Ki(l Kbibyte),则环境变量 CONTAINER_MEMORY_LIMIT_KIBIBYTES的值就是 4096。

对于CPU资源请求量和使用限制可以被设定为1,也就意味着整颗CPU的计算能力,也可以设定为1m,即千分之一核的计算能力。对于内存的资源请求和使用限制可以设定为1 (字节),也可以是1k(kilobute)或1Ki (kbibute),同样也可以设为1M (megavyte)或者1Mi(mebibyte),等等。
在完成创建pod后,可以使用kubectl exec命令来查看容器中的所有环境变量,如下面的代码清单所示。
代码 8.2 downward pod中的环境变量
$ kubectl exec downward env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=downward
CONTAINER_MEMORY_LIMIT_KIBIBYTES=4096
POD_NAME=downward
POD_NAMESPACE=default
POD_IP=10.0.0.10
NODE_NAME=gke-kubia-default-pool-32a2cac8-sgl7
SERVICE_ACCOUNT=default
CONTAINER_CPU_REQUEST_MILLICORES=15
KUBERNETES_SERVICE_HOST=10.3.240.1
KUBERNETES_SERVICE_PORT=443
所有在这个容器中运行的进程都可以读取并使用它们需要的变量。
1.3 通过downwardAPI卷来传递元数据
如果更倾向于使用文件的方式而不是环境变量的方式暴露元数据,可以定义一个downwardAPI卷并挂载到容器中。由于不能通过环境变量暴露,所以必须使用downwardAPI卷来暴露pod标签或注解。为什么不能后面讨论原因。
与环境变量一样,需要显示地指定元数据字段来暴露份进程。下面我们将把前面的示例从使用环境变量修改为使用存储卷,如下面的代码清单所示。
#代码8.3 —个带有downwardAPi卷的pod示例:downward-api-volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: downward
labels:
foo: bar
annotations: #通过downwardAPI卷来暴露这些标签和注解
key1: value1
key2: |
multi
line
value
spec:
containers:
- name: main
image: busybox
command: ["sleep", "9999999"]
resources:
requests:
cpu: 15m
memory: 100Ki
limits:
cpu: 100m
memory: 4Mi
volumeMounts: #在/etc/downward目录下挂载这个downward卷
- name: downward
mountPath: /etc/downward
volumes:
- name: downward #通过将卷名字设定为downward来定义一个downwardAPI卷
downwardAPI:
items:
- path: "podName" #pod的名称(来自manifest文件中的metadata.name字段)将被写入podName中
fieldRef:
fieldPath: metadata.name
- path: "podNamespace"
fieldRef:
fieldPath: metadata.namespace
- path: "labels" #pod的标签将被保存到/etc/downward/labels文件中
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
- path: "containerCpuRequestMilliCores"
resourceFieldRef:
containerName: main
resource: requests.cpu
divisor: 1m
- path: "containerMemoryLimitBytes"
resourceFieldRef:
containerName: main
resource: limits.memory
divisor: 1
现在没有通过环境变量来传递元数据,而是定义了一个叫作downward的卷,并且通过/etc/downward目录挂载到我们的容器中。卷所包含的文件会通过卷定义中的downwardAPI.items属性来定义。
对于想要在文件中保存的每一个pod级的字段或者容器资源字段,都分别在downwardAPI.items中说明了元数据被保存和引用的path(文件名),如图8.3所示。

从之前列表的manifest中删除原来的pod,并且新建一个pod。然后查看己挂载到downwardAPI卷目录的内容,存储卷被挂载在/etc/downward/目录下,列出目录中的文件,如下面的代码清单所示。
#代码8.4 downwordAPI卷中的文件
$ kubectl exec downward ls -lL /etc/downward
-rw-r- -r-- 1 root root 134 May 25 10:23 annotations
-rw-r- -r-- 1 root root 2 May 25 10:23 containerCpuRequestMilliCores
-rw-r- -r-- 1 root root 7 May 25 10:23 containerMemoryLimitBytes
-rw-r- -r-- 1 root root 9 May 25 10:23 labels
-rw-r- -r-- 1 root root 8 May 25 10:23 podName
-rw-r- -r-- 1 root root 7 May 25 10:23 podNamespace
注意:与configMAp和secret卷一样,可以通过pod定义中downwardAPI卷的defaultMode属性来改变文件的访问权限设置。
每个文件都对应了卷定义中的一项。文件的内容与之前例子中的元数据字段和值,这里不再重复展示。不过由于不能通过环境变量的方式暴露label和annotation,所以看一下暴露的这两个文件的代码清单。
#代码8.5 展示 downwardAPI卷中的标签和注解
$ kubectl exec downward cat /etc/downward/labels
foo="bar"
$ kubectl exec downward cat /etc/downward/annotations
key1="value1"
key2="multi\nline\nvalue\n"
kubernetes.io/config.seen="2016-11-28T14:27:45.664924282Z"
kubernetes.io/config.source="api"
正如上面看到的,每一个标签和注解都以key=value的格式保存在单独的行中,如对应多个值,则写在同一行,并且用回车符\n连接。
修改标签和注解
可以在pod运行时修改标签和注解。当标签和注解被修改后, Kubernetes会更新存有相关信息的文件,从而使pod可以获取最新的数据。这也解释了为什么不能通过环境变量的方式暴露标签和注解,在环境变量方式下,一旦标签和注解被修改,新的值将无法暴露。
在卷的定义中引用容器级的元数据
需要说明一点,当暴露容器级的元数据时,如容器可使用的资源限制或者资源请求(使用字段resourceFieldRef),必须指定引用资源字段对应的容器名称,如下面的代码清单所示。
#代码8.6 在downwardAPI卷中引用容器级的元数据
spec:
volumes:
- name: downward
downwardAPI:
items:
- path: "containerCpuRequestMilliCores"
resourceFieldRef:
containerName: main #必须制定容器名称
resource:requests.cpu
divisor: 1m
这样做的理由很明显,因为对于卷的定义是基于pod级的,而不是容器级的。 当我们引用卷定义某一个容器的资源字段时,我们需要明确说明引用的容器的名称。这个规则对于只包含单容器的pod同样适用。
使用卷的方式来暴露容器的资源请求和使用限制比环境变量的方式稍显复杂, 但好处是如果有必要,可以传递一个容器的资源字段到另一个容器(当然两个容器必须处于同一个pod)。使用环境变量的方式,一个容器只能传递它自身资源申请求和限制的信息。
何时使用Dowanward API方式
Downward API方式并不复杂,它使得应用独立于Kubernetes。这一点在处理部分数据己在环境变量中的现有应用时特别有用。 Downward API方式使得我们不必通过修改应用,或者使用shell脚本获取数据再传递给环境变量的方式来暴露数据。
不过通过Downward API的方式获取的元数据是相当有限的,如果需要获取更多的元数据,需要使用直接访问Kubernetes API服务器的方式。在与KubernetesAPI服务器交互章中讲解。
Kubernetes通过downwardAPI传递元数据的更多相关文章
- Kubernetes学习笔记(七):访问Pod元数据与Kubernetes API
Downward API 我们已经了解到,使用ConfigMap和Secret向应用传递配置数据,这对于运行前预设的数据是可行的.但是对于那些不能预先知道的,就需要使用Downward API. Do ...
- 从应用访问Pod元数据-DownwardApi的应用
对于某些需要调度之后才能知道的数据,比如 pod 的 ip,主机名,或者 pod 自身的名称等等,k8s 依旧很贴心的提供了 Downward API 的方式来获取此类数据,并且可以通过环境变量或者文 ...
- Kubernetes排错:用容器的元数据提供新思路
在这篇文章中,让我们讨论一下Kubernetes中的元数据(Metadata),以及如何利用它来监控系统的性能. 元数据(Metadata) 是一个较为高大上的词.它的含义是"用来描述其他数 ...
- 【译】Asp.net core应用在 Kubernetes上内存使用率过高问题分析
原文:https://blog.markvincze.com/troubleshooting-high-memory-usage-with-asp-net-core-on-kubernetes/ ps ...
- WCF 之 生成元数据和代理
在WCF开发概述中讲解了手工方式的WCF应用,其实实际开发中使用更多的使用配置方式和元数据来实现WCF,下面我们来看一个具体的Demo,这个例子和WCF开发概述中使用的是同一个例子,只是实现方式不同, ...
- Rancher 2.3实现K8S一键式升级!再也不用同步升级Rancher啦!
在Rancher 2.3之前,Rancher的新版本总是随着Kubernetes的新版本一起发布,如果你想要使用最新版本的Kubernetes,那么你需要先升级Rancher才能使用.Rancher ...
- [目录]Pentaho Kettle解决方案:使用PDI构建开源ETL解决方案
第一部分:开始 1 ETL入门 1.1 OLTP和数据仓库对比 1.2 ETL是什么 1.2.1 ETL解决方案的演化过程 1.2.2 ET ...
- pandas教程1:pandas数据结构入门
pandas是一个用于进行python科学计算的常用库,包含高级的数据结构和精巧的工具,使得在Python中处理数据非常快速和简单.pandas建造在NumPy之上,它使得以NumPy为中心的应用很容 ...
- Django---->视图(View)
视图层之路由配置系统(views) URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个 ...
随机推荐
- [刷题] PTA 03-树3 Tree Traversals Again
用栈实现树遍历 1 #include<stdio.h> 2 #include<string.h> 3 #define MAXSIZE 30 4 5 int Pre[MAXSIZ ...
- CENTOS7network config文件不能直接bak 必须建立bak目录再bak
CENTOS7network config文件不能直接bak 必须建立bak目录再bak
- gparted 当分区空间大于1T 用gparted分区
lsblkfdisk -lparted -s /dev/sdb mklabel msdos parted -s /dev/sdb mkpart primary 0 100%lsblk dfparted ...
- wps中新罗马字体如何设置Times New Roman
word wps中新罗马字体如何设置Times New Roman ### WPS字体自带 Times New Roman ###
- 【转载】有图 KVM折腾记..
KVM折腾记...https://lengjibo.github.io/KVM%E6%8A%98%E8%85%BE%E8%AE%B0/ Veröffentlicht am 2018-09-20 | ...
- CentOS 7 设置日期和时间 timedatectl
CentOS 7 设置日期和时间 在CentOS 6版本,时间设置有date.hwclock命令,从CentOS 7开始,使用了一个新的命令timedatectl. timedatectl [root ...
- Python对比两个txt文件内容
difflib模块作为python的标准库模块,无需安装,作用是比对文本之间的差异,且支持输出可读性比较强的html格式.#!coding=utf-8 # 2018-9-19 import sys i ...
- centos7 搭建 nginx web服务 反代理
Nginx("engine x")是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. ...
- maven工具使用json-lib时,JSONArray.fromObject()不能执行的解决方案
前端代码我就不展示了 ,下面说明下我遇到问题的情况,如果不想看可以直接划到黄色字体部分直接找解决方法哦~~(相关jar包我会放在云中,想要的自己下载哦,链接在视频最下面!!) 我的pom文件,如下,导 ...
- Python小白的数学建模课-04.整数规划
整数规划与线性规划的差别只是变量的整数约束. 问题区别一点点,难度相差千万里. 选择简单通用的编程方案,让求解器去处理吧. 『Python小白的数学建模课 @ Youcans』带你从数模小白成为国赛达 ...