節省 AWS 上的 Kubernetes 雲端成本

文章的翻譯是在課程開始前夕準備的 《基於Kubernetes的基礎建設平台》.

節省 AWS 上的 Kubernetes 雲端成本

使用 Kubernetes 時如何節省雲端成本? 沒有單一正確的解決方案,但本文介紹了幾種可以幫助您更有效地管理資源並降低雲端運算成本的工具。

我寫這篇文章時考慮的是適用於 AWS 的 Kubernetes,但它將以(幾乎)完全相同的方式應用於其他雲端供應商。 我假設您的叢集已經配置了自動縮放(集群自動縮放器)。 刪除資源和縮小部署規模只有在減少工作節點(EC2 執行個體)群的情況下才能節省資金。

本文將涵蓋:

清理未使用的資源

在快節奏的環境中工作非常棒。 我們需要科技組織 加速的。 更快的軟體交付也意味著更多的 PR 部署、預覽環境、原型和分析解決方案。 一切都部署在 Kubernetes 上。 誰有時間手動清理測試部署? 人們很容易忘記刪除一週前的實驗。 由於我們忘記關閉某些事情,雲端帳單最終會增加:

節省 AWS 上的 Kubernetes 雲端成本

(亨寧雅各布斯:
智雜:
(引述)科里·奎因:
迷思:您的 AWS 帳戶取決於您擁有的使用者數量。
事實:您的 AWS 分數取決於您擁有的工程師數量。

伊凡·庫爾諾索夫(回應):
事實:您的 AWS 分數是您忘記禁用/刪除的事物數量的函數。)

Kubernetes 看門人 (kube-janitor) 幫忙清理你的叢集。 看門人配置對於全域和本地使用都很靈活:

  • 群集範圍的規則可以定義 PR/測試部署的最大生存時間 (TTL)。
  • 單一資源可以使用 janitor/ttl 進行註釋,例如在 7 天後自動刪除尖峰/原型。

一般規則在 YAML 檔案中定義。 它的路徑是透過參數傳遞的 --rules-file 在 kube-janitor 中。 以下是刪除所有命名空間的範例規則 -pr- 兩天後的名字:

- id: cleanup-resources-from-pull-requests
  resources:
    - namespaces
  jmespath: "contains(metadata.name, '-pr-')"
  ttl: 2d

以下範例規範了 2020 年所有新 Deployments/StatefulSet 的 Deployment 和 StatefulSet Pod 上應用程式標籤的使用,但同時允許在一周內執行沒有此標籤的測試:

- id: require-application-label
  # удалить deployments и statefulsets без метки "application"
  resources:
    - deployments
    - statefulsets
  # см. http://jmespath.org/specification.html
  jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"
  ttl: 7d

在執行 kube-janitor 的叢集上執行 30 分鐘的限時示範:

kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m

成本增加的另一個來源是持久卷 (AWS EBS)。 刪除 Kubernetes StatefulSet 不會刪除其持久性磁碟區 (PVC - PersistentVolumeClaim)。 未使用的 EBS 磁碟區很容易導致每月數百美元的成本。 Kubernetes Janitor 有一個功能可以清理未使用的 PVC。 例如,此規則將刪除所有未由模組安裝且未由 StatefulSet 或 CronJob 引用的 PVC:

# удалить все PVC, которые не смонтированы и на которые не ссылаются StatefulSets
- id: remove-unused-pvcs
  resources:
  - persistentvolumeclaims
  jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
  ttl: 24h

Kubernetes Janitor 可以幫助您保持叢集清潔並防止雲端運算成本慢慢堆積。 有關部署和配置說明,請遵循 自述文件 kube-janitor.

減少非工作時間結垢

測試和登台系統通常只需要在工作時間內運作。 某些生產應用程式(例如後台/管理工具)也只需要有限的可用性,並且可能會在一夜之間被停用。

Kubernetes 縮減器 (kube-downscaler) 讓使用者和操作員在非工作時間縮小系統規模。 部署和 StatefulSet 可以擴展到零副本。 CronJobs 可能會被暫停。 Kubernetes Downscaler 是針對整個叢集、一個或多個命名空間或單一資源進行配置的。 您可以設定“空閒時間”,也可以設定“工作時間”。 例如,要在夜間和週末盡可能減少縮放:

