ヘルスチェック ベースのロード バランシングを構成する

このドキュメントでは、ヘルスチェック ベースのロード バランシングを使用して、Google Kubernetes Engine(GKE)で永続 IP アドレスの高可用性を実装する方法について説明します。標準の永続 IP 構成では、単一の永続 IP アドレスが単一の Pod にマッピングされますが、ヘルスチェック ベースのロード バランシングでは、1 つ以上の永続 IP アドレスからのトラフィックを正常な Pod のプールに分散できます。

特定の永続 IP アドレスを要求し、どの Pod がトラフィックを受信するかを特定するには、GKEIPRoute カスタム リソースを作成します。GKEIPRoute リソースをリージョン ヘルスチェックと統合することで、GKE はネットワーキング レイヤでワークロードをモニタリングし、トラフィックを受信する準備ができている Pod にのみトラフィックを転送します。GKEIPRoute オブジェクトを使用して、オプションのバックアップ Pod を指定することもできます。すべてのプライマリ アクティブ Pod がヘルスチェックに失敗した場合、GKE はトラフィックをこれらのスタンバイ Pod にのみ転送します。

要件と制限事項

  • ヘルスチェック ベースのロード バランシングを使用するには、クラスタが GKE バージョン 1.32.3-gke.1440000 以降である必要があります。GKE は、バージョン 1.35.0-gke.1403000 以降でのみバックアップ Pod の選択をサポートしています。
  • クラスタで GKE Dataplane V2 と Gateway API が有効になっている必要があります。
  • 1 つの GKEIPRoute オブジェクトは、ノードごとに 1 つの一致する Pod のみをサポートします。ノード上の複数の Pod が GKEIPRoute の Pod セレクタと一致する場合、GKE はそのノードで最も新しく作成された Pod を選択します。
  • GKEIPRoute オブジェクトを作成した後は、Gateway クラスを変更できません。
  • ヘルスチェック ベースのロード バランシングは、ワークロードの外部から開始されたトラフィックのみをサポートします。ワークロード内から永続 IP アドレスに送信されるトラフィックはサポートされていません。

始める前に

作業を始める前に、次のタスクが完了していることを確認してください。

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API を有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。gcloud CLI をインストール済みの場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。

ヘルスチェック ベースのロード バランシングを実装する

このセクションでは、ヘルスチェック ベースのロード バランシングを実装するワークフローを簡単に説明します。

  1. リージョン ヘルスチェックを作成する: GKE が Pod のステータスをモニタリングするために使用するパラメータを定義します。このオブジェクトは、どのエンドポイントが正常で、永続 IP アドレスからトラフィックを受信できるかをネットワーク レイヤに伝えます。
  2. クラスタを作成する: GKE Dataplane V2 と Gateway API が有効になっている GKE クラスタを設定します。これらのコンポーネントは、永続 IP ルーティングとヘルスチェック ベースのロード バランシングの管理に必要な基盤となるインフラストラクチャを提供します。
  3. IP アドレスを予約する: クラスタと同じリージョンで静的内部 IP アドレスまたは外部 IP アドレスを選択して予約します。このアドレスは、GKE がアクティブな Pod またはバックアップ Pod のプール全体に分散する永続的なエントリ ポイントとして機能します。
  4. Gateway を作成する: 予約済みの永続 IP アドレスを管理するように Gateway オブジェクトを構成します。GKEIPRoute オブジェクトは、ワークロード用に Gateway から特定の IP アドレスを要求して使用します。
  5. GKEIPRoute オブジェクトを作成する: ラベルセレクタを使用して、永続 IP アドレスを Pod のグループにマッピングするルーティング ルールを定義します。このオブジェクト内で、リージョン ヘルスチェックを参照し、必要に応じてフェイルオーバー シナリオのバックアップ Pod を指定します。
  6. 一致するエンドポイントを表示: 自動生成された EndpointSlice を調べて、GKE がアクティブ Pod とバックアップ Pod を正しく識別していることを確認します。このステップでは、ラベルが想定どおりの Pod と一致し、ネットワーキング レイヤがトラフィックをルーティングする準備ができていることを確認します。

