• 从应用访问Pod元数据-DownwardApi的应用


    对于某些需要调度之后才能知道的数据,比如 pod 的 ip,主机名,或者 pod 自身的名称等等,k8s 依旧很贴心的提供了 Downward API 的方式来获取此类数据,并且可以通过环境变量或者文件(downwardApi卷中)来传递 pod 的元数据。

    可以传递的容器数据包括如下:

    • pod的名称,IP,所在命名空间,运行节点的名称,运行所归属的服务账户名称
    • 每个容器请求的 CPU 和内存的使用量
    • 每个容器可以使用的 CPU 和内存的限制
    • pod 的标签
    • pod 的注解

     

    通过环境变量暴露元数据

      创建一个但容器的 pod

    复制代码
    $ vim ./dowanwardapi-learn.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: downward-learn
    spec:
      containers:
      - name: main
        image: busybox
        command: ["sleep", "999999"]
        resources:
          requests:
            cpu: "15m"
            memory: "100Ki"
          limits:
            cpu: "100m"
            memory: "4Mi"
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: CONTAINER_CPU_REQUEST_MILLICORES
          valueFrom:
            resourceFieldRef:
              resource: requests.cpu
              divisor: "1m"
        - name: CONTAINER_MEMORY_LIMIT_KIBIBYTES
          valueFrom:
            resourceFieldRef:
              resource: limits.memory
              divisor: "1Ki"
    复制代码

      创建完成后我们可以使用 kubectl exec 命令来查看容器中的所有环境变量,如下:

    复制代码
    $ kubectl exec downward-learn env
    kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=downward-learn
    POD_NAME=downward-learn
    POD_IP=10.44.0.3
    NODE_NAME=node1
    CONTAINER_CPU_REQUEST_MILLICORES=15
    CONTAINER_MEMORY_LIMIT_KIBIBYTES=4096
    KUBERNETES_PORT_443_TCP_PROTO=tcp
    KUBERNETES_PORT_443_TCP_PORT=443
    KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
    KUBERNETES_SERVICE_HOST=10.96.0.1
    KUBERNETES_SERVICE_PORT=443
    KUBERNETES_SERVICE_PORT_HTTPS=443
    KUBERNETES_PORT=tcp://10.96.0.1:443
    KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
    HOME=/root
    复制代码

      但是有一些变量并不能根据环境变量暴露,比如 lables 标签和 annotations 注释等等,但是这些可以使用过 dowanwardApi 卷的方式来进行载入。

     

    通过 downwardAPI 卷来传递元数据

      和环境变量一样,通过文件卷的方式也需要显式指定元数据字段来暴露给进程,如下:

    复制代码
    apiVersion: v1
    kind: Pod
    metadata:
      name: downward-learn
    spec:
      containers:
      - name: main
        image: busybox
        command: ["sleep", "999999"]
        resources:
          requests:
            cpu: "15m"
            memory: "100Ki"
          limits:
            cpu: "100m"
            memory: "4Mi"
        volumeMounts:
        - name: downward
          mountPath: /etc/downard
      volumes:
      - name: downward
        downwardAPI:
          iterms:
          - path: "podName"
            fileRef:
              fieldPath: metadata.name
    ......    
    复制代码

      其中声明元数据和配置的方式没什么不同。

      但是其中需要注意的是,如果是暴露容器级的元数据时,比如容器可使用的资源限制和资源请求(如使用字段 resourceFieldRef),必须指定引入资源字段的容器名称,比如:

    复制代码
    spec:
      volumes:
      - name: downward
        downwardAPI:
          items:
          - path: "containerCpuRequestMilliCores"
            resourceFieldRef: 
              containerName: main      ## 容器名称
              resource: requests.cpu
              divisor: 1m
    复制代码

      这里由于引入了cpu资源限制,所以也贴一下所用到的,在 pod 内查询当前的 cpu 使用进程代码,因为 pod 容器内的查询 cpu 使用和物理机上的还不太一样,在网上找了一些但是都不太适合容器使用,所以自己写了一个

    复制代码
    $ vim cpu.go

    package handler import (
    "fmt" "os" linuxproc "github.com/c9s/goprocinfo/linux" ) var ( prevUsageUser int64 = 0 prevUsageSystem int64 = 0 cpuNum = 1 // 设置该容器内使用的cpu个数 ) func GetCpuCount(stat *linuxproc.Stat) (count float64) { cfsQuota := getCgoupValueByPath("/sys/fs/cgroup/cpu/cpu.cfs_quota_us") cfsPeriod := getCgoupValueByPath("/sys/fs/cgroup/cpu/cpu.cfs_period_us") if cfsQuota == -1 { return float64(len(stat.CPUStats)) } return float64(cfsQuota) / float64(cfsPeriod) } func CpuCountToString(c float64) string { if c == float64(int64(c)) { return fmt.Sprintf("%v", c) } return fmt.Sprintf("%0.1f", c) } // GetCpuUsage should be called every 1 seconds. not quite precise. func GetCpuUsage(cpus float64) (user, system, idle float64) { var currentUsageUser, currentUsageSystem int64 currentUsageUser = getCgoupValueByPath("/sys/fs/cgroup/cpuacct/cpuacct.usage_user") currentUsageSystem = getCgoupValueByPath("/sys/fs/cgroup/cpuacct/cpuacct.usage_sys") if prevUsageUser == 0 && prevUsageSystem == 0 { prevUsageUser = currentUsageUser prevUsageSystem = currentUsageSystem return } user = float64(currentUsageUser-prevUsageUser) / 10000000 / cpus // / 1000,000,000 * 100 = /10,000,000 system = float64(currentUsageSystem-prevUsageSystem) / 10000000 / cpus // / 1000,000,000 * 100 = /10,000,000 idle = 100 - user - system if idle < 0 { idle = 0 } prevUsageUser = currentUsageUser prevUsageSystem = currentUsageSystem return } func getCgoupValueByPath(path string) int64 { data, err := os.ReadFile(path) if err != nil { return 0 } var value int64 n, err := fmt.Sscanf(string(data), "%d", &value) if err != nil || n != 1 { return 0 } return value }
    复制代码

    计算出来当前的容器数值换算为:use 80% = 800

    这样在容器内就能根据元数据和监控脚本时刻监控容器的 cpu 使用率了。


    __EOF__

  • 本文作者: Blackbinbin
  • 本文链接: https://www.cnblogs.com/blackbinbin/p/16686167.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    【Lua基础 第3章】变量、赋值语句、索引、lua中的循环、循环控制语句
    DataWorks概述
    找工作小项目:day16-重构核心库、使用智能指针(3)
    阿里云App备案详细流程_APP备案问题解答
    windows实现自动化按键
    Linux应用基础——串口应用编程
    自行车轴承市场调研:预计2028年将达到25.6亿美元
    Spring boot 整合 JWT
    公网ip和私网ip的区别
    FPGA运算
  • 原文地址:https://www.cnblogs.com/blackbinbin/p/16686167.html