我正在嘗試設定一個 docker swarm。
我需要我的節點透過 TLS 進行通訊。
我已經使用 ExtendedKeyUsage = serverAuth 為管理器節點建立了一個憑證
我已經使用以下 daemon.json 配置了管理器節點:
{
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
"tlscacert": "/var/docker/ca.pem",
"tlscert": "/var/docker/server-cert.pem",
"tlskey": "/var/docker/server-key.pem",
"tlsverify": true
}
為了測試這一點,我創建了一個客戶端證書,使用它從我的筆記型電腦連接到 docker api,並且我能夠成功連接。
現在我需要向叢集新增一個工作節點。
我已經按照與管理節點相同的方式進行了設定;具有類似的 daemon.json。我使用了具有extendKeyUsage = serverAuth的SSL金鑰,並以與管理節點相同的方式證明了客戶端連線。
然後在管理員中我運行了 docker swarm init
要將工作節點加入 swarm,我使用以下指令: docker swarm join --token XXX dockman.myhost.com:2376
但我收到一個錯誤:
Error response from daemon: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate"
我想我可以透過嘗試從工作節點連接到管理節點上的 docker API 來進一步測試它:
sudo docker --tlsverify --tlscacert=/var/docker/ca.pem --tlscert=./server-cert.pem --tlskey=./server-key.pem -H=127.0.0.1:2376 version
結果是:
Client: Docker Engine - Community
Version: 19.03.5
API version: 1.40
Go version: go1.12.12
Git commit: 633a0ea838
Built: Wed Nov 13 07:29:52 2019
OS/Arch: linux/amd64
Experimental: false
The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: Get https://127.0.0.1:2376/v1.40/version: remote error: tls: bad certificate
第二次測試給了我更多的思考。當然它會失敗,因為我正在嘗試連接伺服器證書而不是客戶端證書,但這不正是 docker swarm join 想要做的嗎?將客戶端憑證放入 daemon.json 對我來說沒有意義。我在谷歌上搜尋了伺服器和客戶端都製作一個證書,這是可能的,但似乎是不好的做法。我以為如果需要的話,教程中會涵蓋它。
我一直被困在這一點上。我無法弄清楚需要什麼證書設定。
我一直在關注 https://github.com/docker/docker.github.io/blob/master/swarm/configure-tls.md 這描述了憑證的創建,但根本沒有提及客戶端或伺服器身份驗證。
更新1
我發現一個文檔說證書需要是客戶端和伺服器
https://hub.docker.com/_/swarm/
所以我重新製作了節點證書,既可以作為客戶端,也可以作為伺服器。現在,docker version 命令在從節點運行時有效,但在 swarm join 中無效。
答案1
您將 Swarm 模式(docker swarm
和類似的 CLI)與基於經典容器的 Swarm(作為容器託管在 docker hub 上)混合在一起。這是兩種不同的工具。
兩套文件請參閱:
- 集群模式:https://docs.docker.com/engine/swarm/
- 經典群:https://github.com/docker/classicswarm(先前的文件已從 docker 的網站上刪除)
使用 Swarm 模式無需進行任何手動 TLS 配置,它都是內建的,而且 Swarm 模式的連接埠與 docker API 套接字的連接埠不同。如果沒有充分的理由,您不想在網路上公開 docker API(這是駭客攻擊的常見來源),而 Swarm 模式不是一個原因。
因此,您應該刪除-H
該dockerd
命令的選項以及其中的任何 TLS 選項。然後在第一個管理器上運行docker swarm init
,它將產生 TLS 憑證並提供包含自簽章憑證的雜湊值的令牌。然後,其他管理器和工作器運行 adocker swarm join
來產生客戶端證書,連接到管理器,驗證令牌中管理器證書的雜湊值,並使用加入令牌的秘密部分向管理器驗證自身身分。
以上將對管理者和工人之間的管理平面進行加密。要加密工作人員之間在覆蓋網路上傳輸的數據,您需要在您建立的覆蓋網路上啟用 IPSec:
docker network create --opt encrypted --driver overlay app-overlay-net
有關此功能的文件位於:https://docs.docker.com/v17.09/engine/userguide/networking/overlay-security-model/
答案2
我是正確的,所有憑證都必須是客戶端和伺服器憑證才能運作。
然後我又遇到了其他問題,主要的一個是我使用的主機上的虛擬機器禁止使用連接埠 4789,因為該連接埠由 VMWare 使用。這是用於覆蓋網路的預設資料路徑連接埠。
我必須從群組中完全刪除所有節點和管理器(有效地刪除它)並使用資料路徑連接埠參數重新初始化它:
docker swarm init --data-path-port=7777
(我還指定了廣告位址作為每個節點的IP,但我認為這不是必需的)
當然,我所有的 docker 秘密、docker 配置和一些 docker 網路都在過程中遺失,必須重新建立。
完成此操作並更改防火牆以允許使用資料路徑連接埠在節點之間進行 UDP 通訊後,一切又恢復正常了。
因為群體網路是加密的,我認為它應該可以正常工作。