ステップ 1: リージョン ヘルスチェックとファイアウォール ルールを作成する

リージョン ヘルスチェックを作成するには、ヘルスチェックを作成するの手順に沿って操作します。ここで指定した名前は、GKEIPRoute 構成で使用されます。次に例を示します。

gcloud compute health-checks create http reg-lb-hc \
    --region=us-central1 \
    --check-interval=5s \
    --timeout=5s \
    --healthy-threshold=2 \
    --unhealthy-threshold=2

Google Cloud からのヘルスチェック プローブがノードに到達できるようにするには、ファイアウォール ルールを作成する必要があります。

ステップ 2: GKE クラスタを作成する

Gateway API と GKE Dataplane V2 を有効にしてクラスタを作成します。次に例を示します。

gcloud container clusters create cluster-1 \
    --enable-dataplane-v2 \
    --gateway-api=standard \
    --region=us-central1

クラスタのデフォルトの VPC ネットワークとは異なる VPC ネットワークで GKEIPRoute オブジェクトを構成する場合は、マルチネットワーク機能を備えた GKE クラスタを作成する必要があります。詳細については、Pod のマルチネットワーク サポートを設定するをご覧ください。

ステップ 3: IP アドレスを予約する

ワークロードに使用する IP アドレスを予約します。Google 提供の IP アドレスを予約するか、独自の IP アドレスを使用する(BYOIP)かを選択できます。

ステップ 3a: Google 提供の IP アドレスを予約する

外部 IP アドレスを予約するには、次のコマンドを実行します。

gcloud compute addresses create ADDRESS_NAME \
   --region=REGION

次のように置き換えます。

  • ADDRESS_NAME: このアドレスに関連付ける名前。
  • REGION: このアドレスを予約するリージョン。これは、IP アドレスを割り振るリソースと同じリージョンにする必要があります。

    : 永続 IP アドレスのトラフィック ルーティングを処理する転送ルールはリージョンであるため、IP アドレスを予約するときにリージョンを指定する必要があります。ルーティングが正しく機能するには、IP アドレスと GKE クラスタが同じリージョンに存在する必要があります。

内部 IP アドレスを予約するには、次のコマンドを実行します。

gcloud compute addresses create ADDRESS_NAME \
    --region REGION
    --subnet SUBNETWORK \
    --addresses IP_ADDRESS

次のように置き換えます。

  • ADDRESS_NAME: 予約する 1 つ以上のアドレスの名前。複数のアドレスの場合は、各アドレスをスペースで区切ったリストで指定します。例: example-address-1 example-address-2 example-address-3。
  • REGION: このリクエストのリージョン。
  • SUBNETWORK: この内部 IPv4 アドレスのサブネット。
  • IP_ADDRESS: 選択したサブネットのプライマリ IP アドレス範囲の未使用の内部 IP アドレス。

トラフィックがプライベート ネットワーク内で正しくルーティングされるようにするには、内部 IP アドレスがクラスタのデフォルト サブネットまたは追加のネットワーク サブネットに属している必要があります。

外部 IP アドレスと内部 IP アドレスの詳細、または Google Cloud コンソールを使用してアドレスを予約する方法については、静的外部 IP アドレスを予約する静的内部 IP アドレスを予約するをご覧ください。

ステップ 3b: お客様所有 IP アドレスを使用する(BYOIP)

Google 提供の IP アドレスに依存するのではなく、お客様所有の IP アドレス(BYOIP)を使用することもできます。BYOIP は、アプリケーションに特定の IP アドレスが必要な場合や、既存のシステムを Google Cloudに移行する場合に便利です。BYOIP を使用する場合は、Google は、お客様が IP アドレス範囲を所有していることを確認します。 Google Cloudに IP アドレスがインポートされた後は、それらを GKE Pod の IP アドレスとして割り振ることができます。詳細については、お客様所有 IP アドレスの使用をご覧ください。

