3 大陸にまたがる Docker Swarm:稼働率 100% を想定して設計した高可用性構成

公開日 読了時間 38 分

1 つのデータセンターは単一障害点です。本記事では、拠点が 1 つまるごと停止しても問題ない Docker Swarm を 3 大陸にまたがって構築します。マネージャーのクォーラム、WireGuard、リージョンごとの入口、Geo-DNS フェイルオーバー、データベースのレプリケーション、そして運用までを扱います。

ハードウェアやネットワークがどれほど優れていても、1 つのデータセンターに置いたサーバーは単一障害点です。電源やネットワークの障害、あるいはメンテナンス作業での単純なミスなどで拠点が停止すれば、アプリケーションは使えなくなります。複数のデータセンターにまたがる Docker Swarm は、まさにこの問題を解決します。コンテナは 3 つの独立した拠点で、理想的には 3 つの大陸で動作します。そのうち 1 拠点が完全に停止しても残りの 2 拠点が処理を引き継ぎ、ユーザーがそれに気づくことはありません。

本記事では、稼働率 100% を想定して設計した Docker Swarm クラスターの構築方法をステップごとに解説します。構成要素は、北米、ヨーロッパ、アジアに 1 台ずつ置いたサーバー、ノード間を結ぶ暗号化された WireGuard ネットワーク、大陸 1 つがまるごと停止しても失われないマネージャーのクォーラム、リージョンごとの入口、そしてユーザーを最寄りの正常な拠点へ自動的に誘導する DNS フェイルオーバーです。さらに、この構成でもなお何が停止しうるのか、そしてそのリスクにもどう備えるのかを率直に説明します。

Docker Swarm で稼働率 100% は実現できるのか

3 大陸にまたがる Docker Swarm は、稼働率 100% を想定して設計されています。単一のサーバー、単一のデータセンター、単一の大陸のいずれも、それだけでアプリケーションを停止させることはできません。それでも、絶対的な可用性を保証することは誰にもできません。大手クラウド事業者でさえ例外ではなく、その最も高い保証値も 99.99% から 99.999% です。原因はデータセンターではなく、すべての拠点に共通するものにあります。本記事では、技術的に可能な限り 100% に近づけられるよう、まさにそうした共通の要素も取り上げます。

可用性を数字で見る

可用性年間のダウンタイム月間のダウンタイム
99%87.6 時間7.3 時間
99.9%8.76 時間43.8 分
99.99%52.6 分4.4 分
99.999%5.3 分26 秒

1 年を 8,760 時間、1 か月を 730 時間として計算しています。「9」が 1 つ増えるごとに許容されるダウンタイムは 10 分の 1 になり、まさにそこから、1 台のサーバーではもはや担えない仕事が始まります。

3 大陸に分散する効果が大きい理由

可用性がそれぞれ 99.9% の、互いに独立した 3 つの拠点が同時に停止するのは、計算上、3 拠点すべてで同時に障害が起きた場合だけです。0.1% × 0.1% × 0.1% で 0.0000001% になります。拠点同士が離れているほど、実際の独立性は高まります。電力網、ネットワーク回線、気象条件、メンテナンスの時間帯がそれぞれ別々になるからです。そのため、北米、ヨーロッパ、アジアへの分散は、サーバーで実現できる耐障害性のなかで最も強力な形です。

3 大陸に分散してもなお停止しうるもの

残るリスクは、すべての拠点に共通する依存関係です。そして、そのどれにも対策があります。

  • 不具合のあるアップデートも、クラスターは正常なアップデートと同じように、すべての拠点へ確実に配布してしまいます。対策:ヘルスチェックと自動ロールバック、さらにリージョンごとに順番に行うアップデート。
  • DNS は、すべてのユーザーが必ず経由する 1 か所です。対策:世界中に分散したネットワークとフェイルオーバーを備えた DNS プロバイダーと、短い TTL。
  • データベースは、すべての拠点で同じデータを保持している必要があります。対策:自動切り替えを備えたレプリケーション(データに関するセクションを参照)。
  • 証明書やドメインの期限切れは、すべての拠点に同時に影響します。対策:自動更新と有効期限の監視。
  • 切り替えそのものにも、ヘルスチェックと DNS が反応するまでの時間がかかります。たいていは 1 分から 2 分で、その間は一部のリクエストが失敗することがあります。対策:短いチェック間隔、短い TTL、失敗したリクエストを再試行するクライアント。

アーキテクチャの全体像

