外部負荷分散向け Ingress の設定

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

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

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

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API を有効にします。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。

HttpLoadBalancing アドオンの有効化

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

HttpLoadBalancing アドオンは、Google Cloud コンソールか Google Cloud CLI を使用して有効にできます。

Console

  1. Google Cloud コンソールで [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 アドレスを作成

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

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

外部 HTTP(S) ロードバランサを作成する

この演習では、URL パスに応じてリクエストを異なるサービスに転送するように外部 HTTP(S) ロードバランサを構成します。

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
    

    このマニフェストでは、次のプロパティを持つサービスが記述されています。

    • greeting: hello ラベルと version: one ラベルの両方を持つすべての Pod はこの Service のメンバーです。
    • GKE は、TCP ポート 60000 で Service に送信されたリクエストを TCP ポート 50000 でメンバー Pod のいずれかひとつに転送します。
    • サービス タイプは 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
    

    このマニフェストでは、次のプロパティを持つサービスが記述されています。

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

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

Ingress を作成する

リクエストの URL パスに応じてリクエストのルーティング ルールを指定する Ingress を作成します。Ingress を作成すると、GKE Ingress コントローラが外部 HTTP(S) ロードバランサを作成して構成します。

  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 クラスは、外部 HTTP(S) ロードバランサをデプロイします。

    • gce-internal クラスは、内部 HTTP(S) ロードバランサをデプロイします。

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

    • GKE は、backend.service ごとに Google Cloud バックエンド サービスを作成します。

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

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

    kubectl apply -f my-ingress.yaml
    

外部 HTTP(S) ロードバランサをテストします。

ロードバランサが構成されるまで約 5 分待ってから、外部 HTTP(S) ロードバランサをテストします。

  1. Ingress を確認します。

    kubectl get ingress my-ingress --output yaml
    

    外部 HTTP(S) ロードバランサの 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 の仕組み

外部 HTTP(S) ロードバランサは、クライアントとアプリケーションの間のプロキシとして機能します。クライアントからの 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 コントローラでは、上り(内向き)トラフィックと Google Cloud ヘルスチェックのトラフィックの両方を許可するファイアウォール ルールを作成できます。

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

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 このアノテーションを使用して、セルフマネージド証明書リソースまたは Google マネージド証明書リソースを GKE Ingress リソースに接続します。詳細については、HTTP(S) ロード バランシングでの複数の 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 このアノテーションを使用して、ロードバランサがネットワーク エンドポイント グループを使用するように指定します。コンテナ ネイティブのロードバランサの使用をご覧ください。

次のステップ