外部アプリケーション ロードバランサ用の Ingress を構成する

このページでは、Kubernetes Ingress オブジェクトを作成して外部アプリケーション ロードバランサを構成する方法について説明します。

このページを読む前に、GKE ネットワーキングのコンセプトを理解しておく必要があります。

始める前に

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

  • Google Kubernetes Engine API を有効にする。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、gcloud components update コマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
  • すでに Autopilot クラスタまたは Standard クラスタが存在していることを確認する。新しいクラスタを作成するには、Autopilot クラスタの作成をご覧ください。

HttpLoadBalancing アドオンを有効にする

クラスタで HttpLoadBalancing アドオンが有効になっている必要があります。このアドオンはデフォルトで有効になっています。Autopilot クラスタでは、このアドオンを無効にできません。

HttpLoadBalancing アドオンを有効にするには、 Cloud de Confiance コンソールまたは Google Cloud CLI を使用します。

コンソール

  1. Cloud de Confiance コンソールで [Google Kubernetes Engine] ページに移動します。

    Google Kubernetes Engine に移動

  2. 変更するクラスタの名前をクリックします。

  3. [ネットワーキング] の [HTTP 負荷分散] フィールドで、[ HTTP 負荷分散の編集] をクリックします。

  4. [HTTP ロード バランシングを有効にする] チェックボックスをオンにします。

  5. [変更を保存] をクリックします。

gcloud

gcloud container clusters update CLUSTER_NAME --update-addons=HttpLoadBalancing=ENABLED

CLUSTER_NAME は、使用するクラスタの名前に置き換えます。

静的 IP アドレスを作成

外部アプリケーション ロードバランサは、1 つ以上の Service にリクエストをルーティングするために使用できる安定した IP アドレスを 1 つ提供します。永続的な IP アドレスが必要な場合は、Ingress を作成する前にグローバル静的外部 IP アドレスを予約する必要があります。

エフェメラル IP アドレスではなく静的 IP アドレスを使用するように既存の Ingress を変更すると、GKE がロードバランサの転送ルールを再作成するときに、ロードバランサの IP アドレスが変更されることがあります。

外部アプリケーション ロードバランサを作成する

この演習では、URL パスに応じてリクエストを異なる Service に転送するように外部アプリケーション ロードバランサを構成します。

Deployment と Service を作成する

hello-world-1hello-world-2 という名前の Service を使用する 2 つの Deployment を作成します。

  1. 次のマニフェストを hello-world-deployment-1.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-world-deployment-1
    spec:
      selector:
        matchLabels:
          greeting: hello
          version: one
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
            version: one
        spec:
          containers:
          - name: hello-app-1
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
            env:
            - name: "PORT"
              value: "50000"
    

    このマニフェストでは、3 つのレプリカを含む Deployment のサンプルを記述しています。

  2. マニフェストをクラスタに適用します。

    kubectl apply -f hello-world-deployment-1.yaml
    
  3. 次のマニフェストを hello-world-service-1.yaml として保存します。

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-world-1
    spec:
      type: NodePort
      selector:
        greeting: hello
        version: one
      ports:
      - protocol: TCP
        port: 60000
        targetPort: 50000
    

    このマニフェストでは、次のプロパティを持つ Service を記述しています。

    • greeting: hello ラベルと version: one ラベルの両方を持つすべての Pod はこの Service のメンバーです。
    • GKE は、TCP ポート 60000 で Service に送信されたリクエストを TCP ポート 50000 でメンバー Pod のいずれかに転送します。
    • Service タイプは NodePort です。これは、コンテナ ネイティブのロード バランシングを使用しない場合には必須です。コンテナ ネイティブのロード バランシングを使用している場合は、サービスのタイプに制限はありません。type: ClusterIP の使用をおすすめします。
  4. マニフェストをクラスタに適用します。

    kubectl apply -f hello-world-service-1.yaml
    
  5. 次のマニフェストを hello-world-deployment-2.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-world-deployment-2
    spec:
      selector:
        matchLabels:
          greeting: hello
          version: two
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
            version: two
        spec:
          containers:
          - name: hello-app-2
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
            env:
            - name: "PORT"
              value: "8080"
    

    このマニフェストでは、3 つのレプリカを含む Deployment のサンプルを記述しています。

  6. マニフェストをクラスタに適用します。

    kubectl apply -f hello-world-deployment-2.yaml
    
  7. 次のマニフェストを hello-world-service-2.yaml として保存します。

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-world-2
    spec:
      type: NodePort
      selector:
        greeting: hello
        version: two
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080
    

    このマニフェストでは、次のプロパティを持つ Service を記述しています。

    • greeting: hello ラベルと version: two ラベルの両方を持つすべての Pod はこの Service のメンバーです。
    • GKE は、TCP ポート 80 で Service に送信されたリクエストを TCP ポート 8080 でメンバー Pod のいずれかに転送します。
  8. マニフェストをクラスタに適用します。

    kubectl apply -f hello-world-service-2.yaml
    

