高可用性コンテナ アプリケーションをデプロイする

このページでは、Google Distributed Cloud(GDC)のエアギャップで堅牢で高可用性(HA)の Kubernetes コンテナ アプリケーションを構築するための推奨されるデプロイ戦略について説明します。コンテナ アプリケーションを複数の GDC ゾーンにデプロイし、非同期ストレージ レプリケーションを構成して、予期しないダウンタイムやローカル災害が発生した場合にアプリケーションとそのデータを復元できるようにする必要があります。

このページは、組織のアプリケーション ワークロードの作成を担当するアプリケーション オペレーター グループ内のデベロッパーを対象としています。詳細については、GDC エアギャップの対象読者に関するドキュメントをご覧ください。

目標

  • GDC ユニバースの 2 つ以上のゾーンに Kubernetes クラスタを作成します。
  • グローバル ロード バランシングを構成します。
  • コンテナ ワークロードを各ゾーン Kubernetes クラスタにデプロイします。
  • ストレージをプロビジョニングして Pod に接続します。
  • ブロック ストレージまたはオブジェクト ストレージを使用して、非同期ストレージ レプリケーションを構成します。

始める前に

  • 複数のゾーンが使用可能な GDC ユニバースで作業していることを確認します。gdcloud zones list を実行して、ユニバースで使用可能なゾーンを一覧表示します。詳細については、ユニバース内のゾーンを一覧表示するをご覧ください。

  • 組織の IAM 管理者に次のロールの付与を依頼します。

    • コンテナ ワークロードを作成して管理する名前空間管理者(namespace-admin)ロール。

    • Kubernetes クラスタとそのノードプールを作成して管理するためのユーザー クラスタ管理者(user-cluster-admin)ロールとユーザー クラスタ デベロッパー(user-cluster-developer)ロール。

    • ロードバランサ管理者(load-balancer-admin)とグローバル ロードバランサ管理者(global-load-balancer-admin)のロール。ロードバランサを作成して管理するには、これらのロールが必要です。

    • ボリューム レプリケーション グローバル管理者ロール(app-volume-replication-admin-global)。ボリューム レプリケーションを管理するには、このロールが必要です。

    • ゾーン間でプロジェクト ネットワーク ポリシーを作成して管理するグローバル PNP 管理者(global-project-networkpolicy-admin)ロール。

    • Harbor インスタンス管理者(harbor-instance-admin)、Harbor インスタンス閲覧者(harbor-instance-viewer)、Harbor プロジェクト作成者(harbor-project-creator)のロール。これらのロールは、アーティファクト レジストリでコンテナ イメージを作成して管理するために必要です。

    • ブロック ストレージ リソースのボリューム レプリケーション関係を管理するボリューム レプリケーション グローバル管理者(app-volume-replication-admin-global)ロール。

    • ストレージ バケットを作成して管理するためのプロジェクト バケット オブジェクト管理者(project-bucket-object-admin)ロールとプロジェクト バケット管理者(project-bucket-admin)ロール。

    詳細については、ロールの説明をご覧ください。

  • gdcloud CLI をインストールして構成し、ゾーン コンテキストとグローバル コンテキストを構成します。詳細については、ゾーン間のリソースを管理するをご覧ください。

  • kubectl CLI をインストールして構成します。グローバル API サーバー、管理 API サーバー、Kubernetes クラスタに適切な kubeconfig ファイルを設定します。詳細については、kubeconfig ファイルを手動で生成するをご覧ください。

複数のゾーンに Kubernetes クラスタを作成する

Kubernetes クラスタはゾーンリソースであるため、各ゾーンにクラスタを個別に作成する必要があります。

コンソール

  1. ナビゲーション メニューで、[Kubernetes Engine] > [クラスタ] を選択します。

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

  3. [名前] フィールドに、クラスタの名前を指定します。

  4. クラスタの Kubernetes バージョンを選択します。

  5. クラスタを作成するゾーンを選択します。

  6. [プロジェクトを接続] をクリックし、既存のプロジェクトを選択してクラスタに接続します。オンにして [保存] をクリックします。クラスタの作成後に、[プロジェクトの詳細] ページでプロジェクトを関連付けたり、関連付けを解除したりできます。コンテナ ワークロードをデプロイする前に、クラスタにプロジェクトを関連付ける必要があります。

  7. [次へ] をクリックします。

  8. クラスタのネットワーク設定を構成します。クラスタの作成後にこれらのネットワーク設定を変更することはできません。Kubernetes クラスタでサポートされているデフォルトのインターネット プロトコルは、インターネット プロトコル バージョン 4(IPv4)のみです。

    1. ロードバランサの IP アドレス プールのサイズ(20 など)を指定します。

    2. 使用するサービス CIDR(クラスレス ドメイン間ルーティング)を選択します。ロードバランサなどのデプロイされたサービスには、この範囲から IP アドレスが割り当てられます。

    3. 使用する Pod CIDR を選択します。クラスタは、この範囲から Pod と VM に IP アドレスを割り当てます。

    4. [次へ] をクリックします。

  9. クラスタ用に自動生成されたデフォルトのノードプールの詳細を確認します。 [編集] をクリックして、デフォルトのノードプールを変更します。

  10. 追加のノードプールを作成するには、[ノードプールを追加] を選択します。デフォルトのノードプールを編集するときや、新しいノードプールを追加するときに、次のオプションを使用してカスタマイズします。

    1. ノードプールに名前を割り当てます。ノードプールの作成後に名前を変更することはできません。
    2. ノードプール内に作成するワーカーノードの数を指定します。
    3. ワークロードの要件に最も適したマシンクラスを選択します。次の設定のリストを表示します。

      • マシンタイプ
      • CPU
      • メモリ
    4. [保存] をクリックします。

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

  11. GDC ユニバース内の各ゾーンに対して、上記の手順を繰り返します。HA 戦略で必要なすべてのゾーンに Kubernetes クラスタが存在することを確認します。

