一些应用需要具备 self-aware 能力,获取关于自身的一些信息。Kubernetes 的 Downward API 就提供了一种简单的将元数据注入到应用中的机制。
大多数云原生应用都是无状态的,没有与其他应用相关的标识。然而,即便是这些应用,有时候也需要使用应用自身及其运行环境的信息。包括一些只有在运行时才能知道的数据,比如 Pod 名称(有随机后缀)、Pod IP(重启会变化)和应用程序所在的主机名等;或者在 Pod 级别定义的静态信息比如对特定资源的需求和限制;又或者一些动态信息如注释和标签,可以由用户在运行时更改。
这些元数据适用于多种不同的场景,比如基于容器可用的资源,我们可能需要优化应用的 thread-pool 大小,或更改垃圾收集算法、内存分配等。在记录日志或发送 metrics 到监控服务器时需要 Pod 名称、hostname。
上述需求并不只存在于容器中,对于资源元数据会发生变化的任何动态环境都是成立的。比如 AWS 就提供了 Instance Metadata 和 User Data 服务,可以在任意 EC2 实例上访问从而获取关于自身的元数据。
Kubernetes 的思路则更加优雅和易于使用。Downward API 允许通过环境变量和文件将 Pod 的元数据传递给容器。同使用 ConfigMap 和 Secrets 传递应用相关的数据是相同的原理,只不过这些数据都不是用户创建的。
我们只需要指定我们想要获取的信息的 key,Kubernetes 就会动态地填充这些值。
重点在于通过 Downward API,元数据注入到 Pod 中并且本地可用,应用并不需要一个类似客户端的东西与 Kubernetes API 交互。
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: MEMORY_LIMIT
valueFrom:
resourceFieldRef:
container: random-generator
resource: limits.memory
上述配置使用 fieldRef
访问 Pod 级别的元数据。fieldRef.fieldPath
支持的键值如下表:
Name | Description |
---|---|
spec.nodeName | Name of node hosting the Pod |
status.hostIP | IP address of node hosting the Pod |
metadata.name | Pod name |
metadata.namespace | Namespace in which the Pod is running |
status.podIP | Pod IP address |
spec.serviceAccountName | ServiceAccount that is used for the Pod |
metadata.uid | Unique ID of the Pod |
metadata.labels['key'] | Value of the Pod’s label key |
metadata.annotations['key'] | Value of the Pod’s annotation key |
resourceFieldRef.resource
支持的键值如下表:
Name | Description |
---|---|
requests.cpu | A container’s CPU request |
limits.cpu | A container’s CPU limit |
limits.memory | A container’s memory request |
requests.memory | A container’s memory limit |
用户可以在 Pod 运行时修改特定的元数据比如 lable 和 annotation。除非 Pod 重启,环境变量不会反映这些改动。
但是 downwardAPI
卷能够反映 label 和 annotation 的改动,通过 metadata.labels
和 metadata.annotations
捕获所有的 label 和 annotation 信息。
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
volumeMounts:
- name: pod-info
mountPath: /pod-info
volumes:
- name: pod-info
downwardAPI:
items:
- path: labels
fieldRef:
fieldPath: metadata.labels
- path: annotations
fieldRef:
fieldPath: metadata.annotations
Downward API 上的值能够作为文件 mount 到 Pod 中,labels
文件包含所有的 label,以 name=value
的格式逐行保存。当 label 变动时,此文件的内容也会跟着变化。
通过 downwardAPI
卷,元数据在 Pod 运行时的变化会反映到挂载的文件中。当然应用同时需要具备检测到此文件改动的功能,若此功能不具备,则重启 Pod 仍旧是必须的操作。
总结
在很多场景下,应用都需要是 self-aware 的,能够获取关于自身及运行环境的信息。Kubernetes 的 Downward API 为自省和元数据注入提供了一种非侵入的方式。它的一个缺点在于只提供了固定数量的 key,如果应用需要更多数据,尤其是关于其他资源或集群的元数据,则必须从 API Server 处查询。