クラスタ間での Ingress のデプロイ

このページでは、GKE クラスタ間でアプリケーションにサービスを提供する Ingress のデプロイ方法について説明します。マルチクラスタ Ingress の詳細については、マルチクラスタ Ingress をご覧ください。

デプロイのチュートリアル

以下のタスクでは、whereami という名前の架空のアプリと MultiClusterIngress を 2 つのクラスタにデプロイします。Ingress は、アプリのデプロイ用に共有仮想 IP アドレス(VIP)を提供します。

このページは、マルチクラスタ Ingress の設定で 2 つのクラスタを作成して登録した作業に基づいています。2 つのクラスタがフリートにも登録されていることを確認します。

gcloud container clusters list

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

NAME    LOCATION        MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
gke-eu  europe-west1-b  1.16.8-gke.9    ***             e2-medium      1.16.8-gke.9     2          RUNNING
gke-us  us-central1-b   1.16.8-gke.9    ***             e2-medium      1.16.6-gke.13 *  2          RUNNING

Namespace の作成

フリートには Namespace の同一性という特徴があるため、同じ Namespace が同じグループで所有および管理されるように、クラスタ間で Namespace の作成と管理を調整することをおすすめします。Namespace は、チームごと、環境ごと、アプリケーションごと、アプリケーション コンポーネントごとに作成できます。あるクラスタ内の Namespace ns1 の意味と使用法が別のクラスタ内の ns1 のものと同じである限り、必要に応じて細かく Namespaces を設定できます。

この例では、各クラスタでアプリケーションごとに whereami Namespace を作成します。

  1. 次のコンテンツを含むファイルを namespace.yaml という名前で作成します。

    apiVersion: v1
    kind: Namespace
    metadata:
      name: whereami
    
  2. gke-us コンテキストに切り替えます。

    kubectl config use-context gke-us
    
  3. Namespace を作成します。

    kubectl apply -f namespace.yaml
    
  4. gke-eu コンテキストに切り替えます。

    kubectl config use-context gke-eu
    
  5. Namespace を作成します。

    kubectl apply -f namespace.yaml
    

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

    namespace/whereami created
    

アプリのデプロイ

  1. 次のコンテンツを含むファイルを deploy.yaml という名前で作成します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-deployment
      namespace: whereami
      labels:
        app: whereami
    spec:
      selector:
        matchLabels:
          app: whereami
      template:
        metadata:
          labels:
            app: whereami
        spec:
          containers:
          - name: frontend
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.8
            ports:
            - containerPort: 8080
    
  2. gke-us コンテキストに切り替えます。

    kubectl config use-context gke-us
    
  3. whereami アプリをデプロイします。

    kubectl apply -f deploy.yaml
    
  4. gke-eu コンテキストに切り替えます。

    kubectl config use-context gke-eu
    
  5. whereami アプリをデプロイします。

    kubectl apply -f deploy.yaml
    
  6. whereami アプリが各クラスタに正常にデプロイされたことを確認します。

    kubectl get deployment --namespace whereami
    

    両方のクラスタで、出力は次のようになります。

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    whereami-deployment   1/1     1            1           12m
    

構成クラスタを使用したデプロイ

アプリケーションが gke-usgke-eu にデプロイされたので、構成クラスタに MultiClusterIngressMultiClusterService のリソースをデプロイすることによって、ロードバランサをデプロイします。これは、Ingress リソースと Service リソースのマルチクラスタに相当します。

設定ガイドで、gke-us クラスタを構成クラスタとして構成しました。構成クラスタは、すべてのクラスタに Ingress をデプロイして構成するために使用されます。

  1. コンテキストを構成クラスタに設定します。

    kubectl config use-context gke-us
    

MultiClusterService

  1. 次のコンテンツを含むファイルを mcs.yaml という名前で作成します。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    
  2. whereami アプリと一致する MultiClusterService リソースをデプロイします。

    kubectl apply -f mcs.yaml
    
  3. whereami-mcs リソースが構成クラスタに正常にデプロイされたことを確認します。

    kubectl get mcs -n whereami
    

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

    NAME       AGE
    whereami-mcs   9m26s
    

    この MultiClusterService は、app: whereami と Pod を一致させるすべてのクラスタに派生ヘッドレス Service を作成します。Service が、gke-us クラスタ kubectl get service -n whereami に存在することを確認できます。

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

    NAME                                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
    mci-whereami-mcs-svc-lgq966x5mxwwvvum   ClusterIP   None          <none>        8080/TCP         4m59s
    

