1.Swarm模式

Swarm模式是Docker未来的趋势。Swarm模式支持用户集群化管理多个Docker主机,同时还能通过声明式的方式部署应用。每个Swarm都由管理者和工作者节点构成,节点可以是Linux或者Windows。管理者节点构成了集群中的控制层,并负责集群配置以及工作负载的分配。工作者节点就是运行应用代码的容器。

正如所预期的,Swarm模式包括很多开箱即用的安全特性,同时还设置了合理的默认值。这些安全特性包括以下几点。

  • 加密节点ID。
  • 基于TLS的认证机制。
  • 安全准入令牌。
  • 支持周期性证书自动更新的CA配置。
  • 加密集群存储(配置DB)。
  • 加密网络。

接下来将详细介绍如何构建安全的Swarm,以及如何进行安全相关的配置。

为了完成下面的内容,读者需要至少3个Docker主机,每个都运行1.13或者更高版本的Docker。示例中3个Docker主机分别叫作“mgr1”“mgr2”“wrk1”。每台主机上都安装Ubuntu 16.04,其上运行了Docker 18.01.0-ce。同时还有一个网络负责联通3台主机,并且主机之间可以通过名称互相ping通。安装完成后如图15.6所示。




docker怎么修改网卡IP 修改docker ip_docker

图15.6 3个Docker主机



(1)配置安全的Swarm集群

读者可以在其Swarm集群管理者节点上运行下面的命令。在本例中,命令运行于“mgr1”节点之上。

$ docker swarm initSwarm initialized: current node (7xam...662z) is now a manager.To add a worker to this swarm, run the following command:    docker swarm join --token      SWMTKN-1-1dmtwu...r17stb-ehp8g...hw738q 172.31.5.251:2377To add a manager to this swarm, run 'docker swarm join-token manager'and follow the instructions.

上面的命令就是配置安全Swarm集群所要做的全部工作!

“mgr1”被配置为Swarm集群中的第一个管理节点,也是根CA节点。Swarm集群已经被赋予了加密Swarm ID,同时“mgr1”节点为自己发布了一个客户端认证信息,标明自己是Swarm集群管理者。证书的更新周期默认设置为90天,集群配置数据库也已经配置完成并且处于加密状态。安全令牌也已经成功创建,允许新的管理者和工作者节点加入到Swarm集群中。以上全部内容都只需要一条命令

实验环境如图15.7所示。




docker怎么修改网卡IP 修改docker ip_docker swarm 指定ip_02

图15.7 实验环境



现在将“mgr2”节点加入到集群中,作为额外的管理者节点。

将新的管理者节点加入到Swarm需要两步。第一步,需要提取加入管理者到集群中所需的令牌;第二步,在“mgr2”节点上执行docker swarm join命令。只要将管理者准入令牌作为docker swarm join命令的一部分,“mgr2”就作为管理者节点加入Swarm。

在“mgr1”上运行下面的命令获取管理者准入令牌。

$ docker swarm join-token managerTo add a manager to this swarm, run the following command:    docker swarm join --token     SWMTKN-1-1dmtwu...r17stb-2axi5...8p7glz     172.31.5.251:2377

命令输出内容给出了管理者加入Swarm所需运行的准确命令。准入令牌和IP地址在读者自己的实验环境中是不一样的。

复制该命令并在“mgr2”节点上运行。

$ docker swarm join --token SWMTKN-1-1dmtwu...r17stb-2axi5...8p7glz > 172.31.5.251:2377This node joined a swarm as a manager.

“mgr2”现在已经作为另一个管理者加入Swarm。

{注:} 

join命令的格式是docker swarm join --token :。

可以通过在任意管理者节点上运行docker node ls命令来确认上述操作。

$ docker node lsID               HOSTNAME  STATUS   AVAILABILITY  MANAGER STATUS7xamk...ge662z   mgr1      Ready    Active        Leaderi0ue4...zcjm7f * mgr2      Ready    Active        Reachable

上述输出内容中显示“mgr1”和“mgr2”都加入了Swarm,并且都是Swarm管理者。最新的配置如图15.8所示。




docker怎么修改网卡IP 修改docker ip_字段_03

图15.8 “mgr1”和“mgr2”都加入了Swarm



两个管理者这个数量,大概是最糟糕的一种情况了。但是这只是一个实验环境,而不是什么核心业务生产环境,所以糟糕点也无所谓。

向Swarm中加入工作者也只需两步。第一步需要获取新工作者的准入令牌,第二步是在工作者节点上运行docker swarm join命令。

在任意管理者节点上运行下面的命令,获取工作者准入令牌。

$ docker swarm join-token workerTo add a worker to this swarm, run the following command:    docker swarm join --token     SWMTKN-1-1dmtw...17stb-ehp8g...w738q     172.31.5.251:2377

