对于某些需要调度之后才能知道的数据,比如 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 使用率了。

从应用访问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. ooday04 Java_面向对象_重写_static

    方法的重写(override/overriding):重新写.覆盖 发生在父子类中,方法名相同,参数列表相同 重写方法被调用时,看对象的类型------------这是规定,记住就OK 当派生类觉得超 ...

  2. 使用Huggingface在矩池云快速加载预训练模型和数据集

    作为NLP领域的著名框架,Huggingface(HF)为社区提供了众多好用的预训练模型和数据集.本文介绍了如何在矩池云使用Huggingface快速加载预训练模型和数据集. 1.环境 HF支持Pyt ...

  3. 实践GoF的23种设计模式:观察者模式

    摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...

  4. SQL Server、MySQL主从搭建,EF Core读写分离代码实现

    一.SQL Server的主从复制搭建 1.1.SQL Server主从复制结构图 SQL Server的主从通过发布订阅来实现 1.2.基于SQL Server2016实现主从 新建一个主库&quo ...

  5. 关于char[]数组通过scanf赋值使用上的一些问题。。

    关于char[]数组通过scanf赋值使用上的一些问题. 假如我们有这么一段代码 #include <stdio.h> int main(void){ char c1[2]; scanf( ...

  6. 先导,对IOC容器的理解

    先导,对IOC容器的理解 通俗的讲就是把你的class类交给spring的IOC容器去管理 需要对该类的属性注入一些值,就可以通过spring提供的xml文件或者注解进行注入 自己使用时在IOC容器工 ...

  7. Spring源码 20 手写模拟源码

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  8. Spring源码 04 IOC XML方式

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  9. 微信小程序/校园社区论坛/微信云开发/云函数

    一.框架来源 1.非常非常感谢B站up主"梦千的曾哥哥"的开源框架. 没有他就没有这个小程序.如果有想做的同学,可以直接移步他的视频那里开始学习.我水平不够,就不教具体怎么配置环境 ...

  10. 基于Anacoda搭建虚拟环境cudnn6.0+cuda8.0+python3.6+tensorflow-gpu1.4.0

    !一定要查准cudnn,cuda,tensorflow-gpu对应的版本号再进行安装,且本文一切安装均在虚拟环境中完成. 下文以笔者自己电脑为例,展开安装教程阐述(省略anaconda安装教程): 1 ...