部署容器化 Web 应用

本教程介绍如何将 Web 应用打包到 Docker 容器映像中 ,并在 Google Kubernetes Engine (GKE) 集群上运行该容器映像。然后将 Web 应用部署为可随用户需求而扩缩、支持负载平衡的副本集。

目标

  • 将示例 Web 应用打包到 Docker 映像中。
  • 将 Docker 映像上传到 Artifact Registry。
  • 创建 GKE 集群。
  • 将示例应用部署到集群。
  • 管理部署的自动扩缩。
  • 将示例应用公开发布到互联网。
  • 部署示例应用的新版本。

准备工作

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

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 启用 Artifact Registry and Google Kubernetes Engine API。

    启用 API

选项 A:使用 Cloud Shell

您可以使用 Cloud Shell 来执行本教程中所述的操作,该环境中预装了本教程中用到的 gclouddockerkubectl 命令行工具。如果使用 Cloud Shell,则无需在工作站上安装这些命令行工具。

如需使用 Cloud Shell,请执行以下操作:

  1. 转到 Google Cloud Console
  2. 点击 Cloud Console 窗口顶部的激活 Cloud Shell 激活 Shell 按钮 按钮。

    一个 Cloud Shell 会话随即会在 Cloud Console 底部的新框内打开,并显示命令行提示符。

    Cloud Shell 会话

选项 B:在本地使用命令行工具

如果您希望在工作站上按照本教程中的说明操作,请按照以下步骤安装必要的工具。

  1. 安装 Cloud SDK,其中包含 gcloud 命令行工具。

  2. 使用 gcloud 命令行工具,安装 Kubernetes 命令行工具。kubectl 用于与 Kubernetes 通信,Kubernetes 是 GKE 的集群编排系统:

    gcloud components install kubectl
    
  3. 在工作站上安装 Docker 社区版 (CE)。您将用它为应用构建容器映像。

  4. 安装 Git 源代码控制工具以从 GitHub 获取示例应用。

创建代码库

在本教程中,您将映像存储在 Artifact Registry 中并从注册表中部署。Artifact Registry 是 Google Cloud 上推荐的容器注册表。在本快速入门中,您需要创建一个名为 hello-repo 的代码库。

  1. PROJECT_ID 环境变量设置为您的 Google Cloud 项目 ID (PROJECT_ID)。构建容器映像并将其推送到代码库时,您将使用此环境变量。

    export PROJECT_ID=PROJECT_ID
    
  2. 确认 PROJECT_ID 环境变量的值正确无误:

    echo $PROJECT_ID
    
  3. gcloud 命令行工具设置项目 ID

    gcloud config set project $PROJECT_ID
    

    输出:

    Updated property [core/project].
    
  4. 使用以下命令创建 hello-repo 代码库:

    gcloud artifacts repositories create hello-repo \
       --repository-format=docker \
       --location=REGION \
       --description="Docker repository"
    

    REGION 替换为代码库的地区,例如 us-west1。要查看可用位置的列表,请运行以下命令:

     gcloud artifacts locations list
    

构建容器映像

在本教程中,您将部署一个名为 hello-app示例 Web 应用,这是一个用 Go 编写的 Web 服务器,可在端口 8080 上响应所有请求并显示 Hello, World! 消息。

GKE 接受 Docker 映像作为应用部署格式。 在将 hello-app 部署到 GKE 之前,您必须将 hello-app 源代码打包为 Docker 映像。

如需构建 Docker 映像,您需要具有源代码和 Dockerfile。 Dockerfile 中包含有关如何构建该映像的说明。

  1. 通过运行以下命令下载 hello-app 源代码和 Dockerfile:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/hello-app
    
  2. hello-app 构建和标记 Docker 映像:

    docker build -t REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1 .
    

    此命令指示 Docker 使用当前目录中的 Dockerfile 构建映像,将其保存到本地环境,并使用名称(例如 us-west1-docker.pkg.dev/my-project/hello-repo/hello-app:v1)对其进行标记。该映像将在下一部分中被推送到 Artifact Registry。

    • PROJECT_ID 变量会将容器映像与您的 Google Cloud 项目中的 hello-repo 代码库相关联。
    • us-west1-docker.pkg.dev 前缀是指您的代码库的区域主机 Artifact Registry
  3. 运行 docker images 命令以验证构建是否成功:

    docker images
    

    输出:

    REPOSITORY                                                 TAG     IMAGE ID       CREATED          SIZE
    us-west1-docker.pkg.dev/my-project/hello-repo/hello-app    v1      25cfadb1bf28   10 seconds ago   54 MB
    

