GKE Autopilot と Spanner を使用してアプリをデプロイする

このチュートリアルでは、コンテナ化されたウェブ アプリケーションを Google Kubernetes Engine(GKE)Autopilot クラスタにデプロイし、バックエンドで Google Spanner データベースを使用してデータを保存する方法について説明します。このサンプル アプリケーションはゲーム プレーヤーのテーブルを管理します。アプリのグラフィカル ユーザー インターフェース(GUI)を使用して、プレーヤーを追加または削除できます。

Spanner はフルマネージドで水平スケーリング可能なグローバルに分散されたリレーショナル データベース サービスで、パフォーマンスと高可用性を損なうことなく ACID トランザクションと SQL セマンティクスを提供します。

このページを読む前に、Kubernetes について理解しておいてください。

GKE と Spanner を選ぶ理由

デベロッパーは、アプリケーションに必要なストレージ リソースやコンピューティング リソースの確認、需要が変動する時間帯における RAM や CPU の消費量の予測、ピーク負荷時のアプリケーション障害の心配に時間を費やしたいとは思わないでしょう。

GKE Autopilot をフルマネージド Kubernetes サービスとして使用し、Spanner をフルマネージド データベース サービスとして使用すると、安定したインフラストラクチャ上でアプリを迅速に開発してデプロイできるため、リソースの構成と管理が簡単になります。GKE Autopilot は、ランタイムの要件に基づいてクラスタに対してノードを追加または削除することで、アプリをホストするためのインフラストラクチャの構成とスケーリングを行います。同様に、Spanner では、ストレージまたはコンピューティングの要件が変わったときに、手動での介入を最小限に抑えながら動的にスケールアウトおよびスケールインできます。

たとえば、大ヒットが期待される次のゲームをリリースするとして、その人気が急速に高まるとします。そのため、リリース期間中にウェブ トラフィックが大量に発生することになります。Spanner は、GKE Autopilot を使用してアプリケーションの最大可用性を維持しながら、コンピューティング リソースを瞬時に増加、減少、再割り当てする機能を提供して、この急激なスループットに対処します。

Spanner を構成する

Spanner を構成するには、Spanner インスタンスと Spanner データベースを作成する必要があります。

Spanner インスタンスを作成する

Spanner インスタンスとは、そのインスタンスで作成された Spanner データベースによって使用されるリソースの割り当てです。

リージョン構成で hello-instance という Spanner インスタンスを作成し、100 処理単位のコンピューティング容量を計算します。

gcloud spanner instances create hello-instance \
    --config=regional-COMPUTE_REGION \
    --description="Spanner sample instance" \
    --processing-units=100

このチュートリアルでは、COMPUTE_REGIONus-west1 に置き換えます。

Spanner データベースの作成

Spanner データベースには、テーブル、ビュー、インデックスが含まれます。データベースは、構成(リージョンまたはマルチリージョン)、使用可能なコンピューティング容量、ストレージなどのプロパティを、親インスタンスから継承します。

GoogleSQL 言語を使用して、Players というテーブルを持つ hello-database という名前の Spanner データベースを作成します。Cloud Shell で次のクエリを実行します。

gcloud spanner databases create hello-database \
    --instance=hello-instance \
    --database-dialect=GOOGLE_STANDARD_SQL \
    --ddl="CREATE TABLE Players (
        PlayerUuid STRING(36) NOT NULL,
        FirstName STRING(1024),
        LastName STRING(1024),
        BirthDate DATE) PRIMARY KEY(PlayerUuid)"

GKE Autopilot クラスタを作成する

Spanner を構成したら、Autopilot クラスタを作成し、GKE 用 Workload Identity 連携を使用して、安全かつ管理しやすい方法でデータベースにアクセスします。

hello-cluster という名前の Autopilot クラスタを作成します。Autopilot クラスタでは、GKE 用 Workload Identity 連携がデフォルトで有効になっています。

gcloud container clusters create-auto CLUSTER_NAME \
  --location=CONTROL_PLANE_LOCATION

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

  • CLUSTER_NAME: hello-cluster
  • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine の リージョン。このチュートリアルでは、Spanner インスタンスを作成したのと同じリージョン us-west1 を使用します。レイテンシを短縮するために、同じリージョン内に Spanner インスタンスと GKE Autopilot クラスタを作成することをおすすめします。

