应用往往需要获取所运行环境的一些信息,包括应用自身以及集群中其他组件的信息。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服务器交互章中讲解。

最新文章

  1. [.NET逆向] 破解NET的四大神器
  2. jquery.Huploadify 上传
  3. Android Studio 如何切换sdk
  4. mybatis实战教程(mybatis in action)之一:开发环境搭建
  5. (谷歌浏览器等)解决css中点击input输入框时出现外边框方法【outline:medium;】
  6. 使用java理解程序逻辑 第三章 选择结构一
  7. 刷机(手机自带的recovery)
  8. MongoDB - MongoDB CRUD Operations, Query Documents
  9. BAT-使用BAT方法删除目录下0KB文件
  10. JSF 2 dropdown box example
  11. 【数学相关、规律】Codeforces 696B Puzzles
  12. 清除float常用方法(:after和clear:both)
  13. 转: 理解AngularJS中的依赖注入
  14. Cf 444C DZY Loves Colors(段树)
  15. struts1.x中web.xml文件的配置
  16. 多表连接时USING和ON的区别,USING会去掉重复列,ON显示重复列。
  17. 常见的java设计模式
  18. js:获取事件源的兼容性写法
  19. POE 供电
  20. 面试汇总——知道什么是同源策略吗?那怎么解决跨域问题?知道 JSONP 原理吗?

热门文章

  1. 2.HTML案例二 头条页面
  2. Linux_控制作业(管理)
  3. static在C/C++中的作用-(转自华山大师兄)
  4. 校准仪的开发 ---等下整理 迪文屏的ICO文件 和输出配置问题
  5. centos更换损坏硬盘uuid改变导致系统不能正常启动处理
  6. 链路追踪_SkyWalking的部署及使用
  7. Git 系列教程(14)- 远程分支
  8. PaddlePaddle推理部署
  9. 用Microsoft DirectX光线跟踪改善渲染质量
  10. 激光雷达数据到云cloud