读者可以在指定工作者的节点上运行该命令。准入令牌和IP地址会有所不同。

复制如下所示命令到“wrk1”上并且运行。

$ docker swarm join --token SWMTKN-1-1dmtw...17stb-ehp8g...w738q > 172.31.5.251:2377This node joined a swarm as a worker.

在任意Swarm管理者上运行docker node ls命令。

$ docker node lsID                HOSTNAME   STATUS   AVAILABILITY  MANAGER STATUS7xamk...ge662z *  mgr1       Ready    Active        Leaderailrd...ofzv1u    wrk1       Ready    Activei0ue4...zcjm7f    mgr2       Ready    Active        Reachable

目前读者已经拥有包含两个管理者和一个工作者的Swarm集群。管理者配置为高可用(HA),并且复用集群存储。最新的配置如图15.9所示。




docker怎么修改网卡IP 修改docker ip_docker怎么修改网卡IP_04

图15.9 将管理者配置为高可用(HA)



(2)了解Swarm安全背后的原理

到目前为止,读者已经成功搭建了安全的Swarm集群。接下来一起花费几分钟了解一下这背后涉及的安全技术。

1)Swarm准入令牌

向某个现存的Swarm中加入管理者和工作者所需的唯一凭证就是准入令牌。因此,保证准入令牌的安全十分关键!不要将其发布到公开的Github仓库中。

每个Swarm都包含两种不同准入令牌。

  • 管理者所需准入令牌。
  • 工作者所需准入令牌。

有必要理解Swarm准入令牌的格式。每个准入令牌都由4个不同的字段构成,中间采用虚线(-)连接。

PREFIX - VERSION - SWARM ID - TOKEN

PREFIX永远是“SWMTKN”,这样允许读者通过表达式匹配到该令牌,以避免意外将其发布到公共环境当中;VERSION这一列则展示了Swarm的版本信息;SWARM ID列是Swarm认证信息的一个哈希值;TOKEN这一列的内容决定了该令牌是管理者还是工作者的准入令牌。

如下所示,对于指定Swarm的管理者和工作者准入令牌,除了最后TOKEN字段的内容之外没有任何区别。

  • 管理者:SWMTKN-1-1dmtwusdc...r17stb-2axi53zjbs45lqxykaw8p7glz

。 - 工作者:SWMTKN-1-1dmtwusdc...r17stb-ehp8gltji64jbl45zl6hw738q

如果用户认为当前准入令牌存在风险,仅用一条命令就可以取消该准入令牌授权,同时发布新的准入令牌。在下面的示例中,取消了已经授权的管理者准入令牌,之后又发布了新的令牌。

$ docker swarm join-token --rotate managerSuccessfully rotated manager join token.To add a manager to this swarm, run the following command:    docker swarm join --token      SWMTKN-1-1dmtwu...r17stb-1i7txlh6k3hb921z3yjtcjrc7      172.31.5.251:2377

需要注意的是,新旧令牌只有最后字段存在区别。SWARM ID还是相同的。

准入令牌保存在集群配置的数据库中,默认是加密的。

2)TLS和双向认证

每个加入Swarm的管理者和工作者节点,都需要发布自己的客户端证书。这个证书用于双向认证。证书中定义了节点相关信息,包括从属的Swarm集群以及该节点在集群中的身份(管理者还是工作者)。

在Linux主机上,读者可以指定使用下面的命令查看指定节点的客户端证书。

$ sudo openssl x509   -in /var/lib/docker/swarm/certificates/swarm-node.crt   -text  Certificate:      Data:          Version: 3 (0x2)          Serial Number:              80:2c:a7:b1:28...a8:af:89:a1:2a:51:89      Signature Algorithm: ecdsa-with-SHA256          Issuer: CN=swarm-ca          Validity              Not Before: Jul 19 07:56:00 2017 GMT              Not After : Oct 17 08:56:00 2017 GMT              Subject: O=mfbkgjm2tlametbnfqt2zid8x, OU=swarm-manager,              CN=7xamk8w3hz9q5kgr7xyge662z              Subject Public Key Info:

上述输出中,Subject中用到了O、OU以及CN字段分别表示Swarm ID、节点角色以及节点ID信息。

  • 组织字段O保存的是Swarm ID。
  • 组织单元字段OU保存的是节点在Swarm中的角色。
  • 规范名称字段CN保存的是节点的加密ID。

如图15.10所示。




docker怎么修改网卡IP 修改docker ip_Docker_05

图15.10 Subject中使用的字段



在Validity中,还可以直接看到证书的更新周期。

上述信息可以在docker system info命令的输出中得到验证。

