Podman (Compose)を使ったMongoDBレプリカセットの注意点

著者
Damian
Terlecki
1分間の読書
データベース

インターネット上では、MongoDBレプリカセットをセットアップするための、動作するdocker/docker-compose設定を簡単に見つけることができます。 しかし、Linuxホストマシンからpodman-composeで接続設定をしようとしたとき、なぜか、どれもうまくいきませんでした。 問題を概説すると、通常レプリカセットは、--replSet--bind_ip(オプションで--port)を付けて実行されているmongodインスタンスに接続した後、シェルを通じて初期化されます。

rs.initiate(
   {
      _id: "myReplSet",
      version: 1,
      members: [
         { _id: 0, host : "mongodb0.example.net:27017" },
         { _id: 1, host : "mongodb1.example.net:27017" },
         { _id: 2, host : "mongodb2.example.net:27017" }
      ]
   }
)

すべてを支配する1つのホスト名

設定で定義されたホストメンバーは、各ノードからとクライアント側の両方からアクセス可能でなければなりません。 mongodbN.example.netの代わりにhost.docker.internalが使用されているのをよく見かけるでしょう。 デフォルトのブリッジネットワークでは、これはサービスのextra_hostsプロパティを使用して、Dockerネットワークのhost-gatewayにマッピングされます。 Podmanを使用する場合、同等のhost.containers.internalがあり、これはextra hostsを定義しなくても動作するはずです。

注意: 'invalid IP address in add-host: "host-gateway"'というエラーが出た場合、Linux上で古いバージョンのdockerエンジン/podmanを実行している可能性があります。最も基本的なケースでは、これを172.17.0.1に交換できますが、複数のネットワークで実行している場合は異なる場合があります。 より良いがより複雑な解決策を見つけるには、このSOスレッドを確認してください。

あるいは、サービス名を使用するか、サービスのcontainer_namehostnameを設定して、カスタムホスト名でRSをセットアップすることもできます。

ポートバインディング

2番目の注意点はポート設定です。単一のブリッジは、各ノードのポートが異なる必要があること(例:270172701827019)を意味し、 メンバーの定義、mongodの設定、およびホストのポートバインディングと一致しなければなりません。

不一致があると、次のような問題が発生する可能性があります:

  • クライアントのクラスタビューからノードが削除される(ノードの正規アドレスがサーバーアドレスと一致しない)。
  • ホストマシンからすべてのノードにアクセスする際に問題が発生する。
  • レプリカセット設定で自分自身を見つけようとしてRSの初期化エラーが発生する。

UnknownHostException

3番目の注意点は、host.docker.internalはLinuxホストでは解決できず、デフォルトのループバックアドレス127.0.0.1にマッピングするエントリを/etc/hostsに追加する必要があることです。 しかし、Podmanでは、ホストの/etc/hostsがコンテナの/etc/hostsに含まれるため、RSの初期化エラーが発生します。

コンテナの`/etc/hosts`にホストマシンから複製された`host.docker.internal`エントリのスクリーンショット `/etc/hosts`内の重複した`host.docker.internal`が間違ったIPに解決されることによるレプリケーションエラーのスクリーンショット

--no-hostsオプションは最近(Podman 4.0)利用可能になりましたが、host.containers.internal/host.docker.internalと競合します。 場当たり的ですが、mongodの起動前にコンテナの/etc/hostsを更新するという解決策があります。 しかし、最新の(Podman 4.1)設定プロパティを介して、この動作をグローバルに無効にする方がはるかに優れています。 場所は$HOME/.config/containers/containers.confです。

[containers]
base_hosts_file="none"

まとめ

特にLinux上やPodmanを使用して、開発用にDocker化されたMongoDBレプリカセットを設定する際に問題が発生した場合は、 以下を確認してください:

  • レプリカセットは、各ノードおよびクライアント(例:ホストマシン)から到達可能なホスト名とポートの組み合わせで設定する必要があります。
  • 各ノードに異なるポートを使用して、RSビューがブリッジネットワーク上のポートバインディングと一致するようにします。
  • メンバーのホストプロパティにはhost.docker.internalextra_hostsが必要な場合あり)/host.containers.internal(Podman)を使用します。
  • カスタムホスト名でRSを設定する必要がある場合は、代わりにサービスのcontainer_namehostnameを使用します。
  • ホストマシンでホスト名に到達できないエラーが発生した場合は、ホストの/etc/hostsにRSホスト名を追加します。
  • Podmanの場合、containers.confファイルを介してホストマシンからの/etc/hostsのコピーを無効にします。
  • Linuxでの最後の手段として、サービスのプロパティnetwork_mode: hostを使用し、localhost上のRSにすぐに接続します。