zoukankan      html  css  js  c++  java
  • 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 '
    ';
              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 '
    ';
              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 '
    
    '; cat /etc/podinfo/labels; fi;
              if [[ -e /etc/podinfo/annotations ]]; then
                echo -en '
    
    '; 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"}]}}
    "
    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"}]}}
    "
    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 '
    ';
              if [[ -e /etc/podinfo/cpu_limit ]]; then
                echo -en '
    '; cat /etc/podinfo/cpu_limit; fi;
              if [[ -e /etc/podinfo/cpu_request ]]; then
                echo -en '
    '; cat /etc/podinfo/cpu_request; fi;
              if [[ -e /etc/podinfo/mem_limit ]]; then
                echo -en '
    '; cat /etc/podinfo/mem_limit; fi;
              if [[ -e /etc/podinfo/mem_request ]]; then
                echo -en '
    '; 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 名称注入这个环境变量中。

  • 相关阅读:
    十分钟上手-搭建vue开发环境(新手教程)
    如何去掉bootstrap table中表格样式中横线竖线
    进阶攻略|前端最全的框架总结
    进阶攻略|前端完整的学习路线
    2018上半年GitHub上最热门的开源项目
    三分钟教你学会如何将密文解码成明文
    【前端图表】echarts实现散点图x轴时间轴
    IOS应用开发版本控制工具之Versions使用
    从零开始学ios开发(十七):Storyboards(上)
    ios按钮点击后翻转效果
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/14777018.html
Copyright © 2011-2022 走看看