Kubernetes ロードバランサーとは何ですか?
Kubernetesにおけるロードバランシングとは、高可用性、スケーラビリティ、および最適なパフォーマンスを確保するために、ネットワークトラフィックを複数のポッドに分散させるプロセスです。ポッドは一時的なものであり、そのIPアドレスは頻繁に変化するため、Kubernetesでは「サービス」と「インジェス」を使用して、アプリケーションにアクセスするための安定したエンドポイントを提供します。
内部および外部の負荷分散の種類:
Kubernetes では、トラフィックがクラスタ内部から発生したものか外部から発生したものかによって、トラフィックを管理するためのいくつかのネイティブ手法が用意されています:
- ClusterIP(内部):デフォルトのサービスタイプです。クラスタ内部からのみアクセス可能な、安定した内部IPアドレスを提供します。主にサービス間の通信に使用されます。
- NodePort(外部):各ノードの IP アドレス上で、特定のポート(30000~32767)にサービスを公開します。外部からのアクセスが可能ですが、通常は開発やテストの目的で使用されます。
- ロードバランサー(外部):本番環境向けの標準構成です。クラウドプロバイダーのロードバランサー(例:AWS ELB、Google Cloud Load Balancer、Azure Load Balancerなど)をプロビジョニングし、外部トラフィックをサービスへルーティングします。
- Ingress(レイヤー 7):外部の HTTP および HTTPS ルートを管理する API オブジェクトです。基本的なロードバランサーとは異なり、Ingress は URL ベースのルーティング、SSL テリミネーション、名前ベースの仮想ホスティングなどの高度な機能をサポートしています。
Kubernetesのロードバランサーは、ポッドが作成、破棄、あるいはノード間で再スケジューリングされる場合でも、リクエストを適切なポッドにルーティングするという複雑な処理を抽象化することで機能します。この抽象化は、ワークロードが絶えず変化する環境において極めて重要です。Kubernetesは、アーキテクチャにロードバランシングを統合することで、開発者や運用担当者が、デプロイメントごとにトラフィックのルーティングを手動で設定することなく、耐障害性のあるアプリケーションを構築できるようにします。
この記事の内容:
Kubernetes 環境は、その設計上、動的なものです。Pod は頻繁に作成、破棄、再スケジューリングされるため、静的ルーティングでは信頼性が低下します。ロードバランシングにより、こうした変化があってもトラフィックを正しく流すことができます:
- ポッドの動的なライフサイクル:ポッドは一時的なものであり、いつでも変更される可能性があります。ロードバランシングにより、手動での更新を必要とせずに、正常に稼働しているインスタンスへトラフィックがルーティングされます。
- 高可用性:トラフィックを複数のポッドに分散させることで、単一障害点を回避できます。1つのポッドに障害が発生しても、他のポッドが引き続きリクエストを処理します。
- スケーラビリティ:アプリケーションは、多くの場合、ポッドの追加や削除によって水平方向にスケーリングされます。ロードバランサーは、ポッドの数に応じてトラフィックの分散を調整します。
- サービスの抽象化:Kubernetesのサービスは安定したエンドポイントを提供し、ロードバランシングによって基盤となるポッドの複雑さが隠蔽されます。クライアントは個々のポッドのIPアドレスを追跡する必要がありません。
- リソースの効率的な活用:トラフィックが各ポッドに均等に分散されるため、一部のインスタンスに過負荷がかかる一方で、他のインスタンスが遊休状態になることを防ぎます。
- 内部および外部トラフィックへの対応:Kubernetes は、クラスタ内部の通信と外部ユーザーからのリクエストの両方を処理します。それぞれのシナリオに応じて、異なるロードバランシングの仕組みが採用されています。
- フォールトトレランスと回復力:ロードバランサーは、正常に動作していないポッドを検出し、それらへのトラフィックの送信を停止します。
Kubernetes は、クラスター内(内部)およびクラスターの境界(外部)の両方において、複数の負荷分散手法をサポートしています。内部負荷分散は、クラスター内のサービスやポッド間でトラフィックをルーティングします。外部負荷分散は、クラスター外のユーザーやシステムに対してアプリケーションを公開し、外部ネットワークからの着信トラフィックを処理します。
クラスターIP(内部)
ClusterIP は Kubernetes のデフォルトのサービスタイプであり、クラスター内の通信を目的として設計されています。ClusterIP タイプでサービスが作成されると、Kubernetes はそのサービスに、クラスターのネットワーク内からのみアクセス可能な安定した仮想 IP アドレスを割り当てます。これにより、基盤となるポッドが作成されたり破棄されたりしても、ポッドとサービスは一貫したアドレスを使用して通信できるようになります。内部 DNS システムは、サービス名をその ClusterIP に解決します。
ClusterIP は kube-proxy を使用して、サービスを支える利用可能なポッド間でリクエストを分散させます。このアプローチは、コンポーネントがクラスター外部にエンドポイントを公開することなく通信するマイクロサービスアーキテクチャにおいて有効です。ただし、割り当てられた IP アドレスは Kubernetes 環境の外からはルーティングできないため、ClusterIP ではアプリケーションを外部ユーザーに公開することはできません。
NodePort(外部)
NodePort は、各ノードの IP アドレスの静的ポート上で Kubernetes サービスを公開し、外部からアクセスできるようにします。NodePort を使用する場合、Kubernetes はあらかじめ定義された範囲(通常は 30000~32767)からポートを割り当てます。クラスタ内のいずれかのノードのこのポートに送信されたトラフィックは、そのサービスおよびそれを構成するポッドに転送されます。
NodePortは設定が簡単で、クラウドプロバイダーとの連携も不要ですが、いくつかの制限があります。競合を避けるため、公開ポートは慎重に管理する必要があり、外部からのトラフィックは特定のノードのIPアドレスとポートを宛先とする必要があります。NodePortは、開発環境や、外部のロードバランサーやインジェストコントローラーなどが提供する、より高度なロードバランシングソリューションの構成要素としてよく使用されます。
ロードバランサー(外部)
「LoadBalancer」サービスタイプは、サポートされているクラウドプロバイダーと連携し、Kubernetes サービスへトラフィックをルーティングする外部ロードバランサーをプロビジョニングします。LoadBalancer サービスが作成されると、Kubernetes は AWS ELB、Azure Load Balancer、Google Cloud Load Balancer などのクラウドネイティブなロードバランサーをリクエストし、外部からのリクエストをそのサービスのバックエンドポッドに転送するように設定します。
LoadBalancer サービスは、クラスター外部からの安定したアクセスが求められる本番環境に適しています。ただし、各 LoadBalancer サービスでは通常、個別の外部ロードバランサーがプロビジョニングされるため、インフラコストが増加する可能性があります。より複雑なルーティングを実現したり、外部ロードバランサーの数を減らしたりするために、組織では LoadBalancer をインジェストコントローラーと組み合わせたり、高度なネットワークプラグインを利用したりすることがよくあります。
Ingress(レイヤー7)
Ingressは、レイヤー7(アプリケーション層)におけるロードバランシングとルーティングを提供するKubernetesリソースです。IngressコントローラーはHTTPおよびHTTPSトラフィックを監視し、ホスト名、URLパス、ヘッダーなどのルールに基づいてリクエストをバックエンドサービスにルーティングします。これにより、単一の外部IPアドレスを通じて複数のサービスを公開することが可能となり、複数のLoadBalancerやNodePortサービスの必要性を減らすことができます。
Ingressは、SSL/TLSのターミネーション、認証、レート制限もサポートしています。Ingressの導入と設定には、NGINX、Traefik、あるいはクラウドネイティブなオプションなどのIngressコントローラーが必要であり、適切なルール管理とインフラストラクチャとの互換性が求められます。
プラカシュ・シンハ
プラカシュ・シンハ氏は、Radwareのテクノロジーエグゼクティブ兼エバンジェリストであり、戦略、製品管理、製品マーケティング、エンジニアリングの分野で29年以上の経験を有しています。シンハ氏は、シスコ、インフォマティカ、タンデム・コンピューターズといった大手テクノロジー企業において、アーキテクチャ、エンジニアリング、製品管理の各部門で指導的立場を務めてきました。シンハ氏は、BIT(メスラ校)で電気工学の学士号を、カリフォルニア大学バークレー校のハース・スクール・オブ・ビジネスでMBAを取得しています。
専門家からのアドバイス:
私の経験から、Kubernetesのロードバランシングをより効果的に最適化するためのヒントを以下に紹介します:
1. トポロジーを意識したルーティングを意図的に活用してください。東西方向のトラフィックについては、サポートされている場合はトポロジーヒントまたはゾーンを意識したルーティングを有効にし、可能な限りリクエストが同じゾーン内に留まるようにしてください。これにより、ゾーン間の遅延やクラウドデータ転送コストを削減できますが、レプリカが均等に分散されている場合にのみ、その効果が十分に発揮されます。
2. ポッドの終了前に、接続のドレイン処理を調整する。 [追加] preStop フックと十分な量 契約解除猶予期間(秒) これにより、長時間にわたるリクエストが、エンドポイントが消失する前に完了できるようになります。これがなければ、Kubernetes上ではローリングアップデートが正常に実行されているように見えても、クライアント側でのリセットや断続的な502エラーが発生してしまいます。
3. 負荷の高いノードでは、conntrackの飽和状態に注意してください。多くの「ランダムな」負荷分散の問題は、実際にはバーストトラフィック下でのLinuxのconntrackテーブルの枯渇によるものです。conntrackの使用状況を監視し、制限値を慎重に引き上げ、ピーク負荷時のフェイルオーバーをテストしてください。ノードがステートテーブルの制約を受けると、kube-proxyの動作が著しく低下するためです。
4. 大規模なサービスには、IPVS または eBPF データパスを優先してください。ポッドやサービスの数が増えると、iptables ベースの転送では、エンドポイントの入れ替わりの際にレイテンシや運用上のノイズが発生します。IPVS または eBPF ベースの実装は、通常、収束が速く、頻繁なエンドポイントの更新にもよりスムーズに対応できます。
5. 起動状態、レディネス、過負荷について、それぞれ個別のヘルスセマンティクスを定義する。ポッドは稼働中で技術的にはレディな状態であっても、全トラフィックを受け入れるには安全でない場合がある。依存関係のヘルス状態、キャッシュのウォームアップ状況、キューの深さを反映したレディネスシグナルを公開し、飽和状態がユーザーに顕在化する前に、バランサーがトラフィックの送信を停止するようにする。
Kubernetes で外部ロードバランサーを作成するには、LoadBalancer タイプでサービスを定義します。これにより、Kubernetes は外部トラフィックをアプリケーションにルーティングするクラウドベースのロードバランサーをプロビジョニングするよう指示されます。手順はKubernetes のドキュメントを基に作成されています。
前提条件
稼働中のKubernetesクラスターと、設定済みのkubectl CLIが必要です。クラスターは、外部ロードバランサーをサポートする環境で実行されている必要があります。ワーカーノードが少なくとも2つあるクラスターを使用してください。
ステップ 1: LoadBalancer サービスを作成する
YAMLマニフェストを使用して、type: LoadBalancer: を設定し、サービスを定義します。
apiVersion: v1 kind: Service metadata: name: example-service spec: selector: app: example ports: - port: 8765 targetPort: 9376 type: LoadBalancer
次のコマンドでマニフェストを適用します:
kubectl apply -f service.yaml
あるいは、kubectl を使用してサービスを直接作成することもできます:
kubectl expose deployment example \ --port=8765 \ --target-port=9376 \ --name=example-service \ --type=LoadBalancer
このコマンドは、参照先のデプロイメントと同じラベルセレクタを使用するサービスを作成します。
ステップ 2:外部 IP アドレスを取得する
サービスが作成されると、Kubernetes は外部ロードバランサーをプロビジョニングします。その IP アドレスを確認するには、次のコマンドを実行します:
kubectl describe services example-service
出力結果の中で、「LoadBalancer Ingress」という項目を探してください。ここには、サービスに割り当てられた外部IPアドレスが表示されます。
Minikube を使用している場合は、次のコマンドで URL を取得してください:
minikube service example-service --url
手順 3: クライアント IP 保持の設定(オプション)
デフォルトでは、バックエンドのポッドは元のクライアントIPを認識しません。これを保持するには、サービス仕様で `externalTrafficPolicy` を `Local` に設定してください:
仕様: externalTrafficPolicy: Local タイプ: LoadBalancer
これにより、トラフィックはノードローカルのエンドポイントにのみルーティングされ、元のクライアントIPが保持されます。その結果、ポッド間のトラフィック分布が不均一になる可能性があります。
必要に応じて、healthCheckNodePort を使用して特定のヘルスチェックポートを指定することもできます。
注意事項および制限事項
外部ロードバランサーは、個々のポッドではなく、ノード間でトラフィックを分散させます。各ノードで実行されているポッドの数を把握していないため、ポッドレベルではトラフィックが完全に均等化されない場合があります。
交通量の偏り
トラフィックの不均等な分散とは、ロードバランサーが利用可能なポッド間でリクエストを均等に分散できないために発生し、その結果、一部のポッドに過負荷がかかる一方で、他のポッドは稼働率が低いままとなる現象です。この不均衡は、ロードバランサーのアルゴリズムの設定ミス、ネットワークの遅延、あるいは基盤となるインフラストラクチャの制限によって生じることがあります。
Kubernetes では、kube-proxy や外部ロードバランサーがラウンドロビン方式やランダム選択方式を採用する場合がありますが、これらは必ずしもポッドのヘルス状態や現在の負荷を考慮しているわけではありません。その結果、パフォーマンスの低下、レイテンシの増加、およびリソース枯渇によるポッド障害のリスクが高まるといった問題が生じます。
外部ロードバランサーのコスト
クラウドプラットフォームが提供する外部ロードバランサーには追加コストが発生します。これは、各ロードバランサーサービスが、独自の料金体系を持つ専用リソースをプロビジョニングすることが多いためです。公開されているサービスが多い環境では、これらのコストが積み重なり、全体的な予算に影響を及ぼす可能性があります。
この傾向は、動的にスケールするクラスターや、複数のリージョンで運用されるクラスターにおいて、より顕著になります。コストを管理するためには、各サービスに独自の外部ロードバランサーが必要か、それともトラフィックをインジェス・コントローラーを通じて集約できるかを検討してください。
マルチクラウド環境における複雑性
複数のクラウドプロバイダーにわたるロードバランシングの管理は、ネットワークモデル、API、およびロードバランサーの実装の違いにより、複雑さを伴います。各プロバイダーはロードバランサーのプロビジョニングや設定方法を異にしており、その結果、環境間で動作に一貫性がなくなる可能性があります。
そのため、アプリケーションが複数のクラウドにまたがる場合、統一されたデプロイおよびルーティング戦略を維持することが難しくなります。こうした不整合は、サービスの公開、ヘルスチェック、トラフィックルーティングポリシーに影響を及ぼします。たとえば、SSLターミネーション、アイドルタイムアウト、セッションアフィニティなどの機能は、プロバイダーによって動作が異なる場合があります。チームはプロバイダー固有の設定を必要とすることが多く、その結果、運用上のオーバーヘッドが増大し、移植性が低下します。
組織は、Kubernetes におけるロードバランサーのパフォーマンスを向上させるために、以下の対策を検討すべきです。
1. レディネス・プローブおよびライブネス・プローブを使用してトラフィックの流れを制御する
レディネス・プローブは、ポッドがトラフィックを受け入れられるかどうかを判断します。プローブが失敗した場合、Kubernetes はそのポッドをサービスエンドポイントから除外するため、ロードバランサーはそのポッドへのリクエストのルーティングを停止します。これにより、起動中、過負荷状態、または一時的に正常でないポッドへのトラフィックの送信が防止されます。
ライブネスプローブは、ポッドの再起動が必要なタイミングを検知します。これらのプローブが連携して、正常なポッドのみが負荷分散に参加するよう保証します。プローブの間隔やしきい値は慎重に調整してください。設定が厳しすぎると、不要な再起動やトラフィックの低下を招く恐れがあり、逆に設定が緩すぎると、正常でないポッドがリクエストを処理してしまう可能性があります。
2. 適切なロードバランシング層(L4 対 L7)を選択する
レイヤー4(トランスポート層)では、IPアドレスとポートに基づいてトラフィックの負荷分散が行われます。TCP/UDPサービスや高スループットなワークロードに適しています。ClusterIPやNodePortなどのKubernetesサービスは、このレイヤーで動作します。
レイヤー7(アプリケーション層)のロードバランシングは、HTTP/HTTPSのセマンティクスを理解しています。パス、ホスト名、ヘッダー、またはクッキーに基づいてルーティングを行うことができます。イングレスコントローラーはこのレイヤーで動作し、きめ細かなルーティング、TLSターミネーション、または認証を必要とするマイクロサービスやAPIに適しています。アプリケーションの要件に応じて、L4とL7のいずれかを選択してください。
3. トラフィック状況を考慮したオートスケーリングの実装
水平ポッドオートスケーラー(HPA)は、CPUやメモリといったメトリクス、あるいはリクエストレートなどのカスタムメトリクスに基づいて、ポッドの数を調整します。これをロードバランシングと組み合わせることで、動的にスケーリングされるポッド群全体にトラフィックが分散されるようになります。
より良い結果を得るためには、1秒あたりのリクエスト数やキューの長さなど、実際のトラフィックを反映した指標を使用してください。遅延や安定化ウィンドウのスケーリングについても検討してください。ロードバランサーが変化するエンドポイントに継続的に適応しようとすると、急激なスケールアップやスケールダウンによって不安定さが生じる可能性があります。
4. ロードバランサー層でのセキュリティ強化
ロードバランサーは、セキュリティ制御を実施する上で自然な適用ポイントです。ロードバランサーでTLSを終端させることで、トラフィックを暗号化し、アプリケーションポッドの暗号処理負荷を軽減することができます。その他の保護策としては、IP許可リスト、レート制限、Webアプリケーションファイアウォール(WAF)などがあります。
また、このレイヤーでOAuthや相互TLSなどの認証メカニズムを統合することも可能です。これにより、リクエストがバックエンドのポッドに到達する前に、認証済みのユーザーやサービスのみがアプリケーションにアクセスできるようになります。ロードバランサーでセキュリティ制御を一元化することで、個々のサービスにかかる負担を軽減し、アクセスポリシーを一貫して適用できるポイントを提供します。
5. グローバル・サーバー・ロード・バランシングを使用する
グローバルサーバー負荷分散(GSLB)は、トラフィックを複数のクラスターやリージョンに分散させます。DNS やジオルーティングを利用して、ユーザーを最も近い、あるいは状態が良好なエンドポイントへ誘導します。このアプローチは、マルチリージョン展開や災害復旧に有効です。あるリージョンが利用できなくなった場合でも、トラフィックを別のリージョンへリダイレクトすることができます。
フェイルオーバーの速度に影響を与える可能性のある、DNSのキャッシュおよび伝播遅延を考慮してください。これにより、障害発生後、短時間ながらユーザーが利用できないエンドポイントにルーティングされてしまう場合があります。これを軽減するには、DNSのTTL(Time-to-Live)値を短く設定し、自動フェイルオーバー機能を備えたヘルスチェックを使用して、トラフィックをより迅速に正常なリージョンへリダイレクトするようにしてください。
Kubernetesのロードバランシングは、コンテナ化されたワークロード間でトラフィックを分散させ、可用性を維持し、動的な環境全体でのアプリケーションのスケーラビリティをサポートするために不可欠です。しかし、トラフィックの不均一な分散、露出しているイングリッヂポイント、マルチクラウド環境の複雑さなどは、運用上およびセキュリティ上のリスクをもたらす可能性があります。Radwareは、クラウドネイティブ環境向けに設計されたトラフィックインテリジェンス、ランタイム保護、および適応型セキュリティ制御を組み合わせることで、組織がKubernetesのロードバランシングを最適化できるよう支援します。
RadwareKubernetes Web Application Firewall(KWAAP)は、イングリッス・コントローラー、API、およびアプリケーション・ワークロードに対して、Kubernetesネイティブな保護機能を提供します。Kubernetes環境に直接統合され、サービス間の通信やワークロードの挙動を可視化したまま、トラフィックの流れを保護します。適応型保護機能により、公開されているロードバランシング対象サービスを標的としたレイヤー7攻撃、悪意のあるリクエスト、およびAPIの悪用を軽減します。また、リアルタイム分析機能により、分散型コンテナ環境全体における運用状況の把握が向上します。
RadwareCloud WAF Serviceは、インターネットに公開されているKubernetesサービスをOWASP Top 10に挙げられる攻撃、ボットによる悪用、アプリケーション層のDDoS攻撃から保護することで、外部ロードバランシングのセキュリティを強化します。AIを活用したトラフィック検査により、悪意のあるリクエストがバックエンドのワークロードに到達する前に検知されるため、サービスの過負荷やトラフィック分散の混乱といったリスクを軽減します。 また、適応型保護機能により、ハイブリッドおよびマルチクラウド環境全体で一貫したセキュリティポリシーを適用することが可能になります。これにより、外部に公開されているKubernetesアプリケーションの耐障害性が向上します。
RadwareApplication Protection Serviceは、Kubernetesのロードバランサーの背後で動作するアプリケーションやAPIに対して、統合された実行時保護機能を提供します。行動分析と機械学習(ML)を活用した検知機能により、正当なトラフィックの急増と悪意のある活動を区別し、トラフィック管理を改善するとともに、スケーリング時の誤検知を低減します。一元化された可視性により、分散環境や動的なワークロード全体でポリシーの一貫性を維持できます。これらの機能により、組織は安全かつ信頼性の高いアプリケーション配信を維持することができます。
RadwareBot Manager は、スクレイピング、クレデンシャルスタッフィング、偵察、リソース枯渇攻撃など、Kubernetes でホストされているアプリケーションを標的とした自動化された悪用行為を軽減します。高度な検知機能により、正当な自動化と、露出しているインジェストポイントを悪用しようとしたり、ロードバランサーの背後のサービスを過負荷に陥れようとする悪意のあるボットとを区別します。自動化されたトラフィックのノイズを低減することで、パフォーマンスの安定性が向上し、ワークロード全体でのトラフィック分散のバランスを維持するのに役立ちます。また、継続的な監視により、進化し続ける攻撃パターンを可視化することも可能です。