百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

Systemd 对垒 Docker docker systemd cgroup

suiw9 2024-10-31 16:03 22 浏览 0 评论

DevConf.cz是一个由红帽赞助的开发者大会,今年在捷克共和国布尔诺举行。会议上有很多不同的演讲,但最大的主题是容器。大部分演讲是实践性质的,要么是展示如何使用各种容器技术的教程,比如Kubernetes和Atomic.app,要么是对新产品的介绍,比如Cockpit。

不过,红帽容器工程主管 Dan Walsh 所做的演讲无疑是容器主题中最有趣的。他展示的是 Linux 容器世界核心冲突之一:systemd 对垒 Docker 守护进程。这绝非是一个新问题;在 Ubuntu 采用 systemd,以及 CoreOS 引入围绕 systemd 构建的容器系统Rocket 时,这个问题就出现了。

Systemd vs. Docker

“这是 Lennart Poettering,”Walsh 一边展示一张照片一边说。“这是 Solomon Hykes”,他展示了另一张照片。“两个人都不愿意妥协。而我则介于他们之间。”

由于 Walsh 曾受命让 systemd 支持 Docker,他详述了两个系统间代码、个人及运营冲突的历史。从很多方面来说,这也是红帽与 Docker 公司之间补丁冲突的历史。Poettering 是 systemd 的主要作者,并在红帽工作,而 Hykes 则是 Docker 公司的创始人和 CTO。

依据 Walsh 的演讲,冲突的根源在于 Docker 守护进程被设计用来接管很多 systemd 已经从 Linux 中抢夺过来的功能。包括初始化、服务激活、安全及日志。“从很多方面讲,Docker 想成为一个新的 systemd,”他声称,“它梦想成为 systemd。”

他阐述的第一个冲突在于服务初始化与重启。在 systemd 模式中,这些都是由 systemd 控制的;在 Docker 的世界中,则全由 Docker 守护进程控制。比如说,可以在 systemd 单元文件中以 “docker run” 语句来定义服务,以便以容器方式运行它们,也可以在 Docker 守护进程中将服务定义成“自动重启”容器。两种方式都行得通,但混合起来就不行。Docker 文档推荐使用 Docker 自动重启,除非是在混合容器化服务与非容器化服务时;这种情况下它推荐使用 systemd 或 Upstart。

不过,当以容器方式运行的服务依赖于其他容器化服务时,问题就出现了。对于常规服务,systemd 有一个名为sd_notify的功能,可以在服务准备就绪时传递消息,然后就可以启动那些依赖于它们的服务。但是,Docker 采用的是 C/S 架构。客户端为每个用户会话调用docker run及其他命令,但容器的启动和管理是在 Docker 守护进程中进行的(相当于“服务端”)。客户端无法发送 sd_notify 状态消息,因为它不做容器服务的实际管理,也不清楚服务的就绪时间,守护进程也无法发送这类消息,因为它不是通过 systemd 的单元文件调用的。因此,Walsh 的团队尝试了一种迂回的变通方式来启用 sd_notify:

  1. systemd 请求来自 Docker 客户端的 sd_notify
  2. 该客户端发送一条 sd_notify 消息给 Docker 守护进程
  3. 守护进程设置一个容器来完成 sd_notify
  4. 守护进程从该容器获取一条 sd_notify 消息
  5. 守护进程发送一条 sd_notify 消息给该客户端
  6. 该客户端发送一条 sd_notify 消息通知 systemd Docker 容器已就绪

用于启用这个错综复杂系统的补丁未被 Docker 项目接纳,对此 Walsh 毫不意外。sd_notify 确实可以用于 Docker 守护进程自身,因此 systemd 可以依赖于守护进程的运行。但是还是无法为单个容器化服务执行 sd_notify,因此 Docker 项目依然没有可靠的办法来管理容器化服务依赖的启动顺序。

Systemd 有一项功能叫“套接字激活

Walsh 的团队对单个容器的套接字激活更感兴趣。其好处是可以消除“始终运行”容器的额外开销。但是,开发人员发现他们不得不采用与 sd_notify 变通方式类似的方法,差别在于传递的是一个套接字,而不仅仅是一条消息。他们甚至没有尝试实现。

Linux 的cgroup可用来定义每个服务的系统资源额度,比如 CPU、内存及 I/O 限制。Systemd 允许在初始化文件中定义 cgroup 限制,这样你就可以定义服务启动时的资源策略。但是,使用 Docker 时,这又与其 C/S 模式相冲突。Systemd 的 cgroup 设置只对客户端产生作用;不对容器实际运行所在的守护进程产生作用。相反的,每个容器都继承了 Docker 守护进程的 cgroup 设置。不过,用户可以通过docker run命令参数来传递 cgroup 限制,这虽然可行,但未能与系统的整体管理策略整合。

Walsh 能联系得上的唯一成功之处是日志。Docker 的日志也无法与 systemd 的journald协作。容器的日志输出都是在每个容器本地,一旦删除容器,所有日志将被自动清除。从安全审计的角度来看,这是一大败笔。Docker 1.9 开始支持--log-driver=journald开关,将日志记录到 journald 中。不过,Docker 容器默认不使用 journald,因此每次都要传递这个开关。

