原文地址:
https://docs.docker.com/swarm/secure-swarm-tls/
https://docs.docker.com/swarm/configure-tls/
背景及基本概念
Swarm集群中的每个节点都安装Docker Daemon,绑定到一个端口上进行通讯,存在很明显的安全隐患。
特别是在不可信的网络环境中,像互联网。
Docker Swarm
和Docker Daemon
使用TLS(Transport Layer Security)来消除这些安全风险。
注:TLS只是SSL(Secure Socketed Layer
)的后代产物,经常被混用。本文使用TLS术语。
PKI概念
公钥基础设施(PKI, Public Key Infrastructure):它是用于创建和管理数字证书,混合了安全相关技术、策略及步骤等内容,使用认证和加密等机制来保证数字通讯安全。
PKI的技术、策略与程序,包括以下内容:
- 安全地请求证书服务
- 认证请求证书的实体的程序
- 评估实体资格证书的程序
- 发布证书的技术与过程
- 废除证书的技术与过程
Docke Engine和Swarm使用PKI如何提高安全性
Docker命令行客户端(Docker Engine CLI)与Docker Engine需要使用TLS用于安全认证。
配置TLS后,命令行客户端与Docker Engin的通讯全部使用数字认证来完成,在命令行客户端发送命令到Docker Engine前必须提供数字证书。
Docker Engine信任命令行客户端使用的证书,信任是由可信任的第三方提供。
这种可信任的第三方称为CA
(The Certificate Authority Server)。
CA提供创建、签署、发行、废除证书等服务,通过在Docker主机安装CA的根证书提供信任。
任何使用Docker Engine Remote API的客户端(如CLI、UCP)都可以使用TLS。
在Docker使用TLS的三种方式
在Docker使用TLS的三种方式:
- 第三方CA
- 企业内部CA
- 自签证书
第三方CA认证
第三方CA认证,是由第三方公司提供创建、发行、废除以及管理证书的方法,是要收费的。这是一种提供高度信任的企业级可伸缩解决方案。
借助第三方提供的认证服务,对于大的企业,可以节约维护成本和杂费开支。
企业内部CA
许多组织选择实现自己的CA和PKI,例如OpenSSL,微软的Active Directory。最大的好处就是它的可控性,是高度安全可扩展的一种选择。
创建、发行和废除等管理证书的工作,就全部需要自己的管理,会带来一定的成本。
自签证书
自签证书就是用自己的私钥来签署的证书,而不是信任的第三方。
优点是低成本,简单易用。
它缺乏完整的PKI,不能很好地伸缩,不能废除自签证书,因此在这三种TLS方式中安全性最低,并不建议用于不安全的外部网络的生产环境中。
在Docker Swarm环境中配置TLS
* 以下将以企业内部CA
为例介绍如何在Docker Swarm环境中配置TLS *
在生产环境中,需要创建swarm集群环境如下:
- 两个节点构建的集群:node1和node2
- Docker Engine CLI
- Swarm Manager
- CA服务器
除CA服务器外,其它四台主机都要安装Docker Engine。
1. 准备主机
服务器名 | 描述 |
---|---|
ca | Acts as the Certificate Authority (CA) server. |
swarm | Acts as the Swarm Manager. |
node1 | Act as a Swarm node. |
node2 | Act as a Swarm node. |
client | Acts as a remote Docker Engine client |
保证能够使用SSH访问在这5台主机,能够使用DNS域名解析。
默认情况下,swarm manager与swarm node之间使用TCP 2376端口,
Docker Engine client与swarm manager使用 TCP 3376端口。确保网络端口的访问。
2. 创建CA服务
# 在CA服务器上以root权限运行命令
sudo su
# 为CA创建私钥
openssl genrsa -out ca-priv-key.pem 2048
# 为CA创建公钥
openssl req -config /usr/lib/ssl/openssl.cnf -new -key ca-priv-key.pem -x509 -days 1825 -out ca.pem
# 查看创建的公钥和私钥
openssl rsa -in ca-priv-key.pem -noout -text
openssl x509 -in ca.pem -noout -text
3. 创建并签暑keys
为各主机创建keys文件如下:
服务器名称 | Private key | CSR | Certificate |
---|---|---|---|
manager | manager-priv-key.pem | manager.csr | manager-cert.pem |
node1 | node1-priv-key.pem | node1.csr | node1-cert.pem |
node2 | node2-priv-key.pem | node2.csr | node2-cert.pem |
client | client-priv-key.pem | client.csr | client-cert.pem |
创建keys步骤及命令如下:(将<server>
替换成服务器名)
# 在CA服务器上以root权限运行命令
sudo su
# 为使用者创建私钥:<server>-priv-key.pem
openssl genrsa -out <server>-priv-key.pem 2048
# 使用上面生成的私钥为使用者生成csr(certificate signing request)文件:<server>.csr
openssl req -subj "/CN=swarm" -new -key <server>-priv-key.pem -out <server>.csr
# 基于以上创建的CSR创建证书<server>-cert.pem
openssl x509 -req -days 1825 -in <server>.csr -CA ca.pem -CAkey ca-priv-key.pem -CAcreateserial -out <server>-cert.pem -extensions v3_req -extfile /usr/lib/ssl/openssl.cnf
openssl rsa -in <server>-priv-key.pem -out <server>-priv-key.pem
4. 安装keys
将上述在CA服务器上创建的文件复制到相应主机的文件夹/home/ubuntu/.certs
中
原始文件 | 复制到相应主机文件名 |
---|---|
ca.pem | ca.pem |
<server> -cert.pem | cert.pem |
<server> -priv-key.pem | key.pem |
以manager主机为例,在CA主机上ssh连接manager主机,使用scp命令远程复制上述文件(* 如果愿意,当然可以手动复制 *)
# 以root权限运行后面的命令
sudo su
# ssh连接到manager主机
ssh ubuntu@manager 'mkdir -p /home/ubuntu/.certs'
# 远程复制文件
scp ./ca.pem ubuntu@manager:/home/ubuntu/.certs/ca.pem
scp ./manager-cert.pem ubuntu@manager:/home/ubuntu/.certs/cert.pem
scp ./manager-priv-key.pem ubuntu@manager:/home/ubuntu/.certs/key.pem
# 检验完成复制
ls -l /home/ubuntu/.certs/
5. 在Docker Engine Daemon中配置TLS
在每台Docker主机上编辑Docker Engine配置文件,修改DOCKER_OPTS
选项如下:
-H tcp://0.0.0.0:2376 --tlsverify --tlscacert=/home/ubuntu/.certs/ca.pem --tlscert=/home/ubuntu/.certs/cert.pem --tlskey=/home/ubuntu/.certs/key.pem
然后,重启Docker Engine守护进程。
注意:不同的Linux发布版本,Docker Engine配置文件可能有所不同。在Unbuntu上是/etc/default/docker
文件
示例如下:
# 以root权限运行
sudo su
# 编辑Docker Engine配置文件: DOCKER_OPTS=' -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=/home/ubuntu/.certs/ca.pem --tlscert=/home/ubuntu/.certs/cert.pem --tlskey=/home/ubuntu/.certs/key.pem'
vi /etc/default/docker
# 重启服务
service docker restart
6. 创建集群
创建集群不是本节内容重点,以下以Docker Hub作为主机服务服务为例,简略带过集群创建过程。
# 在manager主机上
sudo export TOKEN=$(docker run --rm swarm create)
# 在节点上运行swarm agent
sudo docker run -d swarm join --addr=node1:2376 token://$TOKEN
sudo docker run -d swarm join --addr=node2:2376 token://$TOKEN
7. 用TLS启动Swarm Manger,并测试配置
# 在manager主机上启动manager,指定tls配置
docker run -d -p 3376:3376 -v /home/ubuntu/.certs:/certs:ro swarm manage --tlsverify --tlscacert=/certs/ca.pem --tlscert=/certs/cert.pem --tlskey=/certs/key.pem --host=0.0.0.0:3376 token://$TOKEN
# 在manager上使用TLS查看swarm版本信息(成功)
sudo docker --tlsverify --tlscacert=/home/ubuntu/.certs/ca.pem --tlscert=/home/ubuntu/.certs/cert.pem --tlskey=/home/ubuntu/.certs/key.pem -H swarm:3376 version
# 在manager上不用TSL查看swarm版本信息(服务端信息显示失败)
sudo docker -H swarm:3376 version
8. 在Client主机上配置默认使用TLS
为了不用每次访问其它主机Docker Daemon指定TLS参数,可在客户端配置Engine证书路径。
# 进入client主机
# 创建文件夹/home/ubuntu/.docker
mkdir /home/ubuntu/.docker
# 复制证书到此文件夹
cp /home/ubuntu/.certs/{ca,cert,key}.pem /home/ubuntu/.docker
# 编辑文件~/.bash_profile,设置环境变量
vi ~/.bash_profile
########################################
####### 环境变量 #####
# export DOCKER_HOST=tcp://manager:3376
# export DOCKER_TLS_VERIFY=1
# export DOCKER_CERT_PATH=/home/ubuntu/.docker/
########################################
# 让环境变量生效
source ~/.bash_profile
# 验证命令行访问manager的Swarm manager信息成功
docker version