API

API を直接使用して新しい Kubernetes クラスタを作成するには、各 GDC ゾーンにカスタム リソースを適用します。

  1. Cluster カスタム リソースを作成し、ゾーンの Management API サーバーにデプロイします。

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF \
    apiVersion: cluster.gdc.goog/v1
    kind: Cluster
    metadata:
      name: CLUSTER_NAME
      namespace: platform
    spec:
      clusterNetwork:
        podCIDRSize: POD_CIDR
        serviceCIDRSize: SERVICE_CIDR
      initialVersion:
        kubernetesVersion: KUBERNETES_VERSION
      loadBalancer:
        ingressServiceIPSize: LOAD_BALANCER_POOL_SIZE
      nodePools:
      - machineTypeName: MACHINE_TYPE
        name: NODE_POOL_NAME
        nodeCount: NUMBER_OF_WORKER_NODES
        taints: TAINTS
        labels: LABELS
        acceleratorOptions:
          gpuPartitionScheme: GPU_PARTITION_SCHEME
      releaseChannel:
        channel: UNSPECIFIED
    EOF
    

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

    • MANAGEMENT_API_SERVER: ゾーン Management API サーバーの kubeconfig パス。詳細については、ゾーン コンテキストに切り替えるをご覧ください。
    • CLUSTER_NAME: クラスタの名前。クラスタ名の末尾を -system にすることはできません。-system 接尾辞は、GDC によって作成されたクラスタ用に予約されています。
    • POD_CIDR: Pod の仮想 IP アドレス(VIP)が割り当てられるネットワーク範囲のサイズ。設定しない場合、デフォルト値の 21 が使用されます。
    • SERVICE_CIDR: サービス VIP が割り当てられるネットワーク範囲のサイズ。設定されていない場合、デフォルト値の 23 が使用されます。
    • KUBERNETES_VERSION: クラスタの Kubernetes バージョン(1.26.5-gke.2100 など)。構成可能な Kubernetes バージョンを一覧表示するには、クラスタで使用可能な Kubernetes バージョンを一覧表示するをご覧ください。
    • LOAD_BALANCER_POOL_SIZE: ロードバランサ サービスで使用される重複しない IP アドレスプールのサイズ。設定されていない場合、デフォルト値の 20 が使用されます。
    • MACHINE_TYPE: ノードプールのワーカーノードのマシンタイプ。構成可能な内容については、使用可能なマシンタイプをご覧ください。
    • NODE_POOL_NAME: ノードプールの名前。
    • NUMBER_OF_WORKER_NODES: ノードプールにプロビジョニングするワーカーノードの数。
    • TAINTS: このノードプールのノードに適用する taint。このフィールドは省略できます。
    • LABELS: このノードプールのノードに適用するラベル。Key-Value ペアのリストが含まれています。このフィールドは省略可能です。
    • GPU_PARTITION_SCHEME: GPU ワークロード(mixed-2 など)を実行している場合の GPU パーティショニング スキーム。このフィールドが設定されていない場合、GPU はパーティショニングされません。利用可能なマルチインスタンス GPU(MIG)プロファイルについては、サポートされている MIG プロファイルをご覧ください。
  2. HA 戦略でコンテナ アプリケーションをホストするゾーンごとに、前の手順を繰り返します。

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

異なるゾーンの Pod 間でトラフィックを分散するには、ロードバランサを作成します。外部ロードバランサ(ELB)と内部ロードバランサ(ILB)を作成できます。どちらもゾーンまたはグローバルに構成できます。この例では、コンテナ アプリケーションのグローバル ILB とグローバル ELB を構成します。

グローバル内部ロードバランサを作成する

内部ロードバランサ(ILB)は、組織に割り当てられた内部 IP アドレス プールから組織内のサービスを公開します。ILB サービスには、組織外のエンドポイントからアクセスできません。

コンテナ ワークロードのグローバル ILB を作成するには、次の操作を行います。

gdcloud

gdcloud CLI を使用して、Pod ワークロードをターゲットとする ILB を作成します。

この ILB は、Backend オブジェクトで定義されたラベルに一致するプロジェクト内のすべてのワークロードをターゲットにします。Backend カスタム リソースは、ゾーンにスコープ設定する必要があります。