ステップ 4: Gateway オブジェクトを作成する

Gateway は、L3 ネットワーク タイプのみをサポートする次のいずれかの Gateway クラスを使用して作成します。

  • gke-passthrough-lb-external-managed または
  • gke-passthrough-lb-internal-managed.

次の例では、外部 IP アドレスのプールを管理する Gateway を定義しています。

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: lb-gateway
spec:
  gatewayClassName: gke-passthrough-lb-external-managed

  listeners:
    - name: default
      port: 443
      protocol: none
      allowedRoutes:
        namespaces:
          from: All

  addresses:
    - value: "34.123.10.1/32"
      type: "gke.networking.io/cidr"
    - value: "34.123.10.2/32"
      type: "gke.networking.io/cidr"

上記の例では、次のフィールドに注意してください。

  • addresses: 特定のゲートウェイが権限を管理する IP アドレス範囲のリストを記述します。
  • listeners: GKEIPRoute オブジェクトがこの Gateway を参照できる Namespace を識別します。

リスナーの使用方法について詳しくは、Gateway オブジェクトを作成するをご覧ください。

ステップ 5: ロード バランシングとヘルスチェックの構成を使用して GKEIPRoute オブジェクトを作成する

プライマリ Pod セレクタとバックアップ Pod セレクタを定義し、ステップ 1 で作成したヘルスチェックを関連付ける GKEIPRoute オブジェクトを作成します。

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: default
  name: my-ip-route
spec:
  parentRefs:
  - name: lb-gateway
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  - value: "34.123.10.2/32"
    type: "gke.networking.io/cidr"
  network: default
  podSelector:
    matchLabels:
      component: activePodSelector

  loadBalancing:
    healthCheckName: "reg-lb-hc"
    backupPodSelector:
      namespaceSelector:
        matchLabels:
          environment: test
          dc: us-central
      podSelector:
        matchLabels:
          component: backupPodSelector
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  name: proxy-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: proxy
  template:
    metadata:
      # annotations:  <- Include these lines if the pods are multi-nic pods
      #   networking.gke.io/default-interface: 'eth0'
      #   networking.gke.io/interfaces: '[{"interfaceName":"eth0","network":"default"}, {"interfaceName":"eth1","network":"blue-network"}]'
      labels:
        component: proxy
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

次の点にご注意ください。

  • podSelector: 定義された永続 IP アドレスからトラフィックを受信するプライマリ アクティブ Pod を識別します。このフィールドは、ラベルを使用して、GKEIPRoute リソースと同じ Namespace 内の Pod を照合します。GKE は、このセレクタに一致するすべての正常な Pod にトラフィックを分散します。一致する Pod が同じノードに複数存在する場合、GKE は最も新しく作成された Pod のみを選択してトラフィックを受信します。ここで定義するラベルは、backupPodSelector フィールドのラベルと重複しないようにする必要があります。このフィールドは変更可能です。
  • backupPodSelector: podSelector オブジェクトに一致するすべてのプライマリ Pod がヘルスチェックに失敗した場合にのみトラフィックを受信するスタンバイ Pod を定義します。このセレクタには次のものが含まれます。
    • namespaceSelector: これらのバックアップ Pod を検索するために GKE が検索する Namespace を決定します。ラベルセレクタを使用すると、検索を特定の Namespace に限定できます。このフィールドが省略されているか空の場合、GKE はクラスタ内のすべての Namespace でバックアップ Pod を検索します。
    • podSelector: ラベルに基づいてバックアップ Pod を照合します。これらのラベルは、プライマリ podSelector オブジェクトで使用されるラベルとは異なる必要があります。

このマニフェストの他のフィールドの詳細については、GKEIPRoute オブジェクトを作成するをご覧ください。

ステップ 6: Pod 内で割り当てられた IP アドレスを使用する

