对于某些需要调度之后才能知道的数据,比如 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. 破坏正方形UVA1603

    题目大意 有一个由火柴棍组成的边长为n的正方形网格,每条边有n根火柴,共2n(n+1)根火柴.从上至下,从左到右给每个火柴编号,现在拿走一些火柴,问在剩下的后拆当中ongoing,至少还要拿走多少根火 ...

  2. Nginx 的基本概念

    Nginx 简介 什么是 Nginx Nginx 是一个高性能的 HTTP 和 反向代理 web服务器 占用内存少,并发能力强,高性能,热部署 但不支持 Java,Java 得配合 tomcat 使用 ...

  3. YII自定义小部件

    案例如下 common/widgets/TopMenu.php(地址可以自定义位置,命名空间一定要对应) <?php /** * Created by PhpStorm. * Date: 201 ...

  4. Nginx api接口调用配置

    1 # Nginx api接口调用配置 2 3 # 什么是跨域同源? 4 # 同源策略:协议(http.https.wss--)+域名+端口=一个完整的网站 5 # 跨域:当前所在的网站post(ge ...

  5. 快速体验Spring Boot了解使用、运行和打包 | SpringBoot 2.7.2学习系列

    SpringBoot 2.7.2 学习系列,本节内容快速体验Spring Boot,带大家了解它的基本使用.运行和打包. Spring Boot 基于 Spring 框架,底层离不开 IoC.AoP ...

  6. 服务器配置IP

    1.服务器系统一般有两个或多个网卡.在企业中一般给服务器网卡配一个可连外网的IP,如172.16.20.22 255.255.255.0 172.16.20.1 方便联网下载安装部分软件,若没有VPN ...

  7. MySQL表操作过程的基础代码解析

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. MySQL 的表有很多种,对表的操作主要是增删改查,今天来浅谈一下这些操作的底层代码和流程,以下以 tmp table为例 ...

  8. B端产品需求分析与优先级判断

    需求分析是产品经理工作中的重要一部分,而对B端产品经理来说,因为业务的特殊性,所以需求分析更考验产品经理的基础能力比如还原场景中业务调研的能力.需求价值分析中对价值的界定等. B端厂商的产品需求多数来 ...

  9. 字符编码和python中的文件处理

    字符编码与python文件处理 ---------------- 字符编码 1.常见的编码 ASCII: 美国人发明的,只编码英文字母和符号,1个字节. GB2312: 中国人发明的,增加了中文汉字和 ...

  10. 开源云真机平台-Sonic应用实践

    前言 Sonic是一款开源.支持分布式部署.在线自动化测试的私有云真机平台.偶然接触到这个平台是源于虫师的一篇公众号文章<基于Linux 部署 Sonic>,于是结合文章内容和官网尝试搭建 ...