Kubernetes 教程:根据 PID 获取 Pod 名称
原文链接:https://fuckcloudnative.io/posts/find-kubernetes-pod-info-from-process-id/
在管理 Kubernetes 集群的过程中,我们经常会遇到这样一种情况:在某台节点上发现某个进程资源占用量很高,却又不知道是哪个容器里的进程。有没有办法可以根据 PID 快速找到 Pod 名称呢?
假设现在有一个 prometheus 进程的 PID 是 14338:

为了进一步挖掘信息,有两种思路,一种是挖掘 PID 对应的容器的信息,另一种是挖掘 PID 对应的 Pod 的信息。
1. Container ID
要获取容器的 ID,可以查看 PID 对应的 cgroup 信息:
$ cat /proc/14338/cgroup
11:blkio:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
10:cpuset:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
9:freezer:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
8:hugetlb:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
7:perf_event:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
6:cpuacct,cpu:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
5:pids:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
4:devices:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
3:net_prio,net_cls:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
2:memory:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
1:name=systemd:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/d6f24b62ea28e9e67f7bc06f98de083cc49454f353389cd396f5d3ac6448f19c
可以看到该进程对应的容器 ID 为 d6f24b62...,可以再优化一下上面的命令,直接获取容器 ID:
$ CID=$(cat /proc/14338/cgroup | awk -F '/' '{print $5}')
$ echo ${CID:0:8}
d6f24b62
最后一步根据容器 ID 获取 Pod 名称,如果你的容器运行时是 containerd 或 crio,可以使用 crictl 来获取容器信息:
# Go Template
$ crictl inspect -o go-template --template='{{index .status.labels "io.kubernetes.pod.name"}}' d6f24b62
prometheus-k8s-0
# jq
$ crictl inspect d6f24b62|jq '.status.labels["io.kubernetes.pod.name"]'
"prometheus-k8s-0"
使用 Go template 或 jq 都能获取 Pod 名称,看个人喜好。
如果你的容器运行时是 Docker,可以使用命令行工具 docker 来获取,方法和上面类似。
2. Pod UID
下面来看看第二种方法,先根据 PID 直接获取 Pod UID:
$ cat /proc/14338/mountinfo | grep "etc-hosts" | awk -F / {'print $6'}
8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1
然后根据 Pod UID 获取 Pod 名称:
$ crictl ps -o json | jq '.[][].labels | select (.["io.kubernetes.pod.uid"] == "8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1") | .["io.kubernetes.pod.name"]'|uniq
"prometheus-k8s-0"
3. 整合
方法是有了,怎么才能将所有的步骤合并成一个步骤,一步到位获取 Pod 名称呢?可以在 ~/.bashrc 中添加一个 shell 函数,选择上面的方法 1,并使用 go template 来格式化(你也可以使用上面提到的其他方法,但需要安装 jq):
podinfo() {
CID=$(cat /proc/$1/cgroup | awk -F '/' '{print $5}')
CID=$(echo ${CID:0:8})
crictl inspect -o go-template --template='{{index .status.labels "io.kubernetes.pod.name"}}' $CID
}
执行下面的命令使修改立即生效:
$ source ~/.bashrc
然后就可以使用该函数来获取 Pod 名称啦:
$ podinfo 14338
prometheus-k8s-0
4. 举一反三
这个思路也可以用来解决其他问题,大家要学会举一反三,我举个例子。Kubernetes 中的很多组件都是通过 HTTPS 协议来暴露指标,比如 kubelet,那么如何使用 API 来访问这些指标呢?
先选取一个容器,比如 prometheus,找到它的 PID:
$ ps -ef|grep "/bin/prometheus"
1000 14338 14246 4 7月10 ? 04:29:02 /bin/prometheus --web.console.templates=/etc/prometheus/consoles --web.console.libraries=/etc/prometheus/console_libraries --config.file=/etc/prometheus/config_out/prometheus.env.yaml --storage.tsdb.path=/prometheus --storage.tsdb.retention.time=24h --web.enable-lifecycle --storage.tsdb.no-lockfile --web.route-prefix=/
1000 14402 14246 0 7月10 ? 00:00:10 /bin/prometheus-config-reloader --log-format=logfmt --reload-url=http://localhost:9090/-/reload --config-file=/etc/prometheus/config/prometheus.yaml.gz --config-envsubst-file=/etc/prometheus/config_out/prometheus.env.yaml
root 15956 555 0 18:19 pts/0 00:00:00 grep --color=auto /bin/prometheus
根据 PID 找到 Pod UID:
$ cat /proc/14338/mountinfo | grep "etc-hosts" | awk -F / {'print $6'}
8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1
根据 Pod UID 找到 Service Account 的 token 挂载目录:
$ ll /var/lib/kubelet/pods/8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/volumes/kubernetes.io~secret/prometheus-k8s-token-p7bgb/
总用量 0
lrwxrwxrwx 1 root root 13 7月 10 21:24 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 7月 10 21:24 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 7月 10 21:24 token -> ..data/token
获取 token 信息:
$ export TOKEN=$(cat /var/lib/kubelet/pods/8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/volumes/kubernetes.io~secret/prometheus-k8s-token-p7bgb/token)
通过 curl 直接访问指标:
$ curl -s -H "Authorization: Bearer $TOKEN" --cacert /var/lib/kubelet/pods/8e018a8e-4aaa-4ac6-986a-1a5133a4bcf1/volumes/kubernetes.io~secret/prometheus-k8s-token-p7bgb/ca.crt --insecure https://127.0.0.1:10250/metrics/cadvisor
当然,如果你能找到集群管理员的证书、密钥和 CA 证书,也可以直接使用它们来访问,我就不展开说了。
5. 真奇技淫巧
最后再介绍一个思路清奇的方案,虽然有点小瑕疵,但思路很巧妙,大家可以借鉴一下。Kubernetes 创建的容器中的主机名对应的就是 Pod 名称,沿着这个思路,我们可以得到一个更巧妙的方法,通过 PID 的 uts namespace 来获得容器的主机名,进而就可以知道 Pod 名称,具体可以借助 nsenter 这个工具:
$ nsenter -t 14338 --uts hostname
prometheus-k8s-0
这么一看,确实比上面的方法优雅多了,但这个方法会有一点小问题,当容器使用 HostNetwork 模式运行时,hostname 是宿主机的 hostname,通过这种方法就得不到 Pod 名称。虽然不是通用的方法,但思路还是可以借鉴的,除了使用 nsenter 获取主机名外,还可以通过环境变量来获取,命令如下:
$ xargs -0 -L1 -a /proc/14338/environ | grep HOSTNAME
HOSTNAME=prometheus-k8s-0
解释一下这几个参数:
- -0 : 表示使用
null作为分隔符 - -L : 表示指定多少行作为一个命令行参数。-L1 就表示指定 1 行作为命令行参数,即每一行分别运行一次命令。xargs 的作用就是将标准输入转换为命令行参数,如果 xargs 后面没有跟上真正要执行的命令,就表示使用默认的
echo。所以这里的-L1就表示分隔出来的每一行分别运行一次echo命令。 - -a : 从文件中读取内容,而不是从标准输入读取。
如果你还不理解,好吧我尽力了。
最后再推荐一个项目,可以找到所有容器的 PID 以及对应的 Pod 信息,项目地址:pid2pod。
Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12离线安装包发布地址http://store.lameleg.com ,欢迎体验。 使用了最新的sealos v3.3.6版本。 作了主机名解析配置优化,lvscare 挂载/lib/module解决开机启动ipvs加载问题, 修复lvscare社区netlink与3.10内核不兼容问题,sealos生成百年证书等特性。更多特性 https://github.com/fanux/sealos 。欢迎扫描下方的二维码加入钉钉群 ,钉钉群已经集成sealos的机器人实时可以看到sealos的动态。

