如何从Kubernetes Pod中获取所属Deployment的注解?
确实,Downward API只能暴露Pod自身的元数据,没法直接拿到它所属Deployment的注解——这个问题我之前也帮人解决过,有两种比较靠谱的方案,看你的部署场景来选:
方法一:部署时将Deployment注解注入Pod(推荐,无额外容器)
如果你用Helm、Kustomize这类模板化工具管理Deployment,完全可以在Pod模板里动态把Deployment的deployment.kubernetes.io/revision注解值注入到Pod的环境变量或者本地文件里,这样Pod里的应用直接就能读。
用Helm实现的例子
Helm可以通过lookup函数查询集群里已存在的Deployment元数据,然后把注解值注入到Pod环境变量:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 3 template: spec: containers: - name: myapp image: myapp:latest env: - name: DEPLOYMENT_REVISION # 查询当前namespace下名为myapp的Deployment,提取revision注解 value: {{ (lookup "apps/v1" "Deployment" .Release.Namespace "myapp").metadata.annotations.deployment.kubernetes.io/revision }}
这样每次Helm部署/更新时,都会自动把Deployment的最新revision值注入到Pod里,应用直接通过环境变量$DEPLOYMENT_REVISION就能拿到。
纯YAML手动实现(适合测试场景)
如果不用模板工具,只能手动同步:每次更新Deployment后,把deployment.kubernetes.io/revision的值手动写到Pod模板的环境变量里,虽然繁琐但能满足需求:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp annotations: deployment.kubernetes.io/revision: "5" spec: replicas: 3 template: spec: containers: - name: myapp image: myapp:latest env: - name: DEPLOYMENT_REVISION value: "5"
方法二:用Sidecar/Init Container调用K8s API获取(无需模板工具)
如果不想依赖模板工具,可以给Pod加个Init Container(或者Sidecar),让它通过Kubernetes内部API去查询Deployment的注解,然后把值共享给主容器。
步骤1:给Pod授权读取Deployment
首先要给Pod的服务账号赋予读取Deployment的权限,创建对应的Role和RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: deployment-reader rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: namespace: default name: read-myapp-deployment subjects: - kind: ServiceAccount name: default # 用Pod默认的服务账号即可 namespace: default roleRef: kind: Role name: deployment-reader apiGroup: rbac.authorization.k8s.io
步骤2:在Deployment里添加Init Container
这个Init Container会在主容器启动前,通过K8s API找到当前Pod所属的Deployment,提取revision注解并写入共享卷,主容器直接读文件就行:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp annotations: deployment.kubernetes.io/revision: "5" spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: volumes: - name: revision-volume emptyDir: {} initContainers: - name: fetch-revision image: curlimages/curl:latest command: - sh - -c - | # 通过Pod的ownerReferences找到所属的Deployment名称 DEPLOYMENT_NAME=$(kubectl get pods ${HOSTNAME} -o jsonpath='{.metadata.ownerReferences[0].name}') # 提取Deployment的revision注解 REVISION=$(kubectl get deployment $DEPLOYMENT_NAME -o jsonpath='{.metadata.annotations.deployment\.kubernetes\.io/revision}') # 写入共享卷供主容器读取 echo $REVISION > /mnt/revision/deployment_revision volumeMounts: - name: revision-volume mountPath: /mnt/revision containers: - name: myapp image: myapp:latest volumeMounts: - name: revision-volume mountPath: /mnt/revision # 应用可以读取/mnt/revision/deployment_revision文件获取revision值
如果需要实时同步(比如Deployment更新后Pod重启时自动刷新),可以把Init Container换成Sidecar,定期执行上面的脚本更新文件。
内容的提问来源于stack exchange,提问作者Kir

