Ingress による HTTP/2 を使用した負荷分散

このページでは、Kubernetes の Ingress オブジェクトと Service オブジェクトを使用して、バックエンド サービスとの通信で HTTP/2 を使用するように外部 HTTP(S) ロードバランサを構成する方法について説明します。この機能は、Google Kubernetes Engine バージョン 1.11.2 以降で使用できます。

概要

HTTP(S) ロードバランサは、クライアントとアプリケーションの間のプロキシとして機能します。クライアントは、HTTP/1.1 または HTTP/2 を使用してロードバランサ プロキシと通信できます。ただし、ロードバランサ プロキシからアプリケーションへの接続は、デフォルトで HTTP/1.1 を使用します。Google Kubernetes Engine Pod で実行中のアプリケーションで HTTP/2 リクエストを受信できる場合、アプリケーションにリクエストを転送するときに HTTP/2 を使用するように外部ロードバランサを構成します。

ロードバランサから Pod までの HTTP/2 を表す図(クリックして拡大)

この演習では、Deployment、Service、Ingress を作成します。Service マニフェストに cloud.google.com/app-protocols アノテーションを挿入して、ロードバランサがアプリケーションとの通信に HTTP/2 を使用する必要があることを指定します。その後、サービスを呼び出して、アプリケーションが HTTP/2 リクエストを受信したことを確認します。

始める前に

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

次のいずれかの方法で gcloud のデフォルトの設定を指定します。

  • gcloud init。デフォルトの設定全般を確認する場合に使用します。
  • gcloud config。プロジェクト ID、ゾーン、リージョンを個別に設定する場合に使用します。

gcloud init の使用

エラー One of [--zone, --region] must be supplied: Please specify location を受信した場合は、このセクションの内容を実施します。

  1. gcloud init を実行して、次の操作を行います。

    gcloud init

    リモート サーバーで SSH を使用している場合は、--console-only フラグを指定して、コマンドがブラウザを起動しないようにします。

    gcloud init --console-only
  2. 手順に従って gcloud を承認し、Google Cloud アカウントを使用します。
  3. 新しい構成を作成するか、既存の構成を選択します。
  4. Google Cloud プロジェクトを選択します。
  5. ゾーンクラスタの場合はデフォルトの Compute Engine ゾーン、リージョン クラスタまたは Autopilot クラスタの場合はデフォルトの Compute Engine リージョンを選択します。

gcloud config の使用

  • デフォルトのプロジェクト ID を設定します。
    gcloud config set project PROJECT_ID
  • ゾーンクラスタを使用する場合は、デフォルトのコンピューティング ゾーンを設定します。
    gcloud config set compute/zone COMPUTE_ZONE
  • Autopilot クラスタまたはリージョン クラスタを使用する場合は、デフォルトのコンピューティング リージョンを設定します。
    gcloud config set compute/region COMPUTE_REGION
  • gcloud を最新バージョンに更新します。
    gcloud components update

Deployment を作成する

この Deployment マニフェストでは、echoheaders ウェブ アプリケーションの 2 つのレプリカを実行することを宣言します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoheaders
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echoheaders
  template:
    metadata:
      labels:
        app: echoheaders
    spec:
      containers:
      - name: echoheaders
        image: k8s.gcr.io/echoserver:1.10
        ports:
        - containerPort: 8443

このマニフェストを my-deployment.yaml という名前のファイルにコピーして Deployment を作成します。

kubectl apply -f my-deployment.yaml

Service を作成する

Service のマニフェストを次に示します。

apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/app-protocols: '{"my-port":"HTTP2"}'
  name: echoheaders
  labels:
    app: echoheaders
spec:
  type: NodePort
  ports:
  - port: 443
    targetPort: 8443
    protocol: TCP
    name: my-port
  selector:
    app: echoheaders

このマニフェストを my-service.yaml という名前のファイルに保存して Service を作成します。

kubectl apply -f my-service.yaml

Service を表示します。

kubectl get service echoheaders --output yaml

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

apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/app-protocols: '{"my-port":"HTTP2"}'
    ...
  labels:
    app: echoheaders
  name: echoheaders
  ...
spec:
  clusterIP: 10.39.251.148
  ...
  ports:
  - name: my-port
    nodePort: 30647
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    app: echoheaders
  ...
  type: NodePort
...

