GKE ポッドの内部 HTTP(S) 負荷分散の設定

このドキュメントでは、Google Kubernetes Engine(GKE)ポッドで実行されているサービスに内部 HTTP(S) 負荷分散を構成する手順について説明します。

始める前に

このガイドの手順では、bash や bash などのシェルを使用する必要があります。たとえば、Cloud Shell を使用できます。

このガイドの手順を行う前に、次のドキュメントをご確認ください。

GKE ベースのサービスを使用した内部 HTTP(S) 負荷分散の構成

このセクションでは、GKE ポッド上で実行されるサービスに必要な構成を示します。クライアント VM は、転送ルールで構成した IP アドレスとポートに接続されます。クライアント アプリケーションがこの IP アドレスとポートにトラフィックを送信すると、内部 HTTP(S) ロードバランサの URL マップに従ってバックエンド GKE ポッドにリクエストが転送されます。

この例では、エフェメラル内部 IP アドレスの割り当てを許可せずに、内部転送ルールに予約済み内部 IP アドレスを明示的に設定しています。これは、転送ルールにおすすめのベスト プラクティスです。

転送ルールの IP アドレスには、backend-subnet を使用します。プロキシ専用サブネットを使用すると、転送ルールの作成に失敗します。

バックエンドの構成: GKE クラスタ

このセクションでは、ノードのホスト名を提供する単純なウェブサーバーが稼働する単純なコンテナを実行するため、デモ用の GKE クラスタとデプロイメントを作成します。また、NEG を自動的に作成する ClusterIP サービスも作成します。

Console

Cloud Console を使用してクラスタを作成するには、次の手順を行います。

  1. Cloud Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. [クラスタを作成] をクリックします。

  3. [名前] フィールドに「l7-ilb-cluster」と入力します。

  4. [ロケーション タイプ] で Zonal を選択します。

  5. [ゾーン] で us-west1-b を選択します。

  6. デフォルトのマスター バージョンを選択します。

  7. [可用性、ネットワーキング、セキュリティ、その他の機能] を展開します。

    1. [VPC ネイティブを有効にする(エイリアス IP を使用)] ボックスがチェックされていることを確認します。
    2. [ネットワーク] で lb-network を選択します。
    3. [ノードのサブネット] で backend-subnet を選択します。
    4. Enable HTTP load balancing の横にあるチェックボックスをオンにして、負荷分散が有効になっていることを確認します。
  8. 残りのフィールドについては、デフォルト値のままにするか、必要に応じて調整します。

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

Cloud Console でクラスタを作成する場合は、システム生成のネットワーク タグをプロキシ ファイアウォール フィルタに追加する必要があります。

  1. GKE がクラスタ内のノードに追加したネットワーク タグを検索します。タグはクラスタのハッシュから生成されます。

    1. [VM インスタンス] ページに移動します。

      [VM インスタンス] ページに移動

    2. [] プルダウンで [ネットワーク タグ] を選択します。

    3. GKE ノードにネットワーク タグをコピーします。次のようになります。

          gke-l7-ilb-cluster-id-node
          
  2. fw-allow-proxies ファイアウォール ルールを編集してタグを追加します。

    1. Google Cloud Console の [ファイアウォール ルール] ページに移動します。
      [ファイアウォール ルール] ページに移動
    2. fw-allow-proxies ファイアウォール ルールをクリックしてから、[編集] をクリックします。
    3. [ターゲットタグ] フィールドに、前の手順でコピーしたネットワーク タグを追加します。
    4. [保存] をクリックします。

gcloud

  1. gcloud container clusters create コマンドを使用して、GKE クラスタを作成します。

        gcloud container clusters create l7-ilb-cluster \
            --zone=us-west1-b \
            --network=lb-network \
            --subnetwork=backend-subnet \
            --enable-ip-alias \
            --tags=allow-ssh,load-balanced-backend
        

api

