容器技术的发展可以分为两个阶段,第一个阶段聚焦在IaaS层,仅仅把容器当做更轻量级虚拟机来使用,解决了应用运行时进程级资源隔离的问题;随着Docker的出现,容器虚拟化才有了统一的平台,由此容器技术发展到了第二个阶段,开始聚焦在PaaS层,以应用为中心,统一应用分发标准,实现DevOps。
本篇将针对操作系统、主机配置、容器镜像、容器运行时、Docker Daemon参数、Docker Daemon权限六大方面分享一些docker的运维经验;
操作系统
1.支持的操作系统类型
目前Docker官方支持的操作系统包含桌面版、服务器版、云提供商以及容器操作系统,具体如下:
- 桌面版:Mac、Windows;
- 服务器版:Windows Server、Centos、Debian、Fedora、Oracle Linux、RHEL、SLES、Ubuntu;
- 云提供商:AWS、Azure、阿里云等;
- 容器操作系统:RancherOS、CoreOS、Atomic、Photon;
2.操作系统的选择标准
有关操作系统的选择不能一概而论。首先,企业本身也有对操作系统的规定;其次,应用的不同也要求的操作系统不同;基于以上两点,若没有其他要求,相对而言采用容器操作系统有很大的优势。
容器操作系统相对于其他操作系统的优势有以下几点:
- 精简安全:容器操作系统只包含运行容器所需的必要软件和必要的管理工具,相比传统的操作系统而言会精简很多;所有应用通过容器的方式运行,从而使操作系统和应用软件隔离开来,极大降低了出现安全漏洞的概率;
- 升级回滚:系统采用可回滚的双分区模式,活动的分区通过只读方式挂载,另外一个分区用来自动更新, 通过切换系统分区即可实现快速升级,升级出现问题时,可以快速切换回原来的分区保证系统可用;
- 集群模式:在系统安装的时候便可自动加入内置的ETCD集群中,每个系统都可以通过本机的ETCD读取或发布配置信息和状态数据,通过选举形式在服务器之中选举Leader来同步数据,并以此确保集群之内信息始终可用;
主机配置
从安全性、稳定性、可靠性来讲,如何合理规划Docker运行环境非常重要,也是Docker运维的基础条件,下面会从容器分区、系统内核、Docker版本、Docker Daemon访问控制及日志审计来讲讲怎么规划:
-
单独为容器划分一个分区作为容器的存储空间:所有容器的数据、元数据默认都存储在/var/lib/docker下(当然可以修改docker容器默认的存储路径),很容易造成争抢磁盘空间,导致系统崩溃,推荐在内部存储中单独划分一个分区挂载到该目录上,同样的方法也可以使用外部存储;
-
使用比较新且稳定的Linux内核:官方推荐Linux内核版本为3.10+,但是有些功能模块要求的内核版本更高,如支持MacVlan网络模块就需要内核版本为3.9+,这个时候就得权衡一下Linux内核版本的选择,推荐采用该功能模块推荐的内核版本;
-
使用比较新且稳定的Docker版本:官方推荐的Docker版本为1.9.1+,但从实施和运维经验来看,推荐选择比较稳定的1.12.1版本;
-
只允许可信任的用户来控制Docker Daemon:Docker Daemon控制需要root特权,推荐将可信任的用户加入到一个组中,并将整个组授予root特权;
-
增加Docker Daemon及其相关文件、目录的日志审计:Docker Daemon作为Docker的后台守护进程,对其访问控制、行为操作做日志审计是非常有必要的,一旦出现问题,很方便进行定位,推荐增加Docker文件(docker、daemon.json、docker.service、docker.sock)和目录(/var/lib/docker、/etc/docker、/usr/bin)的日志审计;
容器镜像
镜像是容器运行的基础,所以镜像的安全至关重要,包括基础镜像的安全、软件包的漏洞、暴露的端口、SSH服务、非root用户等;
-
使用可信任的镜像来创建容器:Docker官方或非官方的镜像有很多漏洞,若使用它们来运行容器,很容易被攻击,建议使用Docker官方认证过的镜像,或是自己构建的镜像(建议采用Alpine作为基础镜像),并通过漏洞扫描工具(如Clair);也可以使用容器安全产品,类似AppSafe之类,可以全方位的保障镜像和容器运行时的安全;
-
在容器里面尽量不要安装不必要的软件:不必要的软件会占用磁盘的空间,也会增加系统的安全威胁;有些容器云公司也会提供镜像瘦身的服务,如有容云等;
-
创建一个非root用户的容器:容器拥有root权限,很容易让人通过容器的root权限攻击所在的宿主机,可以在制作镜像的时候指定用户,如:RUN useradd -d /home/username -m -s /bin/bash username;
-
开启Docker的Content Trust选项:Content Trust会将数据通过数字签名发送到远程的Docker Registries或是从远程的Docker Registries接收数据,用来保证镜像在build, create, pull, push, run过程中没有被篡改,开启命令:export DOCKER_CONTENT_TRUST=1;
容器运行时参数
容器运行时的一些参数设置,在整个容器运行过程中非常重要,设置不好会严重影响容器的安全性、性能,下面就讲讲容器运行时需要考虑设置的一些比较重要的参数。
-
为容器创建一个AppArmor Profile文件:AppArmor Profile文件里面包含了各种威胁的安全策略,通过它可以保护宿主机系统和应用程序的各种威胁,设置参数如:docker run –interactive –tty –security-opt=”apparmor:PROFILENAME” centos /bin/bash。
开启SELinux Security选项:SELinux提供了强制访问控制,增强了自主访问模型,可以通过SELinux为系统增加一层额外的安全层,设置参数如:docker run –interactive –tty –security-opt label=level:TopSecret centos /bin/bash。 -
为容器限制Linux内核的Capabilities能力:Linux把原来和超级用户相关的高级权限划分成为不同的单元,称为Capability,这样就可以独立对特定的Capability进行开启或禁止,来增加容器的安全,设置参数如:docker run –interactive –tty –cap-drop=all –cap-add={“NET_ADMIN”,”SYS_ADMIN”} centos:latest /bin/bash。以只读的模式挂载容器的root文件系统,设置参数如:docker run –interactive –tty –read-only –volume /centdata centos /bin/bash
-
设置容器在失败的时候尝试重启的次数:若不设置的话,重启则会不断的尝试重启,参数如:docker run –detach –restart=on-failure:5 nginx。
-
不要挂载宿主机上敏感的目录到容器上,或是以只读的方式挂载:如宿主机上这些目录:/、/boot、/dev、/etc、/lib、/proc、/sys、/usr;
-
在容器里面最好不要运行ssh服务:使用docker exec 或 docker attach来查看容器实例;
-
容器运行时不要映射privileged的端口:处于安全考虑,privileged的TCP/IP端口约束在1024以下,一般的用户是不能使用这个端口;
Docker Daemon参数
Docker Daemon为Docker的守护进程,大致可以分为Docker Server、Engine和Job三部分。Docker Daemon可以认为是通过Docker Server模块接受Docker Client的请求,并在Engine中处理请求,然后根据请求类型,创建出指定的Job并运行。
以下为Docker Daemon的架构示意图:
从上图不难看出Docker Daemon的核心地位,所以它的配置也尤为重要,下文会从安全、性能方面入手,下面具体讲讲该怎么配置Docker Daemon参数:
限制容器之间网络通信:在同一台主机上若不限制容器之间通信,容器之间就会暴露些隐私的信息,所以推荐关闭,设置参数如:docker daemon –icc=false;
-
日志级别设置为info:这样除了debug信息外,可以捕获所有的信息,设置参数如: docker daemon –log-level=”info”;
-
允许Docker Daemon修改iptables:这样可以自动避开错误的网络配置导致的容器和外部的访问问题,设置参数如:docker daemon –iptables=true;
-
使用安全模式访问镜像仓库:Docker Daemon支持安全模式(默认)和非安全模式(–insecure-registry)访问镜像仓库,推荐镜像仓库配置CA证书,Docker Daemon配置安全访问模式,采用TLS安全传输协议;
推荐使用Overlayfs作为Docker的存储驱动:Docker支持很多种储存驱动,CentOS默认的Docker存储驱动为devicemapper,Ubuntu默认的Docker存储驱动为aufs,那Docker储存驱动该怎么选择呢,可以参考下图的对比分析:
推荐为Docker Daemon配置TLS认证:推荐指定Docker Daemon的监听IP、端口及unix socket,并配置TLS认证,通过Docker Daemon的IP+端口访问,设置参数如: ‘–tlsverify’ 、’–tlscacert’ 、’–tlscert’、’–tlskey’ ;
推荐为Docker Daemon开启用户空间支持: Docker Daemon支持Linux内核的user namespace,为Docker宿主机提供了额外的安全,容器使用有root权限的用户,则这个用户亦拥有其宿主机的root权限,外部可以通过容器反向来操控宿主机,设置参数如:docker daemon –userns-remap=default;
推荐为Docker Daemon配置默认的CGroup:某个程序可能会出现占用主机上所有的资源,导致其他程序无法正常运行,或者造成系统假死无法维护,这时候用 cgroups 就可以很好地控制进程的资源占用,设置参数如:docker daemon –cgroup-parent=/foobar;
推荐为Docker配置集中的远程日志收集系统: Docker支持很多种日志驱动,配置集中的远程日志系统用来存储Docker日志是非常有必要的,设置参数如:docker run –log-driver=syslog –log-opt syslog-address=tcp://ip;
推荐使用Docker Registry v2版本: v2版本在性能与安全性方面比v1都增强了很多,如安全性上的镜像签名,可设置参数如:docker daemon –disable-legacy-registry;
Docker Daemon权限
Docker Daemon相关文件和目录的属性及其权限关系到整个Docker运行时的安全,从运维角度来看,合理的规划好属性及其权限尤为重要,下面具体讲讲该怎么配置Docker Daemon权限。
1.设置Docker Daemon一些相关配置文件的属性及其权限
2.设置Docker Daemon一些相关目录的属性及其权限
/etc/docker目录保存的是容器认证及key信息, 设置目录的属性为root:root,权限为755;
/etc/docker/certs.d/目录保存的是registry证书相关的文件,设置目录的属性为root:root,权限为444。