GKEIPRoute オブジェクトを使用して GKE Pod に IP アドレスを割り当てても、アプリケーションで IP アドレスを使用できるわけではありません。IP アドレスはネットワーク ルーティング レベルで処理されますが、Pod のデフォルト構成では認識されません。Pod 内のアドレスを認識して使用するように、Pod 仕様を構成する必要があります。この操作を行うには、Pod に特権権限が必要です。

Pod 仕様は、次のいずれかの方法で構成できます。

  • net.ipv4.ip_nonlocal_bind sysctl を変更する

    Pod securityContextnet.ipv4.ip_nonlocal_bind sysctl を設定すると、システム設定を変更して、アプリケーションがインターフェースに直接割り当てられていない IP アドレスを使用できるようになります。このオプションは、アプリケーションがインターフェースにない IP アドレスにバインドできる場合に便利です。

    Deployment または StatefulSet の YAML 仕様の spec.template.spec に、次を追加します。

    securityContext:
      sysctls:
      - name: net.ipv4.ip_nonlocal_bind
        value: "1"
    
  • 割り当てられた IP アドレスを Pod インターフェースに追加する

    GKEIPRoute オブジェクトによって要求された IP アドレスは、init コンテナを使用して Pod のインターフェースの 1 つに手動で追加できます。これにより、IP アドレスが直接割り当てられたかのように Pod に認識されます。これには NET_ADMIN 機能が必要です。

    Deployment または StatefulSet の YAML 仕様の spec.template.spec に、次を追加します。

    initContainers:
    - name: configure-ips
      image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
      command: ['sh', '-c', 'ip address add ASSIGNED_IP/32 dev eth0']
      securityContext:
        capabilities:
          add:
          - NET_ADMIN
    

    ASSIGNED_IP は、GKEIPRoute オブジェクトに割り当てられた IP アドレスの 1 つに置き換えます。

  • Raw ソケット: より細かい制御が必要な場合、アプリはネットワーク スタックと直接やり取りできます(上級者むけ)。

  • ユーザー空間 IP アドレス スタック: 特殊なケースでは、Pod 内で別のアプリケーションが実行され、IP アドレスを管理する場合があります(非常に高度な方法)。

ステップ 7: 割り当てられた IP アドレスの ARP を有効にする(デフォルト ネットワークのみ)

有効な Address Resolution Protocol(ARP)リクエストとレスポンスを生成し、デフォルト ネットワークの GKEIPRoute オブジェクトによって割り当てられた IP アドレスを使用して Pod への新しい接続を確立するには、arp_announce 変数を構成する必要があります。

arp_announce 変数を設定するには、Pod で次のコマンドを実行します。

echo "2" > /proc/sys/net/ipv4/conf/eth0/arp_announce

ここで、arp_announce 変数は ARP アナウンスメントの処理方法を制御します。これを「2」に設定すると、永続的な IP アドレスに対して ARP の通知が行われ、ネットワーク上の他のデバイスが新しい関連付けについて認識できるようになります。

ステップ 8: 一致するエンドポイントを表示する

トラフィック分散を管理するために、GKE は各 GKEIPRoute オブジェクトの EndpointSlice を作成します。これらのスライスは、その特定のルートのルーティング宛先として指定されたすべての Pod のレジストリとして機能します。

GKE は、アクティブ エンドポイントとバックアップ エンドポイントに対して別々の EndpointSlice を生成します。システムは、ワークロードに基づいて EndpointSlice の数を自動的にスケーリングします。1 つの EndpointSlice は最大 1,000 個のエンドポイントをサポートしますが、一致する Pod の数がこの上限を超えると、GKE は追加のスライスを作成します。

特定の GKEIPRoute オブジェクトのすべての EndpointSlice を表示するには、次のコマンドを実行します。

kubectl get endpointslices --all-namespaces -l \
  networking.gke.io/gkeiproute-name=GKEIPROUTE_NAME,\
  networking.gke.io/gkeiproute-namespace=GKEIPROUTE_NAMESPACE