gcloud CLI を使用して ILB を作成するには、次の操作を行います。

  1. ポッドが実行されている各ゾーンにゾーン Backend リソースを作成して、ILB のエンドポイントを定義します。

    gdcloud compute backends create BACKEND_NAME \
        --labels=LABELS \
        --project=PROJECT \
        --cluster=CLUSTER_NAME \
        --zone=ZONE
    

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

    • BACKEND_NAME: バックエンド リソースに選択した名前(my-backend など)。
    • LABELS: このバックエンド リソースに使用する Pod 間のエンドポイントを定義するセレクタ(app=web など)。
    • PROJECT: プロジェクトの名前。
    • CLUSTER_NAME: 定義されたセレクタのスコープが制限される Kubernetes クラスタ。このフィールドが指定されていない場合、指定されたラベルを持つすべてのエンドポイントが選択されます。このフィールドは省略可能です。
    • ZONE: この呼び出しに使用するゾーン。ゾーンフラグを必要とするすべてのコマンドに対してゾーンフラグをプリセットするには、gdcloud config set core/zone ZONE を実行します。ゾーンフラグは、マルチゾーン環境でのみ使用できます。このフィールドは省略可能です。

    この手順を GDC ユニバースの各ゾーンで繰り返します。

  2. グローバル BackendService リソースを作成します。

    gdcloud compute backend-services create BACKEND_SERVICE_NAME \
        --project=PROJECT \
        --target-ports=TARGET_PORTS \
        --global
    

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

    • BACKEND_SERVICE_NAME: バックエンド サービスの名前。
    • PROJECT: プロジェクトの名前。
    • TARGET_PORTS: このバックエンド サービスが変換するターゲット ポートのカンマ区切りリスト。各ターゲット ポートは、プロトコル、転送ルールのポート、バックエンド インスタンスのポートを指定します。複数のターゲット ポートを指定できます。このフィールドは protocol:port:targetport 形式(TCP:80:8080 など)にする必要があります。このフィールドは省略可能です。
  3. 各ゾーンで、前に作成した Backend リソースに BackendService リソースを追加します。

    gdcloud compute backend-services add-backend BACKEND_SERVICE_NAME \
        --backend-zone=ZONE \
        --backend=BACKEND_NAME \
        --project=PROJECT \
        --global
    

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

    • BACKEND_SERVICE_NAME: グローバル バックエンド サービスの名前。
    • ZONE: バックエンドのゾーン。
    • BACKEND_NAME: ゾーン バックエンドの名前。
    • PROJECT: プロジェクトの名前。

    この手順は、以前に作成したゾーン バックエンドごとに行います。

  4. サービスが利用可能な仮想 IP アドレス(VIP)を定義する内部 ForwardingRule リソースを作成します。

    gdcloud compute forwarding-rules create FORWARDING_RULE_INTERNAL_NAME \
        --backend-service=BACKEND_SERVICE_NAME \
        --cidr=CIDR \
        --ip-protocol-port=PROTOCOL_PORT \
        --load-balancing-scheme=INTERNAL \
        --project=PROJECT \
        --global
    

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

    • FORWARDING_RULE_INTERNAL_NAME: 転送ルールの名前。
    • CIDR: 転送ルールで使用する CIDR。このフィールドは省略可能です。指定しない場合、IPv4/32 CIDR はグローバル IP アドレス プールから自動的に予約されます。この転送ルールと同じ Namespace 内の Subnet リソースの名前を指定します。Subnet リソースは、グローバル サブネットのリクエストと割り当て情報を表します。Subnet リソースの詳細については、サブネットを管理するをご覧ください。
    • PROTOCOL_PORT: 転送ルールで公開するプロトコルとポート。このフィールドは ip-protocol=TCP:80 の形式にする必要があります。公開されるポートは、実際のアプリケーションがコンテナ内で公開しているポートと同じである必要があります。
  5. 構成された ILB を検証するには、作成された各オブジェクトの Ready 条件を確認します。VIP への curl リクエストでトラフィックを確認します。

    1. 割り当てられた VIP を取得するには、転送ルールを説明します。

      gdcloud compute forwarding-rules describe FORWARDING_RULE_INTERNAL_NAME --global
      
    2. 転送ルールのフィールドで指定されたポートの VIP に curl リクエストを送信して、トラフィックを確認します。

      curl http://FORWARDING_RULE_VIP:PORT
      

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

    • FORWARDING_RULE_VIP: 転送ルールの VIP。
    • PORT: 転送ルールのポート番号。

API

KRM API を使用して、コンテナ ワークロードをターゲットとする ILB を作成します。この ILB は、Backend オブジェクトで定義されたラベルに一致するプロジェクト内のすべてのワークロードをターゲットにします。KRM API を使用してグローバル ILB を作成する手順は次のとおりです。

  1. Backend リソースを作成して、ILB のエンドポイントを定義します。コンテナ ワークロードが配置されているゾーンごとに Backend リソースを作成します。

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
    apiVersion: networking.gdc.goog/v1
    kind: Backend
    metadata:
      namespace: PROJECT
      name: BACKEND_NAME
    spec:
      clusterName: CLUSTER_NAME
      endpointsLabels:
        matchLabels:
          app: APP_NAME
    EOF
    

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

    • MANAGEMENT_API_SERVER: ゾーン Management API サーバーの kubeconfig パス。詳細については、ゾーン コンテキストに切り替えるをご覧ください。
    • PROJECT: プロジェクトの名前。
    • BACKEND_NAME: Backend リソースの名前。
    • CLUSTER_NAME: 定義されたセレクタのスコープが制限される Kubernetes クラスタ。このフィールドが指定されていない場合、指定されたラベルを持つすべてのエンドポイントが選択されます。このフィールドは省略可能です。
    • APP_NAME: コンテナ アプリケーションの名前。

    各ゾーンに同じ Backend リソースを使用することも、各ゾーンに異なるラベルセットを持つ Backend リソースを作成することもできます。

  2. 前に作成した Backend リソースを使用して BackendService オブジェクトを作成します。HealthCheck リソースを含めてください。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: BackendService
    metadata:
      namespace: PROJECT
      name: BACKEND_SERVICE_NAME
    spec:
      backendRefs:
      - name: BACKEND_NAME
        zone: ZONE
      healthCheckName: HEALTH_CHECK_NAME
      targetPorts:
      - port: PORT
        protocol: PROTOCOL
        targetPort: TARGET_PORT
    EOF
    

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

    • GLOBAL_API_SERVER: グローバル API サーバーの kubeconfig パス。
    • PROJECT: プロジェクトの名前。
    • BACKEND_SERVICE_NAME: BackendService リソースに選択した名前。
    • HEALTH_CHECK_NAME: 以前に作成した HealthCheck リソースの名前。
    • BACKEND_NAME: ゾーン Backend リソースの名前。
    • ZONE: Backend リソースが存在するゾーン。backendRefs フィールドで複数のバックエンドを指定できます。次に例を示します。

      - name: my-backend-1
        zone: us-east1-a
      - name: my-backend-2
        zone: us-east1-b
      

      targetPorts フィールドは省略可能です。このリソースは、この BackendService リソースが変換するポートを一覧表示します。このオブジェクトを使用する場合は、次の値を指定します。

    • PORT: サービスによって公開されるポート。

    • PROTOCOL: トラフィックが一致する必要があるレイヤ 4 プロトコル。TCP と UDP のみがサポートされます。

    • TARGET_PORT: 値の変換先となるポート(8080 など)。値は、特定のオブジェクト内で繰り返すことはできません。

      targetPorts の例を次に示します。

      targetPorts:
        - port: 80
          protocol: TCP
          targetPort: 8080
      
  3. サービスが利用可能な仮想 IP アドレス(VIP)を定義する内部 ForwardingRule リソースを作成します。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ForwardingRuleInternal
    metadata:
      namespace: PROJECT
      name: FORWARDING_RULE_INTERNAL_NAME
    spec:
      cidrRef: CIDR
      ports:
      - port: PORT
        protocol: PROTOCOL
      backendServiceRef:
        name: BACKEND_SERVICE_NAME
    EOF
    

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

    • GLOBAL_API_SERVER: グローバル API サーバーの kubeconfig パス。
    • PROJECT: プロジェクトの名前。
    • FORWARDING_RULE_INTERNAL_NAME: ForwardingRuleInternal リソースに選択した名前。
    • CIDR: 転送ルールに使用する CIDR。このフィールドは省略可能です。指定しない場合、IPv4/32 CIDR はグローバル IP アドレス プールから自動的に予約されます。この転送ルールと同じ Namespace 内の Subnet リソースの名前を指定します。Subnet リソースは、グローバル サブネットのリクエストと割り当て情報を表します。Subnet リソースの詳細については、サブネットを管理するをご覧ください。
    • PORT: 転送ルールで公開するポート。ports フィールドを使用して、この転送ルールで構成されたバックエンドにパケットが転送される L4 ポートの配列を指定します。少なくとも 1 つのポートを指定する必要があります。port フィールドを使用して、ポート番号を指定します。公開されるポートは、実際のアプリケーションがコンテナ内で公開しているポートと同じである必要があります。
    • PROTOCOL: 転送ルールに使用するプロトコル(TCP など)。ports 配列のエントリは次のようになります。

      ports:
      - port: 80
        protocol: TCP
      
  4. 構成された ILB を検証するには、作成された各オブジェクトの Ready 条件を確認します。VIP への curl リクエストでトラフィックを確認します。

    1. VIP を取得します。

      kubectl get forwardingruleinternal -n PROJECT
      

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

      NAME           BACKENDSERVICE                  CIDR              READY
      ilb-name       BACKEND_SERVICE_NAME            192.0.2.0/32      True
      
    2. 転送ルールのフィールドで指定されたポートの VIP に curl リクエストを送信して、トラフィックをテストします。

      curl http://FORWARDING_RULE_VIP:PORT
      

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

      • FORWARDING_RULE_VIP: 転送ルールの VIP。
      • PORT: 転送ルールのフィールドのポート番号。

