使用 GKE Autopilot 和 Spanner 部署应用


本教程介绍如何将容器化 Web 应用部署到 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 数据库。

  • 使用图形界面部署名为 hello-app-cloud-spanner 的示例 Web 应用。

下表展示了您需要在本教程中创建或使用的 Google Cloud 资源,以及用来标识这些资源的变量和为这些变量指定的值:

资源 变量
Google Cloud 项目 ID PROJECT_ID

创建项目时生成的项目 ID

示例:my-gcp-project

计算区域 COMPUTE_REGION

要在其中创建 Spanner 实例和 GKE 集群的 Compute Engine 区域。建议选择最靠近您客户地理位置的区域,不过在本教程中,我们会使用 us-west1

Spanner 实例 - hello-instance
Spanner 数据库 - hello-database
GKE Autopilot 集群 CLUSTER_NAME hello-cluster
Kubernetes 命名空间 NAMESPACE hello-namespace
Kubernetes 服务账号 KSA_NAME ksa-helloapp
IAM 服务账号 GSA_NAME gsa-helloapp
IAM 服务账号的项目 ID GSA_PROJECT 您的 Google Cloud PROJECT_ID

在本教程中,建议您创建新资源,以便在部署示例应用后轻松安全地删除这些资源。不过,如果您有任何现有命名空间、IAM 服务账号和 Kubernetes 服务账号,也可以使用它们。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

须知事项

请务必满足以下前提条件:

选择或创建项目

您可以使用现有项目,也可以为本教程创建一个新项目。

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  5. 确保您的 Google Cloud 项目已启用结算功能

启用 API

启用 Artifact Registry, Compute Engine, GKE, and IAM Service Account Credentials API。

启用 API

设置 Cloud Shell

在本教程中,您将使用 Cloud Shell 运行 gcloudkubectl 命令。Cloud Shell 是一种 shell 环境,用于管理托管在 Google Cloud 上的资源。它预安装有 Google Cloud CLIkubectl 命令行工具。

在 Google Cloud 控制台中,激活 Cloud Shell。

激活 Cloud Shell

控制台下方的框架内会打开一个 Cloud Shell 会话。

在运行本教程中的命令之前,请确保将默认项目设置为您要在其中部署示例应用的项目 ID。如果尚未进行此项设置,请在 Cloud Shell 中运行以下命令:

gcloud config set project PROJECT_ID

PROJECT_ID 替换为您的项目 ID

授予 IAM 角色

确保您的 Google Cloud 账号具有本教程所需的 IAM 角色

向您的 Google 账号授予角色。对以下每个 IAM 角色运行以下命令一次: roles/iam.serviceAccountAdmin, roles/serviceusage.serviceUsageConsumer, roles/iam.serviceAccountUser, roles/iam.securityAdmin, roles/spanner.admin, roles/container.admin

$ gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
  • PROJECT_ID 替换为您的项目 ID。
  • EMAIL_ADDRESS 替换为您的电子邮件地址。
  • ROLE 替换为每个角色。

配置 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_REGION 替换为 us-west1

创建 Spanner 数据库

Spanner 数据库包含表、视图和索引。数据库会从其父实例继承属性,例如其配置(单区域或多区域)、可用计算容量和存储空间。

使用 GoogleSQL 方言,创建一个名为 hello-database 的 Spanner 数据库,其中包含名为 Players 的表。在 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 的工作负载身份联合以安全且易于管理的方式访问您的数据库。

创建一个名为 hello-cluster 的 Autopilot 集群。默认情况下,Autopilot 集群会启用适用于 GKE 的工作负载身份联合。

gcloud container clusters create-auto CLUSTER_NAME \
  --region=COMPUTE_REGION

替换以下内容:

  • CLUSTER_NAMEhello-cluster
  • COMPUTE_REGION:集群的 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

配置集群以使用适用于 GKE 的工作负载身份联合

