Ingress を使用して外部アプリケーション ロードバランサを設定する


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

背景

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

  1. Ingress

  2. 外部パススルー ネットワーク ロードバランサ

このチュートリアルでは、Ingress を使用します。

Ingress

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

GKE でホストされている HTTP(S) サービスを公開する場合は、ロード バランシングとして HTTP(S) ロード バランシングの利用をおすすめします。

目標

  • GKE クラスタを作成する。
  • サンプル ウェブ アプリケーションをクラスタにデプロイする。
  • 外部アプリケーション ロードバランサの背後でサンプルアプリをインターネットに公開します。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

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

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

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

GitHub からサンプルコードのクローンを作成します。

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/networking/load-balancing

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

次のようにしてデフォルト値を設定しておくと、gcloud コマンドライン ツールでプロジェクト ID および Compute Engine ゾーン オプションを入力する時間が節約されます。
gcloud config set project project-id
gcloud config set compute/zone compute-zone

GKE クラスタを作成する

GKE Autopilot クラスタを作成します。

gcloud container clusters create-auto loadbalancedcluster

ウェブ アプリケーションをデプロイする

次のマニフェストでは、ポート 8080 で HTTP サーバー上でサンプル ウェブ アプリケーション コンテナ イメージを実行する Deployment を記述しています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: default
spec:
  selector:
    matchLabels:
      run: web
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
        imagePullPolicy: IfNotPresent
        name: web
        ports:
        - containerPort: 8080
          protocol: TCP

リソースをクラスタに適用します。

kubectl apply -f web-deployment.yaml

クラスタ内での Deployment の公開

次のマニフェストでは、web Deployment をコンテナ クラスタ内でアクセス可能にする Service を記述しています。

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web
  type: NodePort
  1. リソースをクラスタに適用します。

    kubectl apply -f web-service.yaml
    

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

  2. 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 です。また、この Service には外部 IP アドレスが割り振られていないことに注意してください。デフォルトで GKE ノードに外部からアクセスすることはできないため、この Service を作成しても、インターネットからアプリケーションにアクセスできるようにはなりません。

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

Ingress リソースの作成

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

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

次のマニフェストでは、トラフィックを web Service に転送する Ingress リソースを記述しています。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: basic-ingress
spec:
  defaultBackend:
    service:
      name: web
      port:
        number: 8080

リソースをクラスタに適用します。

kubectl apply -f basic-ingress.yaml

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

アプリケーションへのアクセス

次のコマンドを実行して、アプリケーションに対応するロードバランサの外部 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

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

(省略可)静的 IP アドレスの構成

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

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

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

静的 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. basic-ingress-static.yaml マニフェストでは、web-static-ip という名前の静的 IP リソースを使用するためのアノテーションを Ingress に追加しています。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: basic-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "web-static-ip"
    spec:
      defaultBackend:
        service:
          name: web
          port:
            number: 8080

    マニフェストを確認します。

    cat basic-ingress-static.yaml
    
  3. リソースをクラスタに適用します。

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

    kubectl get ingress basic-ingress
    

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

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

(省略可)1 つのロードバランサで複数のアプリケーションに対応する

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

次のマニフェストでは、同じウェブ アプリケーションのバージョン 2.0 を使用した Deployment を記述しています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web2
  namespace: default
spec:
  selector:
    matchLabels:
      run: web2
  template:
    metadata:
      labels:
        run: web2
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: web2
        ports:
        - containerPort: 8080
          protocol: TCP

リソースをクラスタに適用します。

kubectl apply -f web-deployment-v2.yaml

次のマニフェストでは、web2 という NodePort Service 上のクラスタに web2 を内部公開する Service を記述しています。

apiVersion: v1
kind: Service
metadata:
  name: web2
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web2
  type: NodePort

リソースをクラスタに適用します。

kubectl apply -f web-service-v2.yaml

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

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

リソースをクラスタに適用します。

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 にルーティングされる)。

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

より具体的なパターンのほうが、そうでないものよりも優先されます。/foo/*/foo/bar/* の両方を使用すると、/foo/bar/bat/foo/bar/* と比較されます。

パスの制限とパターン マッチングの詳細については、URL マップのドキュメントをご覧ください。

(省略可)サービスの可用性とレイテンシをモニタリングする

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

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

  1. Google Cloud コンソールの [Service と Ingress] ページに移動します。

    [Service と Ingress] に移動

  2. 稼働時間チェックを作成する Service の名前をクリックします。

  3. [稼働時間チェックの作成] をクリックします。

  4. [稼働時間チェックの作成] ペインで、稼働時間チェックのタイトルを入力し、[次へ] をクリックして [ターゲット] 設定に進みます。

    稼働時間チェックの [ターゲット] フィールドには Service ロードバランサの情報を使用して自動的に入力されます。

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

  5. [次へ] をクリックして [レスポンスの検証] 設定に進みます。

  6. [次へ] をクリックして [アラートと通知] セクションに進みます。

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

  7. [作成] をクリックします。

備考

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

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

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

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

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

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

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

    GKE 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

    オプションの手順でパスによってリクエストをルーティングする Ingress を作成した場合は、Ingress を削除します。

    kubectl delete ingress fanout-ingress

  3. 静的 IP アドレスを削除する: この手順は、オプションの手順を行って静的 IP アドレスを作成した場合にのみ行ってください。

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

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

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

    gcloud container clusters delete loadbalancedcluster

次のステップ