image: hjacobs/kube-downscaler:20.4.3
args:
  - --interval=30
  # не отключать компоненты инфраструктуры
  - --exclude-namespaces=kube-system,infra
  # не отключать kube-downscaler, а также оставить Postgres Operator, чтобы исключенными БД можно было управлять
  - --exclude-deployments=kube-downscaler,postgres-operator
  - --default-uptime=Mon-Fri 08:00-20:00 Europe/Berlin
  - --include-resources=deployments,statefulsets,stacks,cronjobs
  - --deployment-time-annotation=deployment-time

下面是週末擴展叢集工作節點的圖表:

節省 AWS 上的 Kubernetes 雲端成本

從大約 13 個工作節點縮減到 4 個工作節點肯定會對您的 AWS 帳單產生顯著影響。

但是如果我需要在叢集「停機」期間工作怎麼辦? 透過新增 downscaler/exclude: true 註釋,可以永久排除某些部署的擴充。 可以使用 downscaler/exclude-until 註解和格式為 YYYY-MM-DD HH:MM (UTC) 的絕對時間戳暫時排除部署。 如果有必要,可以透過部署帶有註解的 pod 來縮減整個集群 downscaler/force-uptime,例如,透過啟動 nginx 空白:

kubectl run scale-up --image=nginx
kubectl annotate deploy scale-up janitor/ttl=1h # удалить развертывание через час
kubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=true

自述文件 kube-downscaler,如果您對部署說明和其他選項感興趣。

使用水平自動縮放

許多應用程式/服務處理動態載入模式:有時它們的模組空閒,有時它們會滿載工作。 營運永久的 Pod 隊列來應對最大尖峰負載並不經濟。 Kubernetes 支援跨資源的水平自動縮放 水平Pod自動縮放器 (HPA)。 CPU 使用率通常是縮放的一個很好的指標:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        averageUtilization: 100
        type: Utilization

Zalando 創建了一個元件來輕鬆連接自訂指標以進行擴展: Kube 指標適配器 (kube-metrics-adapter) 是 Kubernetes 的通用指標適配器,可收集和提供用於 pod 水平自動縮放的自訂和外部指標。 它支援基於 Prometheus 指標、SQS 佇列和其他設定的擴充。 例如,要將部署擴展到由應用程式本身表示為 /metrics 中的 JSON 的自訂指標,請使用:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
  annotations:
    # metric-config.<metricType>.<metricName>.<collectorName>/<configKey>
    metric-config.pods.requests-per-second.json-path/json-key: "$.http_server.rps"
    metric-config.pods.requests-per-second.json-path/path: /metrics
    metric-config.pods.requests-per-second.json-path/port: "9090"
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: requests-per-second
      target:
        averageValue: 1k
        type: AverageValue

使用 HPA 配置水平自動縮放應該是提高無狀態服務效率的預設操作之一。 Spotify 有一個演示,介紹了他們對 HPA 的經驗和建議: 擴展您的部署,而不是您的錢包.

減少資源超額預訂

Kubernetes 工作負載透過「資源請求」確定其 CPU/記憶體需求。 CPU 資源以虛擬核心或更常見的「毫核心」來衡量,例如 500m 意味著 50% vCPU。 記憶體資源以位元組為單位,可以使用常見的後綴,如500Mi,表示500兆位元組。 資源請求「鎖定」工作節點上的容量,這表示在具有 1000 個 vCPU 的節點上具有 4m CPU 請求的 pod 將僅留下 3 個 vCPU 可供其他 pod 使用。 [1]

鬆弛(超額儲備) 是請求的資源和實際使用之間的差異。 例如,請求 2 GiB 記憶體但僅使用 200 MiB 的 Pod 具有約 1,8 GiB 的「過剩」記憶體。 過量需要花錢。 人們可以粗略估計 1 GiB 冗餘記憶體的成本約為每月 10 美元。 [2]

Kubernetes 資源報告 (kube-resource-report) 顯示超額儲備並且可以幫助您確定節省潛力:

節省 AWS 上的 Kubernetes 雲端成本

Kubernetes 資源報告 顯示按應用程式和命令聚合的多餘部分。 這使您可以找到可以減少資源需求的地方。 產生的 HTML 報告僅提供資源使用情況的快照。 您應該查看一段時間內的 CPU/記憶體使用情況,以確定足夠的資源請求。 以下是「典型」CPU 密集型服務的 Grafana 圖表:所有 Pod 所使用的 CPU 核心均明顯少於 3 個請求的 CPU 核心:

節省 AWS 上的 Kubernetes 雲端成本

將 CPU 請求從 3000m 減少到約 400m 可以為其他工作負載釋放資源,並允許叢集更小。

