Ingress による HTTP(S) 負荷分散の設定

このチュートリアルでは、Ingress リソースを構成することにより、外部 HTTP(S) ロードバランサの背後でウェブ アプリケーションを実行する方法について説明します。

背景

Google Kubernetes Engine(GKE)には、一般公開するアプリケーション用に次の 2 種類の Cloud Load Balancing のサポートが組み込まれています。

  • リソース マニフェストに type:LoadBalancer を指定すると、GKE は LoadBalancer タイプの Service を作成します。GKE は、適切な Google Cloud API 呼び出しを行い、外部ネットワーク ロードバランサまたは内部 TCP / UDP ロードバランサを作成します。cloud.google.com/load-balancer-type: "Internal" アノテーションを追加すると、GKE は内部 TCP / UDP ロードバランサを作成します。追加しない場合、GKE は外部ネットワーク ロードバランサを作成します。

    このいずれかのロードバランサを HTTP(S) トラフィックの処理に使用できますが、これらは OSI レイヤ 3 または 4 で動作します。このため、HTTP 接続や、個々の HTTP リクエストとレスポンスを認識しません。もう 1 つの重要な特長は、リクエストがプロキシ経由で宛先に送信されない点です。

  • リソース マニフェストに type:Ingress を指定すると、GKE は Ingress リソースを作成します。アノテーション、サポート ワークロード、Service を指定すると、独自の Ingress コントローラを作成できます。それ以外の場合、GKE は適切な Google Cloud API 呼び出しを行い、外部 HTTP(S) ロードバランサを作成します。ロードバランサの URL マップのホストルールとパスマッチャーは 1 つ以上のバックエンド サービスを参照します。Ingress で参照されているように、各バックエンド サービスは NodePort タイプの GKE Service に対応しています。各バックエンド サービスのバックエンドは、インスタンス グループまたはネットワーク エンドポイント グループ(NEG)のいずれかです。Ingress の構成の一部として コンテナ ネイティブの負荷分散を構成すると、NEG が作成されます。GKE は、対応する GKE Service が参照するワークロードの readinessProbe 設定に基づいて、バックエン ドサービスごとに Google Cloud ヘルスチェックを作成します。

    GKE でホストされている HTTP(S) サービスを公開する場合は、負荷分散として HTTP(S) 負荷分散の利用をおすすめします。

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud Console で Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。 これには数分かかることがあります。
  4. Google Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

このチュートリアルで使用されている以下のコマンドライン ツールをインストールします。

  • gcloud は、Kubernetes Engine クラスタの作成と削除に使用されます。gcloud は、Google Cloud SDK に含まれています。
  • kubectl は、Kubernetes Engine で使用されるクラスタ オーケストレーション システムである Kubernetes の管理に使用されます。gcloud を使用して kubectl をインストールできます。
    gcloud components install kubectl

gcloud コマンドライン ツールのデフォルトの設定

次のコマンドを実行してデフォルト値を設定しておくと、gcloud コマンドライン ツールでプロジェクト IDCompute Engine ゾーンの各オプションを入力する時間を節約できます。
gcloud config set project project-id
gcloud config set compute/zone compute-zone

コンテナ クラスタの作成

次のコマンドを実行して、loadbalancedcluster という名前のコンテナ クラスタを作成します。

gcloud container clusters create loadbalancedcluster

ステップ 1: ウェブ アプリケーションをデプロイする

ポート 8080 で HTTP サーバーをリッスンするサンプルウェブ アプリケーション コンテナ イメージを使用して、Deployment を作成します。

  1. web-deployment.yaml マニフェストをダウンロードします。
  2. リソースをクラスタに適用します。

    kubectl apply -f web-deployment.yaml
    

ステップ 2: Deployment をサービスとして内部公開する

コンテナ クラスタ内で web Deployment を到達可能にする Service リソースを作成します。

  1. web-service.yaml マニフェストをダウンロードします。
  2. リソースをクラスタに適用します。

    kubectl apply -f web-service.yaml
    

    このコマンドで NodePort タイプの Service を作成すると、クラスタ内のすべてのノードで、ランダムに選択された上位ポート番号(32640 など)を使用して Service を利用できるようになります。

  3. Service が作成され、ノードポートが割り当てられたことを確認します。

    kubectl get service web
    
    出力:
    NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    web       NodePort   10.35.245.219   <none>        8080:32640/TCP   5m
    

    上記のサンプル出力の場合、web Service のノードポートは 32640 です。また、このサービスには外部 IP アドレスが割り当てられていないことに注意してください。デフォルトで GKE ノードに外部からアクセスすることはできないため、この Service を作成しても、インターネットからアプリケーションにアクセスできるようにはなりません。