複数の大陸にまたがる Docker Swarm は、6 つの構成要素から成り立っています。それぞれが特定の障害点を 1 つずつ取り除きます。

構成要素役割防げる障害
3 大陸に置く 3 台のマネージャーノードRaft コンセンサスでクラスターの状態を保持する拠点全体または大陸全体の停止
各リージョンに置くワーカーの処理能力ユーザーの近くでコンテナを実行する個々のサーバーの障害
全ノードを結ぶ WireGuard ネットワークインターネットを経由するクラスターの通信をすべて暗号化するデータセンター間での盗聴や改ざん
リージョンごとの入口(リバースプロキシ)ユーザーのリクエストを受け付け、リージョン内で応答するあるリージョンの入口の障害
ヘルスチェック付きの Geo-DNSユーザーを最寄りの正常な拠点へ誘導する到達できない拠点
レプリケーションされたデータ保管とバックアップデータベースとファイルを複数の場所に保持する拠点の停止によるデータ損失

マネージャーは何台、どこに置くか

Swarm のマネージャーノードは、Raft コンセンサスアルゴリズムでクラスターの状態を管理します。どの変更にも、マネージャーの過半数、いわゆるクォーラムの同意が必要です。過半数が失われると、既存のコンテナは動き続けるものの、クラスターは再スケジューリングも、障害への対応も、アップデートの配布もできなくなります。

マネージャー過半数許容できる障害数
321
532
743

Docker は、マネージャーを奇数台にし、少なくとも 3 つのゾーンに分散することを推奨しています。3 台なら 1-1-1、5 台なら 2-2-1 の比率です。ここから、本記事で最も重要なルールが導かれます。2 拠点では足りません。2 拠点の場合、どちらか一方に必ず多くのマネージャーが置かれることになり、まさにその拠点が停止すれば過半数が失われます。3 拠点があって初めて、どのデータセンターが停止してもクォーラムが維持されます。3 大陸構成なら、大陸 1 つがまるごと停止しても耐えられるということです。

3 大陸か 1 大陸か:トレードオフ

クラスターへの変更、デプロイ、コンテナの再スケジューリングは、どれもマネージャーの過半数による承認を待ちます。ヨーロッパ、北米、アジアの間では、この承認のたびに約 80 から 250 ミリ秒のレイテンシがかかります。ユーザーのリクエストはリージョン内で応答されるため、ユーザーにとっては問題になりません。ただし、デプロイや再スケジューリングは、経路の短いクラスターに比べて目に見えて時間がかかります。

構成長所代償
3 大陸(アメリカ、ヨーロッパ、アジア)独立性を最大限に高められる、世界中のユーザーの近くにサーバーを置ける、大陸 1 つがまるごと停止しても耐えられるクラスター管理が遅くなる、データベースのレプリケーションが長距離になる、リクエストをリージョン内にとどめる必要がある
1 大陸内の 3 拠点(たとえばフランクフルト、ストラスブール、ワルシャワ)クラスター管理が速い、同期レプリケーションを簡単に使える大陸内の広域的な事象がすべての拠点に及ぶ、遠方のユーザーほど経路が長くなる

複数の大陸にユーザーがいて、可用性を最大限に高めたいアプリケーションには 3 大陸構成が適しており、このガイドでもこの構成を構築します。その際に重要なのが、すべてのステップに共通するルールです。どのリクエストもそのリージョン内で応答され、大陸間を行き来することは決してありません。

KernelHost のどの拠点が適しているか

KernelHost は、フランクフルト・アム・マインの maincubes データセンターでサーバーを運用しているほか、ヨーロッパ、北米、アジア太平洋の各拠点で仮想サーバーを提供しています。アメリカの 3 拠点をはじめ、カナダ、ロンドン、ストラスブール、ワルシャワ、ヘルシンキ、シンガポール、日本、シドニー、ムンバイなどです。地図付きの全拠点の一覧は サーバーロケーション のページに掲載しています。本記事の例では、ヨーロッパにフランクフルト・アム・マイン、北米にアメリカ東海岸、アジアにシンガポールを使います。

ガイド:3 大陸にまたがる Docker Swarm を構築する

例では 3 台のサーバーを使います。フランクフルト・アム・マインの swarm-eu、アメリカ東海岸の swarm-us、シンガポールの swarm-asia です。パブリックアドレスにはドキュメント用のアドレス範囲 203.0.113.0/24 を、WireGuard ネットワークには 10.10.0.0/24 を使います。どちらもご自身の値に置き換えてください。3 台のノードはいずれもマネージャーとワーカーを兼ねます。性能を高めたい場合は、後から各リージョンにワーカー専用のノードを追加します。