在本地运行容器(可选)

  1. 使用本地 Docker 引擎测试容器映像:

    docker run --rm -p 8080:8080 REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1
    
  2. 如果您使用的是 Cloud Shell,请点击网页预览按钮 网页预览按钮,然后选择 8080 端口号。GKE 会在新的浏览器窗口中打开其代理服务的预览网址。

  3. 否则,打开一个新的终端窗口(或 Cloud Shell 标签页)并运行以下命令,以验证容器是否正常工作并以“Hello, World!”响应请求。

    curl http://localhost:8080
    

    看到成功响应后,您可以在运行 docker run 命令的标签页中按 Ctrl+C 来关闭容器。

将 Docker 映像推送到 Artifact Registry

您必须将容器映像上传到注册表,以便您的 GKE 集群可以下载并运行该容器映像。在本教程中,您需要将容器存储在 Artifact Registry 中。

  1. 配置 Docker 命令行工具以向 Artifact Registry 进行身份验证:

    gcloud auth configure-docker REGION-docker.pkg.dev
    
  2. 将刚刚构建的 Docker 映像推送到代码库:

    docker push REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1
    

创建 GKE 集群

现在,Docker 映像已存储在 Artifact Registry 中,接下来创建 GKE 集群来运行 hello-app。GKE 集群由运行 KubernetesCompute Engine 虚拟机实例池组成,Kubernetes 是为 GKE 提供支持的开源集群编排系统。

Cloud Shell

  1. 设置 Compute Engine 地区或区域。根据您在 GKE 中选择使用的操作模式,指定默认的可用区或区域。如果您使用标准模式,您的集群是可用区级(对于本教程),因此请设置您的默认计算可用区。如果您使用 Autopilot 模式,您的集群是区域级,因此请设置您的默认计算区域。选择最接近您创建的 Artifact Registry 代码库的地区或区域。

    • 标准集群,例如 us-west1-a

      gcloud config set compute/zone COMPUTE_ZONE
      
    • Autopilot 集群,例如 us-west1

      gcloud config set compute/region COMPUTE_REGION
      
  2. 创建名为 hello-cluster 的集群:

    • 标准集群:

      gcloud container clusters create hello-cluster
      
    • Autopilot 集群:

      gcloud container clusters create-auto hello-cluster
      

    创建 GKE 集群并进行运行状况检查需要几分钟的时间。

  3. 命令完成后,运行以下命令以查看集群的三个节点:

    kubectl get nodes
    

    输出:

    NAME                                           STATUS   ROLES    AGE   VERSION
    gke-hello-cluster-default-pool-229c0700-cbtd   Ready    <none>   92s   v1.18.12-gke.1210
    gke-hello-cluster-default-pool-229c0700-fc5j   Ready    <none>   91s   v1.18.12-gke.1210
    gke-hello-cluster-default-pool-229c0700-n9l7   Ready    <none>   92s   v1.18.12-gke.1210
    

控制台

  1. 转到 Cloud Console 中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 点击 创建

  3. 选择“标准”或 Autopilot 模式,然后点击配置

  4. 名称字段中,输入名称 hello-cluster

  5. 选择可用区或区域:

    • 标准集群:在位置类型下,选择可用区级,然后从可用区下拉列表中选择一个 Compute Engine 可用区,例如 us-west1-a

    • Autopilot 集群:从区域下拉列表中选择一个 Compute Engine 区域,例如 us-west1

  6. 点击创建。这将创建一个 GKE 集群。

  7. 等待集群创建完成。集群准备就绪后,集群名称旁边会显示一个绿色对勾标记。

将示例应用部署到 GKE

您现在可以将构建的 Docker 映像部署到 GKE 集群。

Kubernetes 将应用表示为 Pod,这是可扩缩的单元,包含一个或多个容器。Pod 是 Kubernetes 中最小的可部署单元。通常,您可以将 Pod 部署为可扩缩并分布在整个集群中的副本集。部署副本集的一种方法是通过 Kubernetes 部署来完成操作。