projects.zones.clusters.create メソッドで GKE クラスタを作成します。[project-id] は、実際のプロジェクト ID で置き換えます。

POST https://container.googleapis.com/v1/projects/[project-id]/zones/us-west1-b/clusters
    {
      "cluster": {
        "name": "l7-ilb-cluster",
        "network": "projects/[project-id]/global/networks/lb-network",
        "subnetwork": "projects/[project-id]/regions/us-west1/subnetworks/backend-subnet",
        "initialClusterVersion": "",
        "location": "us-west1-b",
        "nodePools": [{
          "name": "l7-ilb-node-pool",
          "initialNodeCount": 3,
          "config": {
            "tags":["allow-ssh","load-balanced-backend"]
          }
        }],
        "defaultMaxPodsConstraint": {
          "maxPodsPerNode": "110"
        },
        "ipAllocationPolicy": {
          "useIpAliases": true
        }
      }
    }
    

クラスタを操作するための認証情報の取得

gcloud container cluster get-credentials コマンドを使用します。

    gcloud container clusters get-credentials l7-ilb-cluster \
        --zone=us-west1-b
    

ホスト名を提供するテストコンテナでデプロイメントを定義する

デプロイメントとサービスの仕様を使用して hostname.yaml を作成します。

    cat << EOF > hostname.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: hostname
      annotations:
        cloud.google.com/neg: '{"exposed_ports":{"80":{}}}'
    spec:
      ports:
      - port: 80
        name: host1
        protocol: TCP
        targetPort: 8000
      selector:
        run: hostname
      type: ClusterIP

    ---

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        run: hostname
      name: hostname
    spec:
      replicas: 3
      selector:
        matchLabels:
          run: hostname
      template:
        metadata:
          labels:
            run: hostname
        spec:
          containers:
          - image: gcr.io/kubernetes-e2e-test-images/serve-hostname-amd64:1.1
            name: host1
            command:
            - /bin/sh
            - -c
            - /serve_hostname -http=true -udp=false -port=8000
            ports:
            - protocol: TCP
              containerPort: 8000
    EOF
    

構成を適用する

  1. サービス アカウントを使用して Google Cloud へのアクセスを承認していない場合は、gcloud auth application-default login コマンドを実行します。

        gcloud auth application-default login
        
  2. 構成を適用します。

        kubectl apply -f hostname.yaml
        

デプロイメントと GKE 構成を確認する

新しいサービスホスト名が作成され、アプリケーション ポッドが実行されていることを確認します。

    kubectl get svc
    

出力例は次のとおりです。

    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    hostname     ClusterIP   10.71.9.71           80/TCP    41m
    [..skip..]
    

GKE が backend-subnet のセカンダリ IP 範囲としてクラスタ IP 範囲を自動的に作成するため、クラスタ IP アドレスが少し異なります。

    kubectl get pods
    

出力例は次のとおりです。

    NAME                        READY     STATUS    RESTARTS   AGE
    hostname-6db459dcb9-896kh   1/1       Running   0          33m
    hostname-6db459dcb9-k6ddk   1/1       Running   0          50m
    hostname-6db459dcb9-x72kb   1/1       Running   0          33m
    [..skip..]
    

出力には、新しいサービスのホスト名が表示されます。ホスト名アプリケーションのポッドには、RunningSTATUS が必要です。

実際のポッド名はサンプル名と異なります。

NEG の名前を取得する

gcloud compute network-endpoint-groups list コマンドを実行して、クラスタのゾーンとデプロイメントの名前でフィルタリングを行い、NEG の名前を検索します。NEG の名前に DEPLOYMENT_NAME という変数を割り当てます。

    export DEPLOYMENT_NAME=$(gcloud compute network-endpoint-groups list \
           --filter="us-west1-b AND hostname" \
           --format="get(name)")
    echo $DEPLOYMENT_NAME
    

NEG の構成を確認する