グローバル外部ロードバランサを作成する

外部ロードバランサ(ELB)は、組織に割り当てられたプール IP アドレスから、組織外からのアクセス用にサービスを公開します。このプール IP アドレスは、より大きなインスタンス外部 IP アドレス プールから割り当てられます。

コンテナ ワークロードのグローバル ELB を作成するには、次の操作を行います。

gdcloud

gdcloud CLI を使用して、Backend オブジェクトで定義されたラベルに一致するプロジェクト内のすべてのワークロードをターゲットとするグローバル ELB を作成します。Backend カスタム リソースはゾーンにスコープ設定する必要があります。

  1. ELB サービスが機能するには、独自のカスタマイズされた ProjectNetworkPolicy データ転送をポリシーで構成して適用し、この ELB サービスのワークロードへのトラフィックを許可する必要があります。ネットワーク ポリシーは、ロードバランサ自体ではなく、ワークロードへのアクセスを制御します。ELB はワークロードを顧客ネットワークに公開します。このため、外部トラフィックがワークロード ポート(8080 など)にアクセスできるように、明示的なネットワーク ポリシーが必要です。

    この ELB のワークロードへのトラフィックを許可する外部 CIDR アドレスを指定します。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ProjectNetworkPolicy
    metadata:
      namespace: PROJECT
      name: allow-inbound-traffic-from-external
    spec:
      policyType: Ingress
      subject:
        subjectType: UserWorkload
      ingress:
      - from:
        - ipBlock:
            cidr: CIDR
        ports:
        - protocol: TCP
          port: PORT
    EOF
    

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

    • GLOBAL_API_SERVER: グローバル API サーバーの kubeconfig パス。グローバル API サーバーの kubeconfig ファイルをまだ生成していない場合は、kubeconfig ファイルを手動で生成するをご覧ください。
    • PROJECT: プロジェクトの名前。
    • CIDR: ELB にアクセスする必要がある外部 CIDR。このポリシーは、外部ロードバランサが Direct Server Return(DSR)を使用し、送信元外部 IP アドレスを保持して、戻りパスでロードバランサをバイパスするため必要です。詳細については、組織間のトラフィック用のグローバル上り(内向き)ファイアウォール ルールを作成するをご覧ください。
    • PORT: ロードバランサの背後にある Pod のバックエンド ポート。この値は、Service リソースのマニフェストの .spec.ports[].targetPortfield フィールドにあります。このフィールドは省略可能です。

    この構成により、プロジェクト内のすべてのリソースが指定された CIDR 範囲にアクセスできるようになります。

  2. 各ゾーンに Backend リソースを作成して、ELB のエンドポイントを定義します。

    gdcloud compute backends create BACKEND_NAME \
      --labels=LABELS \
      --project=PROJECT \
      --cluster=CLUSTER_NAME \
      --zone=ZONE
    

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

    • BACKEND_NAME: バックエンド リソースの名前(my-backend など)。
    • LABELS: このバックエンド リソースに使用する Pod 間のエンドポイントを定義するセレクタ(app=web など)。
    • PROJECT: プロジェクトの名前。
    • CLUSTER_NAME: 定義されたセレクタのスコープが制限される Kubernetes クラスタ。このフィールドが指定されていない場合、指定されたラベルを持つすべてのエンドポイントが選択されます。このフィールドは省略可能です。
    • ZONE: この呼び出しに使用するゾーン。ゾーンフラグを必要とするすべてのコマンドに対してゾーンフラグをプリセットするには、gdcloud config set core/zone ZONE を実行します。ゾーンフラグは、マルチゾーン環境でのみ使用できます。このフィールドは省略可能です。

    各ゾーンに同じ Backend リソースを使用することも、各ゾーンに異なるラベルセットを持つ Backend リソースを作成することもできます。

  3. グローバル BackendService リソースを作成します。

    gdcloud compute backend-services create BACKEND_SERVICE_NAME \
      --project=PROJECT \
      --target-ports=TARGET_PORTS \
      --health-check=HEALTH_CHECK_NAME \
      --global
    

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

    • BACKEND_SERVICE_NAME: このバックエンド サービスに選択した名前。
    • PROJECT: プロジェクトの名前。
    • TARGET_PORTS: このバックエンド サービスが変換するターゲット ポートのカンマ区切りリスト。各ターゲット ポートは、プロトコル、転送ルールのポート、バックエンド インスタンスのポートを指定します。複数のターゲット ポートを指定できます。このフィールドは、TCP:80:8080 などの protocol:port:targetport 形式にする必要があります。このフィールドは省略可能です。
    • HEALTH_CHECK_NAME: ヘルスチェック リソースの名前。このフィールドは省略可能です。
  4. グローバル BackendService リソースを、前に作成したゾーン Backend リソースに追加します。

    gdcloud compute backend-services add-backend BACKEND_SERVICE_NAME \
      --backend=BACKEND_NAME \
      --backend-zone=ZONE \
      --project=PROJECT \
      --global
    

    この手順は、以前に作成したゾーン バックエンドごとに行います。

  5. サービスが利用可能な VIP を定義する外部 ForwardingRule リソースを作成します。

    gdcloud compute forwarding-rules create FORWARDING_RULE_EXTERNAL_NAME \
      --backend-service=BACKEND_SERVICE_NAME \
      --cidr=CIDR \
      --ip-protocol-port=PROTOCOL_PORT \
      --load-balancing-scheme=EXTERNAL \
      --project=PROJECT \
      --global
    

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

    • FORWARDING_RULE_EXTERNAL_NAME: 転送ルールの名前。
    • CIDR: 転送ルールで使用する CIDR。このフィールドは省略可能です。指定しない場合、IPv4/32 CIDR はグローバル IP アドレス プールから自動的に予約されます。この転送ルールと同じ Namespace 内の Subnet リソースの名前を指定します。Subnet リソースは、グローバル サブネットのリクエストと割り当て情報を表します。Subnet リソースの詳細については、サブネットを管理するをご覧ください。
    • PROTOCOL_PORT: 転送ルールで公開するプロトコルとポート。このフィールドは ip-protocol=TCP:80 の形式にする必要があります。公開されるポートは、実際のアプリケーションがコンテナ内で公開しているポートと同じである必要があります。
    • PROJECT: プロジェクトの名前。
  6. 構成された ELB を検証するには、作成された各オブジェクトの Ready 条件を確認します。VIP への curl リクエストでトラフィックを確認します。

    1. 割り当てられた VIP を取得するには、転送ルールを説明します。

      gdcloud compute forwarding-rules describe FORWARDING_RULE_EXTERNAL_NAME
      
    2. 転送ルールの PROTOCOL_PORT フィールドで指定されたポートの VIP への curl リクエストでトラフィックを確認します。

      curl http://FORWARDING_RULE_VIP:PORT
      

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

      • FORWARDING_RULE_VIP: 転送ルールの VIP。
      • PORT: 転送ルールの PROTOCOL_PORT フィールドのポート番号。

