对于某些需要调度之后才能知道的数据,比如 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. 001 Redis 配置

    Redis缓存 1.配置Redis //Redis 配置文件 @Configuration public class RedisConfiguration { @Bean public RedisTe ...

  2. day10 Map_查找与遍历

    Map 查找表 Map体现的结构是一个多行两列的表格,其中左列称为key,右列称为value. Map总是成对保存数据,并且总是根据key获取对应的value.因此我们可以将查询的条件作为key查询对 ...

  3. Webpack干货系列 | 在 Webpack 5 集成 ESLint 的方法

    程序员优雅哥(youyacoder)简介:十年程序员,呆过央企外企私企,做过前端后端架构.分享vue.Java等前后端技术和架构. 本文摘要:主要讲解运用Webpack 5 中集成 ESLint 的方 ...

  4. .net core3.1 abp学习开始(一)

    vs版本 2019,链接数据库使用Navicat,数据库MySql abp的官网:https://aspnetboilerplate.com/,我们去Download这里下载一个模板,需要选好Targ ...

  5. PHP断点续传(下载)代码

    <?php /** * PHP-HTTP断点续传实现 * @param string $path: 文件所在路径 * @param string $file: 文件名 * @return voi ...

  6. Java基础 | Stream流原理与用法总结

    Stream简化元素计算: 一.接口设计 从Java1.8开始提出了Stream流的概念,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式:依旧先看核心接口的设计: BaseStream: ...

  7. Luogu P5030 长脖子鹿放置(网络流)

    匈牙利T了,Dinic飞了... 按奇偶连 #include <cstdio> #include <iostream> #include <cstring> #in ...

  8. 如何开发一款基于 Vite+Vue3 的在线表格系统(上)

    今天,葡萄带你了解如何基于Vite+Vue3实现一套纯前端在线表格系统. 在正式开始项目介绍之前,首先咱们首先来介绍一下Vite和Vue3. Vue3 Vue是什么?大多前端开发者对这个词已毫不陌生了 ...

  9. 基础1:JS的原型和原型链究竟

    JS的原型和原型链究竟是什么? 1. 从JS创建一个对象开始说起: 1.1 工厂模式创建对象 (缺点是无法知道创建出来的对象是一个什么类型的对象) function createPerson(name ...

  10. C#.NET ORM FreeSql 读取使用 US7ASCII 的 Oracle 数据库中文显示乱码问题

    前言 关于 Oracle US7ASCII 中文乱码的问题,Ado.Net 和 Odbc 无法解决.包括最新的.Net Core..NET6..NET7 都无法解决这个问题. FreeSql 对 Or ...