Ingress を作成する

リクエストの URL パスに応じて、リクエストをルーティングするためのルールを指定する Ingress を作成します。Ingress を作成すると、GKE Ingress コントローラによって外部アプリケーション ロードバランサが作成され、構成されます。

  1. 次のマニフェストを my-ingress.yaml として保存します。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
      annotations:
        # If the class annotation is not specified it defaults to "gce".
        kubernetes.io/ingress.class: "gce"
    spec:
      rules:
      - http:
          paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: hello-world-1
                port:
                  number: 60000
          - path: /v2
            pathType: ImplementationSpecific
            backend:
              service:
                name: hello-world-2
                port:
                  number: 80
    

    このマニフェストでは、次のプロパティを持つ Ingress を記述しています。

    • GKE Ingress クラスは 2 つあります。Ingress クラスを指定するには、kubernetes.io/ingress.class アノテーションを使用する必要があります。spec.ingressClassName を使用して GKE Ingress を指定することはできません。

    • gce クラスは、外部アプリケーション ロードバランサをデプロイします。

    • gce-internal クラスは、内部アプリケーション ロードバランサをデプロイします。

    • アノテーション spec.ingressClassNamekubernetes.io/ingress.class のない Ingress リソースをデプロイすると、GKE によって外部アプリケーション ロードバランサが作成されます。これは、kubernetes.io/ingress.class: gce アノテーションを指定した場合と同じ動作です。詳細については、GKE Ingress コントローラの動作をご覧ください。

    • GKE は、backend.service ごとに Cloud de Confiance バックエンド サービスを作成します。各バックエンド サービスは Kubernetes Service に対応し、各バックエンド サービスは Cloud de Confiance ヘルスチェックを参照する必要があります。このヘルスチェックはクラスタの外部で実装されるため、Kubernetes の liveness Probe または readiness Probe とは異なります。 詳細については、ヘルスチェックをご覧ください。

    • クライアントが URL パス / を使用してロードバランサにリクエストを送信すると、GKE はポート 60000 でリクエストを hello-world-1 Service に転送します。クライアントが URL パス /v2 を使用してロードバランサにリクエストを送信すると、GKE はポート 80 でリクエストを hello-world-2 Service に転送します。path プロパティと pathType プロパティの詳細については、URL パスをご覧ください。

  2. マニフェストをクラスタに適用します。

    kubectl apply -f my-ingress.yaml
    

外部アプリケーション ロードバランサをテストする

ロードバランサが構成されるまで 5 分ほど待ちます。構成されたら、外部アプリケーション ロードバランサをテストします。

  1. Ingress を確認します。

    kubectl get ingress my-ingress --output yaml
    

    出力には、外部アプリケーション ロードバランサの IP アドレスが表示されます。

    status:
      loadBalancer:
        ingress:
        - ip: 203.0.113.1
    
  2. / パスをテストします。

    curl LOAD_BALANCER_IP_ADDRESS/
    

    LOAD_BALANCER_IP_ADDRESS は、ロードバランサの外部 IP アドレスに置き換えます。

    出力は次のようになります。

    Hello, world!
    Version: 1.0.0
    Hostname: ...
    

    出力に 404 エラーが含まれている場合は、数分待ちます。

  3. /v2 パスをテストします。

    curl load-balancer-ip/v2
    

    出力は次のようになります。

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    

外部ロード バランシングでの Ingress の仕組み

外部アプリケーション ロードバランサは、クライアントとアプリケーションの間のプロキシとして機能します。クライアントからの HTTPS リクエストを受け入れるには、ロードバランサは証明書を持っていなければなりません。これにより、適切な送信先であることをクライアントに示すことができます。さらに、ロードバランサには、HTTPS handshake を完了するための秘密鍵も必要です。詳細情報

URL パス