クラスタの作成には最大 8~10 分かかることがあります。

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

NAME: hello-cluster
LOCATION: us-west1
MASTER_VERSION: 1.26.5-gke.1200
MASTER_IP: 192.0.2.1
MACHINE_TYPE: e2-medium
NODE_VERSION: 1.26.5-gke.1200
NUM_NODES: 3
STATUS: RUNNING

Workload Identity Federation for GKE を使用するようにクラスタを構成する

アプリをデプロイする前に、Workload Identity Federation for GKE を使用して Google Cloud に対する認証を行うようにクラスタを構成します。

  1. クラスタにアクセスするための認証情報を取得します。

    gcloud container clusters get-credentials CLUSTER_NAME \
      --location=CONTROL_PLANE_LOCATION
    

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

    • CLUSTER_NAME: hello-cluster
    • CONTROL_PLANE_LOCATION: us-west1

    これにより、クラスタの kubectl を指すように、適切な認証情報とエンドポイント情報で kubeconfig ファイルが更新されます。

  2. Kubernetes サービス アカウントに使用する Namespace を作成します。デフォルトの Namespace を使用することも、既存の Namespace を使用することもできます。

    kubectl create namespace NAMESPACE
    

    NAMESPACE は、作成する新しい Namespace の名前 hello-namespace に置き換えます。

  3. アプリケーションで使用する Kubernetes サービス アカウントを作成します。

    kubectl create serviceaccount KSA_NAME \
      --namespace NAMESPACE
    

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

    • KSA_NAME: ksa-helloapp。作成する新しい Kubernetes サービス アカウントの名前。
    • NAMESPACE: hello-namespace
  4. アプリケーションの IAM サービス アカウントを作成します。

    gcloud iam service-accounts create GSA_NAME \
      --project=GSA_PROJECT
    

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

    • GSA_NAME: gsa-helloapp。作成する新しい IAM サービス アカウントの名前。
    • GSA_PROJECT: 実際の Google Cloudプロジェクト ID。このチュートリアルでは、サンプルアプリをデプロイするのと同じ Google Cloud プロジェクトで IAM サービス アカウントを作成します。したがって、GSA_PROJECT とGoogle Cloud PROJECT_ID は同じです。
  5. IAM サービス アカウントの IAM ポリシー バインディングを追加して、Spanner に対する読み取りと書き込みを行います。

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member "serviceAccount:GSA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/spanner.admin"
    

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

    • PROJECT_ID: 実際の Google Cloud プロジェクト ID
    • GSA_NAME: gsa-helloapp

    例:

    gcloud projects add-iam-policy-binding my-gcp-project \
      --member "serviceAccount:gsa-helloapp@my-gcp-project.iam.gserviceaccount.com" \
      --role "roles/spanner.admin"
  6. 2 つのサービス アカウントの間に IAM ポリシー バインディングを追加して、Kubernetes サービス アカウントが IAM サービス アカウントの権限を借用できるようにします。このバインドで、Kubernetes サービス アカウントが IAM サービス アカウントとして機能するようになるため、Kubernetes サービス アカウントが Spanner に対して読み書きを行うことができます。

    gcloud iam service-accounts add-iam-policy-binding GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
    

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

    • GSA_NAME: gsa-helloapp
    • GSA_PROJECT: 実際の Google Cloud プロジェクト ID
    • PROJECT_ID: 実際の Google Cloud プロジェクト ID
    • NAMESPACE: hello-namespace
    • KSA_NAME: ksa-helloapp

    例:

    gcloud iam service-accounts add-iam-policy-binding gsa-helloapp@my-gcp-project.iam.gserviceaccount.com \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:my-gcp-project.svc.id.goog[hello-namespace/ksa-helloapp]"
  7. Kubernetes サービス アカウントに IAM サービス アカウントのメールアドレスでアノテーションを付けます。これにより、サンプルアプリが Google Cloud サービスへのアクセスに使用するサービス アカウントを認識できます。そのため、アプリが標準の Google API クライアント ライブラリを使用して Google Cloud サービスにアクセスする場合は、その IAM サービス アカウントを使用します。

    kubectl annotate serviceaccount KSA_NAME \
      --namespace NAMESPACE \
      iam.gke.io/gcp-service-account=GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
    

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

    • KSA_NAME: ksa-helloapp
    • NAMESPACE: hello-namespace
    • GSA_NAME: gsa-helloapp
    • GSA_PROJECT: 実際の Google Cloud プロジェクト ID

    例:

    kubectl annotate serviceaccount ksa-helloapp \
      --namespace hello-namespace \
      iam.gke.io/gcp-service-account=gsa-helloapp@my-gcp-project.iam.gserviceaccount.com