Kubernetes 教程:根据 PID 获取 Pod 名称的更多相关文章
- Kubernetes家族容器小管家Pod在线答疑?
Kubernetes家族容器小管家Pod在线答疑 不知道学习k8s的小伙伴们有没有跟我一样的疑问? k8s为什么不是直接运行容器,而是让Pod介入? Pod又是什么?为什么在应用容器化如此普遍的情况下 ...
- Atitit,通过pid获取进程文件路径 java php c#.net版本大总结
Atitit,通过pid获取进程文件路径 java php c#.net版本大总结 1. 通过PID获取进程路径的几种方法2 1.1. GetModuleFileNameEx 想获得进程可执行文件的 ...
- Kubernetes中资源清单与Pod的生命周期(二)
一.资源清单 1,定义: 在k8s中一般使用yaml格式的文件来创建符合我们预期的资源,这样的yaml被称为资源清单. 使用资源清单创建Pod: kubectl apply -f nginx.yaml ...
- Downward API —— 在容器内部获取 Pod 信息
我们知道,每个 Pod 在被超过创建出来之后,都会被系统分配唯一的名字.IP地址,并且处于某个 Namespace 中,那么我们如何在 Pod 的容器内获取 Pod 的这些重要信息呢? 答案就是使用 ...
- Android 获取渠道名称
直接看代码, //获取渠道名称public static String getChannelName(Activity ctx) { if (ctx == null) { return null; } ...
- 【转】 C# 小技巧之获取变量名称
link: http://www.cnblogs.com/gongy/p/lm-2015-04-03.html 今天在自我规范程序设计的时候,变量名匹配字符串来自配置文件,网上找了一会儿发现也有朋友在 ...
- 通过PID获取进程路径的几种方法
通过PID获取进程路径的几种方法 想获得进程可执行文件的路径最常用的方法是通过GetModuleFileNameEx函数获得可执行文件的模块路径这个函数从Windows NT 4.0开始到现在的Vis ...
- 根据UserAgent 获取操作系统名称
/// <summary> /// 根据 User Agent 获取操作系统名称 /// </summary> private sta ...
- delphi根据进程PID获取程序所在路径的函数(用OpenProcess取得句柄,用GetModuleFileNameEx取得程序名)
uses psapi; {根据进程PID获取程序所在路径的函数}function GetProcessExePath(PID: Cardinal): string;varpHandle: THandl ...
随机推荐
- node+ajax实战案例(4)
4.用户登录实现 4.1.用户登录实现思路 1 用户输入登录信息,点击登录的时候把用户登录的这些信息收集起来,然后组装数据通过ajax方式发送到后台 2 后台接到用户输入的登录信息,把这些信息拿去和数 ...
- 堆、栈、数据区、bss、代码段
一个程序的运行是需要内存的,那么我们平常写的程序的内存都是怎么分配的呢 (1)首先我们要知道,内存是真实存在的,内存是一个物理器件.它时由操作系统管理的,我们平常只要使用它就行了,为了方便管理.操作系 ...
- 什么是DevOps?该如何正确的在企业内进行实践
传统IT技术团队中通常都有多个独立的组织-开发团队.测试团队和运维团队.开发团队进行软件开发.测试团队进行软件测试,运维团队致力于部署,负载平衡和发布管理. 他们之间的职能有时重叠.有时依赖.有时候会 ...
- python 的迭代
字典的迭代: #创建字典 dict={'a':1,'b':2,'c':3} #key和value的迭代 for key,value in dict.items(): print(key,':',val ...
- 多线程01-CAS (CompareAndSwap)
1.基本概念 原子性是不可中断的最小操作:在Java中,一般通过加锁或者自旋CAS方式来确保原子操作: 而CAS(compareAnd swap)作为Java中常用的保证原子性的手段,JDK1.5之后 ...
- Problem C Emergency Evacuation 一道思维题
题目描述 输入 输出 样例 样例输入 样例输入一 样例输入二 样例输出 样例输出一 9 样例输出二 1008 一句话题意:给你一个车厢和一些人,这些人都坐在座位上,求这些人全部出去的时间最小值. 分析 ...
- 如何查询到你的wifi所在的公网ip?
浏览器中输入:ip138.com 即可查询到.
- 06 Vue生命周期钩子
生命周期钩子 表示一个vue实例从创建到销毁的这个过程,将这个过程的一些时间节点赋予了对应的钩子函数 钩子函数: 满足特点条件被回调的方法 new Vue({ el: "#app" ...
- Python 读取Excel之xlrd篇
上一期给大家分享了如何用Python读取文本,这次给大家分享如何读取Excel表格内容,拿最常见的.xlsx和.xls格式来讲解. 本章主要知识点有: 读取整篇excel返回list[list[lis ...
- 机器学习实战基础(十七):sklearn中的数据预处理和特征工程(十)特征选择 之 Embedded嵌入法
Embedded嵌入法 嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和算法训练同时进行.在使用嵌入法时,我们先使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值系数从大 ...