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

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

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

通过环境变量暴露元数据

  创建一个但容器的 pod

  1. $ vim ./dowanwardapi-learn.yaml
  2.  
  3. apiVersion: v1
  4. kind: Pod
  5. metadata:
  6. name: downward-learn
  7. spec:
  8. containers:
  9. - name: main
  10. image: busybox
  11. command: ["sleep", "999999"]
  12. resources:
  13. requests:
  14. cpu: "15m"
  15. memory: "100Ki"
  16. limits:
  17. cpu: "100m"
  18. memory: "4Mi"
  19. env:
  20. - name: POD_NAME
  21. valueFrom:
  22. fieldRef:
  23. fieldPath: metadata.name
  24. - name: POD_IP
  25. valueFrom:
  26. fieldRef:
  27. fieldPath: status.podIP
  28. - name: NODE_NAME
  29. valueFrom:
  30. fieldRef:
  31. fieldPath: spec.nodeName
  32. - name: CONTAINER_CPU_REQUEST_MILLICORES
  33. valueFrom:
  34. resourceFieldRef:
  35. resource: requests.cpu
  36. divisor: "1m"
  37. - name: CONTAINER_MEMORY_LIMIT_KIBIBYTES
  38. valueFrom:
  39. resourceFieldRef:
  40. resource: limits.memory
  41. divisor: "1Ki"

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

  1. $ kubectl exec downward-learn env
  2. kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
  3. PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  4. HOSTNAME=downward-learn
  5. POD_NAME=downward-learn
  6. POD_IP=10.44.0.3
  7. NODE_NAME=node1
  8. CONTAINER_CPU_REQUEST_MILLICORES=15
  9. CONTAINER_MEMORY_LIMIT_KIBIBYTES=4096
  10. KUBERNETES_PORT_443_TCP_PROTO=tcp
  11. KUBERNETES_PORT_443_TCP_PORT=443
  12. KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
  13. KUBERNETES_SERVICE_HOST=10.96.0.1
  14. KUBERNETES_SERVICE_PORT=443
  15. KUBERNETES_SERVICE_PORT_HTTPS=443
  16. KUBERNETES_PORT=tcp://10.96.0.1:443
  17. KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
  18. HOME=/root

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

通过 downwardAPI 卷来传递元数据

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

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: downward-learn
  5. spec:
  6. containers:
  7. - name: main
  8. image: busybox
  9. command: ["sleep", "999999"]
  10. resources:
  11. requests:
  12. cpu: "15m"
  13. memory: "100Ki"
  14. limits:
  15. cpu: "100m"
  16. memory: "4Mi"
  17. volumeMounts:
  18. - name: downward
  19. mountPath: /etc/downard
  20. volumes:
  21. - name: downward
  22. downwardAPI:
  23. iterms:
  24. - path: "podName"
  25. fileRef:
  26. fieldPath: metadata.name
  27. ......

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

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

  1. spec:
  2. volumes:
  3. - name: downward
  4. downwardAPI:
  5. items:
  6. - path: "containerCpuRequestMilliCores"
  7. resourceFieldRef:
  8. containerName: main ## 容器名称
  9. resource: requests.cpu
  10. divisor: 1m

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

  1. $ vim cpu.go

    package handler
  2.  
  3. import (
  4. "fmt"
  5. "os"
  6.  
  7. linuxproc "github.com/c9s/goprocinfo/linux"
  8. )
  9.  
  10. var (
  11. prevUsageUser int64 = 0
  12. prevUsageSystem int64 = 0
  13. cpuNum = 1 // 设置该容器内使用的cpu个数
  14. )
  15.  
  16. func GetCpuCount(stat *linuxproc.Stat) (count float64) {
  17. cfsQuota := getCgoupValueByPath("/sys/fs/cgroup/cpu/cpu.cfs_quota_us")
  18. cfsPeriod := getCgoupValueByPath("/sys/fs/cgroup/cpu/cpu.cfs_period_us")
  19.  
  20. if cfsQuota == -1 {
  21. return float64(len(stat.CPUStats))
  22. }
  23.  
  24. return float64(cfsQuota) / float64(cfsPeriod)
  25. }
  26.  
  27. func CpuCountToString(c float64) string {
  28. if c == float64(int64(c)) {
  29. return fmt.Sprintf("%v", c)
  30. }
  31. return fmt.Sprintf("%0.1f", c)
  32. }
  33.  
  34. // GetCpuUsage should be called every 1 seconds. not quite precise.
  35. func GetCpuUsage(cpus float64) (user, system, idle float64) {
  36. var currentUsageUser, currentUsageSystem int64
  37. currentUsageUser = getCgoupValueByPath("/sys/fs/cgroup/cpuacct/cpuacct.usage_user")
  38. currentUsageSystem = getCgoupValueByPath("/sys/fs/cgroup/cpuacct/cpuacct.usage_sys")
  39.  
  40. if prevUsageUser == 0 && prevUsageSystem == 0 {
  41. prevUsageUser = currentUsageUser
  42. prevUsageSystem = currentUsageSystem
  43. return
  44. }
  45.  
  46. user = float64(currentUsageUser-prevUsageUser) / 10000000 / cpus // / 1000,000,000 * 100 = /10,000,000
  47. system = float64(currentUsageSystem-prevUsageSystem) / 10000000 / cpus // / 1000,000,000 * 100 = /10,000,000
  48. idle = 100 - user - system
  49. if idle < 0 {
  50. idle = 0
  51. }
  52.  
  53. prevUsageUser = currentUsageUser
  54. prevUsageSystem = currentUsageSystem
  55.  
  56. return
  57. }
  58.  
  59. func getCgoupValueByPath(path string) int64 {
  60. data, err := os.ReadFile(path)
  61. if err != nil {
  62. return 0
  63. }
  64.  
  65. var value int64
  66. n, err := fmt.Sscanf(string(data), "%d", &value)
  67. if err != nil || n != 1 {
  68. return 0
  69. }
  70. return value
  71. }

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

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

