Docker Swarm secrets
什么是secrets
在docker swarm中,secrets是一组敏感数据,比如:
- 密码
- SSH私钥
- SSL证书
- 数据库密码
- 通用字符串或二进制内容(最大可达500 kb)
在Docker 1.13及更高版本中,可以使用Docker secret集中管理这些数据,安全地传输给需要访问这些数据的容器。secret在docker swarm和传输中是被加密的。只有已被授予访问权限的service可以访问secret
【注意】Docker secret只对集群服务可用,而对独立容器不可用
Docker 如何管理secrets
当向集群添加一个secret时,Docker通过一个相互的TLS链接将secret发送给swarm manager。secret存储在Raft日志中,Raft日志是加密的。Raft日志会被复制到其他swarm manager,确保所有swarm manager数据相同,达到高可用性
当授予新创建的或正在运行的服务对秘密的访问权时,已解密的秘密将被挂载到内存文件系统中的容器中。容器内挂载点的位置默认为Linux容器中的/run/secrets/<secret_name>。在Docker 17.06或更高版本中可以指定自定义位置。
如果节点在运行具有secret访问权限的容器时丢失了与集群的连接,则容器仍然具有访问其secret的权限,但在节点重新连接到集群之前无法接收更新。
不能删除正在运行的服务正在使用的秘密。有关在不中断正在运行的服务的情况下删除秘密的方法,请参考“Rotate a secret ”
要更容易地更新或回滚secret,建议在secret名称中添加版本号或日期。这可以通过在给定容器中控制secret的挂载点来实现。
docker secret 相关命令
- docker secret create
- docker secret inspect
- docker secret ls
- docker secret rm
- --secret flag for docker service create
- --secret-add and --secret-rm flags for docker service update
示例一:简单示例
这个示例展示secret在几个命令中是如何工作的
-
向Docker添加一个secrets。docker secret create命令读取标准输入,因为最后一个参数,表示从中读取秘密的文件被设置为-
[root@node1 ~]# printf "This is a secret" | docker secret create my_secret_data - ua6qvxgbuqtjnhv8bd5lz7fpv
-
创建一个redis服务并授予它访问这个secret的权限。默认情况下,容器可以在/run/secrets/<secret_name>访问secret,但是可以使用target选项自定义容器上的文件名。
[root@node1 ~]# docker service create --name redis --secret my_secret_data redis:alpine kun7yexgygau9b3eh5mnv58r7 overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged
-
查看service
[root@node1 ~]# docker service ls ID NAME MODE REPLICAS IMAGE PORTS kun7yexgygau redis replicated 1/1 redis:alpine
-
进入容器查看secret文件。默认所有人可读,文件名与secret名称相同。
/run/secrets # pwd /var/run/secrets /run/secrets # ls my_secret_data /run/secrets # cat my_secret_data This is a secret/run/secrets #
-
commit容器,secret并不会被提交
$ docker secret ls ID NAME CREATED UPDATED wwwrxza8sxy025bas86593fqs my_secret_data 4 hours ago 4 hours ago $ docker secret rm my_secret_data Error response from daemon: rpc error: code = 3 desc = secret 'my_secret_data' is in use by the following service: redis
-
通过运行update service,从运行的redis服务中删除对secret的访问
[root@node2 ~]# docker service update --secret-rm my_secret_data redis redis overall progress: 1 out of 1 tasks 1/1: running [==================================================>] verify: Service converged [root@node2 ~]#
-
验证secret是否不可再访问
[root@node2 ~]# docker exec -it 1f324 /bin/sh /data # cd /var/run/ /run # ls /run # ls * ls: *: No such file or directory /run # 此时可以看出secret文件不存在,secret不可访问
-
停止service,删除secret
[root@node1 ~]# docker service rm redis redis [root@node1 ~]# docker secret rm my_secret_data my_secret_data
示例二: 在Nginx Service中使用secret
本例分为两部分。第一部分是关于生成站点证书的, 第二部分是配置Nginx容器
GENERATE THE SITE CERTIFICATE生成站点证书
为你的站点生成根CA和TLS证书和密钥。对于生产站点,你可能希望使用Let’s Encrypt之类的服务来生成TLS证书和密钥,但是本示例使用命令行工具。这一步有点复杂,但只是一个设置步骤,以便你可以将某些内容存储为Docker secret。如果你想跳过这些子步骤,可以使用Let 's Encrypt生成站点密钥和证书,命名文件site.key和site.crt,然后跳到 Configure the Nginx container
-
生成root key
[root@node1 ~]# openssl genrsa -out "root-ca.key" 4096 Generating RSA private key, 4096 bit long modulus ..........................................................................................................................................................................................++ ..........++ e is 65537 (0x10001)
-
使用root key生成CSR(证书签名请求文件)
openssl req \ -new -key "root-ca.key" \ -out "root-ca.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA'
-
配置根CA。编辑一个名为root-ca. cnf的新文件,并将以下内容粘贴到其中。这将限制根CA签署叶子证书,而不是中间CA
[root_ca] basicConstraints = critical,CA:TRUE,pathlen:1 keyUsage = critical, nonRepudiation, cRLSign, keyCertSign subjectKeyIdentifier=hash
-
签署证书
$ openssl x509 -req -days 3650 -in "root-ca.csr" \ -signkey "root-ca.key" -sha256 -out "root-ca.crt" \ -extfile "root-ca.cnf" -extensions \ root_ca Signature ok subject=/C=US/ST=CA/L=San Francisco/O=Docker/CN=Swarm Secret Example CA Getting Private key
-
生成site key
[root@node1 ~]# openssl genrsa -out "site.key" 4096 Generating RSA private key, 4096 bit long modulus ............................................................................++ ....................................................................................................++ e is 65537 (0x10001)
-
生成站点证书并使用站点密钥签名
openssl req -new -key "site.key" -out "site.csr" -sha256 \ -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
-
配置站点证书。编辑一个名为site.cnf的新文件,并将以下内容粘贴到其中。这限制了站点证书,因此它只能用于对服务器进行身份验证,而不能用于对证书进行签名。
[server] authorityKeyIdentifier=keyid,issuer basicConstraints = critical,CA:FALSE extendedKeyUsage=serverAuth keyUsage = critical, digitalSignature, keyEncipherment subjectAltName = DNS:localhost, IP:127.0.0.1 subjectKeyIdentifier=hash
-
签署site证书
openssl x509 -req -days 750 -in "site.csr" -sha256 \ -CA "root-ca.crt" -CAkey "root-ca.key" -CAcreateserial \ -out "site.crt" -extfile "site.cnf" -extensions server Signature ok subject=/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost Getting CA Private Key
-
Nginx service 不需要site.csr和site.cnf,但是如果你想生成一个新的站点证书,则需要它们。保护root-ca.key文件。
Configure the Nginx container
-
生成一个非常基本的Nginx配置,它通过HTTPS提供静态文件。TLS证书和密钥存储为Docker机密,因此可以轻松地rotate它们。
在当前目录中,使用以下内容创建一个名为site.conf的新文件server { listen 443 ssl; server_name localhost; ssl_certificate /run/secrets/site.crt; ssl_certificate_key /run/secrets/site.key; location / { root /usr/share/nginx/html; index index.html index.htm; } }
-
创建三个secret,表示key、证书和site.conf。您可以将任何文件作为secret存储,只要它小于500kb。这允许您将key、证书和配置与使用它们的服务解耦。在这些命令中,最后一个参数表示要从主机文件系统上读取secret的文件的路径。在这些示例中,秘密名称和文件名是相同的。
[root@node1 ~]# docker secret create site.key site.key d6c6xr6hdsgqpvdk86tqwmhbg [root@node1 ~]# docker secret create site.crt site.crt p6m3m0djiqn1606ocf6fnjpux [root@node1 ~]# [root@node1 ~]# docker secret create site.conf site.conf czezgjtxtcnc4avrbigxeixbu [root@node1 ~]# [root@node1 ~]# docker secret ls ID NAME DRIVER CREATED UPDATED czezgjtxtcnc4avrbigxeixbu site.conf 38 seconds ago 38 seconds ago p6m3m0djiqn1606ocf6fnjpux site.crt 43 seconds ago 43 seconds ago d6c6xr6hdsgqpvdk86tqwmhbg site.key 47 seconds ago 47 seconds ago
-
创建一个运行Nginx并可以访问这三个secret的service。docker service create命令的最后一部分创建一个符号链接,从site.conf secret到/etc/nginx.conf。,其中Nginx查找额外的配置文件。此步骤发生在Nginx实际启动之前,因此如果更改Nginx配置,则不需要重新构建映像。
在Docker 17.05和更早版本中,secret总是位于/run/secrets/目录中。Docker 17.06及更高版本允许为容器内的secret指定自定义位置。
-
Docker 17.06 and higher:
$ docker service create \ --name nginx \ --secret site.key \ --secret site.crt \ --secret source=site.conf,target=/etc/nginx/conf.d/site.conf \ --publish published=3000,target=443 \ nginx:latest \ sh -c "exec nginx -g 'daemon off;'"
source 指定容器使用 secret 后,secret 会被解密并存放到容器的文件系统中,默认位置为 /run/secrets/<secret_name>。--secret source=site.conf,target=/etc/nginx/conf.d/site.conf 的作用就是指定使用secret site.conf,然后把器解密后的内容保存到容器/etc/nginx/conf.d/site.conf文件中
-
Docker 17.05 and earlier:
$ docker service create \ --name nginx \ --secret site.key \ --secret site.crt \ --secret site.conf \ --publish published=3000,target=443 \ nginx:latest \ sh -c "ln -s /run/secrets/site.conf /etc/nginx/conf.d/site.conf && exec nginx -g 'daemon off;'"
第一个示例同时显示了用于secret的短语法和长语法,第二个示例只显示了短语法。这个简短的语法在/run/secrets/中创建与secret名称相同的文件。在运行的容器中,现在存在以下三个文件
- /run/secrets/site.key
- /run/secrets/site.crt
- /etc/nginx/conf.d/site.conf (or /run/secrets/site.conf if you used the second example)
4.验证Nginx服务正在运行
[root@node1 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
g57n64qa269c nginx replicated 1/1 nginx:latest *:3000->443/tcp
[root@node1 ~]# docker service ps nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
g2no1sh4n2fa nginx.1 nginx:latest node2 Running Running 2 minutes ago
5.访问服务
失败,待查
https://docs.docker.com/engine/swarm/secrets/
https://www.cnblogs.com/wanghui-garcia/p/10245858.html
https://blog.51cto.com/cloudman/2052309