理解容器中超易混淆 Attach 和 Exec 的异同

公众号关注 「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

ecc86de626d94b1ea317842fb1f8f978.png

docker(或podman,或containerdattachexec命令之间的区别是一个常见的混淆源。这是可以理解的——这两个命令有相似的参数,乍一看也有相似的行为。但是,attachexec不可互换。它们旨在涵盖不同的用例,并且命令的实现也不同。但是,可能很难记住何时使用哪个命令。

容器管理 - 看看里面

首先,快速回顾一下docker 架构的样子:

01be6e5b888c1e1cb6a119f5a968c844.png

三个关键要点:

  • 容器管理架构是分层的

  • 一个容器是一个孤立受限的环境+一个进程

  • 在容器管理器和容器之间有一个 shim组件。

attach命令来做什么

在容器内部,有一个常规的Linux 进程。与每个正常进程一样,它具有stdio流 - stdinstdoutstderr。但是当容器以分离(即类似守护进程)模式启动时,这些流会发生什么:

$ docker run -d nginx

回到过去,当您将进程作为守护进程启动时(即,将其与启动进程分离),它将重新指向PID 1,并且它的 stdio 流将被简单地关闭。但是,我们都知道如今使用stdoutstderr流进行日志记录是多么方便,这要归功于容器!

Docker 提出了一个聪明的想法,即在容器和系统的其余部分之间放置一个额外的进程,称为容器运行时shim。在上面的示例中,容器管理器实际上启动了一个 shim 进程,该进程又使用 OCI 兼容的运行时(例如 runc)来启动实际的容器。

这是成为守护进程的 shim 进程 - 它重新指向PID 1,并且其stdio流已关闭:2b366fb281a9fa3ce8f3234215e814ad.png

然而,shim 控制了容器的stdio流!

守护程序的 shim 进程从容器的stdoutstderr读取并将读取的字节转储到日志驱动程序。默认情况下,shim关闭容器的stdin流,但如果-i传递给相应的docker run命令,它可以保持打开状态。

容器运行时 shim 实际上充当服务器!它提供了连接到它的 RPC 手段(例如,一个 UNIX 套接字)。当您这样做时,它开始将容器的stdoutstderr流式传输回套接字的末端。它还可以从此套接字读取并将数据转发到容器的stdin。因此,类似attach到容器的stdio流!

所以,最后,当你运行时docker attach <container>,你基本上创建了一个中继:

terminal <-> docker <-> dockerd <-> shim <-> container's stdio streams
5c9837b08ddb5e430870f275b14dc2cf.png
attach和logs之间的区别

在上图中,docker attach将容器的日志流式传输回终端。但是,该docker logs命令执行类似的操作。那么,有什么区别呢?

logs命令提供了各种选项来过滤日志,而attach在这方面则充当一个简单的tail. 但更重要的是,logs命令建立的流始终是单向的,并连接到容器的日志,而不是直接连接到容器的stdio流。

logs命令只是将容器日志的内容流式传输回您的终端,仅此而已。因此,无论您如何创建容器(交互式或非交互式,是否由伪终端控制),在使用logs命令时都不会意外影响容器。

但是,何时使用attach

  • 如果容器是在交互模式 ( -i)下创建的,则在attach-ing 到容器后在终端中键入的所有内容都将发送到其stdin

  • 您可以(有意或无意地)向容器发送信号 -例如,ctrl+cattach发送SIGINT到容器时击中您的一端。

exec命令来做什么

我希望attach命令现在已经解决了。所以,是时候解决exec对手了!

exec命令实际上是一个完全不同的故事。在attach的情况下,我们将终端连接到现有容器(读取、处理)。但是,该exec命令会启动一个全新的容器!换句话说,execrun命令的一种形式(它本身只是create+的快捷方式start)。

注:该OCI运行规格不具有runexec命令!查看#345#388以获取有关exec功能实际上是如何冗余的有趣讨论,并且可以在仅实现createstart命令的运行时中重现。

#345 https://github.com/opencontainers/runtime-spec/issues/345

#388 https://github.com/opencontainers/runtime-spec/pull/388

但为什么接着说docker exec --help:

Usage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

Run a command in a running container

这里的技巧是,exec命令创建的辅助容器共享目标容器的所有隔离边界!即,相同的netpidmount等命名空间、相同的cgroups层次结构等。因此,从外部看,感觉就像在现有容器内部运行命令。

attachexec命令的混淆是因为exec-uted 命令也是一个拥有自己的stdio流的进程。因此,您可以选择是否exec处于分离模式、是否保持标准输入打开、是否分配伪 TTY 等。此外,当exec-ing 时,中继看起来非常相似:

terminal <-> docker-cli <-> dockerd <-> shim <-> command's stdio streams
0e21ffcc6252788993cf1a30383c1409.png
其他实现

上面的图表和例子主要是关于docker的,但其他容器管理器,如containerdcrio,在运行、执行、attachlogs命令时表现类似。

Podman可能是无守护进程容器管理器最突出的例子。然而,即使是 podman 也使用容器运行时垫片。当您attach到达podman 的容器时,中继中的跳数就少了一跳。

不过,有趣的样本是 KubernetesKubernetes 不直接管理容器。相反,每个集群节点都有一个本地代理,称为kubelet,它又期望节点上存在兼容的容器运行时。但是,在最低级别上,仍然存在相同的垫片和流程:

d7a756630ed6daca0ad50752b4d92ea4.png

docker非常相似,Kubernetes的命令行客户端(kubectl)也提供了类似的UX执行、attachlogs命令。不同之处在于Kubernetes使用的是pod而不是容器。幸运的是,pod只是一组半熔合的容器,所以我们目前学到的所有东西仍然适用。

由于attahclogsexec工作在容器级别上,每个kubectl attachkubectl logskubectl exec都需要指定目标容器(-c <name>)以及pod名称。除非这个pod 用kubectl.kubernetes.io/default-container注释过。

e48b0b5fc5e6022dcb42e02c3ec27905.png
结论

所以,总结一下:

  • 容器是隔离且受限的执行环境。

  • 传统上,每个容器有一个主进程。

  • 容器通常以分离模式启动(即,像守护进程)。

  • 容器运行时 shim 包装容器进程并将其stdoutstderr流式传输到日志。

  • 运行时 shim 允许attach-ing 将终端与容器的stdio流连接起来。

  • 可以重用已运行容器的隔离方式来启动容器。

  • exec命令类似于run从另一个容器重用所有命名空间和 cgroup的命令。

  • 由于exec-ing 默认发生在attach模式下,它可能看起来与attach命令相似,但其目的和实现却大不相同。

参考资料


https://iximiuz.com/en/posts/containers-101-attach-vs-exec/

本文转载自:「云原生CTO」,原文:https://tinyurl.com/32etuh3s,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-linux.com。

44c3e02bd4ea5e6d69e7474295aa3abd.gif

c1cf6762523d04bafc368be1bd760893.png

你可能还喜欢

点击下方图片即可阅读

231d4ab32c955a3914e0b6189f6e6d02.png

5 张图带你搞懂容器网络的工作原理

11e8839d5f35fdb266d78d306a84206b.png
点击上方图片,『美团|饿了么』外卖红包天天免费领

9662751fb9a4d7f939965948791017ff.png

更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 HTML5 和 CSS3 中,我们可以使用更多的特性来实现超链接在鼠标经过时显示不同的效果。下面是一些示例: 1. 使用 CSS3 transition 属性实现渐变效果 HTML 代码: ```html <a href="#">这是一个超链接</a> ``` CSS 代码: ```css a { color: red; text-decoration: none; transition: color 0.3s ease; } a:hover { color: blue; } ``` 在这个示例中,我们为超链接设置了红色的文本颜色和无下划线的文本装饰,使用了 CSS3 transition 属性来实现文本颜色的渐变效果。当用户将鼠标悬停在链接上时,文本颜色将从红色渐变为蓝色。 2. 使用 CSS3 transform 属性实现旋转效果 HTML 代码: ```html <a href="#">这是一个超链接</a> ``` CSS 代码: ```css a { color: red; text-decoration: none; transition: transform 0.3s ease; } a:hover { transform: rotate(45deg); } ``` 在这个示例中,我们为超链接设置了红色的文本颜色和无下划线的文本装饰,使用了 CSS3 transform 属性来实现文本旋转的效果。当用户将鼠标悬停在链接上时,文本将以 45 度的角度旋转。 3. 使用 CSS3 box-shadow 属性实现阴影效果 HTML 代码: ```html <a href="#">这是一个超链接</a> ``` CSS 代码: ```css a { color: red; text-decoration: none; transition: box-shadow 0.3s ease; } a:hover { box-shadow: 0 0 5px blue; } ``` 在这个示例中,我们为超链接设置了红色的文本颜色和无下划线的文本装饰,使用了 CSS3 box-shadow 属性来实现文本阴影的效果。当用户将鼠标悬停在链接上时,文本将出现蓝色的阴影效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值