API

KRM API を使用して、Pod ワークロードをターゲットとする ELB を作成します。この ELB は、Backend オブジェクトで定義されたラベルに一致するプロジェクト内のすべてのワークロードをターゲットにします。KRM API を使用してゾーン ELB を作成する手順は次のとおりです。

  1. ELB サービスが機能するには、独自のカスタマイズされた ProjectNetworkPolicy データ転送をポリシーで構成して適用し、この ELB サービスのワークロードへのトラフィックを許可する必要があります。ネットワーク ポリシーは、ロードバランサ自体ではなく、ワークロードへのアクセスを制御します。ELB はワークロードを顧客ネットワークに公開します。このため、外部トラフィックがワークロード ポート(8080 など)にアクセスできるように、明示的なネットワーク ポリシーが必要です。

    この ELB のワークロードへのトラフィックを許可する外部 CIDR アドレスを指定します。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ProjectNetworkPolicy
    metadata:
      namespace: PROJECT
      name: allow-inbound-traffic-from-external
    spec:
      policyType: Ingress
      subject:
        subjectType: UserWorkload
      ingress:
      - from:
        - ipBlock:
            cidr: CIDR
        ports:
        - protocol: TCP
          port: PORT
    EOF
    

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

    • GLOBAL_API_SERVER: グローバル API サーバーの kubeconfig パス。グローバル API サーバーの kubeconfig ファイルをまだ生成していない場合は、kubeconfig ファイルを手動で生成するをご覧ください。
    • PROJECT: プロジェクトの名前。
    • CIDR: ELB にアクセスする必要がある外部 CIDR。このポリシーは、外部ロードバランサが Direct Server Return(DSR)を使用し、送信元外部 IP アドレスを保持して、戻りパスでロードバランサをバイパスするため必要です。詳細については、組織間のトラフィック用のグローバル上り(内向き)ファイアウォール ルールを作成するをご覧ください。
    • PORT: ロードバランサの背後にある Pod のバックエンド ポート。この値は、Service リソースのマニフェストの .spec.ports[].targetPortfield フィールドにあります。このフィールドは省略可能です。
  2. Backend リソースを作成して、ELB のエンドポイントを定義します。ワークロードが配置されているゾーンごとに Backend リソースを作成します。

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
    apiVersion: networking.gdc.goog/v1
    kind: Backend
    metadata:
      namespace: PROJECT
      name: BACKEND_NAME
    spec:
      clusterName: CLUSTER_NAME
      endpointsLabels:
        matchLabels:
          app: APP_NAME
    EOF
    

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

    • MANAGEMENT_API_SERVER: ゾーン Management API サーバーの kubeconfig パス。ターゲット ゾーンの API サーバーの kubeconfig ファイルをまだ生成していない場合は、kubeconfig ファイルを手動で生成するをご覧ください。
    • PROJECT: プロジェクトの名前。
    • BACKEND_NAME: Backend リソースの名前。
    • CLUSTER_NAME: 定義されたセレクタのスコープが制限される Kubernetes クラスタ。このフィールドを指定しない場合、指定されたラベルを持つすべてのエンドポイントが選択されます。このフィールドは省略可能です。
    • APP_NAME: コンテナ アプリケーションの名前。

    各ゾーンに同じ Backend リソースを使用することも、各ゾーンに異なるラベルセットを持つ Backend リソースを作成することもできます。

  3. 前に作成した Backend リソースを使用して BackendService オブジェクトを作成します。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: BackendService
    metadata:
      namespace: PROJECT
      name: BACKEND_SERVICE_NAME
    spec:
      backendRefs:
      - name: BACKEND_NAME
        zone: ZONE
      healthCheckName: HEALTH_CHECK_NAME
    EOF
    

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

    • BACKEND_SERVICE_NAME: BackendService リソースに選択した名前。
    • HEALTH_CHECK_NAME: 以前に作成した HealthCheck リソースの名前。Pod ワークロードの ELB を構成する場合は、このフィールドを含めないでください。
    • ZONE: Backend リソースが存在するゾーン。backendRefs フィールドで複数のバックエンドを指定できます。次に例を示します。
    - name: my-backend-1
      zone: us-east1-a
    - name: my-backend-2
      zone: us-east1-b
    

  4. サービスが利用可能な VIP を定義する外部 ForwardingRule リソースを作成します。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ForwardingRuleExternal
    metadata:
      namespace: PROJECT
      name: FORWARDING_RULE_EXTERNAL_NAME
    spec:
      cidrRef: CIDR
      ports:
      - port: PORT
        protocol: PROTOCOL
      backendServiceRef:
        name: BACKEND_SERVICE_NAME
    EOF
    

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

    • FORWARDING_RULE_EXTERNAL_NAME: ForwardingRuleExternal リソースに選択した名前。
    • CIDR: 転送ルールで使用する CIDR。このフィールドは省略可能です。指定しない場合、IPv4/32 CIDR はグローバル IP アドレス プールから自動的に予約されます。この転送ルールと同じ Namespace 内の Subnet リソースの名前を指定します。Subnet リソースは、グローバル サブネットのリクエストと割り当て情報を表します。Subnet リソースの詳細については、サブネットを管理するをご覧ください。
    • PORT: 転送ルールで公開するポート。ports フィールドを使用して、この転送ルールで構成されたバックエンドにパケットが転送される L4 ポートの配列を指定します。少なくとも 1 つのポートを指定する必要があります。port フィールドを使用して、ポート番号を指定します。公開されるポートは、実際のアプリケーションがコンテナ内で公開しているポートと同じである必要があります。
    • PROTOCOL: 転送ルールに使用するプロトコル(TCP など)。ports 配列のエントリは次のようになります。
    ports:
    - port: 80
      protocol: TCP
    
  5. 構成された ELB を検証するには、作成された各オブジェクトの Ready 条件を確認します。VIP への curl リクエストでトラフィックをテストします。

    1. プロジェクトの VIP を取得します。

      kubectl get forwardingruleexternal -n PROJECT
      

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

      NAME           BACKENDSERVICE                  CIDR              READY
      elb-name       BACKEND_SERVICE_NAME            192.0.2.0/32      True
      
    2. 転送ルールの PORT フィールドで指定されたポートの VIP に curl リクエストを送信して、トラフィックを確認します。

      curl http://FORWARDING_RULE_VIP:PORT
      

      FORWARDING_RULE_VIP:PORT は、転送ルールの VIP とポート(192.0.2.0:80 など)に置き換えます。