ステップ 1:3 大陸にサーバーを用意する

3 つのリージョンで Debian 12 または 13 のサーバーを 3 台注文し、基本的な堅牢化を行います。鍵認証のみの SSH、自動セキュリティアップデート、個別のユーザーアカウントです。これは 新しいルートサーバーのチェックリスト でカバーしています。docker node ls でどのノードがどこにあるかがすぐにわかるよう、わかりやすいホスト名を付けてください。

hostnamectl set-hostname swarm-eu

ステップ 2:すべてのノードに Docker をインストールする

記事 Debian と Ubuntu に Docker をインストールする で説明しているとおり、3 台すべてのサーバーに公式の Docker リポジトリから Docker Engine をインストールします。その後、各ノードでバージョンを確認してください。3 台とも同じメジャーバージョンにそろえておきます。

docker version --format '{{.Server.Version}}'

ステップ 3:大陸間に WireGuard ネットワークを構築する

ノード同士は、公衆インターネットを介して通信します。クラスターの通信をすべて暗号化し、Swarm のポートが外部から到達できる状態に決してならないよう、3 台のサーバーを WireGuard ネットワークで結びます。まず、各ノードで鍵ペアを生成します。

apt-get install -y wireguard
umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key

次に、各ノードにファイル /etc/wireguard/wg0.conf を作成します。swarm-eu では次のようになります。ほかの 2 台のノードも、これと対称になるように構成します。

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = SWARM_EU_秘密鍵
MTU = 1420

[Peer]
PublicKey = SWARM_US_公開鍵
Endpoint = 203.0.113.12:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25

[Peer]
PublicKey = SWARM_ASIA_公開鍵
Endpoint = 203.0.113.13:51820
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25
systemctl enable --now wg-quick@wg0
ping -c 3 10.10.0.2

すべてのノードが 10.10.0.x のアドレスで応答すれば、ネットワークは完成です。PersistentKeepalive は、ステートフルなファイアウォールの内側でも接続を開いたままに保ちます。ここで ping が示す大陸間の応答時間こそが、クラスターに変更を加えるたびにかかる待ち時間です。

ステップ 4:ファイアウォールで Swarm ノードだけを通す

Docker Swarm では、ノード間で、クラスター管理用のポート 2377/TCP、ノード同士の通信用の 7946/TCP と UDP、オーバーレイネットワーク用の 4789/UDP が必要です。これらのポートは WireGuard インターフェース上でのみ許可します。外部に開けておくのは WireGuard 自体だけで、それもほかのノードに対してだけです。ufw を使う場合、swarm-eu では次のようになります。

ufw allow from 203.0.113.12 to any port 51820 proto udp
ufw allow from 203.0.113.13 to any port 51820 proto udp
ufw allow in on wg0 to any port 2377 proto tcp
ufw allow in on wg0 to any port 7946
ufw allow in on wg0 to any port 4789 proto udp

重要:Docker がコンテナ用に公開したポートは ufw を迂回します。Docker が独自の iptables ルールを設定するためです。そのため、公開するのは入口のポート(80 と 443)だけにし、データベースや管理用のポートは決して公開しないでください。

ステップ 5:Swarm を初期化してマネージャーを追加する

swarm-eu で Swarm を初期化し、管理通信とデータ通信の両方が WireGuard を経由するようにします。

docker swarm init --advertise-addr 10.10.0.1 --data-path-addr 10.10.0.1
docker swarm join-token manager

2 つ目のコマンドは、マネージャーを追加するための参加コマンドを出力します。これを swarm-us と swarm-asia で、それぞれ自身の WireGuard アドレスを指定して実行します。以下は swarm-us の例です。

docker swarm join --token SWMTKN-1-... --advertise-addr 10.10.0.2 --data-path-addr 10.10.0.2 10.10.0.1:2377
docker node ls

その後、docker node ls には 3 つのノードが表示されます。1 つはステータスが Leader、残りの 2 つは Reachable です。参加トークンは秘密情報です。これを知っている人は、自分のマネージャーをお使いのクラスターに紛れ込ませることができます。構築が終わったら、docker swarm join-token --rotate manager でトークンを更新してください。

ステップ 6:Autolock を有効にする

マネージャーは、Raft ログの暗号化に使う鍵を含め、クラスターの状態を /var/lib/docker/swarm/ に保存しています。Autolock を使うと、これらの鍵自体が暗号化され、再起動したマネージャーはロック解除キーを入力するまでクラスターに再参加しなくなります。

