本教程介绍如何监控 Google Kubernetes Engine (GKE) 集群以优化资源利用率。此类优化通常是复杂的任务,因为需要通过降低资源消耗量来减少费用,但同时又不牺牲应用的稳定性和性能。本教程介绍针对过度预配的常见原因设置信息中心和提醒政策的过程,此外还提供资源建议,以帮助您确保应用可靠运行并针对费用优化。
本教程适用于希望优化 GKE 集群和应用以实现低费用、高性能和高应用稳定性的开发者和运营人员。本教程假定您熟悉 Docker、Kubernetes、Kubernetes CronJobs、GKE、Cloud Monitoring 和 Linux。
概览
费用优化通常被误解为旨在降低费用的一次性过程。但是,根据 Gartner 的定义,费用优化是一个需要持续执行的方法,它同时也必须最大限度地提升业务价值。当您将这种方法具体应用于 Kubernetes 领域时,其他角度也十分重要。
如图所示,Kubernetes 上的费用优化要求平衡 4 个不同的目标:降低费用、实现性能目标、实现稳定性以及最大限度地提升业务成果。换言之,降低费用不应以牺牲用户体验或业绩表现为代价,除非已经对这种影响有充分了解或准备。
Google Cloud 提供了平衡这些目标所需的工具。但是,并非所有为工作负载采用云端解决方案(如 Kubernetes)的团队都具备实现性能和稳定性目标的专业知识。通常,他们的解决方案是过度供应环境,以减轻对业务的影响。
过度供应可以在短期内缓解问题,但费用较高。您应该谨慎使用此方法,并且应该仅作为持续的费用优化过程的一部分实施。下图显示了在开展这一费用优化之旅的团队中发现的 4 个问题。
第一个问题是文化问题。许多采用公有云的团队并不适应随用随付的结算方式,并且通常未能完全了解其应用运行的环境(在本例中为 Kubernetes)。最近受到广泛关注的 FinOps 运动就致力于改进这种文化。FinOps 的一个最佳做法是向团队提供有关其支出和业务影响的实时信息。诸如此类的小措施会对公司文化有显著影响,从而产生更为平衡的费用优化等式。
第二个问题是装箱。装箱是将应用加载到 GKE 节点中的能力。应用加载到节点中的效率越高,节省的费用就越多。
第三个问题是优化应用容量。优化容量是为部署在集群中的对象配置适当的资源请求和工作负载自动扩缩目标的能力。为 pod 设置的资源越精确,应用的运行就越可靠,在大多数情况下,您在集群中打开的空间也越多。
最后一个问题是集群在非高峰时段不缩容。理想情况下,为了在需求较低的时段(例如,夜间)节省费用,集群应该能够根据实际需求进行缩容。但在某些情况下,由于工作负载或集群配置阻止了集群自动扩缩器 (CA),导致无法按预期进行缩容。
为了有效地优化环境费用,您必须持续处理这些问题。为了突出实操性内容,本教程的剩余部分将跳过文化问题,并介绍如何使用 Cloud Monitoring 监控 GKE 集群中的装箱及优化应用容量。如需详细了解如何在需求较低的时段优化集群费用,请参阅在非高峰时段缩减 GKE 集群以降低费用。
目标
- 创建 GKE 集群。
- 部署示例应用。
- 设置用于将所需指标导出到 Cloud Monitoring 的组件。
- 动态生成用于监控资源利用率和建议的信息中心。
- 动态生成过度供应和供应不足的提醒政策。
费用
本教程使用 Google Cloud 的以下收费组件:
准备工作
-
在 Google Cloud Console 中,转到项目选择器页面。
-
选择或创建 Google Cloud 项目。
-
确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理。
准备环境
在 Google Cloud 控制台中,打开 Cloud Shell。在本教程中,您将在 Cloud Shell 中执行命令。
Cloud Shell 会话随即会在 Google Cloud 控制台底部打开,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 的 shell 环境,其中包括 Google Cloud CLI 以及已为当前项目设置的值。该会话可能需要几秒钟来完成初始化。
在 Cloud Shell 中,配置您的 Cloud 项目 ID 和电子邮件地址,并启用 Compute Engine、GKE 和 Cloud Monitoring API:
PROJECT_ID=YOUR_PROJECT_ID ALERT_EMAIL=YOUR_EMAIL_ADDRESS CLUSTER=gke-cost-optimization-monitoring gcloud config set project $PROJECT_ID gcloud services enable \ compute.googleapis.com \ container.googleapis.com \ monitoring.googleapis.com gcloud config set compute/region us-central1 gcloud config set compute/zone us-central1-f
请替换以下内容:
YOUR_PROJECT_ID
:您在本教程中使用的项目的 Cloud 项目 ID。YOUR_EMAIL_ADDRESS
:在集群中发现过度供应和供应不足时要通知的电子邮件地址。
您可以选择其他区域和可用区。
克隆
gke-cost-optimization-monitoring
GitHub 代码库:git clone https://github.com/GoogleCloudPlatform/gke-cost-optimization-monitoring cd gke-cost-optimization-monitoring
此代码库中的代码分布在以下文件夹中:
- root:包含 CronJob 用于将自定义指标导出到 Cloud Monitoring 的
main.go
和Dockerfile
文件。 api/
:包含用于操控 Kubernetes 和 Monitoring 对象的golang
API。k8s/templates/
:包含用于在集群中创建 CronJob、VPA 和 Pod 纵向自动扩缩器 (HPA) 的模板。monitoring/dashboards/templates/
:包含用于动态创建装箱和优化应用容量信息中心的模板。monitoring/policies/templates/
:包含用于动态创建装箱和优化应用容量提醒政策的模板。
- root:包含 CronJob 用于将自定义指标导出到 Cloud Monitoring 的
创建 GKE 集群
在 Cloud Shell 中创建一个 GKE 集群:
gcloud container clusters create $CLUSTER \ --enable-ip-alias \ --release-channel=stable \ --machine-type=e2-standard-2 \ --enable-autoscaling --min-nodes=1 --max-nodes=5 \ --enable-vertical-pod-autoscaling
此设置不是生产配置,但适合本教程。在此设置中,您启用 VPA 以获取优化应用容量的基础数据。
部署示例应用
-
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/release/kubernetes-manifests.yaml
Online Boutique 应用是一个演示版的零售网店,由使用不同计算机语言编写的许多个微服务组成。
为了模拟更真实的环境,请为 Online Boutique 部署创建 HPA:
kubectl get deployments --field-selector='metadata.name!=adservice,metadata.name!=cartservice' -o go-template-file=k8s/templates/cpu-hpa.gtpl | kubectl apply -f - kubectl get deployments --field-selector='metadata.name==cartservice' -o go-template-file=k8s/templates/memory-hpa.gtpl | kubectl apply -f -
请注意,您为大多数 Online Boutique 部署创建 CPU 目标 HPA 对象,为
cartservice
部署创建内存目标 HPA,并且不为adservice
创建 HPA 配置。此设置有助于演示不同的信息中心可视化图表,如以下部分所述。
设置用于将指标导出到 Cloud Monitoring 的组件
构建并推送自定义指标导出器代码:
docker build . -t gcr.io/$PROJECT_ID/metrics-exporter docker push gcr.io/$PROJECT_ID/metrics-exporter
此代码负责查询集群中的 VPA 和 HPA 对象,并将基于该数据的自定义指标发送到 Cloud Monitoring。此实现导出 VPA 目标建议和 HPA 资源目标利用率(百分比形式的 CPU 和内存)。
部署 CronJob,以便每分钟将工作负载自动扩缩器指标发送到 Cloud Monitoring:
sed "s/PROJECT_ID/$PROJECT_ID/g" k8s/templates/metrics-exporter.yaml > k8s/metrics-exporter.yaml kubectl create ns custom-metrics kubectl apply -f k8s/metrics-exporter.yaml
如果您在自己的集群(而不是之前创建的集群)中运行本教程,且该集群已启用 Workload Identity,请务必按照使用 Workload Identity 中的步骤操作,以允许将指标导出到 Cloud Monitoring。
为集群中的所有 Deployment、StatefulSet 和 DaemonSet 对象创建 VPA:
rm k8s/vpas.yaml 2> /dev/null ALL_NAMESPACES=$(kubectl get namespaces -o jsonpath={.items[*].metadata.name}) for NAMESPACE in $ALL_NAMESPACES do kubectl get deployments,statefulset,daemonset -n $NAMESPACE -o go-template-file=k8s/templates/vpa.gtpl >> k8s/vpas.yaml done kubectl apply -f k8s/vpas.yaml
上面的代码段为所有命名空间中的所有对象(包括系统对象)创建
Off
模式的 VPA。此方法可以在集群级层和节点池级层提供更准确的建议。但是,为避免使 metrics-server 服务过载,我们建议您不要在部署了数百个应用的大型集群中按原样执行上述脚本。对于大型集群场景,我们建议您仅针对要进行费用优化的命名空间运行上述脚本。在这种场景中,集群和节点池级层的建议是不准确的,因此请忽略或移除这些建议。
设置用于监控资源利用率和建议的信息中心
在 Google Cloud Console 中,前往监控页面。
创建项目。
- 在将您的项目添加到工作区页面中,选择您的 Cloud 项目。
- 点击添加。
创建工作区可能需要几分钟的时间。
在 Cloud Shell 中,动态生成用于费用优化的信息中心:
YOUR_NAMESPACES=$( echo $ALL_NAMESPACES| sed 's/[a-zA-Z0-9_.-]*-system//g; s/gke-[a-zA-Z0-9_.-]*//g; s/kube-public//g; s/kube-node-lease//g; s/custom-metrics//g') for NAMESPACE in $YOUR_NAMESPACES do GTPL_FILE='./monitoring/dashboards/templates/app-rightsizing.gtpl' OUTPUT_FILE="./monitoring/dashboards/app-rightsizing-$CLUSTER-$NAMESPACE.yaml" kubectl get deployments,statefulset,daemonset -n $NAMESPACE -o go-template-file=$GTPL_FILE > $OUTPUT_FILE sed -i.bkp "s/CLUSTER_TO_REPLACE/$CLUSTER/g" $OUTPUT_FILE sed -i.bkp "s/NAMESPACE_TO_REPLACE/$NAMESPACE/g" $OUTPUT_FILE replace="" i=0 while : ; do if grep -q "Y_POS_TO_REPLACE_$i" $OUTPUT_FILE then ((yPos=12 + (4 * $i))) replace="s/Y_POS_TO_REPLACE_$i/$yPos/g; ${replace}" ((i=i+1)) else break fi done eval "sed -i.bkp '$replace' $OUTPUT_FILE" rm "$OUTPUT_FILE.bkp" done sed "s/CLUSTER_TO_REPLACE/$CLUSTER/g" ./monitoring/dashboards/templates/binpacking.yaml > ./monitoring/dashboards/binpacking.yaml
除了创建装箱信息中心之外,此脚本还会为集群中的每个命名空间生成优化应用容量信息中心,但不包括系统命名空间。在本教程中,脚本仅为
default
命名空间生成一个信息中心,因为 Online Boutique 完全部署在该命名空间中。但是,如果您在自己的 GKE 集群中运行相同的脚本,该脚本会为每个命名空间生成一个信息中心。将生成的信息中心导入 Cloud Monitoring:
for filename in monitoring/dashboards/*.yaml; do echo "Creating dashboard policy based on file: $filename" gcloud monitoring dashboards create \ --config-from-file=$filename done
输出内容类似如下:
Creating dashboard policy based on file: monitoring/dashboards/app-rightsizing-gke-cost-optimization-monitoring-default.yaml Created [9c1a6cb6-3424-44a8-b824-f2ec959f6588]. Creating dashboard policy based on file: monitoring/dashboards/binpacking.yaml Created [97f6349d-4880-478d-9da8-ca3c8a433093].
查看优化应用容量信息中心
转到 Monitoring 信息中心页面。
点击 GKE - App Right-Sizing (gke-cost-optimization-monitoring:default) 信息中心。
本部分的其余内容介绍如何查看和解读信息中心中显示的图表。
已安装的演示环境具有稳定的模拟负载。换句话说,图表不会随时间发生大的变化。但如果您在自己的集群中运行相同的教程,则需要等待几个小时(最好是 24 小时或更长时间),以查看扩容和缩容的动态变化以及一天内和一周内的负载分布变化。
如上图所示,信息中心的前三行总结了以下汇总的命名空间信息:
- 第一行:CPU 和内存:命名空间过度供应。提供应用在此给定命名空间内的费用优化程度的概览。
- 第二行:CPU 和内存:前 5 个过度供应的应用。显示寻求改善命名空间的方法时应该首先关注的应用。
- 第三行:CPU 和内存:前 5 个供应不足的应用。与第二行类似,此行显示需要特别关注的应用。但是,在此场景中,您关注的不是节省费用,而是使应用在集群中顺畅运行。如果您看到“无可用数据”消息,则表示未发现机会。
下图是信息中心中显示的每个应用的 CPU、内存和副本的详细信息。每一行代表给定命名空间中的一个应用。通过将开发者请求的应用资源(requested_<cores|memory>
行)与应用实际使用的资源(used_<cores|memory>
行)进行比较,此信息对于优化应用容量非常有用。
以下部分讨论了以上图表中的三行。
第一行:CPU (p/pod)
根据工作负载的配置方式,这些图表显示了可帮助您确定适合应用的容量的不同提示:
VPA CPU 建议 (
vpa_recommended_cores
):如果应用未配置 HPA(信息中心内的CPU: adservice (p/Pod)
图表)或者 HPA 配置了除 CPU 以外的任何指标(信息中心中内的CPU: cartservice (p/Pod)
图表),则会显示此提示。如果您看到这些提示,我们强烈建议您以静态方式应用这些提示,或者如果您愿意查看图表历史记录,请以Initial
或Auto
模式启用 VPA。HP CPU 目标利用率 (
hpa_target_utilization
):如果应用基于 CPU 利用率配置了 HPA(所有其他 CPU 图表),则会显示此提示。在此场景中,我们建议您执行以下操作:- 过度供应情况:如果实际利用率 (
used_cores
) 始终远远低于 HPA 目标 (hpa_target_utilization
),则表示部署以 HPAminReplicas
值中指定的值运行。在此场景中,建议的操作是减小minReplicas
值。 - 供应不足情况:如果实际利用率 (
used_cores
) 始终高于 HPA 目标 (hpa_target_utilization
),则表示部署以 HPAmaxReplicas
值中指定的值运行。此处建议的操作是提高maxReplicas
值或增加请求的资源以增大 pod。 - 了解扩容和缩容:查看
CPU
和Replicas
图表,了解 CPU 上的 HPA 何时触发 pod 扩容和缩容。 - HPA 目标利用率微调:在将任何内容应用于您的环境之前,请查看我们的最佳做法。
- 此外,请务必避免在同一工作负载中将 VPA 和 HPA 与 CPU 或内存混合使用。为此,请使用 MPA。
- 过度供应情况:如果实际利用率 (
第二行:内存 (p/pod)
与 CPU 行类似,根据工作负载的配置方式,这些图表显示了可帮助您确定适合应用的容量的不同提示:
VPA 内存建议 (
vpa_recommended_bytes
):如果应用未配置 HPA(信息中心内的Mem: adservice (p/Pod)
图表)或者 HPA 配置了除内存以外的任何指标(例如Men: emailservice (p/Pod)
),则会显示此提示。请考虑应用此类建议以避免资源浪费和“Out Of Memory Kill”(OOMKill) 事件,或者如果您愿意查看图表历史记录,请以Initial
或Auto
模式启用 VPA。HPA 内存目标利用率 (
hpa_target_utilization
):如果应用基于内存利用率配置了 HPA(信息中心内的Mem: cartservice (p/Pod)
图表),则会显示此提示。在此场景中,我们建议您执行以下操作:- 过度供应情况:如果实际利用率 (
used_bytes
) 始终远远低于 HPA 目标 (hpa_target_utilization
),则表示部署以 HPAminReplicas
值中指定的值运行。在此场景中,建议的操作是减小minReplicas
值。 - 供应不足情况:如果实际利用率 (
used_bytes
) 始终高于 HPA 目标 (hpa_target_utilization
),则表示部署以 HPAmaxReplicas
值中指定的值运行。此处建议的操作是提高maxReplicas
值或增加请求的资源以增大 pod。 - 了解扩容和缩容:查看
Mem
和Replicas
图表,了解内存上的 HPA 何时触发 pod 扩容和缩容。 - HPA 目标利用率微调:在将任何内容应用于您的环境之前,请查看我们的最佳做法。
- 此外,请务必避免在同一工作负载中将 VPA 和 HPA 与 CPU 或内存混合使用。为此,请使用 MPA。
- 过度供应情况:如果实际利用率 (
第三行:副本
此行中的图表显示给定应用具有的 pod 数量。此信息对于了解部署了 HPA 的工作负载的实际使用资源相对于建议资源的波动程度非常有用。
查看装箱信息中心
再次转到 Monitoring 信息中心页面。
点击 GKE - Cluster Bin Packing (gke-cost-optimization-monitoring) 信息中心。
如下面的图表所示,装箱信息中心显示按集群(第一行)和节点池(第二行)汇总的信息。通过将集群和节点池中的可分配容量(allocable_<cores|memory>
行)与开发者请求的应用容量 (requested_<cores|memory>
) 进行比较,此信息对于集群装箱非常有用。
您可以基于这些图表运行的一项有用分析是,了解是否有某个资源类型(例如内存)被耗尽,而另一个资源类型(例如 CPU)被浪费。在此场景下,集群自动扩缩器会触发扩容,因为没有内存可用于将被调度的 pod 放入集群中。另一个常见情况与 pod 密度(即每个节点的 pod 数)有关。在节点池:pod 数量图表中,您可以看到每个节点池中的 pod 密度,并将其与配置的信息进行比较(图表中未提供)。达到节点池的配置密度时,CA 将启动新节点以放入被调度的 pod,即使有足够的 CPU 和内存可用也是如此。
上面的信息中心未提供的另一项重要分析与自动扩缩器的最小和最大配置相关。例如,集群可能不会在夜间缩容,因为您的 HPA 或 CA 需求超过了最小值。此外,CA 可能未在预期的节点池中启动 pod,因为该节点池可能已达到配置的节点数上限。
信息中心限制
- 虽然优化应用容量信息中心显示一个给定命名空间中所有应用的汇总信息,但由于单个信息中心内微件数量的限制,它仅显示前 8 个应用(按名称排序)的 CPU、内存和副本信息。如果您发现显示的应用不是最重要的应用,请修改信息中心以满足您的需求。
- 装箱信息中心提供集群和节点池的汇总数据。在处理大量集群或节点池时,可视化会受到限制,因为不允许针对用于构建图表的 Monitoring Query Language (MQL) 运行过滤条件。
- 在监控包含数百个应用的大型集群时,装箱信息中心需要很长时间来加载。在这种情况下,为了减少加载的数据量,建议您不要使用太长的时间段来过滤信息中心。
设置过度供应和供应不足提醒政策
当贵公司的财务团队询问您为何云帐单金额最近增长了一倍时,您大概不希望告诉他们这是由于过度供应的问题。为避免这种情况,我们强烈建议您创建提醒政策,在您的环境开始偏离计划时触发提醒。
在 Cloud Shell 中,创建通知渠道:
gcloud beta monitoring channels create \ --display-name="Cost Optimization team (Primary)" \ --description="Primary contact method for the Cost Optimization effort" \ --type=email \ --channel-labels=email_address=${ALERT_EMAIL}
输出内容类似如下:
Created notification channel [projects/your_project/notificationChannels/13166436832066782447].
为了简化教程步骤,上述命令创建一个
email
类型的通知渠道。在生产环境中,建议您通过将通知渠道设置为sms
或pagerduty
,使用同步程度较高的策略。设置一个变量,其具有
NOTIFICATION_CHANNEL_ID
占位符中显示的值:NOTIFICATION_CHANNEL_ID=$(gcloud beta monitoring channels list --filter='displayName="Cost Optimization team (Primary)"' | grep 'name:' | sed 's/name: //g')
动态创建和部署提醒政策:
for NAMESPACE in $YOUR_NAMESPACES do for templatefile in monitoring/policies/templates/rightsizing/*.yaml; do outputfile=monitoring/policies/$(basename $templatefile) sed "s/CLUSTER_TO_REPLACE/$CLUSTER/g;s/NAMESPACE_TO_REPLACE/$NAMESPACE/g" $templatefile > $outputfile echo "Creating alert policy based on file: $outputfile" gcloud alpha monitoring policies create \ --policy-from-file=$outputfile \ --notification-channels=$NOTIFICATION_CHANNEL_ID done done for templatefile in monitoring/policies/templates/binpacking/*.yaml; do outputfile=monitoring/policies/$(basename $templatefile) sed "s/CLUSTER_TO_REPLACE/$CLUSTER/g;s/NAMESPACE_TO_REPLACE/$NAMESPACE/g" $templatefile > $outputfile echo "Creating alert policy based on file: $outputfile" gcloud alpha monitoring policies create \ --policy-from-file=$outputfile \ --notification-channels=$NOTIFICATION_CHANNEL_ID done
输出内容类似如下:
Creating alert policy based on file: monitoring/policies/app-rightsizing-cpu-overprovisioning-alert.yaml Created alert policy [projects/rubbo-vpa-3-1/alertPolicies/18091138402474167583]. Creating alert policy based on file: monitoring/policies/app-rightsizing-cpu-underprovisioning-alert.yaml Created alert policy [projects/rubbo-vpa-3-1/alertPolicies/8586234469403227589]. Creating alert policy based on file: monitoring/policies/app-rightsizing-memory-overprovisioning-alert.yaml Created alert policy [projects/rubbo-vpa-3-1/alertPolicies/9685822323903723723]. Creating alert policy based on file: monitoring/policies/app-rightsizing-memory-underprovisioning-alert.yaml Created alert policy [projects/rubbo-vpa-3-1/alertPolicies/15705075159352926212]. Creating alert policy based on file: monitoring/policies/nodepools-binpacking-cpu-overprovisioning-alert.yaml Created alert policy [projects/rubbo-vpa-3-1/alertPolicies/14555072091442814207]. Creating alert policy based on file: monitoring/policies/nodepools-binpacking-memory-overprovisioning-alert.yaml Created alert policy [projects/rubbo-vpa-3-1/alertPolicies/1442392910032052087].
默认情况下,创建的提醒政策包含这样的规范:在超过一天的时间段内,当应用的过度供应超过 80% 并且节点池的过度供应超过 40% 时,则触发提醒。请务必对这些政策进行微调,以满足您的资源利用率要求。
转到 Monitoring 提醒页面以查看提醒政策。
点击任何已创建的政策,然后验证或修改提醒配置的详细信息。
清除数据
为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请执行以下操作。
删除项目
若要避免产生费用,最简单的方法是删除您为本教程创建的项目。
- 在 Google Cloud 控制台中,转到管理资源页面:
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
后续步骤
- 如需详细了解 GKE 费用优化,请参阅在 GKE 上运行费用经过优化的 Kubernetes 应用的最佳做法。
- 如需了解优化 GKE 费用的更多提示和最佳做法,请参阅面向开发者和运维人员的 Google Cloud 费用优化。
- 如需详细了解如何在需求较低的时段优化集群费用,请参阅在非高峰时段缩减 GKE 集群以降低费用。
- 探索有关 Google Cloud 的参考架构、图表和最佳实践。查看我们的 Cloud Architecture Center。