Xav*_*kel 2 google-cloud-platform kubernetes google-kubernetes-engine
我们在google云平台上搭建了一个GKE集群。
我们有一项需要“爆发”计算能力的活动。
想象一下,我们通常平均每小时进行 100 次计算,然后突然我们需要能够在不到两分钟的时间内处理 100000 次计算。然而大多数时候,一切都接近闲置。
我们不想为 99% 的时间都闲置的服务器付费,并希望根据实际使用情况扩展集群(不需要数据持久化,之后可以删除服务器)。我查找了 kubernetes 上有关自动缩放的可用文档,以使用HPA添加更多 pod 并使用添加更多 pod 以及使用集群自动缩放器
然而,这些解决方案似乎都不会真正降低我们的成本或提高性能,因为它们的扩展似乎无法超出 GCP 计划:
想象一下,我们有一个带有 8 个 CPU 的google 计划。我的理解是,如果我们使用集群自动缩放器添加更多节点,我们将不再是每个使用 4 个 CPU 的 2 个节点,而是每个使用 2 个 CPU 的 4 个节点。但总可用计算能力仍为 8 个 CPU。对于具有更多 pod 而不是更多节点的 HPA,也有同样的推理。
如果我们有 8 个 CPU 付款计划,但只使用其中 4 个,我的理解是我们仍然需要按 8 个 CPU 付费,因此缩小规模并不是很有用。
我们想要的是自动缩放以暂时更改我们的付款计划(想象一下从 n1-standard-8 到 n1-standard-16)并获得实际的新计算能力。
我不敢相信我们是唯一拥有此用例的人,但我在任何地方都找不到任何相关文档!我是不是误会了什么?
长话短说:
\n\nGKE 定价:
\n\n\n从 2020 年 6 月 6 日开始,GKE 将收取每个集群每小时 0.10 美元的集群管理费。集群管理费适用以下条件:
\n\n\n
\n- 每个计费帐户一个 区域集群 是 免费的。
\n- 无论集群大小和拓扑如何,费用都是固定的。
\n- 每个集群的计费是按秒计算的。每月月底,总额四舍五入到最接近的美分。
\n
来自工作节点的定价:
\n\n\nGKE 使用 Compute Engine 实例作为集群中的工作节点。您需要根据Compute Engine 的定价为每个实例付费,直到节点被删除为止。Compute Engine 资源按秒计费,一分钟最低使用成本。
\n
输入,集群自动缩放器:
\n\n\n根据工作负载的需求自动调整 GKE 集群\xe2\x80\x99s 节点池的大小。当需求较高时,集群自动缩放程序会将节点添加到节点池中。当需求较低时,集群自动缩放程序会缩小到您指定的最小大小。这可以在您需要时提高工作负载的可用性,同时控制成本。
\n
由于您已经有持久的工作负载,这不会成为问题,我们要做的是创建一个新的节点池:
\n\n\n节点池是集群中具有相同配置的一组节点。每个集群至少有一个 默认 节点池,但您可以根据需要添加其他节点池。
\n
对于此示例,我将创建两个节点池:
\n\nn1-standard-8.污染和容忍:
\n\n再生产:
\n\nPROJECT_ID="YOUR_PROJECT_ID" \nGCP_ZONE="CLUSTER_ZONE" \nGKE_CLUSTER_NAME="CLUSTER_NAME" \nAUTOSCALE_POOL="power-pool" \n\ngcloud container clusters create ${GKE_CLUSTER_NAME} \\\n--machine-type="n1-standard-1" \\\n--num-nodes=1 \\\n--zone=${GCP_ZONE} \\\n--project=${PROJECT_ID}\nRun Code Online (Sandbox Code Playgroud)\n\ngcloud container node-pools create ${GKE_BURST_POOL} \\\n--cluster=${GKE_CLUSTER_NAME} \\\n--machine-type=n1-standard-8 \\\n--node-labels=load=on-demand \\\n--node-taints=reserved-pool=true:NoSchedule \\\n--enable-autoscaling \\\n--min-nodes=0 \\\n--max-nodes=4 \\\n--zone=${GCP_ZONE} \\\n--project=${PROJECT_ID}\nRun Code Online (Sandbox Code Playgroud)\n\n参数注意事项:
\n\n--node-labels=load=on-demand:为电源池中的节点添加标签,以允许使用节点选择器在我们的 AI 作业中选择它们。--node-taints=reserved-pool=true:NoSchedule: 向节点添加污点,以防止在此节点池中意外调度任何其他工作负载。在这里您可以看到我们创建的两个池,具有 1 个节点的静态池和具有 0-4 个节点的可自动扩展池。
由于我们没有在可自动扩展的节点池上运行工作负载,因此它显示 0 个节点正在运行(并且在没有节点执行时免费)。
\n\nparallelism: 4:使用全部 4 个节点来增强性能nodeSelector.load: on-demand:分配给具有该标签的节点。podAntiAffinity:声明我们不希望两个具有相同标签的 Pod app: greedy-job 在同一节点中运行(可选)。tolerations:以使容忍度与我们附加到节点的污点相匹配,因此允许在这些节点中调度这些 pod。apiVersion: batch/v1 \nkind: Job \nmetadata: \n name: greedy-job \nspec: \n parallelism: 4 \n template: \n metadata: \n name: greedy-job \n labels: \n app: greedy-app \n spec: \n containers: \n - name: busybox \n image: busybox \n args: \n - sleep \n - "300" \n nodeSelector: \n load: on-demand \n affinity: \n podAntiAffinity: \n requiredDuringSchedulingIgnoredDuringExecution: \n - labelSelector: \n matchExpressions: \n - key: app \n operator: In \n values: \n - greedy-app \n topologyKey: "kubernetes.io/hostname" \n tolerations: \n - key: reserved-pool \n operator: Equal \n value: "true" \n effect: NoSchedule \n restartPolicy: OnFailure\nRun Code Online (Sandbox Code Playgroud)\n\ngreedyjob.yaml)。此作业将运行四个并行运行的进程,并将在大约 5 分钟后完成。$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 42m v1.14.10-gke.27\n\n$ kubectl get pods\nNo resources found in default namespace.\n\n$ kubectl apply -f greedyjob.yaml \njob.batch/greedy-job created\n\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 0/1 Pending 0 11s\ngreedy-job-72j8r 0/1 Pending 0 11s\ngreedy-job-9dfdt 0/1 Pending 0 11s\ngreedy-job-wqct9 0/1 Pending 0 11s\nRun Code Online (Sandbox Code Playgroud)\n\n$ kubectl describe pod greedy-job-2xbvx\n...\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Warning FailedScheduling 28s (x2 over 28s) default-scheduler 0/1 nodes are available: 1 node(s) didn\'t match node selector.\n Normal TriggeredScaleUp 23s cluster-autoscaler pod triggered scale-up: [{https://content.googleapis.com/compute/v1/projects/owilliam/zones/us-central1-b/instanceGroups/gke-autoscale-to-zero-clus-power-pool-564148fd-grp 0->1 (max: 4)}]\nRun Code Online (Sandbox Code Playgroud)\n\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 0/1 Pending 0 93s\ngreedy-job-72j8r 0/1 ContainerCreating 0 93s\ngreedy-job-9dfdt 0/1 Pending 0 93s\ngreedy-job-wqct9 0/1 Pending 0 93s\n\n$ kubectl nodes\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 44m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 11s v1.14.10-gke.27\nRun Code Online (Sandbox Code Playgroud)\n\n$ k describe pod greedy-job-2xbvx\n...\nEvents:\n Type Reason Age From Message\n ---- ------ ---- ---- -------\n Normal TriggeredScaleUp 2m45s cluster-autoscaler pod triggered scale-up: [{https://content.googleapis.com/compute/v1/projects/owilliam/zones/us-central1-b/instanceGroups/gke-autoscale-to-zero-clus-power-pool-564148fd-grp 0->1 (max: 4)}]\n Warning FailedScheduling 93s (x3 over 2m50s) default-scheduler 0/1 nodes are available: 1 node(s) didn\'t match node selector.\n Warning FailedScheduling 79s (x3 over 83s) default-scheduler 0/2 nodes are available: 1 node(s) didn\'t match node selector, 1 node(s) had taints that the pod didn\'t tolerate.\n Normal TriggeredScaleUp 62s cluster-autoscaler pod triggered scale-up: [{https://content.googleapis.com/compute/v1/projects/owilliam/zones/us-central1-b/instanceGroups/gke-autoscale-to-zero-clus-power-pool-564148fd-grp 1->2 (max: 4)}]\n Warning FailedScheduling 3s (x3 over 68s) default-scheduler 0/2 nodes are available: 1 node(s) didn\'t match node selector, 1 node(s) didn\'t match pod affinity/anti-affinity, 1 node(s) didn\'t satisfy existing pods anti-affinity rules.\nRun Code Online (Sandbox Code Playgroud)\n\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 0/1 Pending 0 3m39s\ngreedy-job-72j8r 1/1 Running 0 3m39s\ngreedy-job-9dfdt 0/1 Pending 0 3m39s\ngreedy-job-wqct9 1/1 Running 0 3m39s\n\n$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 46m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 2m16s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-sf6q Ready <none> 28s v1.14.10-gke.27\n\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 0/1 Pending 0 5m19s\ngreedy-job-72j8r 1/1 Running 0 5m19s\ngreedy-job-9dfdt 1/1 Running 0 5m19s\ngreedy-job-wqct9 1/1 Running 0 5m19s\n\n$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 48m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-39m2 Ready <none> 63s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 4m8s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-sf6q Ready <none> 2m20s v1.14.10-gke.27\n\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 1/1 Running 0 6m12s\ngreedy-job-72j8r 1/1 Running 0 6m12s\ngreedy-job-9dfdt 1/1 Running 0 6m12s\ngreedy-job-wqct9 1/1 Running 0 6m12s\n\n$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 48m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-39m2 Ready <none> 113s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-ggxv Ready <none> 26s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 4m58s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-sf6q Ready <none> 3m10s v1.14.10-gke.27\nRun Code Online (Sandbox Code Playgroud)\n\n
\n
\n在这里我们可以看到所有节点现在都已启动并正在运行(因此,按秒计费)
$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 1/1 Running 0 7m22s\ngreedy-job-72j8r 0/1 Completed 0 7m22s\ngreedy-job-9dfdt 1/1 Running 0 7m22s\ngreedy-job-wqct9 1/1 Running 0 7m22s\n\n$ kubectl get pods\nNAME READY STATUS RESTARTS AGE\ngreedy-job-2xbvx 0/1 Completed 0 11m\ngreedy-job-72j8r 0/1 Completed 0 11m\ngreedy-job-9dfdt 0/1 Completed 0 11m\ngreedy-job-wqct9 0/1 Completed 0 11m\nRun Code Online (Sandbox Code Playgroud)\n\n$ while true; do kubectl get nodes ; sleep 60; done\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 54m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-39m2 Ready <none> 7m26s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-ggxv Ready <none> 5m59s v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 10m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-sf6q Ready <none> 8m43s v1.14.10-gke.27\n\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 62m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-39m2 Ready <none> 15m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-ggxv Ready <none> 14m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 18m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-sf6q NotReady <none> 16m v1.14.10-gke.27\nRun Code Online (Sandbox Code Playgroud)\n\nNotReady并开始删除它们:NAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 64m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-39m2 NotReady <none> 17m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-ggxv NotReady <none> 16m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw Ready <none> 20m v1.14.10-gke.27\n\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 65m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-39m2 NotReady <none> 18m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-ggxv NotReady <none> 17m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-qxkw NotReady <none> 21m v1.14.10-gke.27\n\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 66m v1.14.10-gke.27\ngke-autoscale-to-zero-clus-power-pool-564148fd-ggxv NotReady <none> 18m v1.14.10-gke.27\n\nNAME STATUS ROLES AGE VERSION\ngke-autoscale-to-zero-cl-default-pool-9f6d80d3-x9lb Ready <none> 67m v1.14.10-gke.27\nRun Code Online (Sandbox Code Playgroud)\n\n计算引擎:(请注意,这是来自另一个集群,我将其添加到屏幕截图中是为了向您展示除了默认的持久节点之外,gke-cluster-1-default-pool集群中没有其他节点。)\ngke-autoscale-to-zero
最后的想法:
\n\n\n\n\n缩小规模时,集群自动缩放程序会遵守 Pod 上设置的调度和驱逐规则。这些限制可以防止自动缩放程序删除节点。如果节点包含具有以下任一条件的 Pod,则可以阻止删除该节点:\n 应用程序的PodDisruptionBudget也可以阻止自动缩放;如果删除节点会导致超出预算,则集群不会缩小规模。
\n
您可以注意到,这个过程非常快,在我们的示例中,升级节点大约需要 90 秒,完成缩减备用节点需要 5 分钟,这为您的计费带来了巨大的改善。
\n\n\n\n\n可抢占式虚拟机是最多持续 24 小时且不提供可用性保证的Compute Engine虚拟机实例。抢占式虚拟机的价格低于标准 Compute Engine 虚拟机,并提供相同的机器类型和选项。
\n
我知道您仍在考虑最适合您的应用程序的架构。
\n\n使用APP Engine和IA Platform也是最佳解决方案,但由于您当前在 GKE 上运行工作负载,我想根据要求向您展示一个示例。
\n\n如果您还有任何其他问题,请在评论中告诉我。
\n| 归档时间: |
|
| 查看次数: |
1526 次 |
| 最近记录: |