本文档介绍如何使用 Google Kubernetes Engine (GKE) 部署分布式负载测试框架,该框架使用多个容器为简单的基于 REST 的 API 创建流量。在本文档中,我们会对一个部署到 App Engine 的 Web 应用执行负载测试,该 Web 应用公开了 REST 格式的端点,以捕获传入的 HTTP POST 请求。
您可以使用与此同样的模式为各种场景和应用创建负载测试框架,如消息传递系统、数据流管理系统和数据库系统。
目标
- 定义环境变量以控制部署配置。
- 创建 GKE 集群。
- 执行负载测试。
- (可选)增加用户数量,或者将模式扩展到其他用例。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
- App Engine
- Artifact Registry
- Cloud Build
- Cloud Storage
- Google Kubernetes Engine
您可使用价格计算器根据您的预计使用情况来估算费用。
准备工作
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.
-
Grant roles to your user account. Run the following command once for each of the following IAM roles:
roles/serviceusage.serviceUsageAdmin, roles/container.admin, roles/appengine.appAdmin, roles/appengine.appCreator, roles/artifactregistry.admin, roles/resourcemanager.projectIamAdmin, roles/compute.instanceAdmin.v1, roles/iam.serviceAccountUser, roles/cloudbuild.builds.builder, roles/iam.serviceAccountAdmin
gcloud projects add-iam-policy-binding PROJECT_ID --member="USER_IDENTIFIER" --role=ROLE
- Replace
PROJECT_ID
with your project ID. -
Replace
USER_IDENTIFIER
with the identifier for your user account. For example,user:myemail@example.com
. - Replace
ROLE
with each individual role.
- Replace
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
示例工作负载
下图展示了将客户端请求传送到应用的示例工作负载。
为对该交互进行建模,您可以使用 Locust 这一基于 Python、可跨多个目标路径分发请求的分布式负载测试工具。例如,Locust 可以将请求分发到 /login
和 /metrics
目标路径。工作负载在 Locust 中建模为一组任务。
架构
该架构涉及到两个主要组件:
- Locust Docker 容器映像。
- 容器编排和管理机制。
Locust Docker 容器映像包含 Locust 软件。在克隆与本文档配套的 GitHub 代码库时获得的 Dockerfile 使用的是基本 Python 映像,并且包含用于启动 Locust 服务和执行任务的脚本。为尽可能贴近真实客户端的情况,每个 Locust 任务都进行了加权。例如,每一千个客户端总请求发生一次注册。
GKE 提供容器编排和管理功能。使用 GKE,您可以指定为负载测试框架奠定基础的容器节点的数量。此外,您还可以将负载测试工作器组织到 pod 中,并指定希望 GKE 持续运行的 pod 数量。
为了部署负载测试任务,请执行以下操作:
- 部署负载测试主要实例,Locust 称之为主实例。
- 部署一组负载测试工作器。您要使用这些负载测试工作器创建大量的流量,以便执行测试。
下图展示了使用示例应用进行负载测试的架构。主 Pod 提供用于操作和监控负载测试的网页界面。工作器 Pod 为接受测试的应用生成 REST 请求流量,并将指标发送到主 Pod。
关于负载测试主节点
Locust 主节点是执行负载测试任务的入口点。Locust 主节点配置指定了数个元素,包括容器使用的默认端口:
8089
用于网页界面5557
和5558
用于与工作器通信
此信息稍后将用于配置 Locust 工作器。
您需要部署一个 Service,确保集群内的其他 Pod 可通过 hostname:port
访问所需的端口。这些端口也可以通过描述性端口名称进行引用。
此 Service 使 Locust 工作器能够轻松发现主节点并与之进行可靠的通信,即便主节点发生故障并被 Deployment 替换为新的 Pod 也是如此。
系统会部署带有必要注释的第二个 Service 以创建内部直通网络负载均衡器,以使 Locust Web 应用 Service 可供集群外部使用同一 VPC 网络并与您的集群位于同一 Google Cloud 区域的客户端进行访问。
部署 Locust 主节点后,您可以使用内部直通网络负载均衡器配置的内部 IP 地址来打开网页界面。部署 Locust 工作器后,您可以启动模拟,并通过 Locust 网页界面查看聚合的统计信息。
关于负载测试工作器
Locust 工作器执行负载测试任务。您可以使用单个 Deployment 来创建多个 pod。这些 pod 分布在 Kubernetes 集群中。 每个 pod 都可以使用环境变量来控制配置信息,例如受测系统的主机名以及 Locust 主节点的主机名。
下图显示了 Locust 主节点与 Locust 工作器之间的关系。
初始化通用变量
您必须定义多个变量来控制基础架构元素的部署位置。
打开 Cloud Shell:
您可以从 Cloud Shell 运行本文档中的所有命令。
设置需要自定义的环境变量:
export GKE_CLUSTER=GKE_CLUSTER export AR_REPO=AR_REPO export REGION=REGION export ZONE=ZONE export SAMPLE_APP_LOCATION=SAMPLE_APP_LOCATION
替换以下内容:
GKE_CLUSTER
:GKE 集群的名称AR_REPO
:您的 Artifact Registry 代码库的名称REGION
:将在其中创建 GKE 集群和 Artifact Registry 代码库的区域ZONE
:将在其中创建 Compute Engine 实例的您所在区域中的可用区SAMPLE_APP_LOCATION
:将在其中部署您的示例 App Engine 应用的(区域)位置
这些命令应类似于以下示例:
export GKE_CLUSTER=gke-lt-cluster export AR_REPO=dist-lt-repo export REGION=us-central1 export ZONE=us-central1-b export SAMPLE_APP_LOCATION=us-central
设置以下其他环境变量:
export GKE_NODE_TYPE=e2-standard-4 export GKE_SCOPE="https://www.googleapis.com/auth/cloud-platform" export PROJECT=$(gcloud config get-value project) export SAMPLE_APP_TARGET=${PROJECT}.appspot.com
设置默认可用区,这样您就不必在后续命令中指定这些值:
gcloud config set compute/zone ${ZONE}
创建 GKE 集群
创建具有集群所需的最低权限的服务账号:
gcloud iam service-accounts create dist-lt-svc-acc gcloud projects add-iam-policy-binding ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/artifactregistry.reader gcloud projects add-iam-policy-binding ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/container.nodeServiceAccount
创建 GKE 集群:
gcloud container clusters create ${GKE_CLUSTER} \ --service-account=dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com \ --region ${REGION} \ --machine-type ${GKE_NODE_TYPE} \ --enable-autoscaling \ --num-nodes 3 \ --min-nodes 3 \ --max-nodes 10 \ --scopes "${GKE_SCOPE}"
连接到 GKE 集群:
gcloud container clusters get-credentials ${GKE_CLUSTER} \ --region ${REGION} \ --project ${PROJECT}
设置环境
从 GitHub 克隆示例代码库:
git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
将您的工作目录更改为克隆的代码库:
cd distributed-load-testing-using-kubernetes
构建容器映像
创建 Artifact Registry 代码库:
gcloud artifacts repositories create ${AR_REPO} \ --repository-format=docker \ --location=${REGION} \ --description="Distributed load testing with GKE and Locust"
构建容器映像并将其存储在 Artifact Registry 代码库中:
export LOCUST_IMAGE_NAME=locust-tasks export LOCUST_IMAGE_TAG=latest gcloud builds submit \ --tag ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO}/${LOCUST_IMAGE_NAME}:${LOCUST_IMAGE_TAG} \ docker-image
随附的 Locust Docker 映像嵌入了调用示例应用中的
/login
和/metrics
端点的测试任务。在此示例测试任务集中,提交到这两个端点的相应请求比率为1
到999
。验证 Docker 映像是否在 Artifact Registry 代码库中:
gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO} | \ grep ${LOCUST_IMAGE_NAME}
输出类似于以下内容:
Listing items under project
PROJECT
, locationREGION
, repositoryAR_REPO
REGION
-docker.pkg.dev/PROJECT
/AR_REPO
/locust-tasks sha256:796d4be067eae7c82d41824791289045789182958913e57c0ef40e8d5ddcf283 2022-04-13T01:55:02 2022-04-13T01:55:02
部署示例应用
创建 sample-webapp 并将其部署为 App Engine:
gcloud app create --region=${SAMPLE_APP_LOCATION} gcloud app deploy sample-webapp/app.yaml \ --project=${PROJECT}
出现提示时,输入
y
以继续部署。输出类似于以下内容:
File upload done. Updating service [default]...done. Setting traffic split for service [default]...done. Deployed service [default] to [https://
PROJECT
.appspot.com]示例 App Engine 应用实现
/login
和/metrics
端点:
部署 Locust 主 Pod 和工作器 Pod
将
locust-master-controller.yaml
和locust-worker-controller.yaml
文件中的目标主机、项目和映像参数替换为环境变量值,并创建 Locust 主 Pod 和工作器 Pod Deployment:envsubst < kubernetes-config/locust-master-controller.yaml.tpl | kubectl apply -f - envsubst < kubernetes-config/locust-worker-controller.yaml.tpl | kubectl apply -f - envsubst < kubernetes-config/locust-master-service.yaml.tpl | kubectl apply -f -
验证 Locust Deployment:
kubectl get pods -o wide
输出结果类似于以下内容:
NAME READY STATUS RESTARTS AGE IP NODE locust-master-87f8ffd56-pxmsk 1/1 Running 0 1m 10.32.2.6 gke-gke-load-test-default-pool-96a3f394 locust-worker-58879b475c-279q9 1/1 Running 0 1m 10.32.1.5 gke-gke-load-test-default-pool-96a3f394 locust-worker-58879b475c-9frbw 1/1 Running 0 1m 10.32.2.8 gke-gke-load-test-default-pool-96a3f394 locust-worker-58879b475c-dppmz 1/1 Running 0 1m 10.32.2.7 gke-gke-load-test-default-pool-96a3f394 locust-worker-58879b475c-g8tzf 1/1 Running 0 1m 10.32.0.11 gke-gke-load-test-default-pool-96a3f394 locust-worker-58879b475c-qcscq 1/1 Running 0 1m 10.32.1.4 gke-gke-load-test-default-pool-96a3f394
验证 Service:
kubectl get services
输出结果类似于以下内容:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.87.240.1 <none> 443/TCP 12m locust-master ClusterIP 10.87.245.22 <none> 5557/TCP,5558/TCP 1m locust-master-web LoadBalancer 10.87.246.225 <pending> 8089:31454/TCP 1m
为 Locust 主节点 Web 应用 Service 预配内部直通网络负载均衡器的内部 IP 地址(GKE 外部 IP 地址)时,运行一个监视循环:
kubectl get svc locust-master-web --watch
配置 EXTERNAL-IP 地址后,按
Ctrl+C
退出监视循环。
连接到 Locust 网页前端
您可以使用 Locust 主节点网页界面,针对受测系统执行负载测试任务。
记下网站主机服务的内部负载均衡器 IP 地址:
export INTERNAL_LB_IP=$(kubectl get svc locust-master-web \ -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \ echo $INTERNAL_LB_IP
根据您的网络配置,您可以使用两种方式通过配置的 IP 地址连接到 Locust Web 应用:
网络路由。如果您的网络配置为允许从工作站路由到项目 VPC 网络,则可以直接从工作站访问内部直通网络负载均衡器 IP 地址。
代理和 SSH 隧道。如果工作站和 VPC 网络之间没有网络路由,您可以通过使用
nginx
代理创建 Compute Engine 实例和创建工作站与实例之间的 SSH 隧道来将流量路由到内部直通网络负载均衡器 IP 地址。
网络路由
如果工作站和 Google Cloud 项目 VPC 网络之间有网络流量路由,请打开浏览器,然后打开 Locust 主节点网页界面。如需打开 Locust 界面,请前往以下网址:
http://INTERNAL_LB_IP:8089
将 INTERNAL_LB_IP 替换为您在上一步中记下的网址和 IP 地址。
代理和 SSH 隧道
使用实例名称设置环境变量。
export PROXY_VM=locust-nginx-proxy
使用配置为代理内部直通网络负载均衡器上的 Locust Web 应用端口
8089
的ngnix
Docker 容器启动实例:gcloud compute instances create-with-container ${PROXY_VM} \ --zone ${ZONE} \ --container-image gcr.io/cloud-marketplace/google/nginx1:latest \ --container-mount-host-path=host-path=/tmp/server.conf,mount-path=/etc/nginx/conf.d/default.conf \ --metadata=startup-script="#! /bin/bash cat <<EOF > /tmp/server.conf server { listen 8089; location / { proxy_pass http://${INTERNAL_LB_IP}:8089; } } EOF"
打开从 Cloud Shell 到代理实例的 SSH 隧道:
gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \ -- -N -L 8089:localhost:8089
点击网页预览图标 (),然后从列出的选项中选择更改端口。
在更改预览端口对话框中的端口号字段中输入 8089,然后选择更改并预览。
一个浏览器标签页随即打开,并显示 Locust 网页界面。
在示例应用上运行基本负载测试
在浏览器中打开 Locust 前端后,您会看到一个可用于启动新负载测试的对话框。
将总计用户数量(最大并发数)指定为
10
,并将生成速率(启动用户数/秒)指定为5
位用户/秒。接下来,点击 Start swarming 以开始模拟。
在系统开始大量生成请求后,系统会开始聚合统计数据以获得模拟指标,例如请求数量和每秒请求数,如下图所示:
通过 Google Cloud Console 查看已部署的服务和其他指标。
观察到受测应用的行为后,点击停止以终止测试。
增加用户数量(可选)
如果要增加用于测试应用的负载,可以添加模拟用户。在添加模拟用户之前,请务必确保有充足的资源可支持负载的增加。借助 Google Cloud,您可以在无需重新部署现有 pod 的前提下为 Deployment 添加 Locust 工作器 pod,只要您拥有支持更多 pod 的基础虚拟机资源即可。初始 GKE 集群最初有 3 个节点,最多可通过自动扩缩增加到 10 个节点。
将 Locust 工作器 pod 池扩大到包含 20 个 pod。
kubectl scale deployment/locust-worker --replicas=20
部署和启动新 pod 需要几分钟时间。
如果看到 Pod Unschedulable 错误,则必须向集群添加更多节点。如需了解详情,请参阅调整 GKE 集群的大小。
在 pod 启动完毕之后,返回 Locust 主节点网页界面,重新开始负载测试。
扩展模式
若要扩展此模式,您可以创建新的 Locust 任务,甚至可以改为使用其他负载测试框架。
您可以自定义所收集的指标。例如,您可能想要测量每秒的请求数,可能希望在负载增加时监控响应延迟时间,也可能想要检查响应失败率和错误类型。
如需了解详情,请参阅 Cloud Monitoring 文档。
清理
为避免因本文档中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
删除项目
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
删除 GKE 集群
如果您不想删除整个项目,可运行以下命令来删除 GKE 集群:
gcloud container clusters delete ${GKE_CLUSTER} --region ${REGION}
后续步骤
- 构建可扩缩、弹性佳的 Web 应用。
- 仔细阅读 GKE 文档。
- 尝试 GKE 教程。
- 如需查看更多参考架构、图表和最佳实践,请浏览云架构中心。