通过宿主机查看K8S或者是容器内的Java程序的简单方法
背景
最近一个项目的环境出现了 cannot create native process 的错误提示
出现这个错误提示时, docker exec 或者是 kube exec 进入容器/POD内部后,无法使用jstack等的命令.
然后想简单查看一下问题原因都无从下手.
这次报错的提示信息其实比较奇怪, 也是提示了OOM
但是看 K8S的监控 内存才 12G (POD限制内存27G) CPU都没有用到 1个核心(POD限制 6个CPU)
看到这些数据时感觉并没有出现堆区内存泄漏导致的OOM, 怀疑是线程池资源未回收导致的线程池数量到达上限.
不过一直是没有任何证据, 所以想想办法从外部进行一下信息的简要查看.
第一部分现成信息查看
容器是通过cgroup和namespace实现了资源限制和资源隔离.
虽然Java是跑在K8S管理下面的POD里面的, 但是实际上依旧是Linux系统里面的一个 process
所以理论上可以通过 host 查看 pod内的contianer的部分信息.
所以可以连上host K8S运行此应用的worker节点.
这里吐槽一下 美帝的政治正确下, master 节点都改名 control-plane 了. 不适应.
ps -ef |grep java 可以看到一个进程id
最简单的方法可以使用
top -Hp $pid -bn 1 > docker_jvm.info
就可以查看进程信息.
第二部分尝试进行dump的获取
先安装 gdb
yum install gdb -y
然后可以使用 gcore 命令
然后使用 gcore $pid 的方式形成 dump 文件
但是注意可能会失败
注意在执行gcore 之前需要先执行一下
ulimit -c unlimited
设置 core 无限制, 不然会报错:
warning: Memory read failed for corefile section, 1048576 bytes at 0x7fb380c18000.
具体的执行命令为:
ulimit -c unlimited
time gcore 3019830 -o core
注意这个命令非常耗时, 根据jvm占用内存大小不同而不同.
配置好的机器速度会快一些.
注意 可能会有一些报错:
warning: Target and debugger are in different PID namespaces; thread lists and other data are likely unreliable. Connect to gdbserver inside the container.
warning: Expected absolute pathname for libpthread in the inferior, but got target:/lib/x86_64-linux-gnu/libpthread.so.0.
容器内和host内的进程进行 core 获取是不太一样的.
Core转换为dump文件
之前之前总结过, 这里直接拿来.
需要注意, 如果是 jstack的话 需要安装如下的包才可以, 单独安装 java 是没有的
yum install java-1.8.0-openjdk-devel-*
jstack `which java` core.3019830
可以进行简单的查看
time jmap -dump:format=b,file=heap.hprof `which java` core.3019830
可以使用这个命令从 core文件中获取一下对应的jvm dump 文件.
获取之后就可以使用 mat jprofiler 工具进行分析了.
之前总结的地址:
https://mp.weixin.qq.com/s?__biz=MzU2MTA2MzQyNw==&mid=2247485503&idx=1&sn=5e8454f65a2e0c8dcb336b5ff295476b&chksm=fc7f3b53cb08b245bb02348687d6f7b400861f7b5409a340e103f452b37dea4f8c67e85c9434&token=1159504462&lang=zh_CN#rd
注意事项
除非是jdk的版本完全一样, 不然是无法解析的, 会报错:
sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
这是可以使用 docker 内部的 jdk进行相关的处理
方式为:
docker run -it -v /root:/root jdk:$tag
然后在内部执行就可以了
备注
可能依旧会失败. 并且转换的速度非常缓慢
[root@k8sipv6 ~]# docker exec -it tender_curran bash
root@ef38f1ee8e4f:~# ps -ef |grep jmap
root 33 1 99 17:07 pts/0 00:11:32 jmap -dump:format=b,file=heap.hprof /opt/java/openjdk/bin/java core.3019830
root 63 54 0 17:18 pts/1 00:00:00 grep jmap
可以看到会一直在进行转换, 速度其实挺慢的.
标签:java,查看,dump,宿主机,Java,docker,K8S,root
From: https://www.cnblogs.com/jinanxiaolaohu/p/17892940.html