アップデート1

アップデート1

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 swarmSwarm モード (および同様の CLI) と従来のコンテナー ベースの Swarm (Docker Hub 上のコンテナーとしてホストされる) を混在させています。これらは 2 つの異なるツールです。

2 セットのドキュメントについては、以下を参照してください。

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 通信を許可するようにファイアウォールを変更すると、すべてが再び動作するようになりました。

スウォームネットワークは暗号化されているので、すべて正常に動作するはずです。

関連情報