各ゾーン クラスタにコンテナ ワークロードをデプロイする

コンテナ ワークロードはグローバル リソースではありません。つまり、コンテナ アプリケーションをゾーン Kubernetes クラスタに個別にデプロイする必要があります。

  1. Kubernetes クラスタをホストするゾーンにログインします。

    gdcloud config set core/zone ZONE
    
  2. マネージド Harbor レジストリからコンテナ イメージを使用できることを確認します。詳細については、コンテナ アプリをデプロイするチュートリアルをご覧ください。

  3. コンテナ ワークロードのマニフェスト ファイルを作成し、ゾーン Kubernetes クラスタにデプロイします。

    kubectl --kubeconfig KUBERNETES_CLUSTER -n PROJECT \
        apply -f - <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: DEPLOYMENT_NAME
    spec:
      replicas: NUMBER_OF_REPLICAS
      selector:
        matchLabels:
          run: APP_NAME
      template:
        metadata:
          labels:
            run: APP_NAME
        spec:
          containers:
          - name: CONTAINER_NAME
            image: HARBOR_INSTANCE_URL/HARBOR_PROJECT_NAME/IMAGE:TAG
    EOF
    

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

    • KUBERNETES_CLUSTER: コンテナ ワークロードをデプロイするゾーン Kubernetes クラスタの kubeconfig ファイル。ゾーン Kubernetes クラスタの kubeconfig ファイルをまだ生成していない場合は、kubeconfig ファイルを手動で生成するをご覧ください。
    • PROJECT: コンテナ ワークロードをデプロイするプロジェクト Namespace。
    • DEPLOYMENT_NAME: コンテナ デプロイの名前。
    • NUMBER_OF_REPLICAS: Deployment が管理する複製 Pod オブジェクトの数。
    • APP_NAME: デプロイ内で実行するアプリケーションの名前。
    • CONTAINER_NAME: コンテナの名前。
    • HARBOR_INSTANCE_URL: Harbor インスタンスの URL(harbor-1.org-1.zone1.google.gdc.test. など)。Harbor インスタンスの URL を取得するには、Harbor レジストリ インスタンスを表示するをご覧ください。
    • HARBOR_PROJECT_NAME: Harbor プロジェクトの名前(my-project など)。
    • IMAGE: イメージの名前(nginx など)。
    • TAG: pull するイメージ バージョンのタグ(1.0 など)。
  4. GDC ユニバース内の各ゾーンに対して、上記の手順を繰り返します。コンテナ アプリケーションが、HA 戦略で必要なすべてのゾーンに存在することを確認します。