HTTP(S) ウェブサーバー アプリケーションを公開するには、Ingress リソースを作成する必要があります。

ステップ 3: Ingress リソースを作成する

Ingress は、外部 HTTP(S) トラフィックを内部サービスにルーティングするためのルールと構成の集合をカプセル化する Kubernetes リソースです。

GKE では、Ingress は Cloud Load Balancing を使用して実装されます。クラスタで Ingress を作成すると、GKE により HTTP(S) ロードバランサが作成され、トラフィックをアプリケーションにルーティングするように構成されます。

Kubernetes Ingress はベータ版リソースであり、Ingress オブジェクトの記述方法は変更される可能性がありますが、GKE で Ingress を実装するためにプロビジョニングされる Cloud Load Balancer は、本番環境に対応しています。

次の構成ファイルでは、トラフィックを web サービスに転送する Ingress リソースが定義されています。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: basic-ingress
spec:
  backend:
    serviceName: web
    servicePort: 8080

この Ingress リソースをデプロイするには:

  1. basic-ingress.yaml マニフェストをダウンロードします。
  2. リソースをクラスタに適用します。

    kubectl apply -f basic-ingress.yaml
    

このマニフェストをデプロイすると、Kubernetes の Ingress リソースがクラスタに作成されます。GKE Ingress コントローラでは、Ingress の情報に従って HTTP(S) ロードバランサを作成して構成し、すべての外部 HTTP トラフィック(ポート 80)を、公開した web NodePort サービスにルーティングします。

ステップ 4: アプリケーションにアクセスする

次のコマンドを実行して、アプリケーションに対応するロードバランサの外部 IP アドレスを調べます。

kubectl get ingress basic-ingress
出力:
NAME            HOSTS     ADDRESS         PORTS     AGE
basic-ingress   *         203.0.113.12    80        2m

ブラウザでアプリケーションの外部 IP アドレスを指定すると、次のようなプレーン テキストの HTTP レスポンスが表示されます。

Hello, world!
Version: 1.0.0
Hostname: web-6498765b79-fq5q5

Cloud Console の [負荷分散] にアクセスすると、Ingress コントローラによって作成されたネットワーキング リソースを調べることができます。

ステップ 5: (オプション)静的 IP アドレスを構成する

ドメイン名でウェブサーバーを公開する場合、アプリケーションの外部 IP アドレスを変化しない静的 IP アドレスにする必要があります。

デフォルトで、Ingress によって公開される HTTP アプリケーションに GKE が割り当てるのはエフェメラル外部 IP アドレスです。エフェメラル アドレスは変化する可能性があります。長期間使用する予定のウェブ アプリケーションでは、静的外部 IP アドレスを使用する必要があります。

Ingress リソースに静的 IP アドレスを設定した場合、Ingress を削除しても、それに関連付けられている静的 IP アドレスは削除されないことに注意してください。構成した静的 IP アドレスを再び使用する予定がない場合は、クリーンアップが必要になります。

オプション 1: 既存のエフェメラル IP アドレスを静的 IP アドレスに変換する

Ingress をすでにデプロイしてある場合、Cloud Console の [外部 IP アドレス] セクションで、外部 IP アドレスを変更することなく、アプリケーションの既存のエフェメラル IP アドレスを予約された静的 IP アドレスに変換できます。

