部署容器化 Web 应用

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

目标

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

准备工作

请按照以下步骤启用 Kubernetes Engine API:
  1. 访问 Google Cloud Console 中的 Kubernetes Engine 页面
  2. 创建或选择项目。
  3. 稍作等待,让 API 和相关服务完成启用过程。 此过程可能耗时几分钟。
  4. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

选项 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 获取示例应用。

构建容器映像

在本教程中,您将部署一个名为 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. PROJECT_ID 环境变量设置为您的 Google Cloud 项目 ID (PROJECT_ID)。PROJECT_ID 变量将容器映像与您的项目的 Container Registry 相关联。

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

    echo $PROJECT_ID
    
  4. hello-app 构建和标记 Docker 映像:

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
    

    此命令指示 Docker 使用当前目录中的 Dockerfile 构建映像,并使用名称(例如 gcr.io/my-project/hello-app:v1)对其进行标记。gcr.io 前缀是指映像托管在其中的 Container Registry。运行此命令不会上传映像。

  5. 运行 docker images 命令以验证构建是否成功:

    docker images
    

    输出:

    REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
    gcr.io/my-project/hello-app    v1                  25cfadb1bf28        10 seconds ago      54 MB
    

在本地运行容器(可选)

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

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

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

    curl http://localhost:8080
    

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

将 Docker 映像推送到 Container Registry

您必须将容器映像上传到注册表,以便您的 GKE 集群可以下载并运行该容器映像。在 Google Cloud 中,Container Registry 默认处于启用状态。

  1. 为您正在使用的 Google Cloud 项目启用 Container Registry API

    gcloud services enable containerregistry.googleapis.com
    
  2. 配置 Docker 命令行工具以向 Container Registry 进行身份验证:

    gcloud auth configure-docker
    
  3. 将刚刚构建的 Docker 映像推送到 Container Registry:

    docker push gcr.io/${PROJECT_ID}/hello-app:v1
    

创建 GKE 集群

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

Cloud Shell

  1. gcloud 工具设置项目 ID 选项:

    gcloud config set project $PROJECT_ID
    
  2. 设置您的可用区或区域。根据您在 GKE 中选择使用的操作模式,指定默认的可用区或区域。如果您使用标准模式,您的集群是可用区级(对于本教程),因此请设置您的默认计算可用区。如果您使用 Autopilot 模式,您的集群是区域级,因此请设置您的默认计算区域。选择离您最近的可用区或区域。

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

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

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

    • 标准集群:

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

      gcloud container clusters create-auto hello-cluster
      

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

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

    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=gcr.io/${PROJECT_ID}/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 中的“GKE 工作负载”菜单。

    访问“工作负载”菜单

  2. 点击 部署

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

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

  5. 选择容器映像窗格中,选择您推送到 Container 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 中的 Google Kubernetes Engine“工作负载”菜单。

    访问“工作负载”菜单

  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 gcr.io/${PROJECT_ID}/hello-app:v2 .
    
  3. 将映像推送到 Container Registry。

    docker push gcr.io/${PROJECT_ID}/hello-app:v2
    

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

Cloud Shell

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

    kubectl set image deployment/hello-app hello-app=gcr.io/${PROJECT_ID}/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 中的 Google Kubernetes Engine“工作负载”菜单。

    访问“工作负载”菜单

  2. 点击 hello-app

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

  4. 滚动更新对话框中,将 hello-app 映像 (Image of hello-app) 字段设置为 gcr.io/PROJECT_ID/hello-app:v2,并将 PROJECT_ID 替换为您的项目 ID。

  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. 删除容器映像:此操作会删除推送到 Container Registry 的 Docker 映像。

    gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v1  --force-delete-tags --quiet
    gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v2  --force-delete-tags --quiet
    

后续步骤

亲自尝试

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

免费试用 GKE