Kubernetes Pod の IP アドレスが枯渇しかけている場合に役立つ実証済みの解決策を紹介
Google Cloud Japan Team
※この投稿は米国時間 2024 年 4 月 30 日に、Google Cloud blog に投稿されたものの抄訳です。
Kubernetes の大きな強みの 1 つは、Pod ごとに固有のネットワーク アドレスがあることです。これにより、Pod が VM のように機能するため、デベロッパーはポートの競合などの煩わしい問題を気にする必要がありません。Kubernetes のその特性のおかげで、デベロッパーやオペレーターは作業を簡略化できます。また、設計機能の 1 つとして高い信頼性を獲得しているため、コンテナ オーケストレーターとしての人気が非常に高くなっています。Google Kubernetes Engine(GKE)は、VPC 内のあらゆるクラスタ用にフラットなネットワーク構造を追加導入しています。そのため、各クラスタのそれぞれの Pod に VPC の固有 IP があり、他のクラスタの Pod と直接通信できます(NAT は不要)。これによりコンテナネイティブのロード バランシングなどの高度な機能を利用できるため、有用な特性です。
このアドレス指定レイアウトには多くの利点がありますが、その代わりに、IP が比較的早く消費される場合があります。各クラスタのそれぞれの Pod に同一 VPC の IP アドレスが割り振られ、そうした範囲の空間は拡大が可能なため、IP が非常に早く消費されます。こうした問題に対する解決策として、長い間業界全体で IPv6 が提案されてきました。いずれそれが正解になるのは間違いありませんが、GKE での Pod のアドレス指定はシングルスタック IPv6 に対応しておらず、人によっては、IPv4 を廃止する準備ができていないケースもあるでしょう。そのため重要なのは、IPv4 範囲でこの問題に対処する方法です。
GKE のプロダクト マネージャーとして私が見てきたものの中で最適な解決策は、Pod 用に非 RFC1918 の IP 範囲を使用する方法です。この問題の解決策は他にもありますが、ここでは、GKE で複数のお客様が導入して成功している解決策を紹介します。具体的に見ていきましょう。
10.0.0.0/8 空間を利用して一挙両得
ほとんどの GKE クラスタは RFC1918 空間、特に 10.0.0.0/8 空間のノードを使用して作成されます。コンテナネイティブのアドレス指定など、フラットなネットワーク構造の利点をすべて活かしつつ、10.0.0.0/8 空間も引き続き利用できることはご存じでしょうか。この解決策は、CIDR 範囲内にノードを維持し、より大規模な非 RFC 1918 プライベート アドレス範囲(100.64.0.0/10 や 240.0.0.0/4 など)のうち、Pod の範囲(使用する IP が群を抜いて多い)のみを割り振るというものです。Google Cloud VPC は、こうした他の範囲にネイティブで対応しています。そのため、Google Cloud 内でも、別々のクラスタの Pod 間でも、すべてが「機能」します。たとえば、Cloud SQL などのサービスに接続したり、別々のクラスタの Pod を接続したりできます。
ノードを RFC 1918 空間内に維持することで、IP マスカレードを使用して、Pod のアドレスをノードのアドレスでマスクできます。これにより、VPC 外の他のエンドポイントでは、非 RFC 1918 アドレスを参照する必要がなくなります。Google Cloud 外の各エンドポイント(またはマスカレード ルールでの設定対象)は、想定される 10.0.0.0/8 の IP を参照します。両方の利点を活かせます。100.64.0.0/10 範囲は、共有向けに予約されているため、最初に使用する範囲の候補になり、400 万の Pod アドレスをすぐに使用できます。240.0.0.0/4 では 2 億 5,000 万の Pod 用 IP を利用できる可能性があり、さらに増やせる余地が大きく残っています。
240.0.0.0/4 を VPC での Kubernetes Pod 用の範囲として使用できることは、すぐにはわからないかもしれません。公共のインターネットでは、この範囲は(1989 年以降)将来の用途のために予約されており、理論的にはいずれ割り振られる可能性があります。VPC でこの範囲を私用しても、公共のインターネットには影響しませんが(この範囲を使用するルートが VPC 外でアドバタイズされることはありません)、デメリットはないのでしょうか。いずれこの範囲が割り振られた場合は、ネットワーク内のホストが、この範囲のホストに対するアウトバウンド接続を開始できなくなります。ロード バランシングを利用するインバウンド接続(一般的な手法)には影響しません。つまり、今後この範囲が割り振られたとしても、対象のアドレスで顧客にサービスを提供できることに変わりはありません。
240.0.0.0/4 範囲の使用については、オンプレミス ルーターも Windows ホストもこの範囲に対応していないという懸念点を耳にすることもよくあります。この 2 つの問題については、簡単な解決策があります。この範囲に対応していない宛先に対しては、IP マスカレードを簡単に設定できるためです。つまり、対象のサービスが参照するのは 10.0.0.0/8 のプライマリ範囲の IP のみになります。
Google Cloud 外の Kubernetes プラットフォームには、「アイランド モード」というネットワーク設計があり、同じ Pod の IP 範囲を各クラスタで再利用できます。この機能を GKE にも実装してほしいというご要望をいただいています。私はここで紹介している手法の方がよいと思います。VPC 内でフラットなネットワークの利点を活かしつつ(コンテナネイティブのロード バランシングなどを利用可能)、必要に応じてノードの IP でトラフィックを NAT 変換することも可能です。一方の「アイランド モード」設計では、クラスタの外へ向かうトラフィックがすべて NAT 変換されるため(クラスタ間での Pod から Pod へのトラフィックなど)、VPC 内でできることが制限されます。
サービス IP 範囲
では、Pod については対処できるとして、サービスはどうすればよいでしょうか。サービスの範囲は、IP 割り振りに関する別の懸念事項となります。Autopilot モードの GKE は、すべてのクラスタで同じ /20 範囲を自動的に再利用するようになりました。これにより、ネットワークを割り振らなくても(サービス IP は仮想であり、クラスタ外では無意味なため、固有識別子を付与する必要はありません)、4,000 のサービスを利用できます。ノードベースの GKE Standard モードの場合や、4,000 以上のサービスが必要な場合は、必要なサイズの名前付きサブネットを独自に作成し(240.0.0.0/4 空間外も含む)、リージョン内のすべてのクラスタで流用できます(クラスタの作成時に --services-secondary-range-name パラメータに渡します)。
まとめると、フラットなネットワーク構造の利点を活かしつつ IP の使用量を減らしたい場合は、以下の方法がおすすめです。
-
メインの範囲からノード IP 範囲(10.0.0.0/8 など)を割り振ります。
-
非 RFC 1918 空間(100.64.0.0/10、240.0.0.0/4など)から Pod IP 範囲を割り振る一方で、IP マスカレードを利用し、オンプレミスの宛先や RFC 1918 範囲を想定している場所については、ノードの IP を使用して NAT 変換を行います。
-
4,000 のサービス IP を自動的に提供する Autopilot モードを使用するか、サービス用に名前付きサブネットを作成し、クラスタの作成時にそれを渡すことで、すべてのクラスタで流用します。
一部のお客様は、こうした手法で IP の制約の問題を解決しており、この戦略を、いずれシングルスタック IPv6 Pod のアドレス指定によってクラスタを実行するまでのつなぎにしています。
次のステップ:
-
Cloud VPC が対応している IPv4 範囲の詳細を確認します。
-
GKE の IP マスカレードの詳細を確認します。
-
GKE の Autopilot モードを使うことで、ワークロード ベースの API を利用します(これも運用効率を高めます)。
-Google Kubernetes Engine、グループ プロダクト マネージャー William Denniss