近期Docker 19.03中发布了一个重要的特性 “Rootless Container支持”。趁着五一假期,快速验证一下。本文参考了Experimenting with Rootless Docker 一文的内容,并且补充了更多的细节和上手内容。

Rootless容器背景与架构

Docker和Kubernetes已经成为企业IT架构的基础设施,其自身安全越来越被关注。Docker基于Linux操作系统提供了应用虚拟化能力,通过namespace, cgroup实现了资源的隔离和配额约束。Docker Engine是一个典型的 Client-Server 结构:

Docker Client (TCP/Unix Socket) -> Docker Daemon (Parent/Child Processes) -> Container

由于Linux需要特权用户来创建namespace,挂载分层文件系统等,所以 Docker Daemon 一直以来是以root用户来运行的。这也导致了有Docker访问权限的用户可以通过连接Docker Engine获取root权限,而且可以绕开系统的审计能力对系统进行攻击。这阻碍了容器在某些场景的应用:比如在高性能计算领域,由于传统的资源管理和调度系统需要非特权用户来运行容器,社区实现了另外的容器运行时Singularity 。

Moby社区的 Akihiro Suda,为Docker Engine和Buildkit贡献了rootless容器支持,让Docker Engine以非特权用户方式运行,更好地复用Linux的安全体系。

注意:

  1. 目前rootless容器还在实验阶段,cgroups 资源控制, apparmor安全配置, checkpoint/restore等能力还不支持。
  2. 目前只有Ubuntu提供了在rootless模式下对overlay fs的支持,由于安全顾虑,这个方案尚未得到upstream的支持。其他操作系统需要利用VFS存储驱动,有一定性能影响,并不适合I/O密集型应用。

Rootless容器有几个核心技术

首先是利用 user namespaces 将容器中的root用户uid/gid映射到宿主机的非特权用户范围内。Docker Engine已经提供了 --userns-remap 标志支持了相关能力,提升了容器的安全隔离性。Rootless容器在此之上,让Docker daemon也运行在重映射的用户名空间中。

其次,虽然Linux中的非特权用户可以在用户名空间中创建网络名空间,并且执行iptables规则管理和tcpdump等操作,然而非特权用户无法在宿主机和容器之间创建veth pairs, 这也意味着容器没有外网访问能力。为了解决这个问题,Akihiro 利用用户态的网络“SLiRP”,通过一个TAP设备连接到非特权用户名空间,为容器提供外网连接能力。其架构如下

相关细节请参考,slirp4netns项目

环境准备

本文在一台 CentOS 7.6的虚拟机上进行的验证

创建用户

$ useradd moby
$ passwd moby

将新建用户添加到 sudoers 组

usermod -aG wheel moby

切换到非特权用户

$ su - moby
$ id
uid=1000(moby) gid=1000(moby) groups=1000(moby),10(wheel)

进行uid/gid映射配置

echo "moby:100000:65536" | sudo tee /etc/subuid
echo "moby:100000:65536" | sudo tee /etc/subgid

安装Rootless Docker

curl -sSL https://get.docker.com/rootless | sh

如果第一次安装,需要安装所需软件包

$ curl -sSL https://get.docker.com/rootless | sh
# Missing system requirements. Please run following commands to
# install the requirements and run this installer again.
# Alternatively iptables checks can be disabled with SKIP_IPTABLES=1cat <<EOF | sudo sh -x
curl -o /etc/yum.repos.d/vbatts-shadow-utils-newxidmap-epel-7.repo https://copr.fedorainfracloud.org/coprs/vbatts/shadow-utils-newxidmap/repo/epel-7/vbatts-shadow-utils-newxidmap-epel-7.repo
yum install -y shadow-utils46-newxidmap
cat <<EOT > /etc/sysctl.d/51-rootless.conf
user.max_user_namespaces = 28633
EOT
sysctl --system
EOF

(可选)安装用户态网络协议栈实现 slirp4netns :由于yum 安装的slirp4netns版本比较老无法执行,需要从源码构建。

$ sudo yum install glib2-devel
$ sudo yum group install "Development Tools"
$ git clone https://github.com/rootless-containers/slirp4netns
$ cd slirp4netns
$ ./autogen.sh
$ ./configure --prefix=/usr
$ make
$ sudo make install

