如何在CoreOS上使用TLS安全地设置Shipyard2.0.10
介绍
Docker 是容器化软件的流行选择,而 CoreOS 专门用于集群环境,这使得两者非常适合容器化应用程序。 但是,保持所有容器的组织可能会很复杂,特别是如果它们仅通过 Docker 命令行界面进行管理,或者如果您有多个 CoreOS 实例。
幸运的是,有一个有用的 Docker 管理工具,叫做 Shipyard。 它使您能够通过有用的 GUI 重新启动、销毁和创建容器。 它还允许您管理对特定容器的资源分配以及跨多个 Docker 主机管理容器。 但是,确保 Docker 服务器和 Shipyard 系统的安全非常重要,尤其是在生产环境中使用它们时。
在本指南中,我们将在单个 CoreOS 服务器上设置 Shipyard 2.0.10,并使用 TLS 证书保护 Docker,以确保只有授权的客户端可以连接到它。 TLS 代表 传输层安全 。 它用于在数据从客户端传输到服务器并再次返回时加密数据。 在我们的例子中,我们将使用它来加密我们与 Docker 主机的连接,以及 Docker 与 Shipyard 的连接。
先决条件
要遵循本教程,您将需要:
一个具有至少 512 MB RAM 的 CoreOS Droplet,但建议使用 1 GB 或更多。 确保选择最新的稳定版 CoreOS,而不是 alpha 或 beta 版本。
所有 CoreOS 服务器都需要一个 SSH 密钥,因此如果您还没有,您可以按照 How To Use SSH Keys with DigitalOcean Droplets 的步骤 1 - 3 添加一个。
Docker 主机的完全限定域名 (FQDN) 或子域。
如果您还没有域名,您可以从不同的域名注册商处购买一个。 一旦您有了要使用的域,如何从公共域注册商指向 DigitalOcean 域名服务器 会提供有关如何在 DigitalOcean DNS 下进行设置的说明。
您可以通过添加 A 记录将您的域指向您的 Droplet,如 如何使用 DigitalOcean 设置主机名中所述。
设置 Docker 以使用证书进行身份验证是一个相当高级的主题,因此请阅读 this OpenSSL tutorial 以了解 SSL 证书的工作原理。
第一步——创建服务器证书
我们需要做的第一件事是创建一个证书颁发机构,我们可以使用它来签署服务器和客户端证书。 CoreOS 附带 OpenSSL,这是一个可用于生成和签署证书的实用程序。
首先,我们将创建一个 RSA 私钥。 首先,创建并移动到一个名为 dockertls
的目录,这样很容易记住文件的位置。
mkdir ~/dockertls && cd ~/dockertls
接下来,创建一个 RSA 私钥。 此命令将提示您为密钥创建密码。
openssl genrsa -aes256 -out private-key.pem 4096
让我们分解上面的命令。 genrsa
表示该命令将生成一个私有 RSA 私钥。 -out private-key.pem
指定我们要生成的文件名,即private-key.pem
。 最后一位 4096
是密钥的长度(以位为单位)。 建议将其保持在较高的数字,例如 4096。
接下来,生成一个新证书并使用我们刚刚创建的私钥对其进行签名。 您需要输入创建密钥时选择的密码。
openssl req -new -x509 -sha512 -days 365 -key private-key.pem -out myca.pem
OpenSSL 还将询问一些必需的信息,例如您的服务器的 FQDN 和您的组织所在的县。 尝试尽可能准确地回答这些问题。 这是创建我们的自签名证书颁发机构或 CA 的最后一步。
现在我们有了 CA,我们实际上可以创建一些用于 Docker 守护进程的服务器证书。 以下两个命令生成签名请求。 确保将 example.com
替换为您用于 Docker 的域或子域。
openssl genrsa -out docker-1-key.pem 4096 openssl req -subj "/CN=example.com" -sha512 -new -key docker-1-key.pem -out docker.csr
最后,用 CA 的私钥签名。 您需要再次输入密钥密码。
openssl x509 -req -days 365 -sha256 -in docker.csr -CA myca.pem -CAkey private-key.pem -CAcreateserial -out final-server-cert.pem
这将在当前目录中创建一个名为 final-server-cert.pem
的文件,这是将在 Docker 主机上使用的服务器证书。
第二步——创建客户端证书
现在我们有了服务器证书,我们需要创建一个客户端证书。 每当我们尝试连接到 Docker 主机时,都会使用它。 它将验证客户端连接实际上已由我们的个人 CA 验证和签名。 因此,只有经过授权的客户端才被允许连接并向 Docker 发送命令。
首先,为客户端创建另一个签名请求。
openssl genrsa -out client-key.pem 4096 openssl req -subj '/CN=client' -new -key client-key.pem -out docker-client.csr
对于这个客户端请求,需要做一个额外的小步骤。 我们需要创建一个配置文件,指定生成的证书实际上可以用于客户端身份验证。
echo extendedKeyUsage = clientAuth > client.cnf
上述命令无需使用文本编辑器即可创建一个名为 client.cnf
的文件,其内容为 extendedKeyUsage = clientAuth
。
接下来,使用 CA 密钥对客户端进行签名。
openssl x509 -req -days 365 -sha512 -in docker-client.csr -CA myca.pem -CAkey private-key.pem -CAcreateserial -out client.pem -extfile client.cnf
现在我们有了一个 CA、一个服务器证书和一个客户端证书。
第三步——配置 Docker 和 CoreOS
在这一步中,我们将配置 Docker 守护程序以使用我们的证书。
我们需要修改 Docker 的启动选项。 CoreOS 使用 systemd
来管理服务。 如果您想阅读 systemd
并了解更多信息,可以阅读 如何使用 Systemctl 管理 Systemd 服务和单元。
首先,让我们从编辑 Docker 单元文件开始。 systemctl
命令有一个选项可以帮助我们复制实际的单元文件,而不是直接修改原始文件。 您可以将其视为 Docker 配置的覆盖。
使用 systemctl
打开 Docker 单元文件进行编辑。
sudo systemctl edit --full docker
这将使用 vim
打开文件进行编辑,您可以通过阅读我们的 vim 教程 来学习如何使用它。
找到以 ExecStart=/usr/lib/coreos/dockerd
开头的行。 在该行的 --host=fd://
之后附加下面突出显示的选项,使文件如下所示:
EnvironmentFile=-/run/flannel_docker_opts.env MountFlags=slave LimitNOFILE=1048576 LimitNPROC=1048576 ExecStart=/usr/lib/coreos/dockerd --daemon --host=fd:// --tlsverify --tlscacert=/home/core/dockertls/myca.pem --tlscert=/home/core/dockertls/final-server-cert.pem --tlskey=/home/core/dockertls/docker-1-key.pem -H=0.0.0.0:2376 $DOCKER_OPTS $DOCKER_OPT_BIP $DOCKER_OPT_MTU $DOCKER_OPT_IPMASQ
让我们看一下我们刚刚添加的选项:
--tlsverify
只是打开 TLS 验证,以便只有授权的客户端可以连接。--tlscacert
指定我们的 CA 证书的位置。--tlscert
指定服务器证书位置。--tlskey
指定服务器密钥位置。-H=0.0.0.0:2376
意味着 Docker 将监听来自任何地方的连接,但它仍然不允许任何没有授权客户端密钥或证书的连接。
保存并关闭文件,然后重新加载 Docker 守护进程,以便它使用我们的新配置。
sudo systemctl restart docker
您可以通过检查 Docker 的状态来确保一切正常。
systemctl status docker
查找以 Active: 开头的行。 如果它显示 active (running) 以外的任何内容,请仔细检查您的单元文件编辑并确保生成了所有必需的密钥和证书。
最后,我们可以测试我们的 TLS 验证。
docker --tlsverify --tlscacert=myca.pem --tlscert=client.pem --tlskey=client-key.pem -H=example.com:2376 info
如果一切顺利,你应该会收到一些关于你的 Docker 主机的基本系统信息; 这意味着您刚刚使用 TLS 保护了您的 Docker 主机。 如果出现错误,请使用 systemctl status docker
检查日志。
只要您使用有效的证书和客户端密钥进行连接,您现在就可以从任何地方访问您的 Docker 主机。 您可以生成和签署任意数量的客户端证书,以便在集群中使用。
第四步——安装造船厂
设置 Shipyard 是一个相当简单的过程。 所有的部分都是独立的,有自己的 Docker 容器,所以 Docker 会自动拉取所需的图像。
首先,我们需要设置一个存储 Shipyard 数据库的数据卷。
docker create --name shipyard-rethinkdb-data shipyard/rethinkdb
现在我们实际上可以为 RethinkDB 拉下并生成一个新容器。 这是 Shipyard 用来跟踪来自 Docker 的实时数据的数据库引擎。
docker run -it -d --name shipyard-rethinkdb --restart=always --volumes-from shipyard-rethinkdb-data -p 127.0.0.1:49153:8080 -p 127.0.0.1:49154:28015 -p 127.0.0.1:29015:29015 shipyard/rethinkdb
此命令还确保 RethinkDB 将仅侦听 localhost
。 这是保护此数据库的好方法,因为这意味着没有人能够从服务器外部访问它。
我们将使用 Shipyard 版本 2.0.10,因为它最容易使用 Docker TLS 进行配置。 以下命令将启动一个运行 Shipyard 的新容器并将其链接到 RethinkDB 容器,从而允许它们进行通信。
docker run -it -p 8080:8080 -d --restart=always --name shipyard --link shipyard-rethinkdb:rethinkdb shipyard/shipyard:2.0.10
完成 Shipyard 设置后,访问 http://example.com:8080
或 http://your_server_ip:8080
以访问 Shipyard 控制面板。 您可以使用默认用户名 admin 和密码 shipyard 登录。
Shipyard 将提示您向集群添加新引擎。 单击绿色的 + ADD 按钮,您将看到如下表格:
填写信息如下:
- Name 可以是任何你想要的。 这将是引擎的名称。
- Labels 也可以是任何你想要的。 只需简短,这样您就可以保持容器井井有条。
- CPUs 是您的服务器有多少 CPU。
- Memory 是您的服务器有多少 RAM。
- Address 必须是
https://your_server_ip:2376
才能使用 TLS。
基本选项下方有三个大文本区域。 您将在此处粘贴证书和密钥,以便 Shipyard 可以安全地连接到您的 Docker 主机。
第一个字段 SSL Certificate 需要客户端证书。 打印证书内容。
cat ~/dockertls/client.pem
然后复制输出并将其粘贴到 SSL 证书 框中。
接下来,打印客户端密钥的内容。
cat ~/dockertls/client-key.pem
将输出粘贴到 SSL Key 文本区域。
最后,打印 CA 证书的内容。
cat ~/dockertls/myca.pem
将该内容粘贴到 CA 证书 框中。
单击页面底部的淡蓝色 ADD 按钮。 如果一切配置正确,Shipyard 应该会向您显示此屏幕:
结论
现在,您的 CoreOS 服务器上运行了一个安全的 Docker 主机!
Shipyard 可以帮助您安全可靠地管理您的容器和主机集群。 您还可以将客户端密钥和证书添加到本地计算机,以便您可以从任何地方远程管理 Docker 集群。
对于额外的安全步骤,您可以使用 Nginx 反向代理您的 Shipyard 服务器。 这允许您使用 HTTPS 从本地机器更安全地连接到 Shipyard。 您可以在文章 Docker Explained: How To Containerize and Use Nginx as a Proxy 文章中了解更多信息。 您还可以 启动更多 CoreOS 服务器 并试用 Docker 集群。 您可以使用 Shipyard 管理数百个引擎。