If you must use nscd in a Kubernetes cluster

はじめに

以前、「Kubernetes クラスターでの DNS ベストプラクティス」というドキュメントを執筆し、その中で nscd をコンテナ内の DNS キャッシュとして使用できることに触れました。ただし、その実装方法については具体的な説明を行いませんでした。理由は、nscd 方式がおそらく最も推奨されない方式だからです。本記事では、優先すべき方式、nscd を推奨しない理由、および Kubernetes クラスターで nscd を適切に使用する方法について説明します。

より優れたソリューション

接続プール

Kubernetes クラスター内の DNS 名前解決は、カーネルの問題や負荷の問題など、さまざまな原因で障害が発生することがあります。本記事をお読みいただく前に、そうした DNS 名前解決のトラブルに直面されたことがあるでしょう。多くの場合、根本原因を究明する余裕がないかもしれませんが、DNS 名前解決の使用をできる限り避けることで回避できます。その方法は何かというと、接続プールです。接続プールの導入方法を詳しく説明する必要はないでしょう。DNS 名前解決のコストを削減できるだけでなく、各 TCP 接続のハンドシェイクにかかる追加コストも直接回避できます。

接続プールは持続的接続の管理に使用でき、マイクロサービス間の相互アクセスやデータベースへの直接接続のいずれにも適用できます。ほぼすべての Web フレームワークおよび RPC フレームワークで接続プールをサポートしています。PHP での接続プールサポートについては、公式ドキュメントを参照してください。

ノード DNS キャッシュ

Kubernetes クラスター内のコンテナは、一般的に高密度で配置されます。1 つのクラスターノード上で複数のサービス Pod が実行されます。各クラスターノードでノードレベルの DNS キャッシュコンポーネントを実行し、ローカルのすべてのコンテナの DNS 解決をプロキシおよびキャッシュできます。ACK プロダクトでは、NodeLocal DNSCache キャッシュコンポーネントと対応する Webhook コントローラーを提供しています。このキャッシュコンポーネントは DNS サーバーでもあり、ノード上のインターフェイスをリッスンし、ローカル IP アドレスを介して DNS サービスを公開します。Webhook コントローラーは、Pod のスケジューリング前にこのローカル DNS サーバーの IP アドレスを Pod の設定に書き込みます。これにより、Pod の起動後はキャッシュコンポーネントがデフォルトの DNS サーバーとして使用されます。

キャッシュコンポーネントには以下の利点があります。

・各ノードで 1 つのキャッシュコンポーネントを実行するだけで、リソース消費を削減できます

・キャッシュコンポーネントは DNS サーバーとして透過的に動作し、ビジネスに対する互換性の問題がありません

・サービス Pod からキャッシュコンポーネントへの接続では Conntrack テーブルのエントリを消費せず、CoreDNS への直接リクエストと比べて多数の iptables ルールを回避できます

・キャッシュコンポーネントは TCP プロトコルを使用して CoreDNS に接続し、可用性を向上させます

NodeLocal DNSCache の構成図

nscd 方式を推奨しない理由

互換性

nscd は DNS キャッシュ機能を提供するデーモンプログラムですが、実際には DNS サーバーではありません。TCP/IP モードでも動作しません。nscd はデフォルトで /var/run/nscd/socket をリッスンします。アプリケーションが glibc ライブラリ経由で getaddrinfo などのメソッドを呼び出すと、そのメソッドはソケットの存在を確認します。ソケットが存在する場合、glibc は nscd に DNS リクエストの送信と結果のキャッシュを委譲します。

重要な点は、すべてのアプリケーションが glibc で名前解決を行っているわけではないということです。たとえば、Golang はデフォルトで独自の DNS リゾルバを使用し、nscd ソケットを参照しません。また、一般的な Alpine イメージでは、システムは glibc の代わりに musl を使用しています。ネイティブの musl は nscd による名前解決をまったくサポートしていません。

さらに注目すべき点として、ホストの /var/run/nscd/socket ディレクトリをコンテナにマウントして DNS キャッシュを提供する方式があります。この方式では、ホストとコンテナの glibc バージョンが異なる場合、キャッシュ機能が無効化されたり、名前解決エラーが発生したりする可能性があります。

精度

ラウンドロビン型の負荷分散に複数の A レコードを使用している場合、nscd は最初の A レコードのみをキャッシュして返します。そのため、キャッシュの有効期間中、負荷は 1 つの A レコードにのみ転送されます。NodeLocal DNSCache を使用した場合、キャッシュ結果はランダムに分散されて返されるため、この問題は発生しません。

即時性

DNS 変更の有効期間は、一般的に TTL 以下であるべきです。nscd のキャッシュ機構のデフォルトパラメータでは、変更後に TTL + CACHE_PRUNE_INTERVAL(15 秒)が経過してから更新されます。

適切な使用方法

ここまでの説明を読んでも、nscd 方式を使用する意向のようです。ネット上では 2 つの方式が紹介されています。

方式 1:ホストで nscd を起動

アプローチ:ホスト ECS 上で nscd を起動し、ホストのパス /var/run/nscd/socket を Pod 内にマウントします

デメリット:ホストとコンテナ間で glibc のバージョンが一致していることを厳密に保証する必要があり、そうでない場合は互換性の問題が発生します

方式 2:コンテナ内で nscd を起動

アプローチ:コンテナイメージを変更し、単一のコンテナがビジネスプロセスを起動する前に、nscd をバックグラウンドプロセスとして起動します

デメリット:

・イメージの再作成が必要です

・コンテナの単一責任原則に違反し、ビジネスプロセスがコンテナのメインプロセスではなくなるため、グレースフルイグジットの処理が難しくなります

推奨方式:サイドカーで nscd を起動

アプローチ:コンテナの Deployment YAML を変更し、ビジネスコンテナの実行時に独立した nscd コンテナを起動し、同じディレクトリをマウントして nscd ソケットをビジネスコンテナと共有します。

利点:

・ビジネスへの侵入が少なく、コンテナイメージの再作成が不要です

・ビジネスコンテナとキャッシュコンテナが同じコンテナイメージを使用するため、glibc のバージョン不整合を回避できます

上記では関連のない属性をすべて省略しています。YAML 内の wordpress という名前のコンテナは、ユーザーのビジネスコンテナを表しています。同じ Pod 内に以下の nscd コンテナを注入します。注意点は次の通りです。

1. nscd コンテナには同じサービスイメージの使用を推奨します

2. emptyDir タイプの共有ディレクトリを作成し、ビジネスコンテナと nscd コンテナの両方に同時にマウントします

3. nscd のリソースは必ず制限し、メインコンテナへの影響を防ぎます

4. nscd はコンテナイメージに事前インストールすることも、起動後にインストールすることもできます。以下の例は起動後にインストールする場合です。nscd コンテナの YAML は以下の通りです

ビジネスコンテナと統合した後の YAML は以下の通りです

nscd コンテナとビジネスマスターコンテナは同時に起動されます。nscd コンテナ内の nscd の初期化が完了すると、nscd ソケットが共有の emptyDir ディレクトリに自動的に作成されます。次のビジネスの名前解決リクエストから nscd が正常に使用されます

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone お問い合わせ
Hi, I'm Alibaba Cloud AI Assistant!
I can help with questions and solutions.