“EC2 執行個體的平均 CPU 使用率通常徘徊在個位數百分比範圍內,” 科里·奎因寫道。 而對於 EC2 估計正確的尺寸可能是錯誤的決定在 YAML 檔案中更改一些 Kubernetes 資源查詢非常簡單,並且可以帶來巨大的節省。

但我們真的希望人們更改 YAML 檔案中的值嗎? 不,機器可以做得更好! 庫伯內斯 垂直 Pod 自動縮放器 (VPA) 就是這樣做的:根據工作負載調整資源請求和約束。 以下是 VPA 隨著時間推移調整的 Prometheus CPU 請求(細藍線)的範例圖:

節省 AWS 上的 Kubernetes 雲端成本

Zalando 在其所有集群中都使用 VPA 用於基礎設施組件。 非關鍵應用程式也可以使用 VPA。

金發 來自 Fairwind 的工具可以為命名空間中的每個部署建立 VPA,然後在其儀表板上顯示 VPA 建議。 它可以幫助開發人員為其應用程式設定正確的 CPU/記憶體請求:

節省 AWS 上的 Kubernetes 雲端成本

我寫了一個小 關於 VPA 的博文 2019 年以及最近 CNCF 最終用戶社群討論了 VPA 問題.

使用 EC2 Spot 實例

最後但並非最不重要的一點是,透過使用 Spot 執行個體作為 Kubernetes 工作節點可以降低 AWS EC2 成本 [3]。 與按需價格相比,現貨實例的折扣高達 90%。 在EC2 Spot 上執行Kubernetes 是一個很好的組合:您需要指定幾種不同的執行個體類型以獲得更高的可用性,這意味著您可以以相同或更低的價格獲得更大的節點,並且增加的容量可以由容器化Kubernetes 工作負載使用。

如何在 EC2 Spot 上運行 Kubernetes? 有幾種選擇:使用 SpotInst 等第三方服務(現在稱為“Spot”,不要問我為什麼),或者只是將 Spot AutoScalingGroup (ASG) 添加到您的叢集。 例如,以下是具有多種實例類型的「容量最佳化」Spot ASG 的 CloudFormation 程式碼片段:

MySpotAutoScalingGroup:
 Properties:
   HealthCheckGracePeriod: 300
   HealthCheckType: EC2
   MixedInstancesPolicy:
     InstancesDistribution:
       OnDemandPercentageAboveBaseCapacity: 0
       SpotAllocationStrategy: capacity-optimized
     LaunchTemplate:
       LaunchTemplateSpecification:
         LaunchTemplateId: !Ref LaunchTemplate
         Version: !GetAtt LaunchTemplate.LatestVersionNumber
       Overrides:
         - InstanceType: "m4.2xlarge"
         - InstanceType: "m4.4xlarge"
         - InstanceType: "m5.2xlarge"
         - InstanceType: "m5.4xlarge"
         - InstanceType: "r4.2xlarge"
         - InstanceType: "r4.4xlarge"
   LaunchTemplate:
     LaunchTemplateId: !Ref LaunchTemplate
     Version: !GetAtt LaunchTemplate.LatestVersionNumber
   MinSize: 0
   MaxSize: 100
   Tags:
   - Key: k8s.io/cluster-autoscaler/node-template/label/aws.amazon.com/spot
     PropagateAtLaunch: true
     Value: "true"

有關將 Spot 與 Kubernetes 結合使用的一些注意事項:

  • 您需要處理 Spot 終止,例如在實例停止時合併節點
  • 扎蘭多用途 具有節點池優先權的官方叢集自動縮放
  • 現貨節點 可以被強迫 接受在 Spot 中運行的工作負載的“註冊”

總結

我希望您發現所提供的一些工具對於減少雲端費用很有用。 您也可以在以下位置找到本文的大部分內容 我在 2019 年 DevOps Gathering 上的 YouTube 和幻燈片演講.

在 Kubernetes 上節省雲端成本的最佳實踐是什麼? 請讓我知道 推特(@try_except_).

[1] 事實上,由於保留的系統資源減少了節點的吞吐量,因此仍可用的 vCPU 數量將少於 3 個。 Kubernetes 區分實體節點容量和「預先配置」資源(可分配節點).

[2] 計算範例:一個具有 5 GiB 記憶體的 m8.large 實例每月約 84 美元(eu-central-1,按需),即阻塞 1/8 節點的費用約為每月約 10 美元。

[3] 還有很多方法可以減少您的 EC2 帳單,例如預留執行個體、儲蓄計劃等 - 我不會在這裡討論這些主題,但您絕對應該研究它們!

了解有關課程的更多信息。

來源: www.habr.com

添加評論