安装 Rootless Docker成功之后,会出现如下提示

$ curl -sSL https://get.docker.com/rootless | sh
# systemd not detected, dockerd daemon needs to be started manually/home/moby/bin/dockerd-rootless.sh --experimental --storage-driver vfs# Docker binaries are installed in /home/moby/bin
# Make sure the following environment variables are set (or add them to ~/.bashrc):\n
export XDG_RUNTIME_DIR=/tmp/docker-1000
export DOCKER_HOST=unix:///tmp/docker-1000/docker.sock

验证Rootless容器

执行

$ export XDG_RUNTIME_DIR=/tmp/docker-1000
$ export DOCKER_HOST=unix:///tmp/docker-1000/docker.sock
$ /home/moby/bin/dockerd-rootless.sh --experimental --storage-driver vfs

然后在另外一个窗口执行

$ export XDG_RUNTIME_DIR=/tmp/docker-1000
$ export DOCKER_HOST=unix:///tmp/docker-1000/docker.sock
$ docker version
Client:Version:           master-dockerproject-2019-04-29API version:       1.40Go version:        go1.12.4Git commit:        3273c2e2Built:             Mon Apr 29 23:39:39 2019OS/Arch:           linux/amd64Experimental:      falseServer:Engine:Version:          master-dockerproject-2019-04-29API version:      1.40 (minimum version 1.12)Go version:       go1.12.4Git commit:       9a2c263Built:            Mon Apr 29 23:46:23 2019OS/Arch:          linux/amd64Experimental:     truecontainerd:Version:          v1.2.6GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fbrunc:Version:          1.0.0-rc7+devGitCommit:        029124da7af7360afa781a0234d1b083550f797cdocker-init:Version:          0.18.0GitCommit:        fec3683
$ docker run -d -p 8080:80 nginx
$ curl localhost:8080

利用 iperf3 进行网络性能测试,启动服务器端

$ docker run  -it --rm --name=iperf3-server -p 5201:5201 networkstatic/iperf3 -s

测试容器之间的网络带宽

$ SERVER_IP=$(docker inspect --format "{{ .NetworkSettings.IPAddress }}" iperf3-server)
$ echo $SERVER_IP
172.17.0.2
$ docker run -it --rm networkstatic/iperf3 -c $SERVER_IP
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.03  sec  29.8 GBytes  25.5 Gbits/sec    0             sender
[  4]   0.00-10.03  sec  29.8 GBytes  25.5 Gbits/sec                  receiver

测试容器到宿主机之间的网络带宽(外网访问)

$ HOST_IP=$(hostname --ip-address)
$ echo $HOST_IP
192.168.1.162
$ docker run -it --rm networkstatic/iperf3 -c $HOST_IP
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  1011 MBytes   848 Mbits/sec    0             sender
[  4]   0.00-10.00  sec  1008 MBytes   845 Mbits/sec                  receiver

可以看到容器之间的通信带宽还比较不错,然而容器和宿主机不同网络名空间之间的通信性能有较大的损耗。

总结

Rootless容器在提升Docker/Runc容器的安全隔离性和可管理性方面前进了一大步,可以很好地复用Linux的安全体系,配合seccomp和SELinux等安全配置,可以减少攻击面。社区还提供了无需特权用户的Kubernetes实验版本,可以从如下项目获得 https://github.com/rootless-containers/usernetes

然而Rootless容器无法防范Linux内核的安全风险,目前其网络、存储的性能也有待优化,需要在特定场景中进行使用。也期待社区持续提升容器安全能力与效率,让容器有更加广阔的应用场景。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