次のように置き換えます。

  • GKEIPROUTE_NAME: GKEIPRoute マニフェストの名前。
  • GKEIPROUTE_NAMESPACE: GKEIPRoute マニフェストの Namespace。

次の出力は、EndpointSlice の例を示しています。

apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
 name: {gkeiproute_name-truncated}-{gkeiproute_namespace-truncated}-backup-{unique_hash}
 namespace: {gkeiproute_namespace}
 labels:
  endpointslice.kubernetes.io/managed-by: gkeiproute-controller
  networking.gke.io/gkeiproute-name: {gkeiproute_name}
  networking.gke.io/gkeiproute-namespace: {gkeiproute_namespace}
  networking.gke.io/pip-es-role: backup
 ownerReferences:
  - kind: GKEIPRoute
    name: {gkeiproute_name}
    apiVersion: networking.gke.io/v1
    uid: {uid}
    controller: true
addressType: IPv4
endpoints:
 - addresses:
     - "{pod_ip_address}"
   targetRef:
     Name: {pod_name}
   nodeName: {node_name}

アクティブ エンドポイントまたはバックアップ エンドポイントのいずれかの EndpointSlice を表示するには、pip-eps-role ラベルを使用して結果をフィルタします。次に例を示します。

kubectl get endpointslices --all-namespaces -l \
   networking.gke.io/pip-eps-role=ROLE \
  networking.gke.io/gkeiproute-name=GKEIPROUTE_NAME,

次のように置き換えます。

  • ROLE: 表示するエンドポイントのタイプ(active または backup)。
  • GKEIPROUTE_NAME: 特定の GKEIPRoute オブジェクトの名前。

ヘルスチェック ベースのロード バランシングのトラブルシューティング

このセクションでは、ヘルスチェック ベースのロード バランシングに関連する問題を解決する方法について説明します。

一部のアクティブ Pod が異常な状態だが、バックアップ Pod がトラフィックを受信しない

症状

GKEIPRoute のステータスに Ready が表示されます。これは、一致する Pod の IP アドレス構成が完了したことを示します。ヘルスチェックやその他の診断で、一部のアクティブな Pod が異常であることが示されています。ただし、バックアップ Pod はトラフィックを受信しません。

原因

バックアップ Pod は、すべてのアクティブ Pod が異常になるまでトラフィックを受信しません。それまでは、すべてのトラフィックが残りの正常なアクティブ Pod に分散されます。

解決策

必要に応じて、podSelector フィールドのラベルを更新して、アクティブな Pod と一致しないようにします。GKE は、トラフィックをバックエンド グループに自動的に転送します。

GKEIPRoute が構成されているが、一部の Pod がトラフィックを受信しない

症状

GKEIPRoute のステータスに Ready が表示されます。これは、一致する Pod の IP アドレス構成は完了しているが、一致する Pod の一部がトラフィックを受信していないことを示します。

原因

トラフィックを受信していない Pod は、正常でないか、ヘルスチェックに正しく応答していない可能性があります。一致する Pod がすべて正常でない場合、GKE はヘルスステータスに関係なく、すべての Pod にトラフィックを分散します。

解決策

  • Pod が正常であることを確認する: Google Cloud CLI またはGoogle Cloud コンソールを使用して、Pod がヘルスチェックに正しく応答することを確認します。
  • 必要に応じてさらに調査する: Pod が異常な状態の場合は、ヘルスチェックのファイアウォールが正しく設定されていることと、Pod が応答していることを確認します。

無効なロードバランサ構成のエラー

このセクションでは、GKEIPRoute ステータス エラーのトラブルシューティングについて説明します。

Backup pod and active pod are on the same node

症状

GKEIPRoute のステータスで次のエラーが報告されます。

invalid LB configuration: Backup pod %s and active pod %s are on the same node %s. Active and backup pods must reside on different nodes.

原因