Kubernetes を使用してコンテナ アプリケーションを公開する

コンテナ アプリケーションを公開して、GDC ユニバース内の他のリソースからアクセスできるようにする必要があります。

  1. type: LoadBalancerService リソースを作成します。このリソースは、ネットワーク経由でアプリケーションの Pod を公開します。

    kubectl --kubeconfig KUBERNETES_CLUSTER -n PROJECT \
    apiVersion: v1
    kind: Service
    metadata:
      name: SERVICE_NAME
    spec:
      selector:
        app: APP_NAME
      ports:
        - port: 80
          protocol: TCP
      type: LoadBalancer
    EOF
    

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

    • KUBERNETES_CLUSTER: コンテナ ワークロードをデプロイするゾーン Kubernetes クラスタの kubeconfig ファイル。
    • PROJECT: コンテナ ワークロードが存在するプロジェクト Namespace。
    • SERVICE_NAME: ロードバランサ サービスの名前。
    • APP_NAME: コンテナ アプリケーションに適用したラベル。
  2. すべてのネットワーク トラフィックをデフォルトの Namespace に許可する NetworkPolicy カスタム リソースを作成します。

    kubectl --kubeconfig KUBERNETES_CLUSTER -n PROJECT \
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      annotations:
      name: allow-all
    spec:
      ingress:
      - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      podSelector: {}
      policyTypes:
      - Ingress
    EOF
    

Pod の永続ストレージをプロビジョニングする

アプリケーション Pod に永続ストレージを提供するには、PersistentVolumeClaim リソース(PVC)を作成する必要があります。

次の手順では、GDC standard-rwo StorageClass を使用してボリュームを作成する方法について説明します。

  1. PersistentVolumeClaim リソースを作成するたとえば、ReadWriteOnce アクセスモードと standard-rwo ストレージ クラスで構成します。

    kubectl --kubeconfig KUBERNETES_CLUSTER \
        --namespace PROJECT apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: PVC_NAME
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
      storageClassName: standard-rwo
    EOF
    

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

    • KUBERNETES_CLUSTER: Kubernetes クラスタの kubeconfig ファイル。
    • PROJECT: PVC を作成するプロジェクト Namespace。
    • PVC_NAME: PersistentVolumeClaim オブジェクトの名前。
  2. PersistentVolume(PV)オブジェクトは動的にプロビジョニングされます。Kubernetes クラスタ内の新しい PV のステータスを確認します。

    kubectl get pv --kubeconfig KUBERNETES_CLUSTER
    

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

    NAME       CAPACITY   ACCESS MODES   STATUS      CLAIM     STORAGECLASS   AGE
    pvc-uuidd  10Gi       RWO            Bound       pvc-name  standard-rwo   60s
    
  3. PVC を使用するようにコンテナ ワークロードを構成します。次は、standard-rwo PVC を使用する Pod マニフェストの例です。

    kubectl --kubeconfig KUBERNETES_CLUSTER \
        --namespace PROJECT apply -f - <<EOF
    apiVersion: apps/v1
    kind: Pod
    metadata:
      name: web-server-deployment
      labels:
        app: APP_LABEL
    spec:
      containers:
      - name: CONTAINER_NAME
        image: HARBOR_INSTANCE_URL/HARBOR_PROJECT_NAME/IMAGE:TAG
        volumeMounts:
        - mountPath: MOUNT_PATH
          name: data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: PVC_NAME
    EOF
    

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

    • KUBERNETES_CLUSTER: コンテナ ワークロードをデプロイする Kubernetes クラスタの kubeconfig ファイル。
    • PROJECT: PVC が存在するプロジェクト Namespace。
    • APP_LABEL: コンテナ アプリケーションに適用したラベル。
    • CONTAINER_NAME: コンテナの名前。
    • HARBOR_INSTANCE_URL: Harbor インスタンスの URL(harbor-1.org-1.zone1.google.gdc.test. など)。Harbor インスタンスの URL を取得するには、Harbor レジストリ インスタンスを表示するをご覧ください。
    • HARBOR_PROJECT_NAME: Harbor プロジェクトの名前(my-project など)。
    • IMAGE: イメージの名前(nginx など)。
    • TAG: pull するイメージ バージョンのタグ(1.0 など)。
    • MOUNT_PATH: ボリュームをマウントする Pod 内のパス。
    • PVC_NAME: 作成した PVC。

非同期ストレージ レプリケーションを構成する