容器安全拾遗 - Rootless Container初探相关推荐

  1. 创建新Docker容器时出现“The container name /xxx is already in use by container xxxxxxxxxxx...”问题的解决办法

    创建新Docker容器时出现"The container name "/xxx" is already in use by container xxxxxxxxxxx-& ...

  2. 创建新Docker容器时出现“The container name “/xxx“ is already in use by container xxxxxxxxxxx...”问题的解决办法

    创建新Docker容器时出现"The container name "/xxx" is already in use by container xxxxxxxxxxx-& ...

  3. Centos7.6部署docker容器虚拟化平台(Container 容器端口映射)

    Docker的概述: 实验环境: Centos 7.6版本 Dcoker 概述 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器 中,然后发布到任何流行的 ...

  4. linux container 原理,容器概念与Linux Container原理

    一.容器与LxC 在像KVM等众多主机虚拟化解决方案中,对每一个虚拟机实例提供的是从底层硬件开始一直到上层的环境,在硬件级进行资源划分.虚拟机的内核是运行在硬件内核之上的.由于每个虚拟实例都有自己的运 ...

  5. 启动子容器失败:A child container failed during start

    从经理给你项目让你跑,第一反应是命令:tomcat7:run,会出现结果: [ERROR] No plugin found for prefix 'tomcat7' in the current pr ...

  6. dubbo内置哪几种服务容器_dubbo启动服务之容器(Container)

    讲解dubbo启动服务的时候先来了解下java的spi机制 后期文章会首发于本专栏,欢迎关注 JAVA高级进阶​zhuanlan.zhihu.com 一:SPI 简介 SPI 全称为 (Service ...

  7. data-packed volume container - 每天5分钟玩转 Docker 容器技术(43)

    在上一节的例子中 volume container 的数据归根到底还是在 host 里,有没有办法将数据完全放到 volume container 中,同时又能与其他容器共享呢? 当然可以,通常我们称 ...

  8. Docker学习:容器五种(3+2)网络模式 | bridge模式 | host模式 | none模式 | container 模式 | 自定义网络模式详解

    前言 本讲是从Docker系列讲解课程,单独抽离出来的一个小节,重点介绍容器网络模式, 属于了解范畴,充分了容器的网络模式,更有助于更好的理解Docker的容器之间的访问逻辑. 疑问:为什么要了解容器 ...

  9. 容器(Container)技术介绍

    参考文献: A Brief History of Containers: From the 1970s Till Now The differences between Docker, contain ...

最新文章

  1. PHP的Smarty
  2. 使用opencv dnn 模块调用darknet模型时候出错,不支持relu激活函数
  3. 网络服务-RSYNC
  4. 阿里云oss云存储图片上传在wangEditor富文本编辑器上的集成
  5. AI在这张“问卷”上首次超越人类,SuperGLUE被微软谷歌两家“攻破”
  6. ubuntu16.04 apt-get 报错:E: Unable to locate package update(E: Unable to locate package upgrade)(没解决)
  7. Linux中sort、uniq、cut、wc命令详解
  8. java的方法调用中分不清_java中不太清晰的知识点
  9. Mybatis源码之核心流程分析
  10. MFC开发IM-第十八篇、如何设置编辑框的内容
  11. C语言单元测试框架-cmocka示例
  12. 学游戏设计要什么学历_东莞模具设计培训学模具技术有什么好处为什么学模具技术...
  13. 射频芯片设计EM仿真(二)--对比EM仿真和schmetic仿真
  14. 实模式8086 与 保护模式80286
  15. 新浪低调上线开源镜像站
  16. Fabric.js添加辅助线的方法
  17. 学术会议墙报_第十三届全国振动理论及应用学术会议顺利召开
  18. 解决:用电脑在B站看视频声音太小的问题
  19. 【总结】职业规划和自我总结----------包含职业要求
  20. Hadoop高手之路4-HDFS

热门文章

  1. 邢台职业技术学院计算机系宿舍,邢台职业技术学院宿舍条件怎么样 男生女生宿舍图片...
  2. python3如何安装selenium_Mac-Firefox浏览器+selenium+Python3环境安装
  3. java 委托_java 能不能自己写一个类叫 java.lang.System/String 正确答案
  4. python import如何使用_python之import引用
  5. 路畅安卓最新固件升级_Airpods连接安卓手机音量异常(airpods固件升级)
  6. android 手机壁纸源码,Android工程实现换壁纸功能【附源码】
  7. rac一节点时间比另一个节点快_数据库数据那么多为什么可以检索这么快?
  8. mysql share mode_mysql锁:mysql lock in share mode 和 select for update
  9. android tasker,Tasker:Android系统增强神器
  10. 计算机网络学习笔记(一)——分层模型、协议、服务、连接模式、标准化组织