【问题标题】:Running systemd in docker container causes host crash在 docker 容器中运行 systemd 会导致主机崩溃
【发布时间】:2019-02-16 21:38:04
【问题描述】:

我正在尝试创建一个基于 systemd 的 docker 容器,但是当我尝试运行构建的容器时,我的系统崩溃了。我认为在容器中运行 init 可能会导致冲突,并且在某种程度上与我主机上的 systemd 冲突。

当我尝试运行 docker 容器时,我退出了我的帐户,并简要查看了我的系统在启动过程中的样子。我的主机正在运行 Arch Linux,带有 linux 4.20.7。

只有当我尝试通过/sbin/init 运行 systemd 来“启动”容器时,才会出现问题。

docker run -it \
   --volume=/sys/fs/cgroup:/sys/fs/cgroup:rw \
   --privileged 66304e3bc48

Dockerfile(改编自solita/ubuntu-systemd):

FROM ubuntu:18.04

# Don't start any optional services.
RUN find /etc/systemd/system \
    /lib/systemd/system \
    -path '*.wants/*' \
    -not -name '*journald*' \
    -not -name '*systemd-tmpfiles*' \
    -not -name '*systemd-user-sessions*' \
    -exec rm \{} \;

RUN apt-get update && \
    apt-get install --yes \
    python sudo bash ca-certificates dbus systemd && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN systemctl set-default multi-user.target
RUN systemctl mask dev-hugepages.mount sys-fs-fuse-connections.mount

STOPSIGNAL SIGRTMIN+3

# Workaround for docker/docker#27202, technique based on comments from docker/docker#9212
CMD ["/bin/bash", "-c", "exec /sbin/init --log-target=journal 3>&1"]

我希望容器只是启动运行 systemd,而我不是你可能做错的事。

【问题讨论】:

  • 添加--privileged 赋予了容器进程这个权利,systemd 想要管理很多东西。您能否使用像 supervisord 这样的轻量级 init 进程来实现您的最终目标,或者更好的是,没有专用 init 的单进程容器?
  • 我更愿意这样做,问题是我将它用于配置管理测试,因此我希望容器与主机尽可能匹配。我最终需要测试使用 systemctl 重新启动服务是否有效。
  • “尽可能匹配主机”:Docker 容器无法运行典型的完整主机系统运行的许多东西,包括系统守护进程、远程登录服务等。 如果“匹配主机”是您的目标,那么虚拟机将是更自然的匹配。
  • 是的,不幸的是,这并不可行。我希望在只有 docker 容器可用的 CI 运行期间测试角色。
  • 我在 Ubuntu 19.04 和 Docker nightly builds 中遇到了这个问题。 Ubuntu 18.04 以及当前的 docker 版本也有这个问题。主机系统未重新启动 - X11 似乎正在崩溃或被终止。

标签: docker systemd


【解决方案1】:

Docker 不想在默认情况下将 Systemd 包含在 docker 中,因为它将自己发布为 应用程序容器(这意味着每个容器一个应用程序)。还有一种称为系统容器的容器。最著名的是 OpenVZ、LXC/LXD 和 Systemd-nspawn。所有这些都将运行带有 systemd 的完整操作系统,就好像它是一个虚拟机一样。

与在 LXD 中运行 systemd 相比,在 docker 中使用 systemd 非常危险

甚至还有一个名为 Podman 的新婴儿,它是 docker 的克隆,但当您安装它或使用包含 systemd 的映像时,它默认使用 systemd 内部,就像 ubuntu 云映像 http://uec-images.ubuntu.com/releases/server/bionic/release/

所以我的建议是测试 LXD 和 systemd-nspawn ;并密切关注 Podman,它解决了 docker 不想解决的问题;阅读本文以了解https://lwn.net/Articles/676831/


参考:

https://coreos.com/rkt/docs/latest/rkt-vs-other-projects.html https://podman.io/slides/2018_10_01_Replacing_Docker_With_Podman.pdf https://containerjournal.com/features/system-containers-vs-application-containers-difference-matter

运行时和特权容器的诅咒 https://brauner.github.io/2019/02/12/privileged-containers.html

【讨论】:

    【解决方案2】:

    我最终使用了paulfantom/ubuntu-molecule Docker 映像。

    目前看起来他们只是在安装 systemd,设置一些环境变量,并直接使用 systemd 二进制文件作为入口点。它似乎没有我在原帖中提到的问题。

    Dockerfile

    FROM ubuntu:18.04
    
    ENV container docker
    ENV LC_ALL C
    ENV DEBIAN_FRONTEND noninteractive
    
    RUN sed -i 's/# deb/deb/g' /etc/apt/sources.list
    
    # hadolint ignore=DL3008
    RUN apt-get update \
        && apt-get install -y --no-install-recommends systemd python sudo bash iproute2 net-tools \
        && apt-get clean \
        && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
    
    # hadolint ignore=SC2010,SC2086
    RUN cd /lib/systemd/system/sysinit.target.wants/ \
        && ls | grep -v systemd-tmpfiles-setup | xargs rm -f $1
    
    RUN rm -f /lib/systemd/system/multi-user.target.wants/* \
        /etc/systemd/system/*.wants/* \
        /lib/systemd/system/local-fs.target.wants/* \
        /lib/systemd/system/sockets.target.wants/*udev* \
        /lib/systemd/system/sockets.target.wants/*initctl* \
        /lib/systemd/system/basic.target.wants/* \
        /lib/systemd/system/anaconda.target.wants/* \
        /lib/systemd/system/plymouth* \
        /lib/systemd/system/systemd-update-utmp*
    
    RUN systemctl set-default multi-user.target
    ENV init /lib/systemd/systemd
    VOLUME [ "/sys/fs/cgroup" ]
    
    ENTRYPOINT ["/lib/systemd/systemd"]
    

    【讨论】:

      【解决方案3】:

      “尽可能匹配主机”是docker-systemctl-replacement 脚本的最初目标。您可以在稍后可能在虚拟机上运行的容器中测试驱动器脚本。它允许在没有活动的 systemd 守护进程的情况下执行一些 systemctl 命令。

      如果您愿意,它也可以用作初始化守护进程。启用 systemd 的操作系统在容器中会感觉非常相似。

      【讨论】:

      • 我试过了,但无法正常工作。我想我只是错过了 Python 3,因为在再次尝试并确保它已安装之后,它现在可以工作了。我会试一试,看看它是否能胜任。
      • 啊,我明白了 - 感谢您的反馈。我已经在首页提示了 Python 的要求。 ................... 几年前,所有 docker 镜像都像真正的操作系统一样预装了 Python,但在去年的某个时候发生了变化。到 2019 年,当人们想要使用基于 python 的工具时,在 docker 映像中安装 python 基本上是一项普遍要求。同样,Ansible 想变得聪明,所以现在需要创建 /run/systemd/system 目录。现在把它放在首页上可能是个好主意。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-11
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      相关资源
      最近更新 更多