简化 Pod 故障诊断:kubectl-debug 介绍

640?wx_fmt=jpeg


背景

640?wx_fmt=png


容器技术的一个最佳实践是构建尽可能精简的容器镜像。但这一实践却会给排查问题带来麻烦:精简后的容器中普遍缺失常用的排障工具,部分容器里甚至没有 shell (比如 FROM scratch )。在这种状况下,我们只能通过日志或者到宿主机上通过 docker-cli 或 nsenter 来排查问题,效率很低。Kubernetes 社区也早就意识到了这个问题,在 16 年就有相关的 Issue Support for troubleshooting distroless containers[1] 并形成了对应的 Proposal[2]。遗憾的是,由于改动的涉及面很广,相关的实现至今还没有合并到 Kubernetes 上游代码中。而在 一个偶然的机会下(PingCAP 一面要求实现一个 kubectl 插件实现类似的功能),我开发了 kubectl-debug[2]:通过启动一个安装了各种排障工具的容器,来帮助诊断目标容器。
工作原理

640?wx_fmt=png


我们先不着急进入 Quick Start 环节。kubectl-debug 本身非常简单,因此只要理解了它的工作原理,你就能完全掌握这个工具,并且还能用它做 debug 之外的事情。
我们知道,容器本质上是带有 Cgroup 资源限制和 Namespace 隔离的一组进程。因此,我们只要启动一个进程,并且让这个进程加入到目标容器的各种 Namespace 中,这个进程就能 “进入容器内部”(注意引号),与容器中的进程”看到”相同的根文件系统、虚拟网卡、进程空间了——这也正是 docker exec 和 kubectl exec 等命令的运行方式。
现在的状况是,我们不仅要 “进入容器内部”,还希望带一套工具集进去帮忙排查问题。那么,想要高效管理一套工具集,又要可以跨平台,最好的办法就是把工具本身都打包在一个容器镜像当中。接下来,我们只需要通过这个”工具镜像”启动容器,再指定这个容器加入目标容器的的各种 namespace,自然就实现了 “携带一套工具集进入容器内部”。事实上,使用 docker-cli 就可以实现这个操作:
export TARGET_ID=666666666	
# 加入目标容器的 network, pid 以及 ipc namespace	
docker run -it --network=container:$TARGET_ID --pid=container:$TARGET_ID --ipc=container:$TARGET_ID busybox

这就是 kubectl-debug 的出发点:用工具容器来诊断业务容器 。背后的设计思路和 sidecar 等模式是一致的:每个容器只做一件事情。
具体到实现上,一条 kubectl debug命令背后是这样的:
640?wx_fmt=jpeg
步骤分别是:
  1. 插件查询 ApiServer:demo-pod 是否存在,所在节点是什么

  2. ApiServer 返回 demo-pod 所在所在节点

  3. 插件请求在目标节点上创建 Debug Agent Pod

  4. Kubelet 创建 Debug Agent Pod

  5. 插件发现 Debug Agent 已经 Ready,发起 debug 请求(长连接)

  6. Debug Agent 收到 debug 请求,创建 Debug 容器并加入目标容器的各个 Namespace 中,创建完成后,与 Debug 容器的 tty 建立连接


接下来,客户端就可以开始通过 5,6 这两个连接开始 debug 操作。操作结束后,Debug Agent 清理 Debug 容器,插件清理 Debug Agent,一次 Debug 完成。效果如下图:
640?wx_fmt=gif
开始使用

640?wx_fmt=png


Mac 可以直接使用 brew 安装:
brew install aylei/tap/kubectl-debug

所有平台都可以通过下载 binary 安装:
export PLUGIN_VERSION=0.1.1	
# linux x86_64	
curl -Lo kubectl-debug.tar.gz https://github.com/aylei/kubectl-debug/releases/download/v${PLUGIN_VERSION}/kubectl-debug_${PLUGIN_VERSION}_linux_amd64.tar.gz	
# macos	
curl -Lo kubectl-debug.tar.gz https://github.com/aylei/kubectl-debug/releases/download/v${PLUGIN_VERSION}/kubectl-debug_${PLUGIN_VERSION}_darwin_amd64.tar.gz	
tar -zxvf kubectl-debug.tar.gz kubectl-debug	
sudo mv kubectl-debug /usr/local/bin/

Windows 用户可以在 Release 页面[4]进行下载。
下载完之后就可以开始使用 debug 插件:
kubectl debug target-pod --agentless --port-forward
kubectl 从 1.12 版本之后开始支持从 PATH 中自动发现插件。1.12 版本之前的 kubectl 不支持这种插件机制,但也可以通过命令名 kubectl-debug 直接调用。可以参考项目的中文 README[5]来获得更多文档和帮助信息。
典型案例

640?wx_fmt=png


基础排障
kubectl debug 默认使用 nicolaka/netshoot[6] 作为默认的基础镜像,里面内置了相当多的排障工具,包括:
使用 iftop 查看容器网络流量:
➜  ~ kubectl debug demo-pod	
root @ /	[2] ?  → iftop -i eth0	
interface: eth0	
IP address is: 10.233.111.78	
MAC address is: 86:c3:ae:9d:46:2b	
# (图片略去)

使用 drill 诊断 DNS 解析:
root @ /	[3] ?  → drill -V 5 demo-service	
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0	
;; flags: rd ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0	
;; QUESTION SECTION:	
;; demo-service.    IN  A	
;; ANSWER SECTION:	
;; AUTHORITY SECTION:	
;; ADDITIONAL SECTION:	
;; Query time: 0 msec	
;; WHEN: Sat Jun  1 05:05:39 2019	
;; MSG SIZE  rcvd: 0	
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 62711	
;; flags: qr rd ra ; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0	
;; QUESTION SECTION:	
;; demo-service.    IN  A	
;; ANSWER SECTION:	
;; AUTHORITY SECTION:	
.    30  IN  SOA a.root-servers.net. nstld.verisign-grs.com. 2019053101 1800 900 604800 86400	
;; ADDITIONAL SECTION:	
;; Query time: 58 msec	
;; SERVER: 10.233.0.10	
;; WHEN: Sat Jun  1 05:05:39 2019	
;; MSG SIZE  rcvd: 121

使用 tcpdump 抓包:
root @ /	[4] ?  → tcpdump -i eth0 -c 1 -Xvv	
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes	
12:41:49.707470 IP (tos 0x0, ttl 64, id 55201, offset 0, flags [DF], proto TCP (6), length 80)	demo-pod.default.svc.cluster.local.35054 > 10-233-111-117.demo-service.default.svc.cluster.local.8080: Flags [P.], cksum 0xf4d7 (incorrect -> 0x9307), seq 1374029960:1374029988, ack 1354056341, win 1424, options [nop,nop,TS val 2871874271 ecr 2871873473], length 28	0x0000:  4500 0050 d7a1 4000 4006 6e71 0ae9 6f4e  E..P..@.@.nq..oN	0x0010:  0ae9 6f75 88ee 094b 51e6 0888 50b5 4295  ..ou...KQ...P.B.	0x0020:  8018 0590 f4d7 0000 0101 080a ab2d 52df  .............-R.	0x0030:  ab2d 4fc1 0000 1300 0000 0000 0100 0000  .-O.............	0x0040:  000e 0a0a 08a1 86b2 ebe2 ced1 f85c 1001  .............\..	
1 packet captured	
11 packets received by filter	
0 packets dropped by kernel

访问目标容器的根文件系统:
容器技术(如 Docker)利用了 /proc 文件系统提供的 /proc/{pid}/root/ 目录实现了为隔离后的容器进程提供单独的根文件系统(root filesystem)的能力(就是 chroot 一下)。当我们想要访问 目标容器的根文件系统时,可以直接访问这个目录:
root @ /	[5] ?  → tail -f /proc/1/root/log_	
Hello, world!

