从应用访问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 使用率了。
从应用访问Pod元数据-DownwardApi的应用的更多相关文章
- Kubernetes学习笔记(七):访问Pod元数据与Kubernetes API
Downward API 我们已经了解到,使用ConfigMap和Secret向应用传递配置数据,这对于运行前预设的数据是可行的.但是对于那些不能预先知道的,就需要使用Downward API. Do ...
- kubernets之从应用访问pod元数据以及其他资源
一 downwardAPI的应用 1.1 前面我们介绍了如何通过configmap以及secret将配置传入到pod的容器中,但是传递的这些都是预先能够安排和只晓得,对于那些只有当pod创建起来之 ...
- spark on yarn模式下配置spark-sql访问hive元数据
spark on yarn模式下配置spark-sql访问hive元数据 目的:在spark on yarn模式下,执行spark-sql访问hive的元数据.并对比一下spark-sql 和hive ...
- 第六章 通过Service访问Pod(中)
6.2 Cluster IP 底层实现 Cluster IP 是一个虚拟IP,是由K8s节点上的iptables规则管理的. 使用类似轮询的方法访问Pod. 6.3 DNS 访问Service 在Cl ...
- 第六章 通过Service访问Pod(上)
不应该直接使用Pod的ID地址作为对外提供服务的接口,应为一旦Pod重启,IP地址就变化了,解决方案是使用Service. 6.1 创建Service K8s service从逻辑上代表了一组Pod, ...
- k8s如何访问pod
1. 通过 Service 访问 Pod 我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉.Deployment 等 control ...
- 如何访问Pod
本章看点: 理清Deployment,ReplicaSet和Pod的关系,以及三者之间的网络关系,ip地址和端口号 通过Pod进入docker容器修改里面的内容 外部网络访问Pod里面的应用 一.通过 ...
- 如何访问pod(6)
一.通过 Service 访问 Pod: 我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉.Deployment 等 control ...
- kubernetes如何访问pod服务
一.通过 Service 访问 Pod: 我们不应该期望 Kubernetes Pod 是健壮的,而是要假设 Pod 中的容器很可能因为各种原因发生故障而死掉.Deployment 等 control ...
随机推荐
- 零基础学Java(7)大数
大数 如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中两个很有用的类:BigInteger和BigDecimal.这两个类可以处理包含任意长度数字序列的数值.BigInte ...
- 微信小程序使用echarts/数据刷新重新渲染/图层遮挡问题
1.微信小程序使用echarts,首先下载echarts并导入小程序项目中,因小程序后期上线对文件大小有要求,所以建议进行定制下载导入可减少文件大小占比,也可以下载以前旧版本文件比较小的应付使用 下载 ...
- 006面试题__创建String对象
常见面试题: String s = new String("hello"); 问:创建了几个对象? 答:2个 1. 创建了一个字符常量池,指向了"hello"字 ...
- C++学习记录1
代码1:转义字符 点击查看代码 #include<iostream> using namespace std; void test01()//换行 { cout << &quo ...
- 算法竞赛进阶指南0x33同余
定义 如果整数a,b除以正整数m的余数相同,那么a,b模m同余 . 知识点 拓展欧几里得算法 代码 #include <bits/stdc++.h> using namespace std ...
- Mybatis源码解读-插件
插件允许对Mybatis的四大对象(Executor.ParameterHandler.ResultSetHandler.StatementHandler)进行拦截 问题 Mybatis插件的注册顺序 ...
- 基于gitlab 15.1 pages 搭建内部博客一定行版本
背景 基于 gitlab 15.1版 pages 搭建内部博客,参考官方文档,遇到一个又一个坑.之前看到别人吐槽说 gitlab 官方文档很差,我算是理解了.下面一个个说. 开始 按照官方文档的说法, ...
- python os相关操作
python os模块常用操作 什么时候使用os模块? 操作文件及文件夹(对于文件及文件夹的增删改查) 1.获取当前文件夹的工作目录 注意不是当前文件所在文件,即当前执行python文件的文件夹 pr ...
- 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...
- WPF 截图控件之画笔(八)「仿微信」
前言 接着上周写的截图控件继续更新添加 画笔. 1.WPF实现截屏「仿微信」 2.WPF 实现截屏控件之移动(二)「仿微信」 3.WPF 截图控件之伸缩(三) 「仿微信」 4.WPF 截图控件之绘制方 ...