容器内部的 systemd

Walsh 还想在 Fedora、红帽企业 Linux(RHEL)及 CentOS 容器基础镜像中启用 systemd,部分是因为很多软件包需要 systemctl 功能以便正确安装。他一开始尝试的是使用 “fakesystemd” 来代替 systemctl,该服务用于满足软件包的 systemctl 需要,没有其余的功能。结果这会造成问题,他很快就放弃了,不过还是迟了一步,未能阻止它在 RHEL 7.0 中发布。

在 RHEL 7.1 中,该团队添加了 “systemd-container”,这是 systemd 的一个大幅度删减版本。这依然会对那些软件中需要完整 systemd 的用户造成问题,Poettering 要求容器团队进行修改。在 RHEL 7.2 中,容器具有了真正的 systemd,减少了需要安装的依赖,因此尺寸更小。Walsh 的团队正着手进一步缩减这些依赖。

根据 Walsh 所说,容器中没有 systemd 最大的问题是它“退回到了使用初始化脚本之前。”每个镜像作者都在容器内创建自己的疯狂的启动脚本,而不是使用软件包作者精心制作的启动脚本。他演示了在具有 systemd 的容器内,服务初始化是何尝的简单,创建一个运行 Apache httpd 服务器的容器,其 Dockerfile 只有三行:

FROMfedora
RUNyum-yinstallhttpd;yumcleanall;systemctlenablehttpd;
CMD["/sbin/init"]

不过,要在 Docker 中使用 systemd,有一个主要障碍:运行具有 systemd 的容器要求运行时要带有--privileged标记,这让它变得不安全。这是因为 Docker 守护进程要求容器运行的“服务”应用程序其 PID 永远是1。在具有 systemd 的容器中,其 PID 是1,应用程序则具有其他的 PID,这会造成 Docker 认为容器失败并将其停止。

Poettering 说 PID 1 具有特殊要求。其中之一是杀死那些被它们的调用会话所遗弃的“僵尸”进程。对 Docker 来说,这是一个真正的问题,因为应用程序以 PID 1 运行,却不处理僵尸进程。比如,运行 Oracle 数据库的容器可能在退出时会遗留几千个僵尸进程。另一个要求是写入 syslog,除非配置容器写入日志到 journald,否则将进入 /dev/null

Walsh 尝试了几种办法以便 systemd 在非特权容器中工作,并提交了四个不同的拉取请求(7685、10994、13525及13526)给 Docker 项目。所有请求都被 Docker 维护人员拒绝了。当 Docker 贡献者之一 Jessie Frazelle 带着印有“DockerCon.EU 2015大会时,有关这些修改的争论达到了顶峰。

Systemd与容器的未来

红帽容器团队还大量参与了开放容器项目runC 工具的开发。该项目是开放容器组织(OCI)的实践性产出,OCI 是由 Linux 基金会于2015成立的非营利组织,目的是为容器 API 设置行业标准。OCI 还维护着libcontainer,这是 Docker 用于启动容器的类库。按照 Walsh 所述,Docker 最终需要采纳 runC 作为其技术栈的一部分,以便在其他平台上运行,尤其是 Windows。

使用来自 runC 的成果,红帽人员已经创建了一组名为 “oci-hooks” 的补丁,为 Docker 添加了大量 systemd 支持功能。它使用一个“钩子”,可以在容器启动之后应用程序运行之前触发指定目录下的所有可执行文件。使用这种方法执行的东西中间是RegisterMachine 钩子,它会通知宿主机上 systemd 的 machinectl 容器正在运行。用户可以使用machinectl命令看到所有 Docker 容器,以及 runC 容器:

#machinectl
MACHINECLASSSERVICE
9a65036e4a6dc769d0e40fa80871f95acontainerdocker
fd493b71a79c2b7913be54a1c9c77f1ccontainerrunc
2machineslisted.

这些钩子还允许在非特权容器里运行 systemd。这个拉取请求(17021)同样被 Docker 项目拒绝了。尽管如此,它还是包含在了红帽发行的 Docker 包中。因此,Docker 与 systemd 未来的一部分可能会涉及 Docker 的分叉。

Walsh 同时指出,cgroup、sd_notify 以及套接字激活对 runC 都是开箱即用的。这是因为 runC 不使用 Docker 的 C/S 模型;仅仅是个可执行文件。他看不到 Docker 公司与红帽之间未来在 systemd 问题上修复的突破口。Walsh 预测红帽可能会更多地转向 runC,并远离 Docker 守护进程。按他的话来说,Docker 正忙于 “containerd”,这是一个新的 systemd 替代品,将取代初始化系统的功能。

但是,鉴于自 Docker 项目启动以来短时间内 Linux 容器生态系统的快速变化,几乎不可能预测 systemd、Docker 及 runC 今后一年的关系将如何。毫无疑问的是,将会有更多的变化和冲突报道。

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: