您须要了解的有关调试Docker容器的知识

调试Docker容器多是一个很是具备挑战性的过程。在这里,我将分享一些调试容器的基本技术,主要是Docker的技术,可是这些技术也适用于许多其余类型的Linux容器引擎。我将在此处详细介绍的方法适用于基于Linux的系统。html

撰写此博客文章的灵感来自于externalsecret-operator 的开发团队在实施1password后端期间遇到的一些近期问题,该库提供了与1password API进行通讯的机制。linux

提供一些背景信息:externalsecret-operator是一个很棒的Kubernetes operator,它使secret管理的挑战性下降,并帮助您未来自第三方凭证存储的秘密直接注入到Kubernetes集群中。 (若是您尚未据说过,那么绝对值得尝试一下。咱们的团队正在努力开发它,而且每周都会添加新功能。)git

可是回到调试。在如下状况下,若是咱们在主机上运行operator,那么一切都会按预期进行,而且能够登陆到1password后端:github

docker-debugging-1.png

可是在容器中运行时,咱们会看到如下错误消息:docker

docker-debugging-2.png

看起来没有正常运行,可是咱们应该如何以及在哪里开始调试?shell

从代码分析开始

最好的起点老是源代码,而且由于externalsecret-operator是开源的,因此咱们能够很容易地看到问题出在哪里。我建议使用Sourcegraph工具,该工具可直接在浏览器中工做而且能够进行代码分析。使用Sourcegraph识别代码中有问题的部分的示例:segmentfault

source.jpg

这种快速的代码分析显示出一个好消息和一个坏消息:幸运的是,由于咱们的代码不是问题的根源。但也很不幸,由于1password客户端二进制文件(op)用于直接从1password秘密存储区中获取凭证-不幸的是,这两个都不是开源的。后端

这才是真正的乐趣开始的地方。浏览器

调试在主机系统上有效但在容器中不起做用的那些东西的线索是了解什么是容器。容器是一种在同一主机上运行时将进程彼此隔离的机制,这意味着其管理员能够直接从主机系统访问任何容器。网络

有了这些知识,让咱们看看1password二进制文件是否损坏。首先,咱们必须验证咱们的1password二进制文件不适用于容器的理论是否有效。让咱们手动使用它,使用伪造的登陆数据:

docker-debugging-3.png

答对了!咱们的理论获得证明。 1password二进制文件不适用于该容器;恐慌而不是优雅地退出。如今咱们有了这些信息,咱们应该确认问题是二进制自己仍是容器环境形成的。最好的方法是从新使用与容器镜像中彻底相同的二进制文件。开始吧!

假设咱们对正在运行容器的主机具备root访问权,那么咱们可使用docker top <container id>来查看主机上有问题的容器的PID(进程标识符)是什么:
docker-debugging-4.png

咱们肯定了容器PID,所以如今能够在Linux系统进程表中找到此进程。进入process目录后,咱们应该查看根文件夹,由于它是包含正在运行的容器的文件系统的根文件夹:
docker-debugging-5.png

检查operator

咱们能够访问容器中的全部二进制文件,并在主机名称空间中执行它们。

所以,让咱们看看operator的问题是否来自使用错误的1password二进制文件:
docker-debugging-6.png

1password op二进制文件的行为正确:因为咱们提供了虚假数据,所以没法登陆1password域,但最终并无收到紧急消息。所以,问题不在1password二进制文件以内。

咱们能够看到主机名称空间中的执行错误消息提到了有关无效请求的内容。咱们可能会怀疑容器中的网络是否存在问题,以及操做二进制的panic,若是它没法到达某些外部服务时,这是另外一个须要测试的理论。

如前所述,1password二进制文件不是开源的,所以咱们没法知道它在哪里尝试链接。咱们能够尝试使用Wireshark或tcpdump等网络嗅探器捕获流量。但…

docker-debugging-7.png

…容器镜像不包含任何这些二进制文件。咱们能够将它们安装在Docker镜像中。可是,因为咱们具备对主机的root访问权限,所以能够经过使用nsenter来更轻松地进行操做。

nsenter工具容许咱们输入特定的进程名称空间-所以,例如,咱们能够输入容器的网络名称空间,而且仍然能够访问咱们的宿主工具。让咱们看看实际状况:
docker-debugging-8.png

咱们位于容器网络名称空间中,能够从主机系统访问全部工具。

在另外一个shell中,咱们可使用容器中的op二进制文件再次登陆1password。可是,即便已链接到互联网,也没有生成任何数据包:

docker-debugging-9.png

从新排查1Password Binary

所以,在这一点上,咱们能够假设op二进制panic甚至在创建与外部服务的链接以前就已出现。

如今,咱们能够尝试使用GDB(GNU项目调试器)调试op二进制文件,以查看执行失败的时间。可是1password可能不包含调试符号,所以GBD没法为咱们提供有关执行的任何信息。经过检查操做二进制文件中是否存在调试符号来进行确认:

docker-debugging-10.png

如所假定的,op二进制根本没有调试符号。若是它具备这些符号,那么在几行中将显示除零之外的数字,如在运算符中同样。使用GDB没有任何意义。

另外,GDB不支持跨命名空间调试,所以不可能从主机命名空间中对其进行调试。咱们将必须在Docker映像中安装GDB或从源代码编译GDB

咱们没法使用GDB,但能够在此过程当中“strace”或跟踪系统调用和信号:查看执行二进制文件中op二进制文件调用了哪些系统调用。为此,咱们运行另外一个具备相同镜像的容器,但修改后的入口点将直接指向op二进制文件,并使用先前使用的参数:
docker-debugging-11.png

在另外一个Shell窗口中,咱们将附加到该容器的PID并输入密码:
docker-debugging-12.png

咱们发现它存在一些严重的问题。二进制文件尝试在仅容许超级用户的文件系统的根目录/中建立.op目录:

mkdirat(AT_FDCWD,“ /.op”,0700)= -1 EACCES(权限被拒绝)

让咱们检查一下若是以root用户身份运行此容器会发生什么状况:

run-as-root copy.png

Binary并无panic,而strace代表op实际上试图在超级用户主目录而不是/中建立.op二进制文件。

strace-as-root.png

这使咱们得出结论,即默认用户可能在Docker镜像中配置错误。让咱们检查一下:

docker-debugging-13.png

答对了! / etc / passwd中缺乏默认用户,系统没法识别该默认用户,所以op binary没法肯定其主目录,并尝试在当前工做目录中建立目录。这是不容许的。所以,它会panic。

咱们永远不会忘记Docker容器只是进程,大多数Linux标准调试工具均可以在它们上使用,并消除猜想驱动的调试。

我想再次强调,这些技术主要适用于Linux系统。可是对于那些在Mac上运行容器的人,我建议您研究其余技术,例如使用全部调试工具运行sidecar容器。不管使用什么系统,祝您调试侦探工做顺利!

相关文章
相关标签/搜索