NEG 内のエンドポイントの一覧と詳細を確認するには、gcloud compute network-endpoint-groups list-network-endpointsgcloud compute network-endpoint-groups describe コマンドを使用します。

    gcloud compute network-endpoint-groups describe $DEPLOYMENT_NAME \
        --zone=us-west1-b
    
    gcloud compute network-endpoint-groups list-network-endpoints $DEPLOYMENT_NAME \
        --zone=us-west1-b
    

GKE 用にロードバランサを構成する

この例では、次の内部 HTTP(S) ロードバランサのリソースを作成する方法について説明します。

  • HTTP ヘルスチェック
  • NEG をバックエンドとして使用するバックエンド サービス
  • URL マップ
    • リージョンがターゲット HTTP(S) プロキシに定義されている場合は、必ずリージョン URL マップを参照してください。リージョン URL マップは、受信 URL のホストとパスに定義したルールに基づいて、リクエストをリージョン バックエンド サービスにルーティングします。リージョン URL マップを参照できるのは、同じリージョン内のリージョン ターゲット プロキシのルールのみです。
  • SSL 証明書(HTTPS の場合)
  • ターゲット プロキシ
  • 転送ルール

転送ルールの IP アドレスには、backend-subnet を使用します。プロキシ専用サブネットを使用すると、転送ルールの作成に失敗します。

Console

ロードバランサ タイプの選択

  1. Google Cloud Console で [負荷分散] ページに移動します。
    [負荷分散] ページに移動
  2. [HTTP(S) 負荷分散] で [構成を開始] をクリックします。
  3. [VM 間のみ] を選択します。この設定は、ロードバランサが内部であることを意味します。
  4. [続行] をクリックします。

ロードバランサの準備

  1. ロードバランサの [名前] に「l7-ilb-gke-map」と入力します。
  2. [リージョン] で us-west1 を選択します。
  3. [ネットワーク] で lb-network を選択します。
  4. ウィンドウを開いたままにして続行します。

プロキシ専用サブネットの予約

内部 HTTP(S) 負荷分散の場合は、プロキシ専用サブネットを予約します。

  1. [サブネットの予約] をクリックします。
  2. [名前] に「proxy-only-subnet」と入力します。
  3. [IP アドレス範囲] に「10.129.0.0/23」と入力します。
  4. [追加] をクリックします。

バックエンド サービスの構成

  1. [バックエンドの構成] をクリックします。
  2. [バックエンド サービスの作成または選択] メニューから [バックエンド サービスを作成] を選択します。
  3. バックエンド サービスの [名前] を l7-ilb-gke-backend-service に設定します。
  4. [バックエンド タイプ] で [ネットワーク エンドポイント グループ] を選択します。
  5. [バックエンド] の [新しいバックエンド] カードで次の手順を行います。
    1. GKE によって作成された NEG にネットワーク エンドポイント グループを設定します。名前の決定方法については「NEG の名前を取得する」をご覧ください。
    2. エンドポイントあたりの 5 RPS の最大レートを入力します。Google Cloud では、必要に応じて最大レートを超える場合があります。
    3. [完了] をクリックします。
  6. [ヘルスチェック] セクションで、[ヘルスチェックを作成] を選択し、次のパラメータを選択します。
    1. 名前: l7-ilb-gke-basic-check
    2. プロトコル: HTTP
    3. ポートの指定: サービスポート
    4. [保存して次へ] をクリックします。
  7. [作成] をクリックします。

URL マップの構成

  1. [ホストとパスのルール] をクリックします。l7-ilb-gke-backend-service が、ホストとパスが一致しなかった場合に使用される唯一のバックエンド サービスであることを確認します。

フロントエンドを構成する