docker swarm update --autolock=true
docker swarm unlock

1 つ目のコマンドはロック解除キーを出力するので、パスワードマネージャーに保管してください。2 つ目のコマンドは、マネージャーを再起動するたびに必要になります。このキーがなければ、バックアップからでも Swarm を復元できません。そのため、サーバーとは別の場所に保管してください。

ステップ 7:ノードにリージョンのラベルを付ける

ラベルは、ノードがどこにあるかをスケジューラーに伝えます。次のステップ以降の配置制約は、このラベルを前提にしています。

docker node update --label-add region=eu swarm-eu
docker node update --label-add region=us swarm-us
docker node update --label-add region=asia swarm-asia

ステップ 8:適切な MTU でオーバーレイネットワークを作成する

異なる拠点にあるコンテナ同士は、オーバーレイネットワークを介して通信します。オーバーレイネットワークは WireGuard のトンネルを通るため、MTU を小さくする必要があります。WireGuard の MTU は 1420 バイトで、そのうち 50 バイトをオーバーレイネットワーク(VXLAN)が自身のヘッダーに使うので、残りは 1370 バイトです。

docker network create --driver overlay --attachable --opt com.docker.network.driver.mtu=1370 appnet

MTU が大きすぎると、厄介な症状が出ます。小さなリクエストは通るのに、大きなレスポンスは途中で止まってしまうのです。WireGuard を使わない場合は、代わりに --opt encrypted でオーバーレイネットワークを暗号化することもできます。その場合はノード間で IP プロトコル 50(ESP)も許可する必要があり、Docker は性能が目に見えて低下することを明示的に注意喚起しています。当社では WireGuard をおすすめします。管理通信を含むすべての通信をカバーできるからです。

ステップ 9:各リージョンでアプリケーションを運用する

通常の Swarm サービスは、サービスアドレス宛てのリクエストをクラスター内のすべてのレプリカに振り分けます。つまり、ほかの大陸にあるレプリカにも振り分けられます。3 大陸構成では、リクエストの 2 件に 1 件、あるいは 3 件に 1 件が地球を半周することになります。そこで、リージョンごとに専用のサービスを用意し、配置制約でそれぞれのリージョン内にとどめます。アップデートの設定により、新しいバージョンはコンテナ 1 つずつ順番に展開され、エラーが起きれば自動的にロールバックされます。

for r in eu us asia; do
  docker service create --name web-$r --replicas 2 --network appnet \
    --constraint node.labels.region==$r \
    --update-parallelism 1 --update-delay 30s \
    --update-failure-action rollback \
    registry.example.com/web:1.0
done

コンテナが単に起動しているだけでなく実際に正しく動作しているかを Swarm が判断できるよう、イメージにはヘルスチェックを組み込みます。たとえば、アプリケーションの Dockerfile に次の 1 行を追加します。

HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD wget -qO- http://127.0.0.1:8080/health || exit 1

ヘルスチェックに 3 回続けて失敗したコンテナは置き換えられます。また、アップデート中にヘルスチェックが失敗すると、展開はそこで止まります。

ステップ 10:リージョンごとに入口を用意する

入口の役割は、Caddy、Traefik、nginx などのリバースプロキシが担います。リバースプロキシもリージョンごとに個別のサービスとして動かし、リクエストは自リージョンのアプリケーションにだけ転送します。ホストモードで、ポート 80 と 443 を自リージョンのサーバー上に直接公開します。Caddy は転送先を環境変数から読み取るため、設定は共通のもの 1 つで足ります。

example.com {
    reverse_proxy {$UPSTREAM}:80
}
docker config create caddyfile ./Caddyfile
for r in eu us asia; do
  docker service create --name edge-$r --network appnet \
    --constraint node.labels.region==$r \
    --env UPSTREAM=web-$r \
    --config source=caddyfile,target=/etc/caddy/Caddyfile \
    --publish mode=host,target=80,published=80 \
    --publish mode=host,target=443,published=443 \
    caddy:2
done

すべてのリージョンで、同じドメインの TLS 証明書が必要です。そのため、証明書は DNS チャレンジで取得してください。DNS チャレンジなら、DNS レコードがその時点でどのリージョンを指していても機能します。Caddy では、そのためにお使いの DNS プロバイダー用のモジュールが必要です。プロキシの基本は、記事 nginx をリバースプロキシとして設定する で解説しています。

ステップ 11:フェイルオーバー付きの Geo-DNS を設定する