在本部分中,您将创建一个 Kubernetes Deployment,以便在您的集群上运行 hello-app。此 Deployment 具有副本 (Pod)。一个部署 Pod 仅包含一个容器:即 hello-app Docker 映像。您还将创建一个 HorizontalPodAutoscaler 资源,根据 CPU 负载将 Pod 数量从 3 个扩缩为 1 到 5 个之间。

Cloud Shell

  1. 确保您已连接到 GKE 集群。

    gcloud container clusters get-credentials hello-cluster --zone COMPUTE_ZONE
    
  2. 为您的 hello-app Docker 映像创建 Kubernetes 部署。

    kubectl create deployment hello-app --image=REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1
    
  3. 将部署副本的基准数量设置为 3。

    kubectl scale deployment hello-app --replicas=3
    
  4. 为您的部署创建一个 HorizontalPodAutoscaler 资源。

    kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5
    
  5. 如需查看已创建的 Pod,请运行以下命令:

    kubectl get pods
    

    输出:

    NAME                         READY   STATUS    RESTARTS   AGE
    hello-app-784d7569bc-hgmpx   1/1     Running   0          10s
    hello-app-784d7569bc-jfkz5   1/1     Running   0          10s
    hello-app-784d7569bc-mnrrl   1/1     Running   0          15s
    

控制台

  1. 转到 Cloud Console 中的工作负载页面。

    访问“工作负载”

  2. 点击 部署

  3. 容器部分中,选择现有容器映像

  4. 映像路径字段中,点击选择

  5. 选择容器映像窗格中,选择您已推送到 Artifact Registry 的 hello-app 映像,然后点击选择

  6. 容器部分中,点击完成,然后点击继续

  7. 配置部分中的标签下,输入 app 作为,输入 hello-app 作为

  8. 配置 YAML 下,点击查看 YAML。这将打开一个 YAML 配置文件,该文件表示将要部署到集群中的两个 Kubernetes API 资源:一个 Deployment 资源,以及一个用于该 Deployment 资源的 HorizontalPodAutoscaler 资源。

  9. 点击关闭,然后点击部署

  10. Deployment Pod 准备就绪后,Deployment 详情页面随即打开。

  11. 代管 pod 下,注意 Deployment 三个正在运行的 hello-app Pod。

将示例应用公开发布到互联网

虽然 Pod 确实具有单独分配的 IP 地址,但这些 IP 地址只能从集群内部访问。此外,GKE Pod 设计是临时的,可根据扩缩需求启动或关闭。当 Pod 因错误而崩溃时,GKE 会自动重新部署该 Pod,并且每次都会为 Pod 分配新的 IP 地址。

这意味着对于任何部署,与活跃 Pod 组对应的 IP 地址集是动态的。我们需要一种方法来执行以下操作:1) 将 Pod 组合成一个静态主机名,以及 2) 将集群外的一组 Pod 公开发布到互联网。

Kubernetes 服务可同时解决这两个问题。 这些服务会将 Pod 组合成一个静态 IP 地址,并且可从集群内的任何 Pod 进行访问。 GKE 还会为该静态 IP 地址分配 DNS 主机名。例如 hello-app.default.svc.cluster.local

GKE 中的默认服务类型为 ClusterIP,其中服务将获得只能从集群内部访问的 IP 地址。 如需在集群外部公开 Kubernetes 服务,请创建 LoadBalancer 类型的服务。此类型的服务会为可通过互联网访问的一组 Pod 生成外部负载平衡器 IP 地址。

在本部分中,您将使用 LoadBalancer 类型的 Service 将 hello-app Deployment 公开发布到互联网。

Cloud Shell

  1. 使用 kubectl expose 命令为 hello-app 部署生成 Kubernetes 服务:

    kubectl expose deployment hello-app --name=hello-app-service --type=LoadBalancer --port 80 --target-port 8080
    

    此处,--port 标志指定在负载平衡器上配置的端口号,--target-port 标志指定 hello-app 容器正在侦听的端口号。

  2. 运行以下命令以获取 hello-app-service 的服务详情:

    kubectl get service
    

    输出:

    NAME                 CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
    hello-app-service    10.3.251.122    203.0.113.0     80:30877/TCP     10s
    
  3. EXTERNAL_IP 地址复制到剪贴板(例如:203.0.113.0)。