HTTP の場合:

  1. [フロントエンドの構成] をクリックします。
  2. [フロントエンド IP とポートの追加] をクリックします。
  3. [名前] を l7-ilb-gke-forwarding-rule に設定します。
  4. [プロトコル] を HTTP に設定します。
  5. [サブネットワーク] を backend-subnet に設定します。
  6. [内部 IP] で [静的内部 IP アドレスの予約] を選択します。
  7. 表示されるパネルで、次の情報を入力します。
    1. 名前: l7-ilb-gke-ip
    2. [静的 IP アドレス] セクションで、[ユーザー選択] を選択します。
    3. [カスタム IP アドレス] セクションに「10.1.2.199」と入力します。
    4. [予約] をクリックします。
  8. [ポート] を 80 に設定します。
  9. [完了] をクリックします。

HTTPS の場合:

クライアントとロードバランサ間で HTTPS を使用する場合は、プロキシを構成するために 1 つ以上の SSL 証明書リソースが必要になります。SSL 証明書リソースの作成方法については、SSL 証明書をご覧ください。現在、内部 HTTP(S) ロードバランサでは Google マネージド証明書がサポートされません。

  1. [フロントエンドの構成] をクリックします。
  2. [フロントエンド IP とポートの追加] をクリックします。
  3. [名前] フィールドに「l7-ilb-gke-forwarding-rule」と入力します。
  4. [プロトコル] フィールドで HTTPS (includes HTTP/2) を選択します。
  5. [サブネット] を backend-subnet に設定します。
  6. [内部 IP] で [静的内部 IP アドレスの予約] を選択します。
  7. 表示されるパネルで、次の情報を入力します。
    1. 名前: l7-ilb-gke-ip
    2. [静的 IP アドレス] セクションで、[ユーザー選択] を選択します。
    3. [カスタム IP アドレス] セクションに「10.1.2.199」と入力します。
    4. [予約] をクリックします。
  8. HTTPS トラフィックを許可するように、ポート443 に設定されていることを確認します。
  9. [証明書] プルダウン リストをクリックします。
    1. プライマリ SSL 証明書として使用しようとしているセルフマネージド SSL 証明書リソースがすでにある場合は、プルダウン メニューから選択します。
    2. そうでない場合は、[新しい証明書の作成] を選択します。
      1. [名前] に「l7-ilb-cert」を入力します。
      2. 該当するフィールドに PEM 形式のファイルをアップロードします。
        • 公開鍵証明書
        • 証明書チェーン
        • 秘密鍵
      3. [作成] をクリックします。
  10. プライマリ SSL 証明書リソースに加えて証明書リソースを追加するには、次の手順を行います。
    1. [証明書を追加] をクリックします。
    2. [証明書] リストから証明書を選択するか、[新しい証明書の作成] をクリックし、上記の手順に沿います。
  11. [完了] をクリックします。

構成の完了

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

