本教程使用 Kueue 介绍如何实现 Job 排队系统、配置 Google Kubernetes Engine (GKE) 上不同命名空间之间的工作负载资源和配额共享,以及如何最大限度地提高集群的利用率。
背景
作为基础架构工程师或集群管理员,最大限度地提高命名空间之间的利用率至关重要。一个命名空间中的一批 Job 可能无法充分使用分配给该命名空间的全部配额,而另一个命名空间可能有多个待处理的 Job。如需在不同命名空间的 Job 之间高效地使用集群资源,并提高配额管理的灵活性,您可以在 Kueue 中配置同类群组。同类群组是一组 ClusterQueue,它们可以相互借用未使用的配额。ClusterQueue 用于管理 CPU、内存和硬件加速器等资源池。
您可以参阅 Kueue 文档,了解所有这些概念的详细定义。
目标
本教程适用于希望使用 Kueue 和配额共享在 Kubernetes 上实现 Job 排队系统的基础架构工程师或集群管理员。本教程将模拟两个不同命名空间中的两个团队,每个团队都有自己的专用资源,但可以相互借用。第 3 组资源可以在 Job 累积时用作溢出。
利用 Prometheus Operator 来监控不同命名空间中的 Job 和资源分配。
本教程介绍了以下必要步骤:
- 创建 GKE 集群
- 创建 ResourceFlavors
- 为每个团队创建一个 ClusterQueue 和 LocalQueue
- 创建 Job 并观察允许的工作负载
- 使用同类群组借用未使用的配额
- 添加管理 Spot 虚拟机的溢出 ClusterQueue
费用
本教程使用 Google Cloud的以下收费组件:您可使用价格计算器根据您的预计使用情况来估算费用。
完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理。
准备工作
设置项目
- 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, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
设置 Google Cloud CLI 的默认值
在 Google Cloud 控制台中,启动 Cloud Shell 实例:
打开 Cloud Shell下载此示例应用的源代码:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
设置默认环境变量:
gcloud config set project
PROJECT_ID gcloud config set compute/regionCOMPUTE_REGION 替换以下值:
- PROJECT_ID:您的 Google Cloud 项目 ID。
- COMPUTE_REGION:Compute Engine 区域。
创建 GKE 集群
创建名为
kueue-cohort
的 GKE 集群:您将创建一个集群,该集群在默认池中有 6 个节点(每个可用区 2 个),并且没有自动扩缩功能。 这些是一开始可供团队使用的所有资源,因此它们必须展开竞争。
稍后您将了解 Kueue 如何管理两个团队将发送到相应队列的工作负载。
gcloud container clusters create kueue-cohort --region
COMPUTE_REGION \ --release-channel rapid --machine-type e2-standard-4 --num-nodes 2创建集群后,结果类似于以下内容:
kubeconfig entry generated for kueue-cohort. NAME: kueue-cohort LOCATION: us-central1 MASTER_VERSION: 1.26.2-gke.1000 MASTER_IP: 35.224.108.58 MACHINE_TYPE: e2-medium NODE_VERSION: 1.26.2-gke.1000 NUM_NODES: 6 STATUS: RUNNING
其中,
kueue-cluster
的STATUS
是RUNNING
。创建一个名为
spot
的节点池。此节点池使用 Spot 虚拟机并启用了自动扩缩功能。它从 0 个节点开始,但稍后您会将其提供给团队以用作溢出容量。
gcloud container node-pools create spot --cluster=kueue-cohort --region
COMPUTE_REGION \ --spot --enable-autoscaling --max-nodes 20 --num-nodes 0 \ --machine-type e2-standard-4将 Kueue 的发布版本安装到集群:
VERSION=
VERSION kubectl apply -f \ https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml将 VERSION 替换为字母 v 后跟 Kueue 的最新版本,例如
v0.4.0
。如需详细了解 Kueue 版本,请参阅 Kueue 版本。等待 Kueue 控制器准备就绪:
watch kubectl -n kueue-system get pods
在继续下一步之前,输出应类似于以下内容:
NAME READY STATUS RESTARTS AGE kueue-controller-manager-6cfcbb5dc5-rsf8k 2/2 Running 0 3m
创建两个名为
team-a
和team-b
的新命名空间:kubectl create namespace team-a kubectl create namespace team-b
每个命名空间上都将生成 Job。
创建 ResourceFlavor
ResourceFlavor 表示集群节点中的资源变体,例如不同的虚拟机(例如 Spot 与按需)、架构(例如 x86 与 ARM CPU)、品牌和型号(例如 Nvidia A100 与 T4 GPU)。
ResourceFlavors 使用节点标签和污点与集群中的一组节点匹配。
在此清单中:
- ResourceFlavor
on-demand
的标签设置为cloud.google.com/gke-provisioning: standard
。 - ResourceFlavor
spot
的标签设置为cloud.google.com/gke-provisioning: spot
。
为工作负载分配 ResourceFlavor 时,Kueue 会将工作负载的 Pod 分配给匹配为 ResourceFlavor 定义的节点标签的节点。
部署 ResourceFlavor:
kubectl apply -f flavors.yaml
创建 ClusterQueue 和 LocalQueue
创建两个 ClusterQueue cq-team-a
和 cq-team-b
,以及相应的 LocalQueue lq-team-a
和 lq-team-b
,分别加入命名空间 team-a
和 team-b
。
ClusterQueue 是集群范围对象,用于管理 CPU、内存和硬件加速器等资源池。批处理管理员可以将这些对象的公开范围限制为批处理用户。
LocalQueue 是批处理用户可以列出的命名空间内对象。它们指向 CluterQueue,资源将从中分配,以运行 LocalQueue 工作负载。
ClusterQueue 允许资源有多个变体。在本例中,每个 ClusterQueue 都有两种变体(on-demand
和 spot
),均提供 cpu
资源。ResourceFlavor spot
的配额设置为 0
,暂时不使用。
这两个 ClusterQueue 共享在 .spec.cohort
中定义的名为 all-teams
的同类群组。当两个或更多 ClusterQueue 共享一个同类群组时,它们可以向彼此借用未使用的配额。
如需详细了解同类群组的工作原理以及借用语义,请参阅 Kueue 文档。
部署 ClusterQueue 和 LocalQueue:
kubectl apply -f cq-team-a.yaml
kubectl apply -f cq-team-b.yaml
(可选)使用 kube-prometheus 监控工作负载
您可以使用 Prometheus 监控 Kueue 活跃工作负载和待处理工作负载。如需监控启动的工作负载并观察每个 ClusterQueue 的负载,请将 kube-prometheus 部署到命名空间 monitoring
下的集群:
下载 Prometheus Operator 的源代码:
cd git clone https://github.com/prometheus-operator/kube-prometheus.git
创建 CustomResourceDefinition (CRD):
kubectl create -f kube-prometheus/manifests/setup
创建监控组件:
kubectl create -f kube-prometheus/manifests
允许
prometheus-operator
从 Kueue 组件中抓取指标:kubectl apply -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/prometheus.yaml
切换到工作目录:
cd kubernetes-engine-samples/batch/kueue-cohort
将端口转发设置为在 GKE 集群中运行的 Prometheus 服务:
kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090
在浏览器中通过 localhost:9090 打开 Prometheus 网页界面。
在 Cloud Shell 中:
点击网页预览。
点击更改端口,然后将端口号设置为
9090
。点击更改并预览。
系统会显示以下 Prometheus 网页界面。
在表达式查询框中,输入以下查询,以创建第一个用于监控
cq-team-a
ClusterQueue 的活跃工作负载的面板:kueue_pending_workloads{cluster_queue="cq-team-a", status="active"} or kueue_admitted_active_workloads{cluster_queue="cq-team-a"}
点击添加面板。
在表达式查询框中,输入以下查询,以创建另一个用于监控
cq-team-b
ClusterQueue 的活跃工作负载的面板:kueue_pending_workloads{cluster_queue="cq-team-b", status="active"} or kueue_admitted_active_workloads{cluster_queue="cq-team-b"}
点击添加面板。
在表达式查询框中,输入以下查询,以创建一个用于监控集群中节点数量的面板:
count(kube_node_info)
(可选)使用 Google Cloud Managed Service for Prometheus 监控工作负载
您可以使用 Google Cloud Managed Service for Prometheus 监控 Kueue 活跃工作负载和待处理工作负载。如需查看指标的完整列表,请参阅 Kueue 文档。
为指标访问权限设置身份和 RBAC:
以下配置会创建 4 个 Kubernetes 资源,用于为 Google Cloud Managed Service for Prometheus 收集器提供指标访问权限。
访问 Kueue 指标时,系统会使用
kueue-system
命名空间中名为kueue-metrics-reader
的 ServiceAccount 进行身份验证。与
kueue-metrics-reader
服务账号关联的 Secret 会存储收集器使用的身份验证令牌,以通过 Kueue 部署公开的指标端点进行身份验证。kueue-system
命名空间中名为kueue-secret-reader
的 Role,允许读取包含服务账号令牌的 Secret。为
kueue-metrics-reader
服务账号授予kueue-metrics-reader
ClusterRole 的 ClusterRoleBinding。
apiVersion: v1 kind: ServiceAccount metadata: name: kueue-metrics-reader namespace: kueue-system --- apiVersion: v1 kind: Secret metadata: name: kueue-metrics-reader-token namespace: kueue-system annotations: kubernetes.io/service-account.name: kueue-metrics-reader type: kubernetes.io/service-account-token --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: kueue-secret-reader namespace: kueue-system rules: - resources: - secrets apiGroups: [""] verbs: ["get", "list", "watch"] resourceNames: ["kueue-metrics-reader-token"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kueue-metrics-reader subjects: - kind: ServiceAccount name: kueue-metrics-reader namespace: kueue-system roleRef: kind: ClusterRole name: kueue-metrics-reader apiGroup: rbac.authorization.k8s.io
为 Google Cloud Managed Service for Prometheus 配置 RoleBinding:
根据您使用的是 Autopilot 集群还是 Standard 集群,您需要在
gke-gmp-system
或gmp-system
命名空间中创建 RoleBinding。此资源可让收集器服务账号访问kueue-metrics-reader-token
Secret,以对 Kueue 指标进行身份验证和抓取。apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gmp-system:collector:kueue-secret-reader namespace: kueue-system roleRef: name: kueue-secret-reader kind: Role apiGroup: rbac.authorization.k8s.io subjects: - name: collector namespace: gke-gmp-system kind: ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: gmp-system:collector:kueue-secret-reader namespace: kueue-system roleRef: name: kueue-secret-reader kind: Role apiGroup: rbac.authorization.k8s.io subjects: - name: collector namespace: gmp-system kind: ServiceAccount
配置 PodMonitoring 资源:
以下资源为 Kueue 部署配置了监控,它指定指标通过 HTTPS 在 /metrics 路径上公开。在抓取指标时,该指标会使用
kueue-metrics-reader-token
Secret 进行身份验证。apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: kueue namespace: kueue-system spec: selector: matchLabels: control-plane: controller-manager endpoints: - port: https interval: 30s path: /metrics scheme: https tls: insecureSkipVerify: true authorization: type: Bearer credentials: secret: name: kueue-metrics-reader-token key: token
查询已导出的指标
用于监控基于 Kueue 的系统的 PromQL 查询示例
借助这些 PromQL 查询,您可以监控关键 Kueue 指标(例如,作业吞吐量、按队列划分的资源利用率和工作负载等待时间),以了解系统性能并找出潜在瓶颈。
Job 吞吐量
这会计算每个 cluster_queue 在 5 分钟内允许的工作负载每秒速率。此指标有助于按队列进行细分,从而有助于查明瓶颈,而将其相加可提供整体系统吞吐量。
查询:
sum(rate(kueue_admitted_workloads_total[5m])) by (cluster_queue)
资源利用率
此处假定已启用 metrics.enableClusterQueueResources
。它会计算每个队列的当前 CPU 用量与标称 CPU 配额的比率。值接近 1 表示利用率较高。您可以通过更改资源标签,针对内存或其他资源进行调整。
如需在集群中安装自定义配置的已发布版本的 Kueue,请参阅 Kueue 文档。
查询:
sum(kueue_cluster_queue_resource_usage{resource="cpu"}) by (cluster_queue) / sum(kueue_cluster_queue_nominal_quota{resource="cpu"}) by (cluster_queue)
队列等待时间
这会提供特定队列中工作负载的第 90 百分位等待时间。您可以修改分位数值(例如,0.5 表示中位数,0.99 表示第 99 百分位),以了解等待时间分布情况。
查询:
histogram_quantile(0.9, kueue_admission_wait_time_seconds_bucket{cluster_queue="QUEUE_NAME "})
创建 Job 并观察允许的工作负载
在本部分中,您将在命名空间 team-a
和 team-b
下创建 Kubernetes Job。Kubernetes 中的 Job 控制器会创建一个或多个 Pod,并确保它们成功执行特定任务。
为这两个 ClusterQueue(将休眠 10 秒)生成 Job,包含三个并行 Job,三个 Job 都完成才算完成。然后,Job 会在 60 秒后进行清理。
job-team-a.yaml
在命名空间 team-a
下创建 Job,并指向 LocalQueue lq-team-a
和 ClusterQueue cq-team-a
。
同样,job-team-b.yaml
在 team-b
命名空间下创建 Job,并指向 LocalQueue lq-team-b
和 ClusterQueue cq-team-b
。
启动新终端并运行以下脚本,每秒生成一个 Job:
./create_jobs.sh job-team-a.yaml 1
启动另一个终端,并为
team-b
命名空间创建 Job:./create_jobs.sh job-team-b.yaml 1
观察 Prometheus 中正在排队的 Job。或使用以下命令:
watch -n 2 kubectl get clusterqueues -o wide
输出应类似如下所示:
NAME COHORT STRATEGY PENDING WORKLOADS ADMITTED WORKLOADS
cq-team-a all-teams BestEffortFIFO 0 5
cq-team-b all-teams BestEffortFIFO 0 4
使用同类群组借用未使用的配额
ClusterQueue 可能无法始终达到最大容量。当工作负载在 ClusterQueue 中分布不均匀时,配额用量无法最大化。如果 ClusterQueue 彼此共享相同的同类群组,则 ClusterQueue 可以从其他 ClusterQueue 借用配额,以最大限度地提高配额利用率。
当 ClusterQueue
cq-team-a
和cq-team-b
都有 Job 排队后,在相应的终端上按CTRL+c
停止team-b
命名空间的脚本。命名空间
team-b
中的所有待处理 Job 都得到处理后,命名空间team-a
中的 Job 可以借用cq-team-b
中的可用资源:kubectl describe clusterqueue cq-team-a
由于
cq-team-a
和cq-team-b
共享名为all-teams
的同类群组,因此这些 ClusterQueue 能够共享未使用的资源。Flavors Usage: Name: on-demand Resources: Borrowed: 5 Name: cpu Total: 15 Borrowed: 5Gi Name: memory Total: 15Gi
恢复
team-b
命名空间的脚本。./create_jobs.sh job-team-b.yaml 3
观察被借用的
cq-team-a
资源如何变为0
,而cq-team-b
中的资源用于它自己的工作负载:kubectl describe clusterqueue cq-team-a
Flavors Usage: Name: on-demand Resources: Borrowed: 0 Name: cpu Total: 9 Borrowed: 0 Name: memory Total: 9Gi
使用 Spot 虚拟机增加配额
当需要临时增加配额时(例如,为了满足待处理工作负载中的高需求),您可以通过向同类群组添加更多 ClusterQueue 来配置 Kueue 以满足需求。具有未使用资源的 ClusterQueue 可与属于同一同类群组的其他 ClusterQueue 共享这些资源。
在本教程开始时,您使用 Spot 虚拟机创建了名为 spot
的节点池和名为 spot
且标签设置为 cloud.google.com/gke-provisioning: spot
的 ResourceFlavor。创建一个 ClusterQueue 以使用此节点池和表示它的 ResourceFlavor:
创建一个名为
cq-spot
的新 ClusterQueue,同类群组设置为all-teams
:由于此 ClusterQueue 与
cq-team-a
和cq-team-b
共享一个同类群组,因此 ClusterQueuecq-team-a
和cq-team-b
都可以最多借用 15 个 CPU 请求和 15 Gi 内存的资源。kubectl apply -f cq-spot.yaml
在 Prometheus 中,观察
cq-team-a
和cq-team-b
的允许工作负载如何因共享一个同类群组的cq-spot
的配额增加而激增。或使用以下命令:watch -n 2 kubectl get clusterqueues -o wide
在 Prometheus 中,观察集群中的节点数。或使用以下命令:
watch -n 2 kubectl get nodes -o wide
按
CTRL+c
为team-a
和team-b
命名空间停止这两个脚本。
清理
为避免因本教程中使用的资源导致您的 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.
逐个删除资源
删除 Kueue 配额系统:
kubectl delete -n team-a localqueue lq-team-a kubectl delete -n team-b localqueue lq-team-b kubectl delete clusterqueue cq-team-a kubectl delete clusterqueue cq-team-b kubectl delete clusterqueue cq-spot kubectl delete resourceflavor default kubectl delete resourceflavor on-demand kubectl delete resourceflavor spot
删除 Kueue 清单:
VERSION=
VERSION kubectl delete -f \ https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml删除集群:
gcloud container clusters delete kueue-cohort --region=
COMPUTE_REGION
后续步骤
详细了解如何使用 Kueue 部署批处理系统。
详细了解 GKE 上的作业。