同じ GKEIPRoute オブジェクトに一致するアクティブ Pod とバックアップ Pod が同じノードにスケジュールされます。つまり、同じノードにアクティブとバックアップの両方の podSelector オブジェクトに一致する Pod が存在します。

解決策

アクティブ Pod とバックアップ Pod が異なるノードにあることを確認します。GKEIPRoute 構成を更新し、同じノード上の 2 つの Pod が同じ GKEIPRoute オブジェクトと一致しないように podSelector または backupPodSelector ラベルを調整します。

Pod cannot be selected as both an active and a backup pod

症状

GKEIPRoute のステータスで次のエラーが報告されます。

invalid LB configuration: pod %s cannot be selected as both an active and a backup pod. Active and backup pod sets must be mutually exclusive

原因

1 つ以上の Pod が、podSelector(アクティブ)フィールドと backupPodSelector(スタンバイ)フィールドの両方のラベル セレクタと一致しています。GKE では、この 2 つのグループが相互に排他的である必要があります。1 つの Pod を独自のバックアップとして使用することはできません。

解決策

アクティブ Pod とバックアップ Pod が一意であることを確認します。GKEIPRoute マニフェストの podSelector フィールドまたは backupPodSelector フィールドを変更して、より具体的または明確なラベルキーと値を使用します。

NoPodsFound ステータス

症状

GKEIPRoute マニフェストには NoPodsFound のステータスが表示されます。これは、一致するラベルを持つ Namespace 内に Pod がないことを示します。

考えられる原因

  • ラベルが正しくない: 構成された IP アドレスを使用する Pod のラベルが間違っているか、ラベルがない可能性があります。
  • Pod が存在しない: reactionMode == Exists の場合は、pod.Spec.nodeName フィールドを確認して Pod がノードに割り当てられているかどうかを確認します。GKEIPRoute の Namespace で、セレクタに一致する Pod が実行されていない可能性があります。
  • Pod の準備が完了していない: reactionMode == ReadyCondition の場合は、Pod のステータスが READY かどうかを確認します。一致する Pod が存在しても、READY 状態になっていないとトラフィックを処理できないため、選択されません。

解決策

  • ラベルを確認する: GKEIPRoute オブジェクトの podSelector フィールドのラベルが、対象の Pod に適用したラベルと一致していることを確認します。
  • Pod の存在を確認する: Gateway のリスナーで指定された GKEIPRoute オブジェクトの Namespace に、正しいラベルを持つ Pod が存在することを確認します。reactionMode == Exists の場合は、pod.Spec.nodeName フィールドを確認して、Pod がノードに割り当てられているかどうかを確認します。
  • Pod の準備状況を確認する: reactionMode == ReadyCondition の場合は、Pod のステータスが READY かどうかを確認します。次のコマンドを使用して、Pod が Ready 状態であることを確認します。

    kubectl get pods -n NAMESPACE
    

    他の状態(PendingError など)の Pod は選択されません。

Mutated ステータス(一致する Pod が見つかり、GKEIPRoute IP アドレスのプログラミングが進行中)

症状

GKEIPRoute ステータスに Mutated が表示されます。これは、一致する Pod の IP アドレス構成が進行中であることを示します。

考えられる原因

システムが構成された IP アドレスの GKE データパスと Google Cloud リソースを設定しているため、構成中に Mutated ステータスになります。

解決策

  1. 待機して再試行する: ほとんどの場合、構成プロセスは短時間で自動的に完了します。待機してステータスを確認します。成功すると Ready に変わります。
  2. さらに調査する(必要に応じて): Mutated ステータスが長期間続く場合は、構成エラーが原因である可能性があります。GKEIPRoute オブジェクトの他のステータス条件を確認します。

    • Accepted: GKEIPRoute の設定が有効かどうかを示します。
    • GCPReady: Google Cloud リソースが想定どおりに設定されているかどうかを示します。

これらの条件でエラー メッセージを探して、問題のトラブルシューティングに役立ててください。

次のステップ