$ docker system info          Swarm: active NodeID: 7xamk8w3hz9q5kgr7xyge662z    << Relates to the CN field Is Manager: true    << Relates to the OU field ClusterID: mfbkgjm2tlametbnfqt2zid8x    << Relates to the O field ...         ... CA Configuration: Expiry Duration: 3 months     << Relates to Validity field Force Rotate: 0 Root Rotation In Progress: false

3)配置一些CA信息

通过docker swarm update命令可以配置Swarm证书的更新周期。下面的示例中,将Swarm的证书更新周期修改为30天。

$ docker swarm update --cert-expiry 720h

Swarm允许节点在证书过期前重新创建证书,这样可以保证Swarm中全部节点不会在同一时间尝试更新自己的证书信息。

读者可以在创建Swarm的时候,通过在docker swarm init命令中增加--external-ca参数来指定外部的CA。

docker swarm ca命令可以用于管理CA相关配置。可以在运行该命令时指定--help来查看命令功能。

$ docker swarm ca --helpUsage: docker swarm ca [OPTIONS]Manage root CAOptions:      --ca-cert pem-file               Path to the PEM-formatted root CA                                       certificate to use for the new cluster Path      --ca-key pem-file                to the PEM-formatted root CA                                       key to use for the new cluster      --cert-expiry duration           Validity period for node certificates                                       (ns|us|ms|s|m|h) (default 2160h0m0s)  -d, --detach                         Exit immediately instead of waiting for the                                       root rotation to converge Specifications of      --external-ca external-ca        one or more certificate signing endpoints                                       Print usage      --help                           Suppress progress output  -q, --quiet                          Rotate the swarm CA - if no certificate      --rotate                         or key are provided, new ones will be gene

4)集群存储

集群存储是Swarm的大脑,保存了集群配置和状态数据。

存储目前是基于etcd的某种实现,并且会在Swarm内所有管理者之间自动复制。存储默认也是加密的。

集群存储正逐渐成为很多Docker平台的关键技术。例如,Docker网络和Docker密钥都用到了集群存储。Docker平台的很多部分都已经用到了集群存储,未来对集群存储的利用会更多,而这也是Swarm模式在Docker规划中占据重要地位的原因之一。这还意味着,如果不使用Swarm模式运行Docker,很多Docker特性就无法使用。

集群存储的日常维护由Docker自动完成。但是,在生产环境中,需要为集群存储提供完整的备份和恢复方案。

Swarm模式安全部分的内容到此为止。

2.Docker安全扫描

快速发现代码缺陷的能力至关重要。Docker安全扫描功能使得对Docker镜像中已知缺陷的检测工作变得简单。

{注:} 

在本书编写之时,Docker安全扫描已经可以用于Docker Hub上私有仓库的镜像了。同时该技术还可以作为Docker可信服务本地化部署解决方案的一部分。最后,所有官方Docker镜像都经过了安全扫描,扫描报告在其仓库中可以查阅。

Docker安全扫描对Docker镜像进行二进制代码级别的扫描,对其中的软件根据已知缺陷数据库(CVE数据库)进行检查。在扫描执行完成后,会生成一份详细报告。

打开浏览器访问Docker Hub,并搜索Alpine仓库。图15.11展示了官方Alpine仓库的Tags标签页。




docker怎么修改网卡IP 修改docker ip_docker怎么修改网卡IP_06

图15.11 官方Alpine仓库的Tags标签页



Alpine仓库是官方仓库,这意味着该仓库会自动扫描并生成对应报告。可以看到,镜像标签为edge、latest以及3.6的镜像都通过了已知缺陷的检查。但是alpine:3.5镜像存在已知缺陷(标红)。

如果打开alpine:3.5镜像,可以发现如图15.12所示的详细信息。




docker怎么修改网卡IP 修改docker ip_Docker_07

图15.12 alpine:3.5镜像的详细信息



这是发现自己软件中已知缺陷详情的一种简单方式。

Docker可信镜像仓库服务(Docker Trusted Registry, DTR),属于Docker企业版中本地化镜像仓库服务的一部分内容,提供了相同的Capability,同时还允许用户自行控制其镜像扫描时机以及扫描方式。例如,DTR允许用户选择镜像是在推送时自动触发扫描,还是只能手工触发。同时DTR还允许用户手动更新CVE数据库,这对于DTL无法进行联网来自动更新CVE数据的场景来说,是一种理想的解决方案。

这就是Docker安全扫描,一种深入检测Docker镜像是否存在已知安全缺陷的好方式。当然,能力越大责任越大,当用户发现缺陷后,就需要承担解决相应缺陷的责任了。

3.Docker内容信任

Dockr内容信任(Docker Content Trust,DCT)使得用户很容易就能确认所下载镜像的完整性以及其发布者。在不可信任的网络环境中下载镜像时,这一点很重要。

