優雅地實現安全的容器編排 - Docker Secrets
在微服務架構應用中,眾多組件在集群中動態地創建、伸縮、更新。在如此動態和大規模的分布式係統上,管理和分發密碼、證書等敏感信息將會是非常具有挑戰性的工作。對於容器應用,傳統的秘密分發方式,如將秘鑰存放在容器鏡像中,或是利用環境變量,volume動態掛載方式動態傳入都存在著潛在的安全風險。
為了應對這個問題,在Docker 1.13及更高版本中,Docker推出了Secrets管理,可以在Swarm mode集群中安全地管理密碼、密鑰證書等敏感信息,並允許在多個Docker容器實例之間共享訪問指定的秘密信息。
Docker secret 基本功能與典型場景
Docker命令行工具提供了docker secret
命令來管理敏感信息,
注: docker secret
隻能從Docker Swarm模式的manager節點調用,如果你在本機進行試驗,請先執行 docker swarm init
命令
$ docker secret --help
Usage: docker secret COMMAND
Manage Docker secrets
Options:
--help Print usage
Commands:
create Create a secret from a file or STDIN as content
inspect Display detailed information on one or more secrets
ls List secrets
rm Remove one or more secrets
Run 'docker secret COMMAND --help' for more information on a command.
其中 docker secret create
支持從標準輸入讀取信息,並且存入指定的secret:
首先我們創建兩個 secrets
$ echo "Password4DB" | docker secret create db_password -
$ echo "Password4Root" | docker secret create root_password -
然後我們創建一個“db”服務並引用所創建的secret作為,數據庫密碼和root密碼
$ docker service create --name db \
-d \
--secret db_password \
--secret root_password \
-e MYSQL_USER=dbtest \
-e MYSQL_DATABASE=dbtest \
-e MYSQL_PASSWORD_FILE=/run/secrets/db_password \
-e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/root_password \
mariadb
創建完畢之後,我們可以檢查服務的狀態
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
ouq2xbuu3jrp db replicated 1/1 mariadb:latest
$ docker service logs --tail 100 db
...
db.1.zjmymi0goca0@moby | 2017-05-28 23:35:25 140451437311936 [Warning] 'proxies_priv' entry '@% root@32ab97f50413' ignored in --skip-name-resolve mode.
db.1.zjmymi0goca0@moby | 2017-05-28 23:35:25 140451437311936 [Note] mysqld: ready for connections.
db.1.zjmymi0goca0@moby | Version: '10.1.23-MariaDB-1~jessie' socket: '/var/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution
我們可以通過 docker exec
命令來進入容器內部,查看掛載到/run/secrets/目錄下的秘密文件
$ docker exec -ti 32ab97f50413 bash
root@32ab97f50413:/# cat /run/secrets/db_password
Password4DB
root@32ab97f50413:/# cat /run/secrets/root_password
Password4Root
容器編排中使用 docker secret
從 Docker Compose V3.1開始,支持在容器編排文件中使用 secret,這可以方便地在不同容器中分享所需的敏感信息。下麵我們將使用 Compose 模板來構建一個Wordpress應用,通過 secret 實現 “wordpress”服務容器和“db”服務容器中共享數據庫密碼。
docker-compose.yml
文件如下
version: "3.1"
services:
wordpress:
image: wordpress:latest
secrets:
- wp_db_password
ports:
- 8080:80
environment:
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_NAME=wordpress
- WORDPRESS_DB_PASSWORD_FILE=/run/secrets/wp_db_password
- WORDPRESS_DB_HOST=mariadb
deploy:
replicas: 3
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
mariadb:
image: mariadb
secrets:
- wp_db_password
- root_db_password
environment:
- MYSQL_USER=wordpress
- MYSQL_DATABASE=wordpress
- MYSQL_PASSWORD_FILE=/run/secrets/wp_db_password
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/root_db_password
deploy:
replicas: 1
restart_policy:
condition: on-failure
secrets:
wp_db_password:
external: true
root_db_password:
external: true
通過模板中的 secrets
部分,我們創建和引用 Docker Secrtes,而且在Service 定義中可以非常方便地引用這些秘密信息,實現安全的容器編排。
首先,我們利用命令行創建秘密
$ echo "Password4DB" | docker secret create wp_db_password -
$ echo "Password4Root" | docker secret create root_db_password -
然後利用命令行部署compose模板
$ docker stack deploy -c docker-compose.yml wordpress
Creating network wordpress_default
Creating service wordpress_wordpress
Creating service wordpress_mariadb
由於我們為 “wordpress” 服務定義了 routing mesh 的端口映射,將8080端口暴露為服務的訪問端口。我們可以打開瀏覽器,輸入 https://127.0.0.1:8080 之後,就可以看到 WordPress 著名的配置頁麵了。
關於更多關於 Docker 編排能力的說明,請參見Docker 1.13 編排能力進化
阿裏雲容器服務中使用 Docker Secrets
首先,我們需要創建一個Docker Swarm Mode集群。注意在集群模式中選擇 Docker Swarm Mode。目前它還在 Beta 公測階段,在華東2、美西1等地域開放。
創建集群之後,它會自動構成一個 Docker Swarm集群。
選擇集群,點擊 “管理” >> “秘鑰管理” >> “創建”,來創建新的secret
然後退回容器服務控製台,創建Docker Compose V3模板。
選擇 “鏡像與方案” >> “編排模板” >> “創建”,使用如下內容創建模板 “wordpressv3-secret”
version: "3.1"
services:
wordpress:
image: wordpress:latest
secrets:
- wp_db_password
environment:
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_NAME=wordpress
- WORDPRESS_DB_PASSWORD_FILE=/run/secrets/wp_db_password
- WORDPRESS_DB_HOST=mariadb
labels:
aliyun.routing.port_80: wordpress
deploy:
replicas: 3
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
mariadb:
image: mariadb
secrets:
- wp_db_password
- root_db_password
environment:
- MYSQL_USER=wordpress
- MYSQL_DATABASE=wordpress
- MYSQL_PASSWORD_FILE=/run/secrets/wp_db_password
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/root_db_password
deploy:
replicas: 1
restart_policy:
condition: on-failure
secrets:
wp_db_password:
external: true
root_db_password:
external: true
和上麵示例模板一致,它會使用集群中的 secret “wp_db_password” 和 “root_db_password” 來配置數據庫密碼和root密碼。
與之前示例唯一不同的地方在於,在本模板中使用 aliyun.routing.port_80: wordpress
標簽來指明:將虛擬域名 “wordpress” 的請求路由到容器的 80 端口進行處理。這樣無需在集群上暴露額外的端口,就可以直接通過7層負載均衡來訪問應用了。容器服務內置了7層負載均衡和路由能力。
選擇“創建應用”,輸入應用名稱和部署集群,點擊“下一步”
在“應用配置”頁麵,選擇“創建並部署”,
創建完畢,在應用頁麵就可以看見新的容器應用,在其部署就緒之後,我們可以點擊應用名稱進入應用管理界麵,查看服務和容器信息。
在路由列表,我們可以發現應用注冊過的路由地址,
點擊之後,可以進入“WordPress”的配置頁麵了,是不是很方便呢:-)
關於更多關於阿裏雲容器服務支持Swarm Mode的信息,請閱讀相應文章。
Docker secret 實現原理
Docker 在Swarm mode集群設計中采用了係統化的安全設計。 用戶創建的 Secrets,會以加密的方式存儲在集群中 Manager節點的 Raft Store中。在創建服務時,Secrets 會下發到服務任務所處的 Worker 節點,並以 tmpfs 的形式掛載在容器內部。從而保證了秘鑰等敏感信息可以安全地在分布式集群上分發。通過這樣的措施,即使集群中一台Worker節點被攻破,沒有容器訪問權限的人是無法獲取相應秘密信息的。
在其他容器編排技術中,如Kubernetes也有類似的 Secrets 機製,然而在安全性上還存在較多的問題,期待在未來能夠解決。
總結
安全無小事,微服務架構的應用對容器集群中安全地管理和分發秘密提出了更大的挑戰。通過Docker Secret和Docker編排可以非常簡潔、優雅地解決這個問題,幫助您打造安全的雲原生應用執行環境。
容器服務的Swarm mode還在公測之中,陸續會有更多更酷的功能發布出來,也歡迎大家多提寶貴意見。
了解更多阿裏雲容器服務內容,請訪問 https://www.aliyun.com/product/containerservice
最後更新:2017-05-29 20:32:16