gcloud

  1. gcloud compute health-checks create http コマンドを使用して、HTTP ヘルスチェックを定義します。

        gcloud compute health-checks create http l7-ilb-gke-basic-check \
           --region=us-west1 \
           --use-serving-port
        
  2. gcloud compute backend-services create コマンドを使用して、バックエンド サービスを定義します。

        gcloud compute backend-services create l7-ilb-gke-backend-service \
          --load-balancing-scheme=INTERNAL_MANAGED \
          --protocol=HTTP \
          --health-checks=l7-ilb-gke-basic-check \
          --health-checks-region=us-west1 \
          --region=us-west1
        
  3. gcloud compute backend-services add-backend コマンドを使用して、NEG バックエンド サービスにバックエンドを追加します。

        gcloud compute backend-services add-backend l7-ilb-gke-backend-service \
           --network-endpoint-group=$DEPLOYMENT_NAME \
           --network-endpoint-group-zone=us-west1-b \
           --region=us-west1 \
           --balancing-mode=RATE \
           --max-rate-per-endpoint=5
        
  4. gcloud compute url-maps create コマンドを使用して、URL マップを作成します。

        gcloud compute url-maps create l7-ilb-gke-map \
          --default-service=l7-ilb-gke-backend-service \
          --region=us-west1
        
  5. ターゲット プロキシを作成します。

    HTTP の場合:

    gcloud compute target-http-proxies create コマンドを使用します。

        gcloud compute target-http-proxies create l7-ilb-gke-proxy \
          --url-map=l7-ilb-gke-map \
          --url-map-region=us-west1 \
          --region=us-west1
        

    HTTPS の場合:

    SSL 証明書リソースの作成方法については、SSL 証明書をご覧ください。現在、内部 HTTP(S) ロードバランサでは Google マネージド証明書がサポートされません。

    ファイルパスを変数名に割り当てます。

        `export LB_CERT=path to PEM-formatted file`
        
        `export LB_PRIVATE_KEY=path to PEM-formatted file`
        

    gcloud compute ssl-certificates create コマンドを使用して、リージョン SSL 証明書を作成します。

    gcloud compute ssl-certificates create

        gcloud compute ssl-certificates create l7-ilb-cert \
          --certificate=$LB_CERT \
          --private-key=$LB_PRIVATE_KEY \
          --region=us-west1
        

    リージョン SSL 証明書を使用して、gcloud compute target-https-proxies create コマンドを実行してターゲット プロキシを作成します。

    gcloud compute target-https-proxies create

        gcloud compute target-https-proxies create l7-ilb-gke-proxy \
          --url-map=l7-ilb-gke-map \
          --region=us-west1 \
          --ssl-certificates=l7-ilb-cert
        
  6. 転送ルールを作成します。

    カスタム ネットワークでは、転送ルールでサブネットを参照する必要があります。このサブネットは、VM サブネットでありプロキシ専用サブネットではありません。

    HTTP の場合:

    適切なフラグを設定して、gcloud compute forwarding-rules create コマンドを実行します。

        gcloud compute forwarding-rules create l7-ilb-gke-forwarding-rule \
          --load-balancing-scheme=INTERNAL_MANAGED \
          --network=lb-network \
          --subnet=backend-subnet \
          --address=10.1.2.199 \
          --ports=80 \
          --region=us-west1 \
          --target-http-proxy=l7-ilb-gke-proxy \
          --target-http-proxy-region=us-west1
        

    HTTPS の場合:

    適切なフラグを設定して、gcloud compute forwarding-rules create コマンドを実行します。

        gcloud compute forwarding-rules create l7-ilb-gke-forwarding-rule \
          --load-balancing-scheme=INTERNAL_MANAGED \
          --network=lb-network \
          --subnet=backend-subnet \
          --address=10.1.2.199 \
          --ports=443 \
          --region=us-west1 \
          --target-https-proxy=l7-ilb-gke-proxy \
          --target-https-proxy-region=us-west1
        

api

POST リクエストを regionHealthChecks.insert メソッドに送信して、ヘルスチェックを作成します。[project-id] は実際のプロジェクト ID で置き換えます。

POST https://compute.googleapis.com/compute/v1/projects/[project-id]/regions/{region}/healthChecks
    {
      "name": "l7-ilb-gke-basic-check",
      "type": "HTTP",
      "httpHealthCheck": {
        "portSpecification": "USE_SERVING_PORT"
      }
    }
    

POST リクエストを regionBackendServices.insert メソッドに送信して、リージョン バックエンド サービスを作成します。[project-id] は実際のプロジェクト ID で置き換えます。[neg-name] は、作成した NEG の名前で置き換えます。

POST https://www.googleapis.com/compute/v1/projects/[project-id]/regions/us-west1/backendServices
    {
      "name": "l7-ilb-gke-backend-service",
      "backends": [
        {
          "group": "https://www.googleapis.com/compute/v1/projects/[project-id]/zones/us-west1-b/networkEndpointGroups/[neg-name]",
          "balancingMode": "RATE",
          "maxRatePerEndpoint": 5
        }
      ],
      "healthChecks": [
        "projects/[project-id]/regions/us-west1/healthChecks/l7-ilb-gke-basic-check"
      ],
      "loadBalancingScheme": "INTERNAL_MANAGED"
    }
    

