docker 守护进程选项 --selinux-enabled 有什么作用

what does the docker daemon option --selinux-enabled do

我猜它会标记它启动的容器,但从 ps -eZ 的输出来看,我看不出有什么不同。 例如,容器 etcd 具有相同的域,无论守护进程有无此选项:

system_u:system_r:container_runtime_t:s0 16212 ? 00:00:00 dnsmasq-nanny

但它确实阻止了我的容器 (k8s-dns-dnsmasq-nanny-amd64:1.14.8) 启动并且拒绝日志显示对 /etc/localtime 和 /usr/sbin/dnsmasq 的访问被拒绝。我认为这些是容器文件系统中的文件。如何编写 SELinux 策略以允许访问容器文件系统内部?

简答

  • --selinux-enabled 将启用 selinux 策略,允许标有 svirt_lxc_net_t 的容器进程读取和写入标有 svirt_sandbox_file_t 的文件。
  • 可以通过使用 docker inspect -f '{{ .ProcessLabel }}' <container name>docker inspect -f '{{ .MountLabel }}' <container name>
  • 检查容器来检查容器标签

长答案

--selinux-enabled 选项启用 docker selinux 安全策略,详细描述 here。启用后,此政策将:

  • 使用 svirt_sandbox_file_tsvirt_lxc_net_t 标签标记容器。这可以通过 运行 一个容器并检查应用到它的标签来确认:

    docker inspect <container id> | grep "Label"
    
    "MountLabel": "system_u:object_r:svirt_sandbox_file_t:s0:c557,c611",
    "ProcessLabel": "system_u:system_r:svirt_lxc_net_t:s0:c557,c611",
    

    svirt_sandbox_file_t 是一个 MountLabel,它限制对主机文件系统上文件的访问。 docker selinux docs 说:

    If a file is labeled svirt_sandbox_file_t, then by default all containers can read it. But if the containers write into a directory that has svirt_sandbox_file_t ownership, they write using their own category

    上例中的类别是c557,c611

    svirt_lxc_net_t用于保护进程。根据redhat的解决方案here,用于:

    ... isolate the container processes from the host, and it generates a unique Multi-Category Security label to allow SELinux to prevent one container process from attacking other container processes and content.

您的访问问题很可能是因为主机文件系统上的 selinux 标签阻止从容器内进行访问。例如,selinux docs 表示:

By default, docker gets access to everything in /usr and most things in /etc.

所以你的选择是:

  1. 使用 system_u:object_r:svirt_sandbox_file_t 手动重新标记主机系统上的文件。这通常不推荐用于系统文件和目录,因为它会对主机产生意想不到的影响。

  2. 运行 容器为无限制类型。这将仅禁用此容器的隔离,同时仍继续在主机上强制执行 selinux:

    docker run -it --security-opt label:disable alpine sh