GDC マルチゾーン ユニバースでは、障害復旧シナリオで非同期モードのボリュームやバケットなどのレプリケートされたストレージ リソースを使用できます。これらのストレージ リソース オプションは、同じリージョン内の任意の 2 つのゾーン間で非同期データ レプリケーションを提供します。非同期レプリケーションはバックグラウンドで実行され、障害が発生した場合に目標復旧時点(RPO)をゼロに近い値に設定できます。複製されたすべてのデータはオンラインで、すぐにアクセスできますが、セカンダリ ゾーンへの書き込みを有効にするには、手動のフェイルオーバー手順が必要になる場合があります。

コンテナ アプリケーションには、次のいずれかの非同期ストレージ レプリケーション タイプを選択できます。

オブジェクト ストレージ用のデュアルゾーン バケットを作成する

オブジェクト ストレージ データは、両方のゾーンにデータが保存されている単一のバケットに書き込まれます。データはゾーン間で非同期でコピーされるため、ゾーンに同じオブジェクト バージョンが含まれていない可能性がありますが、追加の変更が行われない限り、最終的には同等になります。ボリューム レプリケーションとは異なり、レプリケートされたバケットはゾーン パーティション中に書き込み可能です。オブジェクトへの書き込みごとに異なるバージョンが生成され、接続が復元された後の最終状態は、いずれかのゾーンの最新バージョンになります。

  1. インフラストラクチャ オペレータ(IO)が BucketLocationConfig カスタム リソースを作成したことを確認します。これは、オブジェクト ストレージのゾーン間の非同期レプリケーションに必要です。このリソースは、ルート グローバル API サーバーにデプロイする必要があります。

  2. デュアルゾーンの Bucket カスタム リソースを作成します。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: object.global.gdc.goog/v1
    kind: Bucket
    metadata:
      name: BUCKET_NAME
      namespace: PROJECT
    spec:
      location: LOCATION_NAME
      description: Sample DZ Bucket
      storageClass: Standard
    EOF
    

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

    • GLOBAL_API_SERVER: グローバル API サーバーの kubeconfig ファイル。
    • BUCKET_NAME: ストレージ バケットの名前。
    • PROJECT: バケットが存在するプロジェクトの名前。
    • LOCATION_NAME: バケット内のオブジェクト データが存在する物理的な場所。これは、既存の BucketLocation リソースの名前にマッピングする必要があります。組織のグローバル API サーバーに利用可能な BucketLocation リソースのリストをクエリするには、kubectl --kubeconfig GLOBAL_API_SERVER bucketlocations を実行します。BucketLocation リソースがない場合は、IO に連絡して、非同期レプリケーションが有効になっていることを確認します。

ゾーン間の非同期ブロック ストレージ レプリケーションを構成する

レプリケートされたブロック ストレージは、プライマリ ボリュームとセカンダリ ボリューム間のブロックの同等性を維持する非同期レプリケート ボリューム(PV)を提供します。非同期であるため、セカンダリ ボリュームには過去のある時点のプライマリ ゾーンの状態が反映されます(RPO はゼロではありません)。セカンダリ ボリュームはレプリケーションのターゲットである間はマウントできません。関係を終了して書き込みを有効にするには、手動での操作が必要です。

ソースゾーンのデータが使用できなくなった場合にフェイルオーバーに使用できる複製データを作成するには、ゾーン間でストレージ レプリケーション関係を構成する必要があります。これは、コンテナ アプリケーションにブロック ストレージを使用している場合に該当します。

開始する前に、インフラストラクチャ オペレーター(IO)が StorageClusterPeering カスタム リソースと StorageVirtualMachinePeering カスタム リソースを作成して構成し、ゾーン間のブロック ストレージ レプリケーションを許可していることを確認します。このリソースは、ルート グローバル API サーバーにデプロイする必要があります。

  1. VolumeReplicationRelationship カスタム リソース YAML ファイルを作成し、グローバル API サーバーにデプロイします。

    kubectl --kubeconfig GLOBAL_API_SERVER apply -f - <<EOF
    apiVersion: storage.global.gdc.goog/v1
    kind: VolumeReplicationRelationship
    metadata:
      name: PVC_REPL_NAME
      namespace: PROJECT
    spec:
      source:
        pvc:
          clusterRef: SOURCE_PVC_CLUSTER
          pvcRef: SOURCE_PVC
        zoneRef: SOURCE_ZONE
    destination:
        pvc:
          clusterRef: DEST_PVC_CLUSTER
        zoneRef: DEST_ZONE
    EOF
    

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

    • GLOBAL_API_SERVER: グローバル API サーバーの kubeconfig ファイル。
    • PVC_REPL_NAME: ボリューム レプリケーション関係の名前。
    • PROJECT: ストレージ インフラストラクチャが存在するプロジェクト。
    • SOURCE_PVC_CLUSTER: PVC がホストされている Kubernetes クラスタ。
    • SOURCE_PVC: レプリケートするソースゾーンの PVC。
    • SOURCE_ZONE: PVC がホストされているソースゾーン。
    • DEST_PVC_CLUSTER: PVC の複製先の Kubernetes クラスタ。
    • DEST_ZONE: PVC のレプリケーション先のゾーン。
  2. 宛先ゾーンに VolumeFailover カスタム リソースを作成します。これにより、ソースゾーンが何らかの理由で利用できなくなった場合に、宛先ゾーンへのレプリケーションが停止します。

    kubectl --kubeconfig MANAGEMENT_API_SERVER apply -f - <<EOF
    apiVersion: storage.gdc.goog/v1
    kind: VolumeFailover
    metadata:
      name: PVC_FAILOVER_NAME
      namespace: PROJECT
    spec:
      volumeReplicationRelationshipRef: PVC_REPL_NAME
    EOF
    

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

    • MANAGEMENT_API_SERVER: ゾーン Management API サーバーの kubeconfig ファイル。
    • PVC_FAILOVER_NAME: PVC フェイルオーバーの名前。
    • PROJECT: ストレージ インフラストラクチャが存在するプロジェクト。
    • PVC_REPL_NAME: ボリューム レプリケーション関係の名前。

次のステップ