最後の構成要素は、ユーザーを適切なリージョンへ導く仕組みです。Geo ルーティングとヘルスチェックを備えた DNS サービスが、ヨーロッパのユーザーをフランクフルト・アム・マインへ、アメリカ大陸のユーザーをアメリカ東海岸へ、アジアのユーザーをシンガポールへ振り分けます。あるリージョンが停止すると、ヘルスチェックが 30 秒から 60 秒以内にそれを検知し、そのリージョンのユーザーを最寄りの正常なリージョンへ振り向けます。リゾルバーが切り替えをすばやく反映できるよう、レコードの有効期間(TTL)は 60 秒に設定してください。ヘルスチェックなしで複数の A レコードを登録するのは、あくまで応急策です。ブラウザーは次のアドレスを試すことが多いものの、すべてのクライアントがそうするわけではなく、停止したリージョンも応答に含まれたままになります。

正直に計算してみましょう。障害の発生から切り替えまでには、チェック間隔と TTL を足した時間がかかります。この例では 1 分から 2 分で、その間、影響を受けたリージョンのユーザーの一部は、まだ停止した拠点にアクセスしてしまいます。失敗したリクエストを少し待ってから再試行するアプリケーションやモバイルアプリなら、この時間をほとんど気づかれずに乗り切れます。

ステップ 12:リージョンの停止をテストする

一度も試したことのないフェイルオーバーが、いざというときにうまく機能することはめったにありません。リージョンのノードを運用から外してそのリージョンの停止を再現し、クラスターと DNS がどう反応するかを観察します。

docker node update --availability drain swarm-asia
docker node ls
docker service ls
docker node update --availability active swarm-asia

そのリージョンのサービスは配置制約でノードに結び付けられているため、別のノードへ移動せず、一時停止した状態になります。そのリージョンのユーザーは DNS フェイルオーバーが引き受けます。そのため、このテストでは特に、ヘルスチェックによってそのリージョンが応答から外れるか、そして隣接リージョンが増えた負荷をさばけるかを確認してください。より厳しいテストを行うなら、WireGuard を停止するなどして、ノードをネットワークから完全に切り離します。大きな変更の後と、少なくとも四半期に 1 回は、このテストを繰り返してください。

データ:高可用性で最も難しい部分

Docker Swarm が複製するのはコンテナであって、データではありません。ボリュームは常に、コンテナが動いているノード上にあります。そのため、Web フロントエンドや API のようなステートレスなサービスはどのリージョンでも問題なく運用できますが、データを扱うものにはすべて独自のレプリケーションが必要です。

大陸をまたいでデータベースをレプリケーションする

データベースには独自のレプリケーション機能が備わっており、データセンターをまたぐ共有ストレージよりも、常にそちらを優先すべきです。大陸をまたぐ場合は、1 つのリージョンにプライマリインスタンスを置き、残る 2 つのリージョンに非同期レプリカを置く構成に実績があります。PostgreSQL なら、ストリーミングレプリケーションと、自動切り替えのための Patroni のようなツールを使います。MariaDB と MySQL なら、組み込みのレプリケーションを使います。読み取りリクエストには各リージョンがローカルで応答し、書き込みはプライマリインスタンスに送られます。正直に言えば、非同期であるということは、プライマリのリージョンが停止した場合に直前の数秒分の書き込みが失われる可能性があるということでもあります。世界中で書き込みを行い、しかも何も失いたくない場合は、CockroachDB や YugabyteDB のような複数リージョン向けに設計されたデータベースを選びます。データベースのノードは、Swarm がデータから切り離して移動させることがないよう、配置制約でそれぞれのリージョンに固定します。

docker service create --name db-asia --constraint node.labels.region==asia ...

ファイルとアップロード

アップロードされたファイルはローカルボリュームではなく、別のリージョンへのレプリケーションを備えた S3 互換のオブジェクトストレージか、自前のレプリケーション対応ストレージシステムに保存します。大陸をまたぐ NFS のようなネットワークファイルシステムは遅いうえ、それ自体が単一障害点になります。

セッションとキャッシュ

アプリケーションがセッションをコンテナのメモリに保存していると、切り替えの際にユーザーのログイン状態が失われます。セッションは、レプリケーションされたデータベースや、Redis のようなレプリケーションされたキャッシュに保存するか、各リージョンが自分で検証できる署名付きトークンを使ってください。

バックアップは引き続き必須

