Kubernetes(k8s)通过环境变量将 Pod 信息呈现给容器
Downward API
有两种方式可以将 Pod 和 Container 字段呈现给运行中的容器:
- 环境变量
- 卷文件
这两种呈现 Pod 和 Container 字段的方式统称为 Downward API。
使用环境变量的方式
用 Pod 字段作为环境变量的值
Pod 的配置文件
cat test_pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-fieldref
spec:
containers:
- name: test-container
image: busybox
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_NODE_NAME MY_POD_NAME MY_POD_NAMESPACE;
printenv MY_POD_IP MY_POD_SERVICE_ACCOUNT;
sleep 10;
done;
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MY_POD_SERVICE_ACCOUNT
valueFrom:
fieldRef:
fieldPath: spec.serviceAccountName
restartPolicy: Never
这个配置文件中,你可以看到五个环境变量。env 字段是一个 EnvVars. 对象的数组。 数组中第一个元素指定 MY_NODE_NAME 这个环境变量从 Pod 的 spec.nodeName 字段获取变量值。 同样,其它环境变量也是从 Pod 的字段获取它们的变量值。
说明: 本示例中的字段是 Pod 字段,不是 Pod 中 Container 的字段。
# 创建Pod
# kubectl apply -f test_pod.yaml
pod/dapi-envars-fieldref created
# 验证 Pod 中的容器运行正常
# kubectl get pods
NAME READY STATUS RESTARTS AGE
dapi-envars-fieldref 1/1 Running 0 5s
# 查看容器日志,输出信息显示了所选择的环境变量的值
# kubectl logs dapi-envars-fieldref
develop-worker-2
dapi-envars-fieldref
default
10.0.2.110
default
要了解为什么这些值在日志中,请查看配置文件中的command和 args字段。 当容器启动时,它将五个环境变量的值写入stdout。每十秒重复执行一次。
接下来,通过打开一个 Shell 进入 Pod 中运行的容器:
# kubectl exec -it dapi-envars-fieldref /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# 在 Shell 中,查看环境变量
/ # printenv
MY_POD_SERVICE_ACCOUNT=default
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.3.255.1:443
DASHBOARD_KUBERNETES_DASHBOARD_SERVICE_HOST=10.3.255.88
HOSTNAME=dapi-envars-fieldref
DASHBOARD_KUBERNETES_DASHBOARD_PORT_9090_TCP_ADDR=10.3.255.88
SHLVL=1
HOME=/root
DASHBOARD_KUBERNETES_DASHBOARD_PORT_9090_TCP_PORT=9090
DASHBOARD_KUBERNETES_DASHBOARD_PORT_9090_TCP_PROTO=tcp
DASHBOARD_KUBERNETES_DASHBOARD_SERVICE_PORT=9090
DASHBOARD_KUBERNETES_DASHBOARD_PORT=tcp://10.3.255.88:9090
MY_POD_NAMESPACE=default
DASHBOARD_KUBERNETES_DASHBOARD_PORT_9090_TCP=tcp://10.3.255.88:9090
TERM=xterm
MY_POD_IP=10.0.2.110
KUBERNETES_PORT_443_TCP_ADDR=10.3.255.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
MY_NODE_NAME=develop-worker-2
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.3.255.1:443
KUBERNETES_SERVICE_HOST=10.3.255.1
PWD=/
DASHBOARD_KUBERNETES_DASHBOARD_SERVICE_PORT_HTTP=9090
MY_POD_NAME=dapi-envars-fieldref
用 Container 字段作为环境变量的值
包含一个容器的 Pod 的配置文件
# cat test_pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-envars-resourcefieldref
spec:
containers:
- name: test-container
image: busybox
command: [ "sh", "-c"]
args:
- while true; do
echo -en '\n';
printenv MY_CPU_REQUEST MY_CPU_LIMIT;
printenv MY_MEM_REQUEST MY_MEM_LIMIT;
sleep 10;
done;
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
env:
- name: MY_CPU_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container # 上面设置的容器名称
resource: requests.cpu
- name: MY_CPU_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.cpu
- name: MY_MEM_REQUEST
valueFrom:
resourceFieldRef:
containerName: test-container
resource: requests.memory
- name: MY_MEM_LIMIT
valueFrom:
resourceFieldRef:
containerName: test-container
resource: limits.memory
restartPolicy: Never
这个配置文件中,你可以看到四个环境变量。env 字段是一个 EnvVars. 对象的数组。数组中第一个元素指定 MY_CPU_REQUEST 这个环境变量从 Container 的 requests.cpu 字段获取变量值。同样,其它环境变量也是从 Container 的字段获取它们的变量值。
说明: 本例中使用的是 Container 的字段而不是 Pod 的字段。
# 创建Pod
# kubectl apply -f test_pod1.yaml
pod/dapi-envars-resourcefieldref created
# 验证 Pod 中的容器运行正常
# kubectl get pods
NAME READY STATUS RESTARTS AGE
dapi-envars-resourcefieldref 1/1 Running 0 6s
# 查看容器日志,输出信息显示了所选择的环境变量的值
# kubectl logs dapi-envars-resourcefieldref
1
1
33554432
67108864
使用文件的方式
Pod字段
包含一个容器的 Pod的配置文件
# cat test_pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example
labels:
zone: us-est-coast
cluster: test-cluster1
rack: rack-22
annotations:
build: two
builder: john-doe
spec:
containers:
- name: client-container
image: busybox
command: ["sh", "-c"]
args:
- while true; do
if [[ -e /etc/podinfo/labels ]]; then
echo -en '\n\n'; cat /etc/podinfo/labels; fi;
if [[ -e /etc/podinfo/annotations ]]; then
echo -en '\n\n'; cat /etc/podinfo/annotations; fi;
sleep 5;
done;
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
volumes:
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "annotations"
fieldRef:
fieldPath: metadata.annotations
在配置文件中,你可以看到 Pod 有一个 downwardAPI 类型的卷,并且挂载到容器中的 /etc/podinfo 目录。
查看 downwardAPI 下面的 items 数组。 每个数组元素都是一个 DownwardAPIVolumeFile 对象。 第一个元素指示 Pod 的 metadata.labels 字段的值保存在名为 labels 的文件中。 第二个元素指示 Pod 的 annotations 字段的值保存在名为 annotations 的文件中。
说明: 本示例中的字段是Pod字段,不是Pod中容器的字段。
# 创建 Pod
# kubectl apply -f test_pod2.yaml
pod/kubernetes-downwardapi-volume-example created
# 验证Pod中的容器运行正常
# kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-downwardapi-volume-example 1/1 Running 0 47s
# 查看容器的日志,输出显示 labels 和 annotations 文件的内容
# kubectl logs kubernetes-downwardapi-volume-example
cluster="test-cluster1"
rack="rack-22"
zone="us-est-coast"
build="two"
builder="john-doe"
kubectl.kubernetes.io/last-applied-configuration="{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"build\":\"two\",\"builder\":\"john-doe\"},\"labels\":{\"cluster\":\"test-cluster1\",\"rack\":\"rack-22\",\"zone\":\"us-est-coast\"},\"name\":\"kubernetes-downwardapi-volume-example\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"while true; do if [[ -e /etc/podinfo/labels ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/labels; fi; if [[ -e /etc/podinfo/annotations ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/annotations; fi; sleep 5; done;\"],\"command\":[\"sh\",\"-c\"],\"image\":\"busybox\",\"name\":\"client-container\",\"volumeMounts\":[{\"mountPath\":\"/etc/podinfo\",\"name\":\"podinfo\"}]}],\"volumes\":[{\"downwardAPI\":{\"items\":[{\"fieldRef\":{\"fieldPath\":\"metadata.labels\"},\"path\":\"labels\"},{\"fieldRef\":{\"fieldPath\":\"metadata.annotations\"},\"path\":\"annotations\"}]},\"name\":\"podinfo\"}]}}\n"
kubernetes.io/config.seen="2021-05-17T15:31:02.676723051+08:00"
kubernetes.io/config.source="api"
# 进入 Pod 中运行的容器,打开一个 Shell
# kubectl exec -it kubernetes-downwardapi-volume-example -- sh
# 在该 Shell中,查看 labels 文件,输出显示 Pod 的所有标签都已写入 labels 文件
/ # cat /etc/podinfo/labels
cluster="test-cluster1"
rack="rack-22"
# 查看annotations文件,
/ # cat /etc/podinfo/annotations
build="two"
builder="john-doe"
kubectl.kubernetes.io/last-applied-configuration="{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{\"build\":\"two\",\"builder\":\"john-doe\"},\"labels\":{\"cluster\":\"test-cluster1\",\"rack\":\"rack-22\",\"zone\":\"us-est-coast\"},\"name\":\"kubernetes-downwardapi-volume-example\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"args\":[\"while true; do if [[ -e /etc/podinfo/labels ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/labels; fi; if [[ -e /etc/podinfo/annotations ]]; then echo -en '\\\\n\\\\n'; cat /etc/podinfo/annotations; fi; sleep 5; done;\"],\"command\":[\"sh\",\"-c\"],\"image\":\"busybox\",\"name\":\"client-container\",\"volumeMounts\":[{\"mountPath\":\"/etc/podinfo\",\"name\":\"podinfo\"}]}],\"volumes\":[{\"downwardAPI\":{\"items\":[{\"fieldRef\":{\"fieldPath\":\"metadata.labels\"},\"path\":\"labels\"},{\"fieldRef\":{\"fieldPath\":\"metadata.annotations\"},\"path\":\"annotations\"}]},\"name\":\"podinfo\"}]}}\n"
kubernetes.io/config.seen="2021-05-17T15:31:02.676723051+08:00"
# 查看/etc/podinfo目录下的文件
/ # ls -al /etc/podinfo/
total 4
drwxrwxrwt 3 root root 120 May 17 07:31 .
drwxr-xr-x 1 root root 4096 May 17 07:31 ..
drwxr-xr-x 2 root root 80 May 17 07:31 ..2021_05_17_07_31_03.519523692
lrwxrwxrwx 1 root root 31 May 17 07:31 ..data -> ..2021_05_17_07_31_03.519523692
lrwxrwxrwx 1 root root 18 May 17 07:31 annotations -> ..data/annotations
lrwxrwxrwx 1 root root 13 May 17 07:31 labels -> ..data/labels
# 在输出中可以看到,labels 和 annotations 文件都在一个临时子目录中。 在这个例子是..2021_05_17_07_31_03.519523692。 在 /etc/podinfo 目录中,..data 是一个指向临时子目录 的符号链接。/etc/podinfo 目录中,labels 和 annotations 也是符号链接。
/ # ls -al /etc/podinfo/..2021_05_17_07_31_03.519523692/
total 8
drwxr-xr-x 2 root root 80 May 17 07:31 .
drwxrwxrwt 3 root root 120 May 17 07:31 ..
-rw-r--r-- 1 root root 1102 May 17 07:31 annotations
-rw-r--r-- 1 root root 58 May 17 07:31 labels
# 用符号链接可实现元数据的动态原子性刷新;更新将写入一个新的临时目录, 然后通过使用rename(2) 完成 ..data 符号链接的原子性更新。
# 说明: 如果容器以 subPath卷挂载方式来使用 Downward API,则该容器无法收到更新事件。
Container 字段
包含一个容器的 Pod 的配置文件
# cat test_pod3.yaml
apiVersion: v1
kind: Pod
metadata:
name: kubernetes-downwardapi-volume-example-2
spec:
containers:
- name: client-container
image: busybox
command: ["sh", "-c"]
args:
- while true; do
echo -en '\n';
if [[ -e /etc/podinfo/cpu_limit ]]; then
echo -en '\n'; cat /etc/podinfo/cpu_limit; fi;
if [[ -e /etc/podinfo/cpu_request ]]; then
echo -en '\n'; cat /etc/podinfo/cpu_request; fi;
if [[ -e /etc/podinfo/mem_limit ]]; then
echo -en '\n'; cat /etc/podinfo/mem_limit; fi;
if [[ -e /etc/podinfo/mem_request ]]; then
echo -en '\n'; cat /etc/podinfo/mem_request; fi;
sleep 5;
done;
resources:
requests:
memory: "32Mi"
cpu: "125m"
limits:
memory: "64Mi"
cpu: "250m"
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
volumes:
- name: podinfo
downwardAPI:
items:
- path: "cpu_limit"
resourceFieldRef:
containerName: client-container
resource: limits.cpu
divisor: 1m
- path: "cpu_request"
resourceFieldRef:
containerName: client-container
resource: requests.cpu
divisor: 1m
- path: "mem_limit"
resourceFieldRef:
containerName: client-container
resource: limits.memory
divisor: 1Mi
- path: "mem_request"
resourceFieldRef:
containerName: client-container
resource: requests.memory
divisor: 1Mi
在这个配置文件中,你可以看到 Pod 有一个 downwardAPI 类型的卷,并且挂载到容器的 /etc/podinfo 目录。查看 downwardAPI 下面的 items 数组。每个数组元素都是一个 DownwardAPIVolumeFile。第一个元素指定名为 client-container 的容器中 limits.cpu 字段的值应保存在名为 cpu_limit 的文件中。
# 创建Pod
# kubectl apply -f test_pod3.yaml
pod/kubernetes-downwardapi-volume-example-2 created
# 查看pod是否运行正常
# kubectl get pods
NAME READY STATUS RESTARTS AGE
kubernetes-downwardapi-volume-example-2 1/1 Running 0 7s
# 打开一个 Shell,进入 Pod 中运行的容器
# kubectl exec -it kubernetes-downwardapi-volume-example-2 -- sh
# 在 Shell 中,查看 cpu_limit 文件
/ # cat /etc/podinfo/cpu_limit
250
/ #
# 可以使用同样的命令查看 cpu_request、mem_limit 和 mem_request 文件
Downward API 的能力
下面这些信息可以通过环境变量和 downwardAPI 卷提供给容器:
能通过 fieldRef 获得的:
- metadata.name - Pod 名称
- metadata.namespace - Pod 名字空间
- metadata.uid - Pod 的 UID
- metadata.labels[''] - Pod 标签 的值 (例如, metadata.labels['mylabel'])
- metadata.annotations[''] - Pod 的注解 的值(例如, - metadata.annotations['myannotation'])
能通过 resourceFieldRef 获得的:
- 容器的 CPU 约束值
- 容器的 CPU 请求值
- 容器的内存约束值
- 容器的内存请求值
- 容器的巨页限制值(前提是启用了 DownwardAPIHugePages 特性门控)
- 容器的巨页请求值(前提是启用了 DownwardAPIHugePages 特性门控)
- 容器的临时存储约束值
- 容器的临时存储请求值
此外,以下信息可通过 downwardAPI 卷从 fieldRef 获得:
- metadata.labels - Pod 的所有标签,以 label-key="escaped-label-value" 格式显示,每行显示一个标签
- metadata.annotations - Pod 的所有注解,以 annotation-key="escaped-annotation-value" 格式显示,每行显示一个标签
以下信息可通过环境变量获得:
- status.podIP - 节点 IP
- spec.serviceAccountName - Pod 服务帐号名称, 版本要求 v1.4.0-alpha.3
- spec.nodeName - 节点名称, 版本要求 v1.4.0-alpha.3
- status.hostIP - 节点 IP, 版本要求 v1.7.0-alpha.1
说明: 如果容器未指定 CPU 和内存限制,则 Downward API 默认将节点可分配值 视为容器的 CPU 和内存限制。
Downward API的动机
对于容器来说,有时候拥有自己的信息是很有用的,可避免与 Kubernetes 过度耦合。 Downward API 使得容器使用自己或者集群的信息,而不必通过 Kubernetes 客户端或 API 服务器来获得。
一个例子是有一个现有的应用假定要用一个非常熟悉的环境变量来保存一个唯一标识。 一种可能是给应用增加处理层,但这样是冗余和易出错的,而且它违反了低耦合的目标。 更好的选择是使用 Pod 名称作为标识,把 Pod 名称注入这个环境变量中。
Kubernetes(k8s)通过环境变量将 Pod 信息呈现给容器的更多相关文章
- kubernetes/k8s CRI分析-kubelet删除pod分析
关联博客<kubernetes/k8s CRI 分析-容器运行时接口分析> <kubernetes/k8s CRI分析-kubelet创建pod分析> 之前的博文先对 CRI ...
- Kubernetes K8S之通过yaml文件创建Pod与Pod常用字段详解
YAML语法规范:在kubernetes k8s中如何通过yaml文件创建pod,以及pod常用字段详解 YAML 语法规范 K8S 里所有的资源或者配置都可以用 yaml 或 Json 定义.YAM ...
- kubernetes/k8s CRI分析-kubelet创建pod分析
先来简单回顾上一篇博客<kubernetes/k8s CRI 分析-容器运行时接口分析>的内容. 上篇博文先对 CRI 做了介绍,然后对 kubelet CRI 相关源码包括 kubele ...
- android开发之java JDK环境变量配置的信息代码 附详细教程。
java环境变量配置: [用户变量]class_path .;%JAVA_HOME%\lib\tools;%JAVA_HOME%\jre PATH ;%JAVA_HOME%\ ...
- Mac下的Docker及Kubernetes(k8s)本地环境搭建与应用部署、管理界面kubernetes-dashboard
mac安装docker: brew cask install docker 当然也可以直接去官网下载docker的pkg文件安装 mac的docker国内镜像:网易的镜像地址:http://hub-m ...
- kubernetes容器编排之定义环境变量以及通过downwardapi把pod信息作为环境变量传入容器内
系列目录 在学习docker的时候,大家可能经常看到不少示例在docker run的时候指定环境变量(比如wordpress的docker示例就是通过环境变量传入账户和密码到容器内).这里之所以经常用 ...
- k8s 获取 Pod ip 添加到环境变量
0x00 事件 有一个需要将 Pod 自身的 ip 地址添加到环境变量的需求,可以在 yaml 文件的 env 中这样设置: env: - name: POD_OWN_IP_ADDRESS value ...
- pod(一):Kubernetes(k8s)创建pod的两种方式
目录 一.系统环境 二.前言 三.pod 四.创建pod 4.1 环境介绍 4.2 使用命令行的方式创建pod 4.2.1 创建最简单的pod 4.2.2 创建pod,指定镜像下载策略 4.2.3 创 ...
- Kubernetes K8S之存储ConfigMap详解
K8S之存储ConfigMap概述与说明,并详解常用ConfigMap示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master CentOS ...
随机推荐
- Oracle归档日志暴增排查优化
1.ORACLE归档日志介绍 归档日志暴增是oracle比较常见的问题,遇到归档日志暴增,我们该如何排查: 归档日志暴增一般都是应用或者人为引起的 理解归档日志存储的是什么 如何排查归档日志暴增原因 ...
- Ubuntu 隐藏所有窗口快捷键不生效问题
在绑定界面卡住时,切换到一个tty窗口,再切回来 gsettings reset-recursively org.gnome.settings-daemon.plugins.media-keys gs ...
- Leetcode 1331. 数组序号转换
给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号. 序号代表了一个元素有多大.序号编号的规则如下: 序号从 1 开始编号. 一个元素越大,那么序号越大.如果两个元素相等,那么它 ...
- ApiDay001 __02 Java_StringBuilder
Java 核心API StringBuilder String 类型的连接性能不好,Java提供了StringBuilder解决字符串连接性能问题. 简单理解 StringBuilder性能好!(重点 ...
- 爬虫部署 Gerapy 安装(centos 8)演示
一.安装 pip3 install -U gerapy 使用python3.68版本安装gerapy,报错提示:ModuleNotFoundError: No module named 'setupt ...
- Netty源码解读(一)-前置准备
前置条件 源码版本netty4.1 了解Java NIO.Reactor模型和Netty的基本使用. 解释一下: Java NIO:了解BIO和NIO的区别以及Java NIO基础API的使用 Rea ...
- MySQL Update执行流程解读
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 一.update跟踪执行配置 使用内部程序堆栈跟踪工具path_viewer,跟踪mysql update 一行数据的执行 ...
- HDU4348 To the moon (主席树)
标记永久化,除非想\(MLE\) 忽然感到主席树不过是函数式的树套树 #include <iostream> #include <cstdio> #include <cs ...
- vue 将markdown字符串转html、修改主题、生成目录
前言 将 markdown 字符串转成 html 显示出来,同时把目录也提取出来一起显示.可以使用 marked 来读取 markdown 字符串解析成 html marked官网:https://m ...
- mysql中文乱码--存入mysql里的中文变成问号的解决办法
今天,服务器里测试的时候,发现存入数据库的中文全部变成问号了! 首先想到这是编码问题:于是乎再次设置数据库的编码为utf8 可是,问题仍然存在: 后来发现,这个问题的根源应该是: 虽然数据库编码是ut ...