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 に接続したところ、正常に接続できました。
ここで、Swarm にワーカー ノードを 1 つ追加する必要があります。
マネージャー ノードと同じ方法で、同様の daemon.json を使用して設定しました。extendedKeyUsage = serverAuth の SSL キーを使用し、マネージャー ノードと同じ方法でクライアント接続を証明しました。
次にマネージャーでdocker swarm initを実行しました
ワーカーノードをスウォームに参加させるには、次のコマンドを使用します: 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
この 2 回目のテストで、考えるべきことがさらにたくさん増えました。もちろん、クライアント証明書ではなくサーバー証明書で接続しようとしているため失敗しますが、docker swarm join がまさにやろうとしていることではないでしょうか。クライアント証明書を daemon.json に入れるのは意味がわかりません。サーバーとクライアントの両方で単一の証明書を作成することを Google で検索したところ、可能ではあるものの、悪い習慣のようです。必要な場合はチュートリアルで説明されているはずだと思いました。
この時点で行き詰まっています。どのような証明書の設定が必要なのかわかりません。
私はフォローしています github.com/docker/docker.github.io/blob/master/swarm/configure-tls.md を参照してください。 ここでは証明書の作成について説明していますが、クライアントまたはサーバーの認証についてはまったく触れられていません。
アップデート1
証明書はクライアントとサーバーの両方に必要であるという文書を見つけました
https://hub.docker.com/_/swarm/
そこで、ノード証明書をクライアントとサーバーの両方になるように作り直しました。これで、docker version コマンドはノードから実行すると機能しますが、swarm join では機能しなくなります。
答え1
docker swarm
Swarm モード (および同様の CLI) と従来のコンテナー ベースの Swarm (Docker Hub 上のコンテナーとしてホストされる) を混在させています。これらは 2 つの異なるツールです。
2 セットのドキュメントについては、以下を参照してください。
- スウォームモード:詳しくはこちら
- クラシックスウォーム:https://github.com/docker/classicswarm(以前のドキュメントは docker の Web サイトから削除されました)
Swarm Mode では TLS を手動で設定する必要はなく、すべて組み込まれており、Swarm Mode のポートは Docker API ソケットのポートとは異なります。正当な理由がない限り、Docker API をネットワーク上に公開することは望ましくありません (これがハッキングの一般的な原因です)。Swarm Mode は理由にはなりません。
したがって、コマンド-H
のオプションdockerd
と、そこにある TLS オプションをすべて削除する必要があります。次に、docker swarm init
最初のマネージャーで を実行し、TLS 資格情報を生成して、自己署名証明書のハッシュを含むトークンを提供します。次に、他のマネージャーとワーカーが をdocker 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
証明書が機能するには、すべてクライアント証明書とサーバー証明書の両方である必要があるというのは正しかったです。
その後、他の問題にも遭遇しました。主な問題は、使用しているホスト上の仮想マシンが、VMWare によって使用されるポート 4789 の使用を禁止していることです。これは、オーバーレイ ネットワークに使用されるデフォルトのデータ パス ポートです。
すべてのノードとマネージャーを Swarm から完全に削除し (実質的に削除)、data-path-port パラメータを使用して再起動する必要がありました。
docker swarm init --data-path-port=7777
(各ノードの IP としてアドバタイズ アドレスも指定しましたが、これは必須ではないと思います)
もちろん、このプロセスではすべての docker シークレット、docker 構成、および一部の docker ネットワークが失われ、再作成する必要がありました。
これを完了し、データ パス ポートを使用してノード間の UDP 通信を許可するようにファイアウォールを変更すると、すべてが再び動作するようになりました。
スウォームネットワークは暗号化されているので、すべて正常に動作するはずです。