2023-07-25
本教程演示了如何使用 Google Kubernetes Engine (GKE) 构建多层 Web 应用。本教程中的应用是一个留言板,访问者可在一份日志中输入文字,并查看其中最新的几个日志条目。
本教程介绍如何使用负载平衡器在外部 IP 上设置留言板 Web 服务,以及如何使用单个主实例 (Leader) 和多个副本(关注者)运行 Redis 集群。
该示例强调了一些重要的 GKE 概念:
下图展示了完成上述目标后创建的集群架构概览:
在本文档中,您将使用 Google Cloud 的以下收费组件:
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
安装本教程中使用的以下命令行工具:
gcloud
用于创建和删除 Kubernetes Engine 集群。gcloud
包含在 gcloud
CLI 中。kubectl
用于管理 Kubernetes(即 Kubernetes Engine 使用的集群编排系统)。您可以使用 gcloud
安装 kubectl
:gcloud config set project project-id
根据您在 GKE 中选择使用的操作模式,然后指定默认的可用区或区域。如果您使用标准模式,您的集群是可用区级(对于本教程),因此请设置您的默认计算可用区。如果您使用 Autopilot 模式,您的集群是区域级,因此请设置您的默认计算区域。
运行以下命令,将 compute-region
替换为您的计算区域,例如 us-west1
:
gcloud config set compute/region compute-region
第一步是创建用于运行留言板应用和 Redis 服务的 GKE 集群。
创建名为 guestbook
的 GKE 集群:
gcloud container clusters create-auto guestbook
您可以使用以下命令列出项目中运行的集群:
gcloud container clusters list
gcloud container clusters describe guestbook
注意:如果您使用的是现有 Google Kubernetes Engine 集群,或者已通过 Google Cloud Console 创建集群,则需要运行以下命令来检索集群凭据,并使用这些凭据配置 kubectl 命令行工具:
gcloud container clusters get-credentials guestbook如果您已使用上面列出的 gcloud container clusters create 命令创建集群,则无需执行此步骤。
留言板应用使用 Redis 来存储其数据。该应用将数据写入 Redis Leader 实例,并从多个 Redis 关注者实例中读取数据。第一步是部署 Redis Leader。
首先,克隆示例清单:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/guestbook
使用名为 redis-leader-deployment
的清单文件部署 Redis Leader。此清单文件指定运行单个副本 Redis Leader Pod 的 Kubernetes Deployment:
guestbook/redis-leader-deployment.yaml
# Copyright 2021 Google LLC## Licensed under the Apache License, Version 2.0 (the 'License');# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an 'AS IS' BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.apiVersion: apps/v1kind: Deploymentmetadata: name: redis-leader labels: app: redis role: leader tier: backendspec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis role: leader tier: backend spec: containers: - name: leader image: 'docker.io/redis:6.0.5' resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379---
运行以下命令以部署 Redis Leader:
kubectl apply -f redis-leader-deployment.yaml
验证 Redis Leader Pod 是否正在运行:
kubectl get pods
输出:
NAME READY STATUS RESTARTS AGE
redis-leader-343230949-qfvrq 1/1 Running 0 43s
运行以下命令以查看 Redis Leader Pod 中的日志:
kubectl logs deployment/redis-leader
输出:
1:M 24 Jun 2020 14:48:20.917 * Ready to accept connections
留言板应用需要与 Redis Leader 通信才能写入其数据。您可以创建一个 Service 来代理传输到 Redis Leader Pod 的流量。
Service 是 Kubernetes 抽象,定义了一个逻辑 Pod 集及其访问政策。Service 实际上是一个命名的负载平衡器,可将流量代理传输到一个或多个 Pod。 设置 Service 时,您需要根据 Pod 标签来说明要代理哪些 Pod。
查看 redis-leader-service.yaml
清单文件,该文件描述了 Redis Leader 的 Service 资源:
guestbook/redis-leader-service.yaml
# Copyright 2021 Google LLC## Licensed under the Apache License, Version 2.0 (the 'License');# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an 'AS IS' BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.apiVersion: v1kind: Servicemetadata: name: redis-leader labels: app: redis role: leader tier: backendspec: ports: - port: 6379 targetPort: 6379 selector: app: redis role: leader tier: backend---
此清单文件创建了一项名为 redis-leader
的 Service,该 Service 带有一组标签选择器。这些标签与上一步中部署的标签集匹配。因此,该 Service 将网络流量路由到上一步中创建的 Redis Leader Pod。
清单的 ports
部分声明了单个端口映射。在本例中,此 Service 将 port: 6379
上的流量路由到匹配指定 selector
标签的容器的 targetPort: 6379
。请注意,Deployment 中使用的 containerPort
必须与 targetPort
匹配才能将流量路由到 Deployment。
通过运行以下命令来启动 Redis Leader Service:
kubectl apply -f redis-leader-service.yaml
验证 Service 已成功创建:
kubectl get service
输出:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.51.240.1 <none> 443/TCP 42s
redis-leader 10.51.242.233 <none> 6379/TCP 12s
虽然 Redis Leader 属于单个 Pod,但您可以通过添加一些 Redis 关注者副本来为其实现高可用性,并满足流量需求。
查看 redis-follower-deployment.yaml
清单文件,该文件描述了 Redis 关注者 Pod 的 Deployment:
guestbook/redis-follower-deployment.yaml
# Copyright 2021 Google LLC## Licensed under the Apache License, Version 2.0 (the 'License');# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an 'AS IS' BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.apiVersion: apps/v1kind: Deploymentmetadata: name: redis-follower labels: app: redis role: follower tier: backendspec: replicas: 2 selector: matchLabels: app: redis template: metadata: labels: app: redis role: follower tier: backend spec: containers: - name: follower image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2 resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379---
如需创建 Redis 关注者 Deployment,请运行以下命令:
kubectl apply -f redis-follower-deployment.yaml
通过查询 Pod 列表,验证这两个 Redis 关注者副本是否正在运行:
kubectl get pods
输出:
NAME READY STATUS RESTARTS AGE
redis-follower-76588f55b7-bnsq6 1/1 Running 0 27s
redis-follower-76588f55b7-qvtws 1/1 Running 0 27s
redis-leader-dd446dc55-kl7nl 1/1 Running 0 119s
获取其中一个 Redis 关注者的 Pod 日志。
kubectl logs deployment/redis-follower
输出:
1:M 24 Jun 2020 14:50:43.617 * Background saving terminated with success
1:M 24 Jun 2020 14:50:43.617 * Synchronization with replica 10.12.3.4:6379 succeeded
留言板应用需要与 Redis 关注者通信以读取数据。如需让 Redis 关注者更容易被发现,您必须设置其他 Service。
redis-follower-service.yaml
定义了 Redis 关注者的 Service 配置:
guestbook/redis-follower-service.yaml
# Copyright 2021 Google LLC## Licensed under the Apache License, Version 2.0 (the 'License');# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an 'AS IS' BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.apiVersion: v1kind: Servicemetadata: name: redis-follower labels: app: redis role: follower tier: backendspec: ports: # the port that this service should serve on - port: 6379 selector: app: redis role: follower tier: backend---
此文件定义一项在端口 6379 上运行的名为 redis-follower
的 Service。请注意,Service 的 selector
字段与上一步中创建的 Redis 关注者 Pod 匹配。
运行以下命令来创建 redis-follower
Service:
kubectl apply -f redis-follower-service.yaml
验证 Service 已成功创建:
kubectl get service
输出:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.51.240.1 <none> 443/TCP 1m
redis-leader 10.51.242.233 <none> 6379/TCP 49s
redis-follower 10.51.247.238 <none> 6379/TCP 3s
在启动并运行了留言板的 Redis 存储后,可以启动留言板 Web 服务器。与 Redis 关注者一样,该前端将使用 Kubernetes Deployment 进行部署。
留言板应用使用 PHP 前端。该前端配置为根据请求属于读取请求还是写入请求,与 Redis 关注者 Service 或 Redis Leader Service 进行通信。该前端公开了一个 JSON 接口,并提供基于 jQuery-Ajax 的用户体验。
查看 frontend-deployment.yaml
清单文件,该文件描述了留言板 Web 服务器的 Deployment:
guestbook/frontend-deployment.yaml
# Copyright 2021 Google LLC## Licensed under the Apache License, Version 2.0 (the 'License');# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an 'AS IS' BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.apiVersion: apps/v1kind: Deploymentmetadata: name: frontendspec: replicas: 3 selector: matchLabels: app: guestbook tier: frontend template: metadata: labels: app: guestbook tier: frontend spec: containers: - name: php-redis image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 env: - name: GET_HOSTS_FROM value: 'dns' resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 80---
如需创建留言板 Web 前端 Deployment,请运行以下命令:
kubectl apply -f frontend-deployment.yaml
如需验证这三个副本正在运行,请查询用于标识 Web 前端的标签列表:
kubectl get pods -l app=guestbook -l tier=frontend
输出:
NAME READY STATUS RESTARTS AGE
frontend-7b78458576-8kp8s 1/1 Running 0 37s
frontend-7b78458576-gg86q 1/1 Running 0 37s
frontend-7b78458576-hz87g 1/1 Running 0 37s
清单文件指定了环境变量 GET_HOSTS_FROM=dns
。当您将配置提供给留言板 Web 前端应用时,前端应用会使用主机名 redis-follower
和 redis-leader
来执行 DNS 查找。DNS 查找将查找您在先前步骤中创建的适当 Service 的 IP 地址。此概念称为 DNS 服务发现。
您在先前步骤中创建的 redis-follower
和 redis-leader
Service 只能在 GKE 集群中访问,因为 Service 的默认类型是 ClusterIP
。 ClusterIP
为 Service 指向的 Pod 集提供单个 IP 地址。此 IP 地址只能在集群内访问。
但是,您需要让留言板 Web 前端 Service 可供外部用户查看。 也就是说,您希望客户端能够从 GKE 集群外部请求 Service。如需完成此请求,您可以根据需求在 Service 配置中指定 type: LoadBalancer
或 type: NodePort
。在此示例中,您将使用 type: LoadBalancer
。指定此配置的 frontend-service.yaml
清单文件如下所示:
guestbook/frontend-service.yaml
# Copyright 2021 Google LLC## Licensed under the Apache License, Version 2.0 (the 'License');# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an 'AS IS' BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.apiVersion: v1kind: Servicemetadata: name: frontend labels: app: guestbook tier: frontendspec: type: LoadBalancer ports: # the port that this service should serve on - port: 80 selector: app: guestbook tier: frontend---
创建 frontend
Service 时,GKE 会创建一个负载平衡器和一个外部 IP 地址。请注意,这些资源需要付费。ports
部分下方的端口声明指定了 port: 80
,未指定 targetPort
。如果忽略 targetPort
属性,则默认为 port
字段的值。在本例中,此 Service 将端口 80 上的外部流量路由到 frontend
Deployment 中容器的端口 80。
要创建 Service,请运行以下命令:
kubectl apply -f frontend-service.yaml
如需访问留言板 Service,请通过运行以下命令找到您设置的 Service 的外部 IP 地址:
kubectl get service frontend
输出:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend 10.51.242.136 109.197.92.229 80:32372/TCP 1m
注意:创建负载平衡器时,EXTERNAL-IP 列可能会显示 <pending>。可能需要几分钟时间才能创建负载平衡器。
复制 EXTERNAL-IP 列中的 IP 地址,然后在浏览器中加载页面。
如需尝试添加一些留言板条目,请尝试输入信息帖,然后点击提交。您输入的消息会显示在前端。此消息表示数据已通过您之前创建的 Service 成功添加到 Redis。
假设您的留言板应用已经运行了一段时间,公共宣传突然激增。您决定为前端添加更多 Web 服务器。由于您的服务器被定义为使用 Deployment 控制器的服务,因此您可以轻松进行扩展。
通过运行以下命令,将 frontend
Pod 数量扩展到 5 个:
kubectl scale deployment frontend --replicas=5
输出:
deployment.extensions/frontend scaled
系统会更新 Deployment 的配置,以指定现在应该运行 5 个副本:Deployment 会调整正在运行的 Pod 数量,以匹配配置。如需验证副本数量,请运行以下命令:
kubectl get pods
输出:
NAME READY STATUS RESTARTS AGE
frontend-88237173-3s3sc 1/1 Running 0 1s
frontend-88237173-twgvn 1/1 Running 0 1s
frontend-88237173-5p257 1/1 Running 0 23m
frontend-88237173-84036 1/1 Running 0 23m
frontend-88237173-j3rvr 1/1 Running 0 23m
redis-leader-343230949-qfvrq 1/1 Running 0 54m
redis-follower-132015689-dp23k 1/1 Running 0 37m
redis-follower-132015689-xq9v0 1/1 Running 0 37m
您可以使用同一命令缩减前端 Pod 的数量。
为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。