サンプルアプリをクラスタにデプロイする

必要なサービスと認証を使用して GKE と Spanner を設定したので、サンプルアプリ hello-app-cloud-spanner をデプロイする準備が整いました。

  1. GitHub リポジトリから Cloud Shell にサンプルアプリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    
  2. ターミナル ウィンドウのツールバーにある コードエディタ ボタン [エディタを開く] をクリックして、Cloud Shell エディタを起動します。

    詳しくはCloud Shell エディタのインターフェースの概要をご覧ください。

  3. Cloud Shell エディタの [エクスプローラ] ペインを開き、kubernetes-engine-samples/databases/hello-app-cloud-spanner/k8s ディレクトリを参照します。

  4. deployment.yaml ファイルを開き、<KSA_NAME> を Kubernetes サービス アカウントの名前である ksa-helloapp に置き換えて serviceAccountName フィールドを更新します。

    KSA_NAME を更新するように yaml を編集します。
    図 1. デプロイ ファイル内の Kubernetes サービス アカウント名を更新する。
  5. Cloud Shell エディタを閉じて、Cloud Shell ターミナルに戻ります。

  6. Cloud Shell ターミナルで、hello-app-cloud-spanner ディレクトリに移動します。

    cd kubernetes-engine-samples/databases/hello-app-cloud-spanner
    
  7. アプリケーションをデプロイします。

    kubectl apply -f k8s/deployment.yaml -n=NAMESPACE
    

    NAMESPACEhello-namespace に置き換えます。

  8. STATUSRunning の状態でアプリケーションがデプロイされるまで待ちます。

    kubectl get pods -n=NAMESPACE --watch
    

    NAMESPACEhello-namespace に置き換えます。

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

    NAME                                       READY   STATUS              RESTARTS   AGE
    hello-app-cloud-spanner-765c9b8779-lfcrc   0/1     ContainerCreating   0          87s
    hello-app-cloud-spanner-765c9b8779-lfcrc   1/1     Running             0          3m15s
    
  9. キーボードの Ctrl+C キーを押してコマンド プロンプトに戻り、その他のコマンドを実行します。

サンプルアプリをインターネットに公開する

クラスタの外部に Kubernetes Service を公開するには、LoadBalancer タイプの Service を作成します。このタイプの Service では、インターネット経由で到達可能な Pod の外部ロードバランサ IP アドレスが生成されます。

  1. ロードバランサをデプロイします。

    kubectl apply -f k8s/service.yaml -n=NAMESPACE
    

    NAMESPACEhello-namespace に置き換えます。

  2. 外部 IP アドレスが割り当てられることを確認します。

    kubectl get service -n=NAMESPACE --watch
    

    NAMESPACEhello-namespace に置き換えます。

  3. 割り当てたら、EXTERNAL-IP203.0.113.0 など)をコピーして、ブラウザで開きます。プレーヤーのデータベースを表示、管理するためのウェブ インターフェースが開きます。

  4. アプリの GUI を使用してプレーヤー レコードを作成または削除できます。このプレーヤー レコードは Spanner データベースに保存されます。

    プレーヤーを追加または削除します。
    図 2. レジストリでプレーヤーを作成または削除する。

    次のクエリを実行して、Spanner データベースがエントリで更新されたかどうかを確認します。

    gcloud spanner databases execute-sql hello-database \
      --instance=hello-instance \
      --sql="SELECT * FROM Players LIMIT 10"
    

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

    PlayerUuid: a1f34bbf-929c-498d-8b16-39bbb29d70e3
    FirstName: John
    LastName: Smith
    BirthDate: 1997-07-12
    
    PlayerUuid: d634e157-96ea-45f2-be3f-fb907ced188e
    FirstName: Jane
    LastName: Doe
    BirthDate: 2013-07-12