オプション 2: 新しい静的 IP アドレスを予約する

  1. web-static-ip という静的外部 IP アドレスを予約します。

    gcloud

    gcloud compute addresses create web-static-ip --global
    

    Config Connector

    注: この手順には Config Connector が必要です。Config Connector をクラスタにインストールするには、インストール手順を実行してください。

    apiVersion: compute.cnrm.cloud.google.com/v1beta1
    kind: ComputeAddress
    metadata:
      name: web-static-ip
    spec:
      location: global
    このマニフェストをデプロイするには、マニフェストを compute-address.yaml というファイル名でマシンにダウンロードしてから、次のコマンドを実行します。
    kubectl apply -f compute-address.yaml

  2. 予約済み IP アドレスを使用するように既存の Ingress リソースを構成します。以前に使用した basic-ingress.yaml マニフェストを次のマニフェストで置き換えます。

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: basic-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "web-static-ip"
    spec:
      backend:
        serviceName: web
        servicePort: 8080
    

    この変更により、web-static-ip という名前の静的 IP リソースを使用するためのアノテーションが Ingress に追加されます。

  3. この変更を既存の Ingress に適用します。

    kubectl apply -f basic-ingress.yaml
    
  4. 外部 IP アドレスを確認します。

    kubectl get ingress basic-ingress
    

    web-static-ip リソースの予約済み IP アドレスを使用するようにアプリケーションの IP アドレスが変更されるまで待ちます。

    既存の Ingress リソースが更新され、ロードバランサが再構成されて、負荷分散ルールが世界中に伝播されるまで、数分かかることがあります。このオペレーションが完了すると、以前にアプリケーションに割り当てられていたエフェメラル IP アドレスが解放されます。

ステップ 6: (オプション)1 つのロードバランサで複数のアプリケーションに対応する

Ingress でルーティング ルールを設定することにより、単一のロードバランサとパブリック IP アドレスで複数のサービスを実行できます。同じ Ingress で複数のサービスをホストすると、インターネットに公開するサービスごとに追加のロードバランサ(課金対象のリソース)を作成しなくて済みます。

同じウェブ アプリケーションのバージョン 2.0 として別のウェブサーバー Deployment を作成します。

web-deployment-v2.yaml をダウンロードして、リソースをクラスタに適用します。

kubectl apply -f web-deployment-v2.yaml

次に、この web2 Deployment を、web2 という名前の NodePort サービス上のクラスタに内部公開します。

web-service-v2.yaml をダウンロードして、リソースをクラスタに適用します。

kubectl apply -f web-service-v2.yaml