从应用访问Pod元数据-DownwardApi的应用的更多相关文章

  1. Kubernetes学习笔记(七):访问Pod元数据与Kubernetes API

    Downward API 我们已经了解到,使用ConfigMap和Secret向应用传递配置数据,这对于运行前预设的数据是可行的.但是对于那些不能预先知道的,就需要使用Downward API. Do ...

  2. kubernets之从应用访问pod元数据以及其他资源

    一  downwardAPI的应用 1.1  前面我们介绍了如何通过configmap以及secret将配置传入到pod的容器中,但是传递的这些都是预先能够安排和只晓得,对于那些只有当pod创建起来之 ...

  3. spark on yarn模式下配置spark-sql访问hive元数据

    spark on yarn模式下配置spark-sql访问hive元数据 目的:在spark on yarn模式下,执行spark-sql访问hive的元数据.并对比一下spark-sql 和hive ...

  4. 第六章 通过Service访问Pod(中)

    6.2 Cluster IP 底层实现 Cluster IP 是一个虚拟IP,是由K8s节点上的iptables规则管理的. 使用类似轮询的方法访问Pod. 6.3 DNS 访问Service 在Cl ...

  5. 第六章 通过Service访问Pod(上)

    不应该直接使用Pod的ID地址作为对外提供服务的接口,应为一旦Pod重启,IP地址就变化了,解决方案是使用Service. 6.1 创建Service K8s service从逻辑上代表了一组Pod, ...

  6. k8s如何访问pod

    1. 通过 Service 访问 Pod 我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉.Deployment 等 control ...

  7. 如何访问Pod

    本章看点: 理清Deployment,ReplicaSet和Pod的关系,以及三者之间的网络关系,ip地址和端口号 通过Pod进入docker容器修改里面的内容 外部网络访问Pod里面的应用 一.通过 ...

  8. 如何访问pod(6)

    一.通过 Service 访问 Pod: 我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉.Deployment 等 control ...

  9. kubernetes如何访问pod服务

    一.通过 Service 访问 Pod: 我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉.Deployment 等 control ...

随机推荐

  1. 零基础学Java(7)大数

    大数 如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中两个很有用的类:BigInteger和BigDecimal.这两个类可以处理包含任意长度数字序列的数值.BigInte ...

  2. 微信小程序使用echarts/数据刷新重新渲染/图层遮挡问题

    1.微信小程序使用echarts,首先下载echarts并导入小程序项目中,因小程序后期上线对文件大小有要求,所以建议进行定制下载导入可减少文件大小占比,也可以下载以前旧版本文件比较小的应付使用 下载 ...

  3. 006面试题__创建String对象

    常见面试题: String s = new String("hello"); 问:创建了几个对象? 答:2个 1. 创建了一个字符常量池,指向了"hello"字 ...

  4. C++学习记录1

    代码1:转义字符 点击查看代码 #include<iostream> using namespace std; void test01()//换行 { cout << &quo ...

  5. 算法竞赛进阶指南0x33同余

    定义 如果整数a,b除以正整数m的余数相同,那么a,b模m同余 . 知识点 拓展欧几里得算法 代码 #include <bits/stdc++.h> using namespace std ...

  6. Mybatis源码解读-插件

    插件允许对Mybatis的四大对象(Executor.ParameterHandler.ResultSetHandler.StatementHandler)进行拦截 问题 Mybatis插件的注册顺序 ...

  7. 基于gitlab 15.1 pages 搭建内部博客一定行版本

    背景 基于 gitlab 15.1版 pages 搭建内部博客,参考官方文档,遇到一个又一个坑.之前看到别人吐槽说 gitlab 官方文档很差,我算是理解了.下面一个个说. 开始 按照官方文档的说法, ...

  8. python os相关操作

    python os模块常用操作 什么时候使用os模块? 操作文件及文件夹(对于文件及文件夹的增删改查) 1.获取当前文件夹的工作目录 注意不是当前文件所在文件,即当前执行python文件的文件夹 pr ...

  9. 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...

  10. WPF 截图控件之画笔(八)「仿微信」

    前言 接着上周写的截图控件继续更新添加 画笔. 1.WPF实现截屏「仿微信」 2.WPF 实现截屏控件之移动(二)「仿微信」 3.WPF 截图控件之伸缩(三) 「仿微信」 4.WPF 截图控件之绘制方 ...