控制台

  1. 转到 Cloud Console 中的工作负载页面。

    转到“工作负载”

  2. 点击 hello-app

  3. 在“Deployment 详情”页面中,点击 操作 > 公开

  4. 公开对话框中,将目标端口设置为 8080。这是 hello-app 容器侦听的端口。

  5. Service 类型下拉列表中,选择负载平衡器

  6. 点击公开,为 hello-app 创建 Kubernetes Service。

  7. 负载平衡器准备就绪后,Service 详情页面随即打开。

  8. 向下滚动到外部端点字段,然后复制 IP 地址。

现在,hello-app Pod 已通过 Kubernetes 服务公开发布到互联网,您可以打开新的浏览器标签页,然后导航到先前复制到剪贴板中的服务 IP 地址。您会看到一条 Hello, World! 消息以及一个 Hostname 字段。Hostname 对应于向浏览器传送 HTTP 请求的三个 hello-app Pod 中的一个。

部署示例应用的新版本

在本部分中,您将通过构建新的 Docker 映像并将其部署到 GKE 集群,来将 hello-app 升级到新版本。

GKE 的滚动更新功能让您可以在不停机的情况下更新 Deployment。在滚动更新期间,GKE 集群将逐步将现有 hello-app Pod 替换为包含新版本的 Docker 映像的 Pod。在更新期间,负载平衡器服务仅将流量路由到可用的 Pod。

  1. 返回到 Cloud Shell,现在您已在其中克隆了 hello 应用源代码和 Dockerfile。 更新 main.go 文件中的函数 hello() 以报告新版本 2.0.0

  2. 构建并标记新的 hello-app Docker 映像。

    docker build -t REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2 .
    
  3. 将该映像推送到 Artifact Registry。

    docker push REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2
    

现在,您可以更新 hello-app Kubernetes 部署来使用新的 Docker 映像。

Cloud Shell

  1. 使用 kubectl set image 命令通过映像更新将滚动更新应用于现有 hello-app Deployment:

    kubectl set image deployment/hello-app hello-app=REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2
    
  2. 运行 v1 映像的 Pod 停止运行后,系统会启动运行 v2 映像的新 Pod。

    watch kubectl get pods
    

    输出:

    NAME                        READY   STATUS    RESTARTS   AGE
    hello-app-89dc45f48-5bzqp   1/1     Running   0          2m42s
    hello-app-89dc45f48-scm66   1/1     Running   0          2m40s
    
  3. 在单独的标签页中,再次导航到 hello-app-service 外部 IP。您现在应该看到 Version 被设置为 2.0.0.

控制台

  1. 转到 Cloud Console 中的工作负载页面。

    转到“工作负载”

  2. 点击 hello-app

  3. Deployment 详情页面上,点击 操作 > 滚动更新

  4. 滚动更新对话框中,将 hello-app 的图片字段设置为 REGION-docker.pkg.dev/PROJECT_ID/hello-repo/hello-app:v2

  5. 点击更新

  6. Deployment 详情页面上,查看有效修订版本部分。您现在应该看到两个修订版本:1 和 2。修订版本 1 对应于您之前创建的初始 Deployment。修订版本 2 是您刚刚执行的滚动更新。

  7. 片刻之后,刷新页面。在代管 Pod 下,hello-app 的所有副本现在均对应于修订版本 2。

  8. 在单独的标签页中,再次导航到您复制的 Service IP 地址。Version 应为 2.0.0.

清除数据

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

  1. 删除 Service:此步骤将取消并释放为 Service 创建的 Cloud Load Balancer:

    kubectl delete service hello-app-service
    
  2. 删除集群:此步骤将删除构成集群的资源,如计算实例、磁盘和网络资源:

    gcloud container clusters delete hello-cluster --zone COMPUTE_ZONE
    
  3. 删除容器映像:此操作会删除推送到 Artifact Registry 的 Docker 映像。

    gcloud artifacts docker images delete \
        REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1 \
        --delete-tags --quiet
    gcloud artifacts docker images delete \
        REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2 \
        --delete-tags --quiet
    

后续步骤

亲自尝试

如果您是 Google Cloud 新手,请创建一个帐号来评估 GKE 在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。

免费试用 GKE