レプリケーションは拠点の停止からは守ってくれますが、ミスからは守ってくれません。誤って削除したレコードは、数秒後にはすべてのリージョンから消えています。そのため、記事 サーバーのバックアップ戦略 で説明しているように、独立した場所への定期的かつ検証済みのバックアップは、あらゆる高可用性アーキテクチャに欠かせません。

運用:アップデート、メンテナンス、監視

リージョンごとに順番にアップデートする

新しいバージョンは全リージョンに同時に展開するのではなく、1 リージョンずつ順番に展開し、次に進む前に各リージョンの様子をしばらく観察します。こうすれば、どのヘルスチェックでも検知できない不具合があっても、影響は多くて 1 リージョンにとどまり、残りの 2 リージョンがそのリージョンのユーザーへのサービスを続けます。

for r in asia us eu; do
  docker service update --image registry.example.com/web:1.1 web-$r || break
  sleep 300
done

アップデートが失敗した場合、ステップ 9 の設定により Swarm が自動的にロールバックし、コマンドがエラーを返した時点で || break がループを終了します。問題が後になってから判明したアップデートは、docker service rollback web-asia で手動でロールバックします。

リージョンのメンテナンス

サーバーの再起動やアップデートが必要な場合は、docker node update --availability drain でそのサーバーを運用から外し、事前に DNS フェイルオーバーでそのユーザーを隣接リージョンへ振り向けておきます。メンテナンスが終わったら、--availability active で運用に戻します。2 台のマネージャーが同時に欠けることがないよう、docker node ls で 3 台すべてが再び到達可能と表示されるまで、次のマネージャーの作業は待ってください。

外部からの監視

各リージョンを個別に、しかもクラスターの外部から監視してください。対象は、入口への到達性、サービスのヘルスチェック、マネージャーの状態、データベースのレプリケーション遅延、証明書とドメインの有効期限です。リージョン全体が応答しなくなった場合でも、アラートは確実に届かなければなりません。個々のサーバーでこうした監視を構築する方法は、記事 サーバー監視を設定する で紹介しています。

秘密情報を安全に配布する

パスワードや鍵は、環境変数や Compose ファイルではなく、Docker Secrets に格納します。Secrets は Raft ログに暗号化して保存され、明示的に割り当てたサービスにだけ渡されます。

printf '%s' 'データベース_パスワード' | docker secret create db_password -
docker service update --secret-add db_password web-eu

複数の大陸にまたがる Swarm に KernelHost を選ぶ理由

複数の大陸にまたがるクラスターでは、1 台のサーバーの場合とは異なる要件が事業者に求められます。実際に決め手となるのは次の点です。

要件重要な理由KernelHost では
複数の大陸にまたがる拠点クォーラムには独立した 3 つの拠点が必要で、ユーザーは短い経路を求めるフランクフルト・アム・マインに加え、ヨーロッパ、北米、アジア太平洋の拠点を 1 社でまとめて提供
無制限のトラフィックWireGuard、オーバーレイネットワーク、データベースのレプリケーションが、大陸間で常に通信を発生させる無制限トラフィックの VPS、通信量の上限なし
DDoS 対策どの入口も外部から到達でき、それゆえ攻撃の標的になるすべての拠点で標準付属、中核拠点のフランクフルト・アム・マインでは 3.2 Tbps の Arbor リアルタイムフィルタリング、null ルーティングなし
完全な root 権限WireGuard、ファイアウォール、Docker Engine には完全な制御が必要すべての KVM ルートサーバーと専用サーバーで利用可能
迅速なプロビジョニング代替ノードやテスト用のリージョンを数分で用意したいフランクフルト・アム・マインで約 30 秒、その他の拠点でも通常は数分
ノードごとの契約の縛りなしノードは需要に応じて増えたり減ったりするPrePaid、最低利用期間なし、初期費用なし
自動化新しいノードをスクリプトで作成したいKernelHost API による注文と操作

料金付きのクラウドプラン一覧と、大手クラウド事業者とのコスト比較は、クラウドサーバーのレンタル のページでご覧いただけます。