这里有一个常见的问题是 free top 等依赖 /proc 文件系统的命令会展示宿主机的信息,这也是容器化过程中开发者需要适应的一点(当然了,各种 runtime 也要去适应,比如臭名昭著的 Java 8u121 以及更早的版本不识别 cgroups 限制[7]问题就属此列)。
诊断 CrashLoopBackoff
排查 CrashLoopBackoff 是一个很麻烦的问题,Pod 可能会不断重启, kubectl exec 和 kubectl debug 都没法稳定进行排查问题,基本上只能寄希望于 Pod 的日志中打印出了有用的信息。为了让针对 CrashLoopBackoff 的排查更方便, kubectl-debug 参考 oc debug 命令,添加了一个 --fork 参数。当指定 --fork 时,插件会复制当前的 Pod Spec,做一些小修改, 再创建一个新 Pod:
  • 新 Pod 的所有 Labels 会被删掉,避免 Service 将流量导到 fork 出的 Pod 上

  • 新 Pod 的 ReadinessProbe 和 LivnessProbe 也会被移除,避免 kubelet 杀死 Pod

  • 新 Pod 中目标容器(待排障的容器)的启动命令会被改写,避免新 Pod 继续 Crash


接下来,我们就可以在新 Pod 中尝试复现旧 Pod 中导致 Crash 的问题。为了保证操作的一致性,可以先 chroot 到目标容器的根文件系统中:
➜  ~ kubectl debug demo-pod --fork	
root @ /	[4] ?  → chroot /proc/1/root	
root @ /	[#] ?  → ls	bin            entrypoint.sh  home           lib64          mnt            root           sbin           sys            tmp            var	dev            etc            lib            media          proc           run            srv            usr	
root @ /	[#] ?  → ./entrypoint.sh	
# 观察执行启动脚本时的信息并根据信息进一步排障

结尾的碎碎念

640?wx_fmt=png


kubectl-debug 一开始只是 PingCAP 在面试时出的 homework,第一版完成在去年年底。当时整个项目还非常粗糙,不仅文档缺失,很多功能也都有问题:
  • 不支持诊断 CrashLoopBackoff 中的 Pod

  • 强制要求预先安装一个 Debug Agent 的 DaemonSet

  • 不支持公有云(节点没有公网 IP 或公网 IP 因为防火墙原因无法访问时,就无法 debug)

  • 没有权限限制,安全风险很大


而让我非常兴奋的是,在我无暇打理项目的情况下,隔一两周就会收到 Pull Request 的通知邮件,一直到今天,大部分影响基础使用体验的问题都已经被解决, kubectl-debug 也发布了 4 个版本(0.0.1, 0.0.2, 0.1.0, 0.1.1)。尤其要感谢 @tkanng,TA 在第一个 PR 时还表示之前没有写过 Go, 而在 0.1.1 版本中已经是这个版本绝大部分 feature 的贡献者,解决了好几个持续很久的 issue,感谢!
最后再上一下项目地址:https://github.com/aylei/kubectl-debug
假如在使用上或者对项目本身有任何问题,欢迎提交 issue,也可以在 文章评论区留言讨论。
相关链接:
  1. https://github.com/kubernetes/kubernetes/issues/27140

  2. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/troubleshoot-running-pods.md

  3. https://github.com/aylei/kubectl-debug

  4. https://github.com/aylei/kubectl-debug/releases/tag/v0.1.1

  5. https://github.com/aylei/kubectl-debug/blob/master/docs/zh-cn.md

  6. https://github.com/nicolaka/netshoot

  7. https://blog.softwaremill.com/docker-support-in-new-java-8-finally-fd595df0ca54


原文链接:https://aleiwu.com/post/kubectl-debug-intro/

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314951.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dotnet 新项目格式与对应框架预定义的宏

在 sdk style 的项目格式支持使用多框架开发&#xff0c;此时需要在代码里面通过宏判断&#xff0c;在编译的时候执行不同的代码。本文告诉大家在框架里面对应的预定义的条件编译符有哪些在让一个 csproj 项目指定多个开发框架 - walterlv告诉大家如何在 sdk style 项目格式如何…

TPL Dataflow .Net 数据流组件,了解一下?

作为单体程序&#xff0c;依赖的第三方服务虽不多&#xff0c;但是2C的程序还是有不少内容可讲&#xff1b;作为一个常规互联网系统&#xff0c;无外乎就是接受请求、处理请求&#xff0c;输出响应。由于业务渐渐增长&#xff0c;数据处理的过程会越来越复杂和冗长&#xff0c;…

Educational Codeforces Round 76 (Rated for Div. 2) F. Make Them Similar 折半搜索

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 一个显然的思路就是2302^{30}230枚举所有的xxx&#xff0c;让后再检查&#xff0c;这个复杂度显然不能接受。 又发现对于每个位置它取多少不受其他位置限制&#xff0c;满足可拼接性&#…

windows container 踩坑记

windows container 踩坑记Intro我们有一些服务是 dotnet framework 的&#xff0c;不能直接跑在 docker linux container 下面&#xff0c;最近一直在折腾把它部署在 windows container 下&#xff0c;折腾的有点恶心&#xff0c;记录一下。Windows Container 介绍Windows Cont…

小白开学Asp.Net Core 《七》

小白开学Asp.Net Core 《七》— — 探究中间件&#xff08;MiddleWare&#xff09;1、何为中间件&#xff1f;中间件是组装到应用程序管道中以处理请求和响应的家伙&#xff0c;管道中的每个组件都要满足以下两个条件选择是否将请求传递给管道中的下一个组件可以在调用管道中的…

aspnetcore 实现简单的伪静态化

aspnetcore 实现简单的伪静态化Intro在我的活动室预约项目中&#xff0c;有一个公告模块&#xff0c;类似于新闻发布&#xff0c;个人感觉像新闻这种网页基本就是发布的时候编辑一次之后就再也不会改了&#xff0c;最适合静态化了&#xff0c; 静态化之后用户请求的就是静态文件…

#530. 「LibreOJ β Round #5」最小倍数 二分 + 数论

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 本来想刷数位dpdpdp&#xff0c;无意间碰到了这个题来水水。 我们知道n!n!n!中质因子ppp的个数为∑i1npi\sum_{i1} \frac{n}{p^i}∑i1​pin​&#xff0c;所以我们就可以二分nnn&#xff0…

《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文

写在开始三年前,曾写过一篇文章:从.NET和Java之争谈IT这个行业,当时遭到某些自认为懂得java就了不起的Javaer抨击,现在可以致敬伟大的.NET斗士甲骨文了  (JDK8以上都需要收费,Android弃用java作为第一语言,别高兴:OpenJDK是甲骨文的).《ASP.NET Core 高性能系列》是一套如何编…

Codeforces Round #599 (Div. 2) E. Sum Balance 图转换 + 子集dp + 环

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 首先我们知道如果所有数的和summodk!0sum\bmod k!0summodk!0那么此时无解&#xff0c;否则我们设needsum/kneedsum/kneedsum/k。 看到kkk这么小&#xff0c;自然的想到是否能状压&#xff…

资深开发者们是如何读书的?---线下读书会记录

读了多少书&#xff1f;怎么读书&#xff1f;——请问大家最近读书了吗&#xff1f;一年大概读了多少本书。有超过20本&#xff0c;超过30本&#xff0c;超过50本吗&#xff1f;在7月14日由长沙互联网活动基地和长沙.NET技术社区组织的小型社区活动&#xff0c;《开发者爱读书•…

架构杂谈《三》

一致性问题前面的《架构杂谈一》和《架构杂谈二》 杂谈了从服务化到微服务架构的演进&#xff0c;并肯定了服务化和微服务架构是一脉相承的。微服务在服务化架构的基础上&#xff0c;对服务化的细节和方案进行了优化和细化&#xff0c;重点突出了无中心化管理的微服务架构&…

腾讯发布 Tencent SCF Toolkit VS Code 插件,轻松开发无服务器云函数

在之前的文章中&#xff0c;我们提到了亚马逊、谷歌、IBM 等大厂都上了 Visual Studio Code 的船。阿里巴巴也在近日发布了 Aliyun Serverless VS Code 插件。近期&#xff0c;腾讯也上了 VS Code 的船&#xff0c;发布了基于 VS Code 的 Tencent SCF Toolkit 插件&#xff0c;…

端到端测试实践:Jenkins集成TestCafe

上一篇《对产品质量的一点思考》中说到自动化测试的重要性&#xff0c;本文简单介绍下怎样在实际项目中实现端到端测试的自动化&#xff0c;在这里我们使用的端到端测试工具是TestCafe。环境Jenkisn&#xff1a;2.183TestCafe&#xff1a;1.3.0为什么采用TestCafe做自动化测试要…

再见Jenkins,从Gitlab代码提交到k8s服务持续交付只需七毛三

Gitlab runner 快速搭建CICD pipeline背景日常开发中&#xff0c;相信大家已经做了很多的自动化运维环境&#xff0c;用的最多的想必就是利用Jenkins实现代码提交到自动化测试再到自动化打包&#xff0c;部署全流水线Jenkins在devops担任了很重要的角色&#xff0c;但是另一方面…

.NET Core 3.0之深入源码理解Kestrel的集成与应用(二)

前言前一篇文章主要介绍了.NET Core继承Kestrel的目的、运行方式以及相关的使用&#xff0c;接下来将进一步从源码角度探讨.NET Core 3.0中关于Kestrel的其他内容&#xff0c;该部分内容&#xff0c;我们无需掌握&#xff0c;依然可以用好Kestrel&#xff0c;本文只是将一些内部…

译 | 使用Roslyn分析器高效编写更好的代码

原文&#xff1a;Mika Dumont翻译&#xff1a;汪宇杰Roslyn 是 .NET 编译器平台&#xff0c;即使在运行代码之前&#xff0c;它也能帮助您捕获 Bug。例如内置于 Visual Studio 中的Roslyn 拼写检查分析器。假设您正在创建一个静态方法&#xff0c;并将 static 单词拼错为 statc…

Codeforces Round #724 (Div. 2) F. Omkar and Akmar 组合数学 + 博弈

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 首先我们先来研究一下这个游戏&#xff0c;手画几个会惊奇的发现&#xff0c;后手这个b怎么怎么画都赢啊&#xff1f;&#xff1f;&#xff1f;对&#xff0c;没错&#xff0c;就是怎么画都…

Visual Studio 支持 Java?谣言止于智者

在去年的某一段时间内&#xff0c;我们经常会看到标题类似为“宇宙第一 IDE Visual Studio 支持 Java 了&#xff01;”的文章。当时&#xff0c;韩老师看到这篇文章也是一脸懵逼。公司里做 Java 的开发童鞋们就坐在韩老师附近&#xff08;嗯&#xff0c;不超过五米的距离&…

Codeforces Round #597 (Div. 2) D. Shichikuji and Power Grid 最小生成树 + 虚拟点

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 看错题导致误入歧途&#xff0c;如果能早点看见翻译也不至于一天多也没想出来。 求联通的最小代价&#xff0c;自然的想到了能不能建边跑最小生成树。 对于两点之间比较好弄&#xff0c;直…

小白开学Asp.Net Core 《八》

小白开学Asp.Net Core 《八》— — .Net Core 数据保护组件1、背景我在搞&#xff08;https://github.com/AjuPrince/Aju.Carefree&#xff09;这个开源项目的时候&#xff0c;想做一些防止恶意攻击的小功能&#xff08;如果 我通过页面 /Dome/GetData?id123&#xff0c;那是不…