以下に示すマニフェストは、次のような Ingress リソースを記述しています。

  • /v2/ でパスが始まるリクエストを web2 Service にルーティングする。
  • 他のすべてのリクエストを web Service にルーティングする。
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: fanout-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: web
          servicePort: 8080
      - path: /v2/*
        backend:
          serviceName: web2
          servicePort: 8080

このマニフェストをデプロイするには、マニフェストを fanout-ingress.yaml に保存して次のコマンドを実行します。

kubectl create -f fanout-ingress.yaml

Ingress をデプロイした後、kubectl get ingress fanout-ingress を実行して、クラスタのパブリック IP アドレスを調べます。

次に、IP アドレスを参照して、両方のアプリケーションが同じロードバランサ上で到達可能であることを確認します。

  • http://<IP_ADDRESS>/ に移動し、レスポンスに Version: 1.0.0 が含まれていることを確認します(リクエストは web Service にルーティングされる)。
  • http://<IP_ADDRESS>/v2/ に移動し、レスポンスに Version: 2.0.0 が含まれていることを確認します(リクエストは web2 Service にルーティングされる)。

GKE Ingress の path フィールドでサポートされているワイルドカード パターン マッチングは、* 文字の使用のみです。たとえば、/*/foo/bar/* などの path フィールドを持つルールを作成できます。path の制限事項については、URL マップのドキュメントをご覧ください。

ステップ 7: (オプション)サービスの可用性とレイテンシをモニタリングする

Google Cloud の稼働時間チェックでは、ユーザーの視点からアプリケーションのブラックボックス モニタリングを実行し、複数の外部 IP からロードバランサの IP アドレスへのレイテンシと可用性を決定します。これに対して、Google Cloud のヘルスチェックは Pod IP に対して内部チェックを実行し、インスタンス レベルでの可用性を決定します。この 2 つは補完的な関係にあり、アプリケーションの健全性を総合的に把握できます。

稼働時間チェックを作成するには、Google Cloud Console または Cloud Monitoring API を使用するか、Cloud Monitoring クライアント ライブラリを使用します。詳しくは、稼働時間チェックの管理をご覧ください。Google Cloud Console を使用して稼働時間チェックを作成する手順は次のとおりです。

  1. Google Cloud Console で [Monitoring] を選択するか、次のボタンをクリックします。

    [Monitoring] に移動

  2. [Monitoring] ナビゲーション パネルで、[稼働時間チェック] を選択し、[稼働時間チェックの作成] をクリックします。

  3. 稼働時間チェックのターゲットとして、次のフィールドを設定します。

    • プロトコルのタイプとして [TCP] を選択します。
    • [リソースの種類] として [URL] を選択します。
    • [Hostname] にロードバランサの IP アドレスを入力します。
    • [Port] フィールドにロードバランサのポート番号を入力します。

    稼働時間チェックのすべてのフィールドの詳細については、稼働時間チェックの作成をご覧ください。

稼働時間チェックをモニタリングするには、アラート ポリシーを作成するか、稼働時間チェック ダッシュボードを表示します。稼働時間チェックに失敗した場合は、アラート ポリシーによってメールまたは別のチャネルで通知されます。アラート ポリシーの概要については、アラートの概要をご覧ください。

備考

デフォルトでは、Ingress は GET リクエストを / パスで実行してアプリケーションの状態を判断することで定期的なヘルスチェックを実行し、HTTP 200 レスポンスを待ちます。別のパスをチェックしたい場合、または別のレスポンス コードを待つ場合は、カスタム ヘルスチェック パスを使用できます。

Ingress は、次のような高度なユースケースをサポートしています。

  • 名前ベースの仮想ホスティング: Ingress を使用して、複数のドメイン名およびサブドメインに対してロードバランサを再利用し、複数の Service を 1 つの IP アドレスとロードバランサで公開できます。これらのタスク用に Ingress を構成する方法については、簡単なファンアウト名前ベースの仮想ホスティングの例をご覧ください。

  • HTTPS の終了: Cloud Load Balancer を使用して HTTPS トラフィックを終了するように Ingress を構成できます。

Ingress を削除すると、関連付けられているリソース(予約された静的 IP アドレスを除く)は Ingress コントローラによって自動的にクリーンアップされます。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

  1. 手動で作成した転送ルールと、Ingress を参照するターゲット プロキシを削除します。

    Ingress コントローラのマネージド URL マップを参照しているターゲット プロキシが不要である場合、1.15.4-gke.22 以降の GKE バージョンでは Ingress を削除できません。Ingress リソースを調べて、次のようなエラー メッセージのイベントを確認します。

     Error during GC: error running load balancer garbage collection routine: googleapi: Error 400: The url_map resource 'projects/project-id/global/urlMaps/k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82' is already being used by 'projects/project-id/global/targetHttpsProxies/k8s2-um-tlw9rhgp-default-my82-target-proxy', resourceInUseByAnotherResource
     

    上記のエラー メッセージの例では、k8s2-um-tlw9rhgp-default-my82-target-proxy は手動で作成されたターゲット https プロキシであり、Ingress コントローラによって作成、管理された URL マップ k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82 を引き続き参照しています。

    そのため、手動で作成したフロントエンド リソース(転送ルールとターゲット プロキシの両方)を削除してから Ingress を削除する必要があります。

  2. Ingress を削除する: アプリケーションに関連付けられているエフェメラル外部 IP アドレスの割り振りとと負荷分散リソースの割り当てを解除します。

    kubectl delete ingress basic-ingress

    「ステップ 6」を行った場合は、次のコマンドを実行して Ingress を削除します。

    kubectl delete ingress fanout-ingress

  3. 静的 IP アドレスを削除する: この手順は、ステップ 5 を行った場合にのみ実行します。

    • ステップ 5 の「オプション 1」に従って既存のエフェメラル IP アドレスを静的 IP に変換した場合は、Cloud Console にアクセスして静的 IP を削除します。

    • ステップ 5 の「オプション 2」に従った場合は、次のコマンドを実行して静的 IP アドレスを削除します。

      gcloud compute addresses delete web-static-ip --global
  4. クラスタを削除する: コンテナ クラスタのコンピューティング ノードとその他のリソース(クラスタ内の Deployment など)を削除します。

    gcloud container clusters delete loadbalancedcluster

次のステップ