在部署应用之前,配置您的集群以使用适用于 GKE 的工作负载身份联合向 Google Cloud 进行身份验证。

  1. 获取凭据以访问集群:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --region=COMPUTE_REGION
    

    请替换以下内容:

    • CLUSTER_NAMEhello-cluster
    • COMPUTE_REGIONus-west1

    这会使用相应的凭据和端点信息更新 kubeconfig 文件,以将 kubectl 指向您的集群。

  2. 创建用于 Kubernetes 服务账号的命名空间。您还可以使用默认命名空间或任何现有命名空间。

    kubectl create namespace NAMESPACE
    

    NAMESPACE 替换为您要创建的新命名空间的名称,即 hello-namespace

  3. 为您的应用创建 Kubernetes 服务账号:

    kubectl create serviceaccount KSA_NAME \
      --namespace NAMESPACE
    

    请替换以下内容:

    • KSA_NAMEksa-helloapp,即您要创建的新 Kubernetes 服务账号的名称。
    • NAMESPACEhello-namespace
  4. 为您的应用创建 IAM 服务账号:

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

    请替换以下内容:

    • GSA_NAMEgsa-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_NAMEgsa-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. 通过在两个服务账号之间添加 IAM 政策绑定,允许 Kubernetes 服务账号模拟 IAM 服务账号。此绑定允许 Kubernertes 服务账号充当 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_NAMEgsa-helloapp
    • GSA_PROJECT:您的 Google Cloud 项目 ID
    • PROJECT_ID:您的 Google Cloud 项目 ID
    • NAMESPACEhello-namespace
    • KSA_NAMEksa-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. 使用 IAM 服务账号的电子邮件地址为 Kubernetes 服务账号添加注解。这样,您的示例应用便知道要用于访问 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_NAMEksa-helloapp
    • NAMESPACEhello-namespace
    • GSA_NAMEgsa-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 Editor。

    如需了解详情,请参阅 Cloud Shell Editor 界面概览

  3. 打开 Cloud Shell Editor 的探索器窗格,然后浏览到 kubernetes-engine-samples/databases/hello-app-cloud-spanner/k8s 目录。

  4. 打开 deployment.yaml 文件,将 <KSA_NAME> 替换为 Kubernetes 服务账号的名称 ksa-helloapp,以更新 serviceAccountName 字段。

    修改 yaml 以更新 KSA_NAME。
    图 1:在部署文件中更新 Kubernetes 服务账号名称。
  5. 关闭 Cloud Shell Editor,然后返回到 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
    

    NAMESPACE 替换为 hello-namespace

  8. 等待应用部署完毕,即 STATUS 显示为 Running

    kubectl get pods -n=NAMESPACE --watch
    

    NAMESPACE 替换为 hello-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
    

    NAMESPACE 替换为 hello-namespace

  2. 监视要分配的外部 IP 地址:

    kubectl get service -n=NAMESPACE --watch
    

    NAMESPACE 替换为 hello-namespace

  3. 分配完成后,复制 EXTERNAL-IP(例如 203.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
    

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

删除 Google Cloud 项目:

gcloud projects delete PROJECT_ID

如果您删除了项目,则表示您的清理已完成。如果您没有删除项目,您可以继续删除 GKE 和 Spanner 资源。

删除 GKE 资源

  1. 删除 Service。此命令将取消分配您为 Service 创建的 Google Cloud 负载均衡器:

    kubectl delete service hello-app-cloud-spanner -n=NAMESPACE
    

    NAMESPACE 替换为 hello-namespace

  2. 删除 GKE 集群。 此命令将删除构成集群的各项资源,如计算实例、磁盘和网络资源:

    gcloud container clusters delete CLUSTER_NAME --region=COMPUTE_REGION
    

    请替换以下内容:

    • CLUSTER_NAMEhello-cluster
    • COMPUTE_REGIONus-west1

删除 Spanner 资源

  1. 删除 Spanner 数据库:

    gcloud spanner databases delete hello-database --instance=hello-instance
    
  2. 删除 Spanner 实例:

    gcloud spanner instances delete hello-instance
    

后续步骤