同様のヘッドレス Service が gke-eu にも存在します。これらのローカル Service は、Pod エンドポイントを動的に選択して、グローバルな Ingress ロードバランサをバックエンドでプログラムするために使用されます。

MultiClusterIngress

  1. 次のコンテンツを含むファイルを mci.yaml という名前で作成します。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
    

    この構成では、すべてのトラフィックが、whereami Namespace に存在する whereami-mcs という名前の MultiClusterService にルーティングされます。

  2. whereami-mcs をバックエンドとして参照する MultiClusterIngress リソースをデプロイします。

    kubectl apply -f mci.yaml
    

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

    multiclusteringress.networking.gke.io/whereami-ingress created
    

    MultiClusterIngress のスキーマは Kubernetes Ingress と同じです。Ingress リソースのセマンティクスも、backend.serviceName フィールドを除き同じです。

MultiClusterIngressbackend.serviceName フィールドは、Kubernetes クラスタの Service ではなく、Fleet API の MultiClusterService を参照します。つまり、TLS の終端など、Ingress の設定はすべて同じ方法で構成できます。

デプロイの成功ステータスを検証する

Google Cloud ロードバランサのデプロイでは、新しいロードバランサのデプロイに数分かかることがあります。新しいリソースをデプロイする必要がないため、既存のロードバランサの更新は、より短時間で完了します。MultiClusterIngress リソースは、MultiClusterIngress の代わりとして作成された、基盤となる Compute Engine リソースの詳細を示します。

  1. デプロイが成功したことを確認します。

    kubectl describe mci whereami-ingress -n whereami
    

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

    Name:         whereami-ingress
    Namespace:    whereami
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"networking.gke.io/v1","kind":"MultiClusterIngress","metadata":{"annotations":{},"name":"whereami-ingress","namespace":"whe...
    API Version:  networking.gke.io/v1
    Kind:         MultiClusterIngress
    Metadata:
      Creation Timestamp:  2020-04-10T23:35:10Z
      Finalizers:
        mci.finalizer.networking.gke.io
      Generation:        2
      Resource Version:  26458887
      Self Link:         /apis/networking.gke.io/v1/namespaces/whereami/multiclusteringresses/whereami-ingress
      UID:               62bec0a4-8a08-4cd8-86b2-d60bc2bda63d
    Spec:
      Template:
        Spec:
          Backend:
            Service Name:  whereami-mcs
            Service Port:  8080
    Status:
      Cloud Resources:
        Backend Services:
          mci-8se3df-8080-whereami-whereami-mcs
        Firewalls:
          mci-8se3df-default-l7
        Forwarding Rules:
          mci-8se3df-fw-whereami-whereami-ingress
        Health Checks:
          mci-8se3df-8080-whereami-whereami-mcs
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-e4adffe6-whereami-mci-whereami-mcs-svc-lgq966x5m-808-88670678
          zones/us-central1-b/networkEndpointGroups/k8s1-a6b112b6-whereami-mci-whereami-mcs-svc-lgq966x5m-808-609ab6c6
        Target Proxies:
          mci-8se3df-whereami-whereami-ingress
        URL Map:  mci-8se3df-whereami-whereami-ingress
      VIP:        34.98.102.37
    Events:
      Type    Reason  Age                    From                              Message
      ----    ------  ----                   ----                              -------
      Normal  ADD     3m35s                  multi-cluster-ingress-controller  whereami/whereami-ingress
      Normal  UPDATE  3m10s (x2 over 3m34s)  multi-cluster-ingress-controller  whereami/whereami-ingress
    

    この Ingress デプロイのステータスを示すフィールドがいくつかあります。

    • Events は最初に見るべき場所です。エラーが発生した場合は、ここに表示されます。

    • Cloud Resource は、マルチクラスタ Ingress コントローラによって作成された転送ルール、バックエンド サービス、ファイアウォール ルールなどの Compute Engine リソースを一覧表示します。これらが一覧表示されない場合は、まだ作成されていない状態です。Console または gcloud コマンドを使用して、個々の Compute Engine リソースを調べ、そのステータスを取得できます。

    • VIP は、割り振られた IP アドレスをリストします。VIP が存在しても、ロードバランサがまだトラフィックを処理していない可能性があります。数分経っても VIP が表示されない場合や、10 分以内にロードバランサが 200 レスポンスを返さない場合は、トラブルシューティングとオペレーションをご覧ください。

    出力イベントが Normal の場合、MultiClusterIngress のデプロイが成功している可能性はありますが、完全なトラフィック パスが機能していることを判断する唯一の方法は、テストを行うことです。

  2. アプリケーションが /ping エンドポイントを使用して VIP で機能していることを確認します。

    curl INGRESS_VIP/ping
    

    INGRESS_VIP は、仮想 IP(VIP)アドレスに置き換えます。

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

    {
    "cluster_name": "gke-us",
    "host_header": "34.120.175.141",
    "pod_name": "whereami-deployment-954cbf78-mtlpf",
    "pod_name_emoji": "😎",
    "project_id": "my-project",
    "timestamp": "2021-11-29T17:01:59",
    "zone": "us-central1-b"
    }
    

    出力にアプリケーションのリージョンとバックエンドが表示されます。

  3. ブラウザで http://INGRESS_VIP の URL にアクセスして、アプリケーションへのサービス提供元のリージョンが表示された、グラフィカル バージョンのアプリケーションを確認できます。

    トラフィックの転送先のクラスタは、ロケーションによって異なります。GCLB は、クライアント トラフィックを、容量のある最も近いバックエンドに転送するように設計されています。

リソースの仕様

MultiClusterService の仕様

MultiClusterService 定義は次の 2 つで構成されます。

  1. Kubernetes クラスタで作成される Service を定義する template セクション。template セクションには一般的な Service でサポートされているフィールドがありますが、MultiClusterService でサポートされているフィールドは selectorports の 2 つのフィールドだけが存在します。他のフィールドは無視されます。

  2. 各クラスタでトラフィックを受信するクラスタを定義するセクションと、各クラスタの負荷分散プロパティを定義するセクションである、オプションの clusters セクション。clusters セクションが指定されていない場合、またはクラスタがリストされていない場合は、デフォルトですべてのクラスタが使用されます。

次のマニフェストは、標準の MultiClusterService を記述しています。

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      selector:
        app: POD_LABEL
      ports:
      - name: web
        protocol: TCP
        port: PORT
        targetPort: TARGET_PORT

以下を置き換えます。

  • NAME: MultiClusterService の名前。この名前は、MultiClusterIngress リソースの serviceName フィールドで参照されます。
  • NAMESPACE: MultiClusterService がデプロイされている Kubernetes Namespace。これは、フリート内のすべてのクラスタで、MultiClusterIngress および Pod と同じ Namespace にする必要があります。
  • POD_LABEL: フリート内のすべてのクラスタでこの MultiClusterService のバックエンドとして選択される Pod を決定するラベル。
  • PORT: この MultiClusterService を参照する MultiClusterIngress によって参照されるポートと一致する必要があります。
  • TARGET_PORT: GCLB から Pod にトラフィックを送信するために使用されるポート。このポートをサービスポートとして使用し、各クラスタに NEG が作成されます。

MultiClusterIngress の仕様

次の mci.yaml は、ロードバランサのフロントエンドを記述します。

apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      backend:
       serviceName: DEFAULT_SERVICE
       servicePort: PORT
      rules:
        - host: HOST_HEADER
          http:
            paths:
            - path: PATH
              backend:
                serviceName: SERVICE
                servicePort: PORT

以下を置き換えます。

  • NAME: MultiClusterIngress リソースの名前。
  • NAMESPACE: MultiClusterIngress がデプロイされている Kubernetes Namespace。これは、フリート内のすべてのクラスタで、MultiClusterService および Pod と同じ Namespace にする必要があります。
  • DEFAULT_SERVICE: ホストルールまたはパスルールに一致しないすべてのトラフィックのデフォルトのバックエンドとして機能します。これは必須フィールドであり、他のホストまたはパスの一致が構成されている場合でも、MultiClusterIngress でデフォルトのバックエンドを指定する必要があります。
  • PORT: 有効なポート番号。これは、MultiClusterService リソースの port フィールドと一致する必要があります。
  • HOST_HEADER: HTTP ホストヘッダー フィールドによってトラフィックを照合します。host フィールドは省略可能です。
  • PATH: HTTP URL のパスによってトラフィックを照合します。path フィールドは省略可能です。
  • SERVICE: この MultiClusterIngress と同じ Namespace と構成クラスタにデプロイされる MultiClusterService の名前です。

マルチクラスタ Ingress の機能

このセクションでは、マルチクラスタ Ingress のその他の機能を構成する方法について説明します。

クラスタの選択

デフォルトでは、マルチクラスタ Ingress から派生した Service は、すべてのメンバー クラスタでスケジュール設定されます。ただし、特定のクラスタに Ingress ルールを適用することもできます。ユースケースには、次のようなものがあります。

  • 構成クラスタを分離するために、構成クラスタを除くすべてのクラスタにマルチクラスタ Ingress を適用する。
  • クラスタ間でワークロードを青緑色に移行する。
  • クラスタのサブセットにのみ存在するアプリケーション バックエンドにルーティングする。
  • 異なるクラスタに存在するバックエンドへのホスト / パスのルーティングに単一の L7 VIP を使用する。

クラスタの選択では、MultiClusterService オブジェクト内のリージョン / 名前でクラスタを選択できます。これにより、MultiClusterIngress が指すクラスタと派生した Service がスケジュールされる場所を制御できます。クラスタを一意に参照できるように、同じフリートとリージョン内のクラスタで名前の重複が生じないようにします。

  1. mcs.yaml を開きます。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    

    この仕様では、デフォルトで現在すべてのクラスタで派生した Service が作成されています。

  2. クラスタ セクションに次の行を追加します。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
      clusters:
      - link: "us-central1-b/gke-us"
      - link: "europe-west1-b/gke-eu"
    

    この例では、gke-us クラスタと gke-eu クラスタでのみ派生した Service のリソースを作成します。Ingress ルールを個別に適用するには、クラスタを選択する必要があります。MultiClusterService の「クラスタ」セクションが指定されていない場合、またはクラスタが一覧表示されていない場合は、デフォルトで「すべて」のクラスタと解釈されます。

HTTPS サポート

Kubernetes Secret は HTTPS をサポートしています。HTTPS サポートを有効にする前に、静的 IP アドレスを作成する必要があります。この静的 IP では、HTTP と HTTPS で同じ IP アドレスを共有できます。詳細については、静的 IP の作成をご覧ください。

静的 IP アドレスを作成したら、Secret を作成できます。

  1. Secret を作成します。

    kubectl -n whereami create secret tls SECRET_NAME --key PATH_TO_KEYFILE --cert PATH_TO_CERTFILE
    

    次のように置き換えます。

    • SECRET_NAME は、Secret の名前に置き換えます。
    • PATH_TO_KEYFILE は、TLS 鍵ファイルのパスに置き換えます。
    • PATH_TO_CERTFILE は、TLS 証明書ファイルのパスで置き換えます。
  2. mci.yaml ファイルを Secret 名で更新します。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    

    SECRET_NAME は、Secret の名前に置き換えます。STATIC_IP_ADDRESS は、静的 IP の作成で割り振ったアドレスの IP アドレスまたは完全な URL です。

  3. MultiClusterIngress リソースを再デプロイします。

    kubectl apply -f mci.yaml
    

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

    multiclusteringress.networking.gke.io/whereami-ingress configured
    

BackendConfig のサポート

BackendConfig CRD では、Compute Engine の BackendService リソースの設定をカスタマイズできます。サポートされている仕様は次のとおりです。

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: whereami-health-check-cfg
  namespace: whereami
spec:
  healthCheck:
    checkIntervalSec: [int]
    timeoutSec: [int]
    healthyThreshold: [int]
    unhealthyThreshold: [int]
    type: [HTTP | HTTPS | HTTP2 | TCP]
    port: [int]
    requestPath: [string]
  timeoutSec: [int]
  connectionDraining:
    drainingTimeoutSec: [int]
  sessionAffinity:
    affinityType: [CLIENT_IP | CLIENT_IP_PORT_PROTO | CLIENT_IP_PROTO | GENERATED_COOKIE | HEADER_FIELD | HTTP_COOKIE | NONE]
    affinityCookieTtlSec: [int]
  cdn:
    enabled: [bool]
    cachePolicy:
      includeHost: [bool]
      includeQueryString: [bool]
      includeProtocol: [bool]
      queryStringBlacklist: [string list]
      queryStringWhitelist: [string list]
  securityPolicy:
    name: ca-how-to-security-policy
  logging:
    enable: [bool]
    sampleRate: [float]
  iap:
    enabled: [bool]
    oauthclientCredentials:
      secretName: [string]

BackendConfig を使用するには、アノテーションを使用して MultiClusterService リソースに接続します。

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: whereami-mcs
  namespace: whereami
  annotations:
    cloud.google.com/backend-config: '{"ports": {"8080":"whereami-health-check-cfg"}}'
spec:
 template:
   spec:
     selector:
       app: whereami
     ports:
     - name: web
       protocol: TCP
       port: 8080
       targetPort: 8080

BackendConfig セマンティクスの詳細については、Service ポートと BackendConfig の関連付けをご覧ください。

gRPC のサポート

マルチクラスタ Ingress で gRPC アプリケーションを構成するには、かなり詳細な設定を行う必要があります。ロードバランサを適切に構成するには、次のヒントを参考にしてください。

  1. ロードバランサからアプリケーションへのトラフィックが HTTP/2 であることを確認します。これは、アプリケーション プロトコルを使用して構成します。
  2. アプリケーションが SSL 用に正しく構成されていることを確認します。これは、HTTP/2 の要件です。なお、自己署名証明書も使用できます。
  3. L7 外部ロードバランサでは mTLS がサポートされていないため、アプリケーションで mTLS をオフにする必要があります。

リソースのライフサイクル

構成の変更

MultiClusterIngress リソースと MultiClusterService リソースは標準の Kubernetes オブジェクトとして動作するため、オブジェクトへの変更は非同期でシステムに反映されます。変更が無効な構成になった場合、関連付けられた Google Cloud オブジェクトは変更されず、オブジェクトのイベント ストリームでエラーが発生します。構成に関連付けられたエラーは、イベントとして報告されます。

Kubernetes リソースの管理

Ingress オブジェクトを削除すると、HTTP(S) ロードバランサが破棄され、トラフィックは定義済みのどの MultiClusterService にも転送されなくなります。

MultiClusterService を削除すると、各クラスタ内の関連する派生サービスが削除されます。

クラスタの管理

ロードバランサの対象となるクラスタのセットは、フリートでクラスタを追加または削除することで変更できます。

たとえば、gke-eu クラスタを Ingress のバックエンドとして削除するには、次のコマンドを実行します。

gcloud container fleet memberships unregister CLUSTER_NAME \
  --gke-uri=URI

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • URI: GKE クラスタの URI。

ヨーロッパのクラスタを追加するには、次のコマンドを実行します。

gcloud container fleet memberships register europe-cluster \
  --context=europe-cluster --enable-workload-identity

クラスタ登録オプションの詳細については、GKE クラスタの登録をご覧ください。

クラスタの登録または登録解除を行うと、すべての Ingress のバックエンドとしてのステータスが変更されることにご注意ください。上記の場合、gke-eu クラスタを登録解除すると、作成したすべての Ingress の利用可能なバックエンドとして削除されます。新しいクラスタを登録する場合は、その逆です。

マルチクラスタ Ingress の無効化

マルチクラスタ Ingress を無効にする前に、まず MultiClusterIngress リソースと MultiClusterService リソースを削除し、関連付けられたネットワーキング リソースが削除されたことを確認する必要があります。

マルチクラスタ Ingress を無効にするには、次のコマンドを使用します。

gcloud container fleet ingress disable

マルチクラスタ Ingress を無効にする前に MultiClusterIngress リソースと MultiClusterService リソースを削除しないと、次のようなエラーが発生することがあります。

Feature has associated resources that should be cleaned up before deletion.

マルチクラスタ Ingress を強制的に無効にするには、次のコマンドを使用します。

gcloud container fleet ingress disable --force

アノテーション

MultiClusterIngress リソースと MultiClusterService リソースでは、次のアノテーションがサポートされています。

MultiClusterIngress アノテーション

アノテーション 説明
networking.gke.io/frontend-config MultiClusterIngress リソースと同じ Namespace 内の FrontendConfig リソースを参照します。
networking.gke.io/static-ip グローバル静的 IP のリテラル IP アドレスを指します。
networking.gke.io/pre-shared-certs グローバル SSLCertificate リソースを参照します。

MultiClusterService アノテーション

アノテーション 説明
networking.gke.io/app-protocols このアノテーションを使用して、ロードバランサとアプリケーション間の通信用のプロトコルを設定します。有効なプロトコルは HTTP、HTTPS、HTTP/2 です。ロードバランサとアプリケーション間の HTTPSIngress による HTTP/2 を使用したロードバランサをご覧ください。
cloud.google.com/backend-config このアノテーションを使用して、servicePort に関連付けられるバックエンド サービスを構成します。詳細については、Ingress の機能をご覧ください。

SSL ポリシーと HTTPS リダイレクト

FrontendConfig リソースを使用して、SSL ポリシーと HTTPS リダイレクトを構成できます。SSL ポリシーを使用すると、ロードバランサが受け入れる暗号スイートと TLS バージョンを指定できます。HTTPS リダイレクトを使用すると、HTTP/ポート 80 から HTTPS/ポート 443 へのリダイレクトを強制できます。次の手順では、SSL ポリシーと HTTPS リダイレクトを一緒に構成します。これらは個別に構成することもできます。

  1. TLS v1.2 より前のバージョンを使用するリクエストを拒否する SSL ポリシーを作成します。

    gcloud compute ssl-policies create tls-12-policy \
     --profile MODERN \
     --min-tls-version 1.2 \
     --project=PROJECT_ID
    

    PROJECT_ID は、GKE クラスタが実行されているプロジェクト ID に置き換えます。

  2. ポリシーを表示してポリシーが作成されていることを確認します。

    gcloud compute ssl-policies list --project=PROJECT_ID
    

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

    NAME           PROFILE  MIN_TLS_VERSION
    tls-12-policy  MODERN   TLS_1_2
    
  3. このサンプルのように、foo.example.com の証明書を作成します。key.pemcert.pem を取得したら、これらの認証情報を MultiClusterIngress リソースによって参照される Secret として保存します。

    kubectl -n whereami create secret tls SECRET_NAME --key key.pem --cert cert.pem
    
  4. 次の FrontendConfig リソースを frontendconfig.yaml として保存します。FrontendConfig でサポートされるフィールドの詳細については、FrontendConfig リソースの構成をご覧ください。

    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: frontend-redirect-tls-policy
      namespace: whereami
    spec:
      sslPolicy: tls-12-policy
      redirectToHttps:
        enabled: true
    

    この FrontendConfig により、HTTPS リダイレクトと、最小 TLS バージョン 1.2 を適用する SSL ポリシーが有効になります。

  5. frontendconfig.yaml を構成クラスタにデプロイします。

    kubectl apply -f frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    

    MCI_CONFIG_CLUSTER は、構成クラスタの名前に置き換えます。

  6. 次の MultiClusterIngress を mci-frontendconfig.yaml として保存します。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: foo-ingress
      namespace: whereami
      annotations:
        networking.gke.io/frontend-config: frontend-redirect-tls-policy
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: default-backend
            servicePort: 8080
          rules:
          - host: foo.example.com
            http:
              paths:
                - backend:
                    serviceName: whereami-mcs
                    servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    
    • STATIC_IP_ADDRESS は、すでにプロビジョニングされている静的グローバル IP アドレスに置き換えます。
    • SECRET_NAME は、foo.example.com 証明書が保存されている Secret に置き換えます。

    HTTPS リダイレクトを有効にする場合、次の 2 つの要件を満たす必要があります。

    • TLS は、spec.tls フィールドまたは事前共有証明書アノテーション networking.gke.io/pre-shared-certs を使用して有効にする必要があります。HTTPS リダイレクトが有効になっていても、HTTPS が有効でないと、MultiClusterIngress はデプロイされません。
    • 静的 IP は networking.gke.io/static-ip アノテーションを介して参照する必要があります。MultiClusterIngress で HTTPS を有効にする場合は、静的 IP が必要です。
  7. MultiClusterIngress を構成クラスタにデプロイします。

    kubectl apply -f mci-frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    
  8. 1~2 分待ってから foo-ingress を調べます。

    kubectl describe mci foo-ingress --context MCI_CONFIG_CLUSTER
    

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

    • Cloud Resources ステータスにリソース名が示されます。
    • VIP フィールドに、ロードバランサの IP アドレスが示されます。
    Name:         foobar-ingress
    Namespace:    whereami
    
    ...
    
    Status:
      Cloud Resources:
        Backend Services:
          mci-otn9zt-8080-whereami-bar
          mci-otn9zt-8080-whereami-default-backend
          mci-otn9zt-8080-whereami-foo
        Firewalls:
          mci-otn9zt-default-l7
        Forwarding Rules:
          mci-otn9zt-fw-whereami-foobar-ingress
          mci-otn9zt-fws-whereami-foobar-ingress
        Health Checks:
          mci-otn9zt-8080-whereami-bar
          mci-otn9zt-8080-whereami-default-backend
          mci-otn9zt-8080-whereami-foo
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluste-mci-default-backend-svc--80-9e362e3d
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-bar-svc-067a3lzs8-808-89846515
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-foo-svc-820zw3izx-808-8bbcb1de
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluste-mci-default-backend-svc--80-a528cc75
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-bar-svc-067a3lzs8-808-36281739
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-foo-svc-820zw3izx-808-ac733579
        Target Proxies:
          mci-otn9zt-whereami-foobar-ingress
          mci-otn9zt-whereami-foobar-ingress
        URL Map:  mci-otn9zt-rm-whereami-foobar-ingress
      VIP:        34.149.29.76
    Events:
      Type     Reason  Age                From                              Message
      ----     ------  ----               ----                              -------
      Normal   UPDATE  38m (x5 over 62m)  multi-cluster-ingress-controller  whereami/foobar-ingress
    
  9. HTTP リクエストを curl 経由で送信して、HTTPS リダイレクトが正しく機能することを確認します。

    curl VIP
    

    VIP は、MultiClusterIngress の IP アドレスに置き換えます。

    出力には、リクエストが HTTPS ポートにリダイレクトされていることが示されます。これは、リダイレクトが正しく機能していることを示します。

  10. TLS バージョン 1.1 を使用して HTTPS リクエストを送信し、TLS ポリシーが正しく機能することを確認します。このドメインに DNS は構成されていないため、--resolve オプションを使用して curl に IP アドレスを直接解決するように指示します。

    curl https://foo.example.com --resolve foo.example.com:443:VIP --cacert CERT_FILE -v
    

    この手順では、MultiClusterIngress の保護に使用する証明書 PEM ファイルが必要です。正常な出力は次のようになります。

    ...
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=foo.example.com
    *  start date: Sep  1 10:32:03 2021 GMT
    *  expire date: Aug 27 10:32:03 2022 GMT
    *  common name: foo.example.com (matched)
    *  issuer: O=example; CN=foo.example.com
    *  SSL certificate verify ok.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x7fa10f00e400)
    > GET / HTTP/2
    > Host: foo.example.com
    > User-Agent: curl/7.64.1
    > Accept: */*
    >
    * Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
    < HTTP/2 200
    < content-type: application/json
    < content-length: 308
    < access-control-allow-origin: *
    < server: Werkzeug/1.0.1 Python/3.8.6
    < date: Wed, 01 Sep 2021 11:39:06 GMT
    < via: 1.1 google
    < alt-svc: clear
    <
    {"cluster_name":"gke-us","host_header":"foo.example.com","metadata":"foo","node_name":"gke-gke-us-default-pool-22cb07b1-r5r0.c.mark-church-project.internal","pod_name":"foo-75ccd9c96d-dkg8t","pod_name_emoji":"👞","project_id":"mark-church-project","timestamp":"2021-09-01T11:39:06","zone":"us-central1-b"}
    * Connection #0 to host foo.example.com left intact
    * Closing connection 0
    

    レスポンス コードは 200 で、TLSv1.2 が使用されています。これは、すべてが正常に機能していることを示します。

    次に、TLS 1.1 への接続を試行して、SSL ポリシーが正しい TLS バージョンを適用していることを確認します。このステップを行うには、SSL ポリシーが 1.2 以降のバージョンになるように構成されている必要があります。

  11. 前のステップと同じリクエストを送信しますが、今回は TLS バージョン 1.1 を適用します。

    curl https://foo.example.com --resolve foo.example.com:443:VIP -v \
      --cacert CERT_FILE \
      --tls-max 1.1
    

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

    * Added foo.example.com:443:34.149.29.76 to DNS cache
    * Hostname foo.example.com was found in DNS cache
    *   Trying 34.149.29.76...
    * TCP_NODELAY set
    * Connected to foo.example.com (34.149.29.76) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: cert.pem
      CApath: none
    * TLSv1.1 (OUT), TLS handshake, Client hello (1):
    * TLSv1.1 (IN), TLS alert, protocol version (582):
    * error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    * Closing connection 0
    curl: (35) error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    

    TLS handshake が失敗していれば、SSL ポリシーが TLS 1.1 を正常にブロックしています。

静的 IP の作成

  1. 静的 IP を割り振ります。

    gcloud compute addresses create ADDRESS_NAME --global
    

    ADDRESS_NAME は、割り振る静的 IP の名前に置き換えます。

    次のように、作成したアドレスの完全な URL が出力に表示されます。

    Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME].
    
  2. 作成したばかりの IP アドレスを確認します。

    gcloud compute addresses list
    

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

    NAME          ADDRESS/RANGE  TYPE      STATUS
    ADDRESS_NAME  STATIC_IP_ADDRESS  EXTERNAL  RESERVED
    

    この出力に含まれる情報:

    • 定義した ADDRESS_NAME
    • 割り振られた STATIC_IP_ADDRESS
  3. mci.yaml ファイルを静的 IP で更新します。

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
    

    STATIC_IP_ADDRESS は、次のいずれかに置き換えます。

    • 割り振られた IP アドレス。例: 34.102.201.47
    • 作成したアドレスの完全な URL。例: "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME"

    STATIC_IP_ADDRESS は、リソース名(ADDRESS_NAME)ではありません。

  4. MultiClusterIngress リソースを再デプロイします。

    kubectl apply -f mci.yaml
    

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

    multiclusteringress.networking.gke.io/whereami-ingress configured
    
  5. デプロイの成功ステータスを検証するの手順を行い、STATIC_IP_ADDRESS でデプロイが実行されていることを確認します。

事前共有証明書

事前共有証明書は、Kubernetes Secret に保存されている証明書ではなく、Google Cloud にアップロードされる証明書で、ロードバランサが TLS 終端に使用します。これらの証明書は GKE から Google Cloud に帯域外でアップロードされ、MultiClusterIngress リソースで参照されます。事前共有証明書または Kubernetes Secret を介した複数の証明書もサポートされています。

マルチクラスタ Ingress で証明書を使用するには、networking.gke.io/pre-shared-certs アノテーションと証明書の名前が必要です。特定の MultiClusterIngress に複数の証明書が指定されている場合、証明書は事前定義された順序でクライアントに提示されます。

次のコマンドを実行して、使用可能な SSL 証明書を一覧表示できます。

gcloud compute ssl-certificates list

次の例では、事前共有証明書の共通名と一致する特定のホストへのクライアント トラフィックを記述することで、ドメイン名と一致する証明書が提示されます。

kind: MultiClusterIngress
metadata:
  name: shopping-service
  namespace: whereami
  annotations:
    networking.gke.io/pre-shared-certs: "domain1-cert, domain2-cert"
spec:
  template:
    spec:
      rules:
      - host: my-domain1.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain1-svc
              servicePort: 443
      - host: my-domain2.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain2-svc
              servicePort: 443

Google マネージド証明書

Google マネージド証明書は、networking.gke.io/pre-shared-certs アノテーションによって MultiClusterIngress リソースでサポートされます。マルチクラスタ Ingress は、MultiClusterIngress リソースへの Google マネージド証明書の適用をサポートしていますが、単一クラスタ Ingress とは異なり、MultiClusterIngress リソースでは Kubernetes ManagedCertificate リソースの宣言型生成はサポートされていません。元の Google マネージド証明書は、MultiClusterIngress に接続する前に、compute ssl-certificates create API を使用して直接作成する必要があります。手順は次のとおりです。

  1. この手順のステップ 1 で Google マネージド証明書を作成します。証明書はマルチクラスタ Ingress によって適用されるため、ステップ 2 に進まないでください。

    gcloud compute ssl-certificates create my-google-managed-cert \
        --domains=my-domain.gcp.com \
        --global
    
  2. networking.gke.io/pre-shared-certs アノテーションを使用して、MultiClusterIngress 内の証明書の名前を参照します。

    kind: MultiClusterIngress
    metadata:
    name: shopping-service
    namespace: whereami
    annotations:
      networking.gke.io/pre-shared-certs: "my-google-managed-cert"
    spec:
    template:
      spec:
        rules:
        - host: my-domain.gcp.com
          http:
            paths:
            - backend:
                serviceName: my-domain-svc
                servicePort: 8080
    

上記のマニフェストで証明書が MultiClusterIngress にアタッチされ、バックエンド GKE クラスタのトラフィックを終了できます。証明書が期限切れになる前に、Google Cloud によって証明書が自動更新されます。更新は透過的に行われます。マルチクラスタ Ingress を更新する必要はありません。

アプリケーション プロトコル

デフォルトでは、ロードバランサ プロキシからアプリケーションへの接続は HTTP 経由で行われます。networking.gke.io/app-protocols アノテーションを使用して、ロードバランサがリクエストをアプリケーションに転送するときに HTTPS または HTTP/2 を使用するようにロードバランサを構成できます。次の例の annotation フィールドで、http2MultiClusterService ポート名、HTTP2 はロードバランサが使用するプロトコルを表します。

kind: MultiClusterService
metadata:
  name: shopping-service
  namespace: whereami
  annotations:
    networking.gke.io/app-protocols: '{"http2":"HTTP2"}'
spec:
  template:
    spec:
      ports:
      - port: 443
        name: http2

BackendConfig

アノテーションの構成方法については、上記のセクションをご覧ください。

次のステップ