この演習では、Service について次の項目を把握することが重要です。

  • Service のタイプは NodePort です。これは Service の必須タイプで、Ingress に関連付けられます。

  • app: echoheaders というラベルを持つすべての Pod は Service のメンバーです。これは、selector フィールドで指定されています。

  • Service にはポートが 1 つあり、その名前は my-port です。cloud.google.com/app-protocols アノテーションは、my-port が HTTP/2 プロトコルを使用する必要があることを指定します。

  • TCP ポート 443 の Service に向かうトラフィックは、いずれかのメンバー Pod の TCP ポート 8443 にルーティングされます。これは、porttargetPort フィールドで指定されています。

Ingress を作成する

Ingress のマニフェストを次に示します。

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: echomap
spec:
  backend:
    serviceName: echoheaders
    servicePort: 443

このマニフェストを my-ingress.yaml という名前のファイルにコピーして Ingress を作成します。

kubectl apply -f my-ingress.yaml

Kubernetes Ingress コントローラが HTTP(S) ロードバランサを構成するまで数分かかります。構成が完了したら Ingress を表示します。

kubectl get ingress echomap --output yaml

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

kind: Ingress
metadata:
  ...
  name: echomap
  ...
spec:
  backend:
    serviceName: echoheaders
    servicePort: 443
status:
  loadBalancer:
    ingress:
    - ip: 203.0.113.2

この演習では、Ingress について次の項目を把握することが重要です。

  • 受信トラフィックの IP アドレスは loadBalancer:ingress の下に表示されます。

  • 受信リクエストは、echoheaders Service のメンバーである Pod にルーティングされます。この演習では、メンバー Pod に app: echoheaders というラベルが付いています。

  • リクエストは、echoheaders Service マニフェストで指定されているターゲット ポート上の Pod にルーティングされます。この演習では、Pod のターゲット ポートは 8443 です。

ロードバランサが HTTP/2 をサポートしていることを確認する

gcloud

  1. バックエンド サービスを一覧表示します。

    gcloud compute backend-services list
    
  2. バックエンド サービスの説明を設定します。

    gcloud beta compute backend-services describe backend-service-name --global
    

    backend-service-name はバックエンド サービスの名前です。

  3. 出力で、プロトコルが HTTP/2 になっていることを確認します。

    backends:
    ...
    description: '{...,"kubernetes.io/service-port":"443","x-features":["HTTP2"]}'
    ...
    kind: compute#backendService
    loadBalancingScheme: EXTERNAL
    protocol: HTTP2
    ...
    

Console

  1. Google Cloud Console の [負荷分散] ページに移動します。

    [負荷分散] ページに移動

  2. [名前] で、ロードバランサを探します。

    Google Cloud Console に表示される HTTP ロードバランサのスクリーンショット(クリックして拡大)
  3. バックエンド サービスを表示するには、ロードバランサの名前をクリックします。

  4. バックエンド サービスのエンドポイント プロトコルHTTP/2 であることを確認します。

    Google Cloud Console に表示される HTTP/2 バックエンド サービスのスクリーンショット(クリックして拡大)

サービスを呼び出す

ロードバランサとバックエンド サービスが構成されるまで数分待ちます。ブラウザのアドレスバーにロードバランサの外部 IP アドレスを入力します。

ロードバランサから Pod へのリクエストに関する情報が出力に表示されます。

Hostname: echoheaders-7886d5bc68-xnrwj
...
Request Information:
  ...
  method=GET
  real path=/
  query=
  request_version=2
  request_scheme=https
  ...

Request Headers:
  ...
  x-forwarded-for=[YOUR_IP_ADDRESS], 203.0.113.2
  x-forwarded-proto=http
...

この演習では、上記の出力について次の項目を把握することが重要です。

  • request_version=2 は、ロードバランサと Pod の間のリクエストで HTTP/2 が使用されたことを示します。

  • x-forwarded-proto=http は、ユーザーとロードバランサの間のリクエストで HTTP/2 ではなく HTTP 1.1 が使用されたことを示します。

次のステップ

  • Ingress での HTTP 負荷分散を設定する。

  • Ingress を使用して Ingress アプリケーションの静的 IP とドメイン名を構成する。

  • Ingress ロードバランサの SSL 証明書を構成する。

  • 複数のリージョンに存在する複数の Google Kubernetes Engine クラスタで実行されるアプリケーションがある場合は、マルチクラスタ Ingress を構成してユーザーに最も近いリージョンのクラスタにトラフィックをルーティングする。