POST リクエストを regionUrlMaps.insert メソッドに送信して、URL マップを作成します。[project-id] は実際のプロジェクト ID で置き換えます。

POST https://compute.googleapis.com/compute/v1/projects/[project-id]/regions/us-west1/urlMaps
    {
      "name": "l7-ilb-gke-map",
      "defaultService": "projects/[project-id]/regions/us-west1/backendServices/l7-ilb-gke-backend-service"
    }
    

regionTargetHttpProxies.insert メソッドに POST リクエストを送り、ターゲット HTTP プロキシを作成します。[project-id] はプロジェクト ID で置き換えます。

POST https://www.googleapis.com/compute/v1/projects/[project-id]/regions/us-west1/targetHttpProxy
    {
      "name": "l7-ilb-gke-proxy",
      "urlMap": "projects/[project-id]/global/urlMaps/l7-ilb-gke-map",
      "region": "us-west1"
    }
    

forwardingRules.insert メソッドに POST リクエストを送り、転送ルールを作成します。[project-id] はプロジェクト ID で置き換えます。

POST https://www.googleapis.com/compute/v1/projects/[project-id]/regions/us-west1/forwardingRules
    {
      "name": "l7-ilb-gke-forwarding-rule",
      "IPAddress": "10.1.2.199",
      "IPProtocol": "TCP",
      "portRange": "80-80",
      "target": "projects/[project-id]/regions/us-west1/targetHttpProxies/l7-ilb-gke-proxy",
      "loadBalancingScheme": "INTERNAL_MANAGED",
      "subnetwork": "projects/[project-id]/regions/us-west1/subnetworks/backend-subnet",
      "network": "projects/[project-id]/global/networks/lb-network",
      "networkTier": "PREMIUM",
    }
    

テスト

ゾーンに VM インスタンスを作成して接続をテストする

    gcloud compute instances create l7-ilb-client-us-west1-b \
        --image-family=debian-9 \
        --image-project=debian-cloud \
        --zone=us-west1-b \
        --network=lb-network \
        --subnet=backend-subnet \
        --tags=l7-ilb-client,allow-ssh
    

ロードバランサをテストする

クライアント インスタンスにログインして、内部 HTTP(S) ロードバランサの転送ルールの IP アドレスを介してバックエンドの HTTP(S) サービスに到達可能であることと、NEG のエンドポイント間でトラフィックの負荷分散が行われていることをテストします。

各クライアント インスタンスへ SSH を介して接続する

    gcloud compute ssh l7-ilb-client-us-west1-b \
        --zone=us-west1-b
    

IP がホスト名を提供していることを確認する

    curl 10.1.2.199
    

HTTPS テストの場合、curl は次のもので置き換えます。

    curl -k -s 'https://test.example.com:443' --connect-to test.example.com:443:10.1.2.199:443
    

-k フラグを指定すると、curl は証明書の検証をスキップします。

100 個のリクエストを実行し負荷分散されていることを確認する

HTTP の場合:

    {
    RESULTS=
    for i in {1..100}
    do
        RESULTS="$RESULTS:$(curl --silent 10.1.2.199)"
    done
    echo "***"
    echo "*** Results of load-balancing to 10.1.2.199: "
    echo "***"
    echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
    echo
    }
    

HTTPS の場合:

    {
    RESULTS=
    for i in {1..100}
    do
        RESULTS="$RESULTS:$(curl -k -s 'https://test.example.com:443' --connect-to test.example.com:443:10.1.2.199:443
    )"
    done
    echo "***"
    echo "*** Results of load-balancing to 10.1.2.199: "
    echo "***"
    echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
    echo
    }
    

複数のプロキシが curl コマンドごとに負荷分散を行いますが、バックエンドの選択を調整しません。したがって、このテストではバックエンドは同じ数のリクエストを受信しません。ただし、長期的にみると(数千~数百万件のリクエスト)、各バックエンドが受信するリクエストの割合は均等に分布するようになります。

次のステップ