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 相关命令

示例一:简单示例

这个示例展示secret在几个命令中是如何工作的

  1. 向Docker添加一个secrets。docker secret create命令读取标准输入,因为最后一个参数,表示从中读取秘密的文件被设置为-

    [root@node1 ~]# printf "This is a secret" | docker secret create my_secret_data -
    ua6qvxgbuqtjnhv8bd5lz7fpv
    
  2. 创建一个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 
    
  3. 查看service

    [root@node1 ~]# docker service ls
    ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
    kun7yexgygau        redis               replicated          1/1                 redis:alpine 
    
  4. 进入容器查看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 #
    
  5. 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
    
  6. 通过运行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 ~]# 
    
  7. 验证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不可访问
    
  8. 停止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

  1. 生成root key

    [root@node1 ~]# openssl genrsa -out "root-ca.key" 4096
    Generating RSA private key, 4096 bit long modulus
    ..........................................................................................................................................................................................++
    ..........++
    e is 65537 (0x10001)
    
  2. 使用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'
    
  3. 配置根CA。编辑一个名为root-ca. cnf的新文件,并将以下内容粘贴到其中。这将限制根CA签署叶子证书,而不是中间CA

    [root_ca]
    basicConstraints = critical,CA:TRUE,pathlen:1
    keyUsage = critical, nonRepudiation, cRLSign, keyCertSign
    subjectKeyIdentifier=hash
    
  4. 签署证书

    $ 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
    
    
  5. 生成site key

    [root@node1 ~]# openssl genrsa -out "site.key" 4096
    Generating RSA private key, 4096 bit long modulus
    ............................................................................++
    ....................................................................................................++
    e is 65537 (0x10001)
    
  6. 生成站点证书并使用站点密钥签名

    openssl req -new -key "site.key" -out "site.csr" -sha256 \
              -subj '/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost'
    
  7. 配置站点证书。编辑一个名为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
    
  8. 签署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
    
    
  9. Nginx service 不需要site.csr和site.cnf,但是如果你想生成一个新的站点证书,则需要它们。保护root-ca.key文件。

Configure the Nginx container

  1. 生成一个非常基本的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;
        }
    }
    
  2. 创建三个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
    
    
  3. 创建一个运行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

posted @ 2019-06-13 15:38  漂泊的蒲公英  阅读(1171)  评论(0编辑  收藏  举报