よくある失敗とその防ぎ方

  • マネージャーを 2 拠点にしか置いていない。 過半数を持つ拠点が停止すると、クラスターが止まります。解決策:3 拠点に置き、1-1-1 または 2-2-1 で分散する。
  • マネージャーの台数が偶数になっている。 4 台のマネージャーでも許容できる障害数は 3 台と同じで、合意形成の手間だけが増えます。解決策:3 台、5 台、または 7 台。
  • リクエストが大陸間を行き来している。 全リージョンで 1 つのサービスアドレスを使うと、ユーザーを地球の半周分も遠回りさせてしまいます。解決策:リージョンごとに 1 つのサービスと 1 つの入口。
  • Swarm のポートが外部から到達できる。 ポート 2377 とオーバーレイネットワークは、決してインターネットに公開してはいけません。解決策:WireGuard 経由に限定し、外部に開けるのは 80、443、そしてほかのノード向けの WireGuard だけにする。
  • MTU の設定を忘れている。 大きなレスポンスは止まり、小さなレスポンスは通ります。解決策:WireGuard の MTU が 1420 なら、オーバーレイの MTU は 1370。
  • コンテナのポートを ufw で守れると思っている。 公開されたポートについては、Docker が ufw を迂回します。解決策:公開するのは入口だけにする。
  • データベースをレプリケーションなしでボリュームに置いている。 リージョンが停止すると、データにアクセスできなくなります。解決策:データベースをレプリケーションし、配置をリージョンに固定する。
  • 全リージョンを同時にアップデートしている。 その場合、1 つの不具合が世界中のすべてのユーザーに影響します。解決策:1 リージョンずつ順番に展開する。
  • DNS の TTL が長い。 TTL が 1 日だと、フェイルオーバーが効くのは翌日になってからです。解決策:60 秒。
  • バックアップの代わりにレプリケーションに頼っている。 ミスも正常なデータと同じように複製されます。解決策:それに加えて、独立した場所に検証済みのバックアップを取る。

まとめ

  • 3 大陸にまたがる Docker Swarm は、稼働率 100% を想定して設計されています。拠点や大陸が 1 つまるごと停止しても、アプリケーションが止まることはありません。
  • 可用性を絶対的に保証することは誰にもできません。残るリスクは DNS、不具合のあるアップデート、データベース、証明書で、そのどれにも対策があります。
  • 3 拠点に 3 台のマネージャーが最低限の構成です。障害に強いクォーラムを作るには、2 拠点では足りません。
  • リクエストはそれぞれのリージョン内にとどめます。リージョンごとに 1 つのサービスと 1 つの入口を置き、さらにヘルスチェックと短い TTL を備えた Geo-DNS を組み合わせます。
  • WireGuard がクラスターの通信を暗号化し、Swarm のポートは外部から見えなくなり、オーバーレイの MTU は 1370 に下がります。
  • Swarm が複製するのはコンテナであって、データではありません。データベースには独自のレプリケーションが必要で、バックアップも引き続き必須です。
  • KernelHost は、ヨーロッパ、北米、アジア太平洋の拠点、無制限のトラフィック、すべての拠点での DDoS 対策、そして最低利用期間のない PrePaid 方式の料金体系を提供しています。

よくあるご質問