Ingress の path フィールドでサポートされているワイルドカード文字は「*」のみです。「*」はスラッシュ(「/」)の直後に置かれる必要があり、パターンの最後の文字でなければなりません。たとえば、/*/foo/*/foo/bar/* は有効なパターンですが、*/foo/bar*/foo/*/bar は有効ではありません。

より具体的なパターンのほうが、そうでないものよりも優先されます。/foo/*/foo/bar/* の両方を使用すると、/foo/bar/bat/foo/bar/* と比較されます。パスの制限とパターン マッチングの詳細については、URL マップのドキュメントをご覧ください。

1.21.3-gke.1600 より前のバージョンを実行している GKE クラスタの場合、pathType フィールドでサポートされている値は ImplementationSpecific のみです。バージョン 1.21.3-gke.1600 以降を実行しているクラスタの場合、pathType には PrefixExact の値もサポートされています。

HTTP の無効化

クライアントとロードバランサ間のすべてのトラフィックで HTTPS を使用する場合は、HTTP を無効にできます。詳しくは、HTTP の無効化をご覧ください。

ロードバランサとアプリケーション間の HTTPS

GKE Pod で実行しているアプリケーションが HTTPS リクエストを受信できる場合は、ロードバランサがリクエストをアプリケーションに転送するときに HTTPS を使用するようにロードバランサを構成できます。詳しくは、ロードバランサとアプリケーション間の HTTPS(TLS)をご覧ください。

クライアントとロードバランサ間の HTTP/2

クライアントは HTTP/2 を使用してロードバランサにリクエストを送信できます。構成は不要です。

ロードバランサとアプリケーション間の HTTP/2

GKE Pod で実行しているアプリケーションが HTTP/2 リクエストを受信できる場合は、ロードバランサがリクエストをアプリケーションに転送するときに HTTP/2 を使用するようにロードバランサを構成できます。詳しくは、Ingress での HTTP/2 を使用した負荷分散をご覧ください。

ネットワーク エンドポイント グループ

クラスタがコンテナネイティブのロード バランシングをサポートしている場合は、ネットワーク エンドポイント グループ(NEG)を使用することをおすすめします。GKE クラスタ 1.17 以降と一定の条件下では、コンテナネイティブの負荷分散がデフォルトであり、明示的な cloud.google.com/neg: '{"ingress": true}' Service のアノテーションは必要ありません。

共有 VPC

Ingress リソースをデプロイする GKE クラスタがサービス プロジェクトにあり、GKE コントロール プレーンでホスト プロジェクトのファイアウォール リソースを管理する場合、共有 VPC を使用したクラスタのファイアウォール リソースの管理の説明のように、サービス プロジェクトの GKE サービス アカウントには、ホスト プロジェクトの適切な IAM 権限が付与されている必要があります。これにより、Ingress コントローラは、上り(内向き)トラフィックと Cloud de Confiance ヘルスチェックのトラフィックの両方を許可するファイアウォール ルールを作成できます。

以下に、Ingress リソースログに存在する可能性があるイベントの例を示します。このエラーは、権限が正しく構成されていないときに、Ingress コントローラがヘルスチェックの上り(内向き)トラフィックを許可するファイアウォール ルールを作成できない場合に発生します。 Cloud de Confiance

Firewall change required by security admin: `gcloud compute firewall-rules update <RULE_NAME> --description "GCE L7 firewall rule" --allow tcp:<PORT> --source-ranges 130.211.0.0/22,35.191.0.0/16 --target-tags <TARGET_TAG> --project <HOST_PROJECT>

ホスト プロジェクトからファイアウォール ルールを手動でプロビジョニングする場合は、Ingress リソースに networking.gke.io/suppress-firewall-xpn-error: "true" アノテーションを追加することで firewallXPNError イベントをミュートできます。

外部 Ingress アノテーションの概要

Ingress アノテーション

アノテーション 説明
kubernetes.io/ingress.allow-http クライアントと HTTP(S) ロードバランサ間の HTTP トラフィックを許可するかどうかを指定します。有効な値は true と false です。デフォルトは "true" です。HTTP の無効化をご覧ください。
ingress.gcp.kubernetes.io/pre-shared-cert このアノテーションを使用して、証明書リソースを GKE Ingress リソースに関連付けます。詳細については、外部アプリケーション ロードバランサでの複数の SSL 証明書の使用をご覧ください。
kubernetes.io/ingress.global-static-ip-name このアノテーションを使用して、以前に作成した静的外部 IP アドレスをロードバランサが使用するように指定します。HTTP(S) ロードバランサの静的 IP アドレスをご覧ください。
networking.gke.io/v1beta1.FrontendConfig このアノテーションを使用して、ロードバランサのクライアント向け構成をカスタマイズします。詳細については、Ingress の構成をご覧ください。
networking.gke.io/suppress-firewall-xpn-error Ingress ロードバランサの場合、権限不足のために Kubernetes でファイアウォール ルールを変更できないと、数分ごとに firewallXPNError イベントが作成されます。GLBC 1.4 以降では、Ingress リソースに networking.gke.io/suppress-firewall-xpn-error: "true" アノテーションを追加することで firewallXPNError イベントをミュートできます。このアノテーションを削除すると、ミュートを解除できます。有効な値は truefalse です。デフォルト値は false です。
アノテーション 説明
cloud.google.com/app-protocols このアノテーションを使用して、ロードバランサとアプリケーション間の通信用のプロトコルを設定します。有効なプロトコルは HTTP、HTTPS、HTTP2 です。ロードバランサとアプリケーション間の HTTPSIngress による HTTP/2 を使用したロードバランサをご覧ください。
cloud.google.com/backend-config このアノテーションを使用して、サービスに関連付けられるバックエンド サービスを構成します。詳細については、Ingress の構成をご覧ください。
cloud.google.com/neg このアノテーションを使用して、ロードバランサがネットワーク エンドポイント グループを使用するように指定します。コンテナ ネイティブのロードバランサの使用をご覧ください。

次のステップ