【问题标题】:Set node label to the pod environment variable将节点标签设置为 pod 环境变量
【发布时间】:2023-03-24 11:56:01
【问题描述】:

如何将 Node 标签设置为 Pod 环境变量?我需要知道 pod 内的标签 topology.kubernetes.io/zone 值。

【问题讨论】:

    标签: kubernetes


    【解决方案1】:

    Downward API 目前不支持将节点信息暴露给 Pod/容器。在 GitHib 上有一个 open issue 关于它,但目前还不清楚它何时会实现。

    这就留下了从 Kubernetes API 获取节点标签的唯一选择,就像 kubectl 所做的那样。这并不容易实现,尤其是如果您希望将标签作为环境变量。我会给你一个例子,如何使用 initContainer、curl 和 jq 来完成它,但如果可能的话,我建议你宁愿在你的应用程序中实现它,因为它会更容易和更干净。

    要请求标签,您需要获得相应权限。因此,下面的示例创建了一个具有get(描述)节点权限的服务帐户。然后,initContainer 中的脚本使用服务帐户发出请求并提取标签。 test 容器从文件中读取环境变量和echo 一个。

    例子:

    # Create a service account
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: describe-nodes
      namespace: <insert-namespace-name-where-the-app-is>
    ---
    # Create a cluster role that allowed to perform describe ("get") over ["nodes"]
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: describe-nodes
    rules:
      - apiGroups: [""]
        resources: ["nodes"]
        verbs: ["get"]
    ---
    # Associate the cluster role with the service account
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: describe-nodes
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: describe-nodes
    subjects:
    - kind: ServiceAccount
      name: describe-nodes
      namespace: <insert-namespace-name-where-the-app-is>
    ---
    # Proof of concept pod
    apiVersion: v1
    kind: Pod
    metadata:
      name: get-node-labels
    spec:
      # Service account to get node labels from Kubernetes API
      serviceAccountName: describe-nodes
    
      # A volume to keep the extracted labels
      volumes:
        - name: node-info
          emptyDir: {}
    
      initContainers:
        # The container that extracts the labels
        - name: get-node-labels
    
          # The image needs 'curl' and 'jq' apps in it
          # I used curl image and run it as root to install 'jq'
          # during runtime
          # THIS IS A BAD PRACTICE UNSUITABLE FOR PRODUCTION
          # Make an image where both present.
          image: curlimages/curl
          # Remove securityContext if you have an image with both curl and jq
          securityContext:
            runAsUser: 0
    
          # It'll put labels here
          volumeMounts:
            - mountPath: /node
              name: node-info
    
          env:
            # pass node name to the environment
            - name: NODENAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: APISERVER
              value: https://kubernetes.default.svc
            - name: SERVICEACCOUNT
              value: /var/run/secrets/kubernetes.io/serviceaccount
            - name: SCRIPT
              value: |
                set -eo pipefail
    
                # install jq; you don't need this line if the image has it
                apk add jq
    
                TOKEN=$(cat ${SERVICEACCOUNT}/token)
                CACERT=${SERVICEACCOUNT}/ca.crt
    
                # Get node labels into a json
                curl --cacert ${CACERT} \
                     --header "Authorization: Bearer ${TOKEN}" \
                     -X GET ${APISERVER}/api/v1/nodes/${NODENAME} | jq .metadata.labels > /node/labels.json
    
                # Extract 'topology.kubernetes.io/zone' from json
                NODE_ZONE=$(jq '."topology.kubernetes.io/zone"' -r /node/labels.json)
                # and save it in a file in a format suitable for sourcing
                echo "export NODE_ZONE=${NODE_ZONE}" > /node/zone
          command: ["/bin/ash", "-c"]
          args:
            - 'echo "$$SCRIPT" > /tmp/script && ash /tmp/script'
    
      containers:
        # The container that need the label value
        - name: test
          image: debian:buster
          command: ["/bin/bash", "-c"]
          # source ENV variable from file, echo NODE_ZONE, and keep running doing nothing
          args: ["source /node/zone && echo $$NODE_ZONE && cat /dev/stdout"]
          volumeMounts:
            - mountPath: /node
              name: node-info
    

    【讨论】:

      【解决方案2】:

      你可以使用InitContainer

      ...
      spec:
            initContainers:
            - name: node2pod
              image: <image-with-k8s-access>
              env:
              - name: NODE_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: spec.nodeName
             ...
      

      参考:Node Label to Pod


      编辑更新

      类似的解决方案可能是Inject node labels into Kubernetes pod

      【讨论】:

        猜你喜欢
        • 2014-04-14
        • 2021-03-09
        • 1970-01-01
        • 2019-06-10
        • 1970-01-01
        • 1970-01-01
        • 2019-02-09
        相关资源
        最近更新 更多