Docker Swarm で稼働率 100% を保証できますか?
3 大陸にまたがる Docker Swarm は、稼働率 100% を想定して設計されています。単一のサーバー、データセンター、大陸のいずれも、単独ではアプリケーションを止められないからです。それでも、可用性を絶対的に保証することは誰にもできず、大手クラウド事業者も例外ではありません。残るリスクは、DNS、不具合のあるアップデート、データベース、証明書といった共通の依存関係です。これには、自動ロールバック付きのヘルスチェック、リージョンごとに順番に行うアップデート、データベースのレプリケーション、監視が有効です。
高可用性の Docker Swarm には、マネージャーノードが何台必要ですか?
最低 3 台で、3 つの独立した拠点に分散させます。マネージャーは Raft コンセンサスでクラスターの状態を保持し、どの変更にも過半数の同意を必要とします。3 台なら 1 台、5 台なら 2 台、7 台なら 3 台の障害まで耐えられます。Docker は、奇数台にしたうえで少なくとも 3 つのゾーンに分散することを推奨しており、3 台の場合は 1-1-1 の比率です。
Docker Swarm に 2 つのデータセンターでは足りないのはなぜですか?
2 拠点の場合、どちらか一方に必ず多くのマネージャーが置かれるからです。まさにその拠点が停止するとマネージャーの過半数が失われ、クラスターは再スケジューリングも、障害への対応も、アップデートの配布もできなくなります。稼働中のコンテナは動き続けますが、クラスターとしては何もできない状態です。3 拠点があって初めて、どのデータセンターが停止してもクォーラムが維持されます。
Swarm のマネージャーを別々の大陸に分散できますか?
はい。北米、ヨーロッパ、アジアにマネージャーを 1 台ずつ置いた Swarm は、大陸 1 つがまるごと停止しても耐えられます。その代償はクラスター管理が遅くなることです。どの変更も、80 から 250 ミリ秒のレイテンシがある長距離回線越しの承認を待つためです。ただし、各リクエストがそれぞれのリージョン内で応答される限り、つまりリージョンごとに 1 つのサービスと 1 つの入口を置いている限り、ユーザーには影響ありません。
Docker Swarm にはどのポートが必要ですか?
Docker Swarm では、ノード間でクラスター管理用のポート 2377/TCP、ノード間通信用のポート 7946/TCP と UDP、オーバーレイネットワーク用のポート 4789/UDP が必要です。オーバーレイネットワークで組み込みの暗号化を使う場合は、IP プロトコル 50(ESP)も許可しなければなりません。これらのポートはどれもインターネットに公開すべきではなく、ノード間の WireGuard ネットワーク内だけで通すのが最も安全です。
WireGuard は必要ですか?それとも暗号化オーバーレイネットワークで十分ですか?
暗号化オーバーレイネットワーク(--opt encrypted)が保護するのはコンテナのデータ通信だけで、Docker によれば性能が目に見えて低下します。一方、WireGuard はノード間のすべての通信を、管理通信やノード間通信も含めて暗号化し、Swarm のポートをすべてインターネットから遠ざけます。複数のデータセンターにまたがるクラスターには、オーバーレイの MTU を 1370 バイトにしたうえで WireGuard を使うことをおすすめします。
大陸間のフェイルオーバーはどのように機能しますか?
Geo ルーティングとヘルスチェックを備えた DNS サービスが、各ユーザーを最寄りのリージョンへ振り分け、30 秒から 60 秒ごとにそのリージョンの入口が応答するかを確認します。あるリージョンが停止すると、そのアドレスを返さなくなり、ユーザーを最寄りの正常なリージョンへ誘導します。TTL が 60 秒なら、切り替えはたいてい 1 分から 2 分で完了します。
拠点が停止したとき、データベースはどうやって利用可能な状態を保ちますか?
Docker ではなく、データベース自体のレプリケーションによってです。Swarm が複製するのはコンテナであって、ボリュームではありません。実績があるのは、1 つのリージョンにプライマリインスタンスを置き、ほかのリージョンにレプリカを置く構成で、PostgreSQL ならたとえば自動切り替えに Patroni を使います。大陸をまたぐレプリケーションは非同期で行われるため、万一の際には直前の数秒分の書き込みが失われる可能性があります。世界中でデータを失わずに書き込む必要がある場合は、CockroachDB や YugabyteDB のような複数リージョン向けのデータベースを使います。
複数拠点には Docker Swarm と Kubernetes のどちらが向いていますか?
Docker Swarm は構築も運用もはるかに簡単で、多くのアプリケーションにはこれで十分です。Kubernetes は自動化、スケーリング、エコシステムの面で選択肢が多い一方、より多くの知識が求められます。大陸をまたぐ場合、Kubernetes はリージョンごとに 1 つのクラスターとして運用し、それらを GitOps でまとめて展開するのが一般的です。これに対して Swarm では、1 つのクラスターを複数の大陸にまたがって構成できます。
3 大陸にまたがる Swarm に適した KernelHost の拠点はどこですか?
KernelHost は、フランクフルト・アム・マインのほか、ヨーロッパ、北米、アジア太平洋の各拠点でサーバーを提供しています。アメリカの 3 拠点、カナダ、ロンドン、ストラスブール、ワルシャワ、ヘルシンキ、シンガポール、日本、シドニー、ムンバイなどです。3 大陸構成で実績のある組み合わせは、フランクフルト・アム・マイン、アメリカ東海岸、シンガポールです。すべての拠点を 1 社でまとめて、DDoS 対策付き、PrePaid 方式の料金体系でご利用いただけます。
3 大陸にまたがる Docker Swarm の費用はどのくらいですか?
基本となるのは、リージョンごとに 1 台、計 3 台のサーバーと、ヘルスチェック付きの DNS サービスです。WireGuard、オーバーレイネットワーク、データベースのレプリケーションは拠点間で常に通信を発生させるため、トラフィック無制限のプランが決め手になります。大手クラウド事業者の多くでは、まさにこの通信に 1 GB ごとの追加料金がかかります。KernelHost の無制限トラフィックの VPS は通信量の上限がなく、PrePaid 方式で、最低利用期間も初期費用もありません。

Docker Swarm 高可用性 マルチリージョン WireGuard Geo-DNS フェイルオーバー Docker クラウド