从更高层面来看,DCT允许开发者对发布到Docker Hub或者Docker可信服务的镜像进行签名。当这些镜像被拉取的时候,会自动确认签名状态。图15.13展示了这一过程。

DCT还可以提供关键上下文,如镜像是否已被签名从而可用于生产环境,镜像是否被新版本取代而过时等。

在本书编写之际,DTC提供的上下文还在初期,配置起来相当复杂。

在Docker主机上启用DCT功能,所要做的只是在环境中将DOCKER_CONTENT_TRUST变量设置为1。

$ export DOCKER_CONTENT_TRUST=1




docker怎么修改网卡IP 修改docker ip_docker_08

图15.13 镜像被拉取时自动确认签名状态



在实际环境中,用户可能希望在系统中默认开启该特性。

如果使用Docker统一配置层(Docker企业版的一部分),需要勾选图中15.14所示Run Only Signed Images复选项。这样会强制所有在UCP集群中的节点只运行已签名镜像。




docker怎么修改网卡IP 修改docker ip_docker swarm 指定ip_09

图15.14 勾选Only run signed images复选项



由图15.14中可知,UCP在DCT的基础上进行进一步封装,提供了已签名镜像的安全首选项信息。例如,用户可能有这样的需求:在生产环境中只能使用由secops签名的镜像。

一旦DCT功能开启,就不能获取并使用未签名镜像了。图15.15展示了开启DCT之后,如果再次尝试通过Docker CLI或者UCP Web UI界面拉取未签名镜像时所报的错误(两个示例都尝试拉取标签为“unsigned”的镜像)。




docker怎么修改网卡IP 修改docker ip_docker怎么修改网卡IP_10

图15.15 拉取未签名镜像时报错



图15.16展示了DCT是如何阻止Docker客户端拉取一个被篡改的镜像的。图15.17展示了DCT如何阻止客户端拉取旧镜像。




docker怎么修改网卡IP 修改docker ip_docker怎么修改网卡IP_11

图15.16 拉取被篡改的镜像




docker怎么修改网卡IP 修改docker ip_docker_12

图15.17 拉取旧镜像



Docker内容信任是一种很重要的技术,能帮助用户检查从Docker服务中拉取的镜像。该技术的基础模式配置起来非常简单,但是类似上下文等一些高级特性,现阶段配置起来还是非常复杂的。

4.Docker密钥

很多应用都需要密钥。比如密码、TLS证书、SSH key等。

在Docker1.13版本之前,没有一种标准且安全的方式能让密钥在应用间实现共享。常见的方式是开发人员将密钥以文本的方式写入环境变量(我们都这么做过)。这与理想状态差距甚远。

Docker1.13引入了Docker密钥,将密钥变成Docker生态系统中的一等公民。例如,增加了一个新的子命令docker secret来管理密钥。在Docker的UCP界面中,也有专门的地方来创建和管理密钥。在后台,密钥在创建后以及传输中都是加密的,使用时被挂载到内存文件系统,并且只对那些已经被授权了的服务开放访问。这确实是一种综合性的端到端解决方案。

图15.18展示了其总体流程。

下面依次介绍图15.18中所示工作流的每一步。

(1)密钥被创建,并且发送到Swarm。

(2)密钥存放在集群存储当中,并且是加密的(每个管理者节点都能访问集群存储)。

(3)B服务被创建,并且使用了该密钥。

(4)密钥传输到B服务的任务节点(容器)的过程是加密的。

(5)B服务的容器将密钥解密并挂载到路径/run/secrets下。这是一个临时的内存文件系统(在Windows Docker中该步骤有所不同,因为Windows中没有内存文件系统这个概念)。

(6)一旦容器(服务任务)完成,内存文件系统关闭,密钥也随之删除。

(7)A服务中的容器不能访问该密钥。




docker怎么修改网卡IP 修改docker ip_docker怎么修改网卡IP_13

图15.18 引入Docker密钥



用户可以通过docker secret子命令来管理密钥,可以通过在运行docker service create命令时附加--secret,从而为某个服务指定密钥。

###小结 Docker可以通过配置变得特别安全。Docker支持全部的Linux主流安全技术,包括Namespace、Control Group、Capability、MAC以及Seccomp。Docker为这些安全技术设定了合理的默认值,但是用户也可以自行修改配置,或者禁用这些安全技术。

在通用的Linux安全技术之上,Docker平台还引入了大量自有安全技术。Swarm模式基于TLS构建,并且配置上极其简单灵活。安全扫描对镜像进行二进制源码级别扫描,并提供已知缺陷的详细报告。Docker内容信任允许用户对内容进行签名和认证,密钥目前也是Docker中的一等公民。

最终结论就是,无论用户希望Docker环境有多安全,Docker都可以实现。这一切都取决于用户如何配置Docker。