Crane: 腾讯开源一款基于 FinOps 超强大云资源分析与成本优化平台
公眾號關注?「奇妙的 Linux 世界」
設為「星標」,每天帶你玩轉 Linux !
Crane(https://gocrane.io/) 是一個基于 FinOps 的云資源分析與成本優化平臺,它的愿景是在保證客戶應用運行質量的前提下實現極致的降本。Crane 已經在騰訊內部自研業務實現了大規模落地,部署數百個 K8s?集群、管控 CPU 核數達百萬,在降本增效方面取得了階段性成果。
以騰訊某部門集群優化為例,通過使用 FinOps Crane,該部門在保障業務穩定的情況下,資源利用率提升了 3 倍;騰訊另一自研業務落地 Crane 后,在一個月內實現了總 CPU 規模 40 萬核的節省量,相當于成本節約超 1000 萬元/月。
Crane?會通過下面 3 個方面來開啟成本優化之旅:
成本展示: Kubernetes 資源( Deployments, StatefulSets )的多維度聚合與展示。
成本分析: 周期性的分析集群資源的狀態并提供優化建議。
成本優化: 通過豐富的優化工具更新配置達成降本的目標。
核心功能包括:成本可視化和優化評估;內置了多種推薦器 - 資源推薦、副本推薦、閑置資源推薦;基于預測的水平彈性器;負載感知的調度器;基于 QOS 的混部。下面我們來詳細了解下 Crane 的各項功能。
安裝
我們這里使用 Helm 的方式來進行安裝,首先需要安裝 Prometheus 和 Grafana(如果您已經在環境中部署了 Prometheus 和 Grafana,可以跳過該步驟)。
Crane?使用 Prometheus 獲取集群工作負載對資源的使用情況,可以使用如下所示命令安裝 Prometheus:
$?helm?repo?add?prometheus-community?https://finops-helm.pkg.coding.net/gocrane/prometheus-community $?helm?upgrade?--install?prometheus?-n?crane-system?\--set?pushgateway.enabled=false?\--set?alertmanager.enabled=false?\--set?server.persistentVolume.enabled=false?\-f?https://gitee.com/finops/helm-charts/raw/main/integration/prometheus/override_values.yaml?\--create-namespace??prometheus-community/prometheus由于 Crane 的?Fadvisor?會使用 Grafana 來展示成本預估,所以我們也需要安裝 Grafana:
$?helm?repo?add?grafana?https://finops-helm.pkg.coding.net/gocrane/grafana $?helm?upgrade?--install?grafana?\-f?https://gitee.com/finops/helm-charts/raw/main/integration/grafana/override_values.yaml?\-n?crane-system?\--create-namespace?grafana/grafana上面我們指定的 values 文件中配置了 Prometheus 數據源以及一些相關的 Dashboard,直接安裝后即可使用。
然后接下來安裝 crane 與 fadvisor,同樣直接使用 Helm Chart 安裝即可,如下命令所示:
$?helm?repo?add?crane?https://finops-helm.pkg.coding.net/gocrane/gocrane $?helm?upgrade?--install?crane?-n?crane-system?--create-namespace?crane/crane $?helm?upgrade?--install?fadvisor?-n?crane-system?--create-namespace?crane/fadvisor安裝后可以查看 Pod 列表了解應用狀態:
$?kubectl?get?pods?-n?crane-system NAME?????????????????????????????????????????????READY???STATUS?????????????RESTARTS?????????AGE crane-agent-8jrs5????????????????????????????????0/1?????CrashLoopBackOff???71?(2m26s?ago)???3h23m crane-agent-t2rpz????????????????????????????????0/1?????CrashLoopBackOff???71?(65s?ago)?????3h23m craned-776c7b6c75-gx8cp??????????????????????????2/2?????Running????????????0????????????????3h28m fadvisor-56fcc547b6-zvf6r????????????????????????1/1?????Running????????????0????????????????158m grafana-5cd57f9f6b-d7nk5?????????????????????????1/1?????Running????????????0????????????????3h32m metric-adapter-887f6548d-qcbb8???????????????????1/1?????Running????????????0????????????????3h28m prometheus-kube-state-metrics-5f6f856ffb-4lrrr???1/1?????Running????????????0????????????????3h34m prometheus-node-exporter-97vmz???????????????????1/1?????Running????????????0????????????????3h27m prometheus-node-exporter-m2gr9???????????????????1/1?????Running????????????0????????????????3h27m prometheus-server-7744f66fb4-lw2sz???????????????2/2?????Running????????????0????????????????3h34m需要注意我們這里 crane-agent 啟動失敗了,這是因為我的 K8s 集群使用的是 containerd 這種容器運行時,需要明確聲明指定使用的運行時 endpoint:
$?kubectl?edit?ds?crane-agent?-n?crane-system #?......spec:containers:-?args:-?--v=2-?--runtime-endpoint=/run/containerd/containerd.sock??#?指定有containerd的sock文件command:-?/crane-agent #?......此外還需要更新 crane-agent 的 rbac 權限:
$?kubectl?edit?clusterrole?crane-agent #?...... -?apiGroups:-?ensurance.crane.ioresources:-?podqosensurancepolicies-?nodeqoss??#?增加?nodeqoss?和?podqoss?資源的權限-?podqoss #?......然后我們可以再創建一個 Ingress 對象來暴露 crane 的 dashboard 服務:
apiVersion:?networking.k8s.io/v1 kind:?Ingress metadata:name:?ingress-crane-dashboardnamespace:?crane-system spec:ingressClassName:?nginxrules:-?host:?crane.k8s.local?#?change?to?your?domainhttp:paths:-?path:?/pathType:?Prefixbackend:service:name:?cranedport:number:?9090直接應用該 ingress 資源對象即可,當然前提是你已經安裝了 ingress-nginx:
$?kubectl?get?pods?-n?ingress-nginx NAME????????????????????????????????????????????READY???STATUS????RESTARTS??????AGE ingress-nginx-controller-7647c44fb9-6gcsf???????1/1?????Running???8?(44m?ago)???21d ingress-nginx-defaultbackend-7fc5bfd66c-gqmmj???1/1?????Running???8?(44m?ago)???21d $?kubectl?get?ingress?-n?crane-system NAME??????????????????????CLASS???HOSTS?????????????ADDRESS????????PORTS???AGE ingress-crane-dashboard???nginx???crane.k8s.local???192.168.0.52???80??????11s將?crane.k8s.local?映射到?192.168.0.52?后就可以訪問 crane 的 dashboard 了:
第一次訪問 dashboard 的時候需要添加一個 K8s 集群,添加添加集群按鈕開始添加,填入正確的?CRNE Endpoint?地址即可。
然后切換到集群總覽可以查看到當前集群的一些成本相關數據,由于目前數據還不足,所以會有一些空的圖表。
在成本分布頁面可以按照維度成本、集群成本和利用率指標以及命名空間成本來展示成本的分布情況。智能推薦
在 dasbhoard 中開箱后就可以看到相關的成本數據,是因為在添加集群的時候我們安裝了推薦的規則。
推薦框架會自動分析集群的各種資源的運行情況并給出優化建議。Crane?的推薦模塊會定期檢測發現集群資源配置的問題,并給出優化建議。智能推薦提供了多種 Recommender 來實現面向不同資源的優化推薦。
在成本分析>推薦規則頁面可以看到我們安裝的兩個推薦規則。
這些推薦規則實際上是安裝在 K8s 集群上的?RecommendationRule CRD對象:$?kubectl?get?RecommendationRule NAME?????????????RUNINTERVAL???AGE idlenodes-rule???24h???????????16m workloads-rule???24h???????????16m
workloads-rule?這個推薦規則的資源對象如下所示:
apiVersion:?analysis.crane.io/v1alpha1 kind:?RecommendationRule metadata:name:?workloads-rulelabels:analysis.crane.io/recommendation-rule-preinstall:?"true" spec:resourceSelectors:-?kind:?DeploymentapiVersion:?apps/v1-?kind:?StatefulSetapiVersion:?apps/v1namespaceSelector:any:?truerunInterval:?24hrecommenders:-?name:?Replicas-?name:?ResourceRecommendationRule?是一個全部范圍內的對象,該推薦規則會對所有命名空間中的 Deployments 和 StatefulSets 做資源推薦和副本數推薦。相關規范屬性如下所示:
每隔 24 小時運行一次分析推薦,runInterval?格式為時間間隔,比如: 1h,1m,設置為空表示只運行一次。
待分析的資源通過配置?resourceSelectors?數組設置,每個?resourceSelector?通過?kind、apiVersion、name?選擇 K8s 中的資源,當不指定 name 時表示在?namespaceSelector?基礎上的所有資源。
namespaceSelector?定義了待分析資源的命名空間,any: true?表示選擇所有命名空間。
recommenders?定義了待分析的資源需要通過哪些?Recommender?進行分析。目前支持兩種?Recommender:
資源推薦(Resource): 通過 VPA 算法分析應用的真實用量推薦更合適的資源配置
副本數推薦(Replicas): 通過 HPA 算法分析應用的真實用量推薦更合適的副本數量
資源推薦
Kubernetes 用戶在創建應用資源時常常是基于經驗值來設置 request 和 limit,通過資源推薦的算法分析應用的真實用量推薦更合適的資源配置,你可以參考并采納它提升集群的資源利用率。該推薦算法模型采用了 VPA 的滑動窗口(Moving Window)算法進行推薦:
通過監控數據,獲取 Workload 過去一周(可配置)的 CPU 和內存的歷史用量。
算法考慮數據的時效性,較新的數據采樣點會擁有更高的權重。
CPU 推薦值基于用戶設置的目標百分位值計算,內存推薦值基于歷史數據的最大值。
副本數推薦
Kubernetes 用戶在創建應用資源時常常是基于經驗值來設置副本數。通過副本數推薦的算法分析應用的真實用量推薦更合適的副本配置,同樣可以參考并采納它提升集群的資源利用率。其實現的基本算法是基于工作負載歷史 CPU 負載,找到過去七天內每小時負載最低的 CPU 用量,計算按 50%(可配置)利用率和工作負載 CPU Request 應配置的副本數。
當我們部署 crane 的時候會在同一個命名空間中創建一個名為?recommendation-configuration?的 ConfigMap 對象,包含一個 yaml 格式的?RecommendationConfiguration,該配置訂閱了?recommender?的配置,如下所示:
$?kubectl?get?cm?recommendation-configuration?-n?crane-system?-oyaml apiVersion:?v1 data:config.yaml:?|-apiVersion:?analysis.crane.io/v1alpha1kind:?RecommendationConfigurationrecommenders:-?name:?Replicas??#?副本數推薦acceptedResources:-?kind:?DeploymentapiVersion:?apps/v1-?kind:?StatefulSetapiVersion:?apps/v1-?name:?Resource??#?資源推薦acceptedResources:-?kind:?DeploymentapiVersion:?apps/v1-?kind:?StatefulSetapiVersion:?apps/v1 kind:?ConfigMap metadata:name:?recommendation-configurationnamespace:?crane-system需要注意的是資源類型和 recommenders 需要可以匹配,比如 Resource 推薦默認只支持 Deployments 和 StatefulSets。
同樣的也可以再查看一次閑置節點推薦規則的資源對象,如下所示:
$?kubectl?get?recommendationrule?idlenodes-rule?-oyaml apiVersion:?analysis.crane.io/v1alpha1 kind:?RecommendationRule metadata:labels:analysis.crane.io/recommendation-rule-preinstall:?"true"name:?idlenodes-rule spec:namespaceSelector:any:?truerecommenders:-?name:?IdleNoderesourceSelectors:-?apiVersion:?v1kind:?NoderunInterval:?24h創建?RecommendationRule?配置后,RecommendationRule 控制器會根據配置定期運行推薦任務,給出優化建議生成?Recommendation?對象,然后我們可以根據優化建議?Recommendation?調整資源配置。
比如我們這里集群中已經生成了多個優化建議?Recommendation?對象。
$?kubectl?get?recommendations NAME????????????????????????????TYPE???????TARGETKIND????TARGETNAMESPACE???TARGETNAME???????STRATEGY???PERIODSECONDS???ADOPTIONTYPE??????????AGE workloads-rule-resource-8whzs???Resource???StatefulSet???default???????????nacos????????????Once???????????????????????StatusAndAnnotation???34m workloads-rule-resource-hx4cp???Resource???StatefulSet???default???????????redis-replicas???Once???????????????????????StatusAndAnnotation???34m #?......可以隨便查看任意一個優化建議對象。
$?kubectl?get?recommend?workloads-rule-resource-g7nwp?-n?crane-system?-oyaml apiVersion:?analysis.crane.io/v1alpha1 kind:?Recommendation metadata:name:?workloads-rule-resource-g7nwpnamespace:?crane-system spec:adoptionType:?StatusAndAnnotationcompletionStrategy:completionStrategyType:?OncetargetRef:apiVersion:?apps/v1kind:?Deploymentname:?fadvisornamespace:?crane-systemtype:?Resource status:action:?Patchconditions:-?lastTransitionTime:?"2022-10-20T07:43:49Z"message:?Recommendation?is?readyreason:?RecommendationReadystatus:?"True"type:?ReadycurrentInfo:?'{"spec":{"template":{"spec":{"containers":[{"name":"fadvisor","resources":{"requests":{"cpu":"0","memory":"0"}}}]}}}}'lastUpdateTime:?"2022-10-20T07:43:49Z"recommendedInfo:?'{"spec":{"template":{"spec":{"containers":[{"name":"fadvisor","resources":{"requests":{"cpu":"114m","memory":"120586239"}}}]}}}}'recommendedValue:?|resourceRequest:containers:-?containerName:?fadvisortarget:cpu:?114mmemory:?"120586239"targetRef:?{}在 dashboard 的資源推薦頁面也能查看到優化建議列表。
在頁面中可以看到當前資源(容器/CPU/Memory)與推薦的資源數據,點擊采納建議即可獲取優化的執行命令。執行命令即可完成優化,其實就是修改資源對象的?resources資源數據。patchData=`kubectl?get?recommend?workloads-rule-resource-g7nwp?-n?crane-system?-o?jsonpath='{.status.recommendedInfo}'`;kubectl?patch?Deployment?fadvisor?-n?crane-system?--patch?"${patchData}"
對于閑置節點推薦,由于節點的下線在不同平臺上的步驟不同,用戶可以根據自身需求進行節點的下線或者縮容。
應用在監控系統(比如 Prometheus)中的歷史數據越久,推薦結果就越準確,建議生產上超過兩周時間。對新建應用的預測往往不準。
自定義推薦
Recommendation Framework 提供了一套可擴展的 Recommender 框架并支持了內置的 Recommender,用戶可以實現一個自定義的 Recommender,或者修改一個已有的 Recommender。
和 K8s 調度框架類似,Recommender 接口定義了一次推薦需要實現的四個階段和八個擴展點,這些擴展點會在推薦過程中按順序被調用。這些擴展點中的一些可以改變推薦決策,而另一些僅用來提供信息。
推薦框架架構Recommender 接口定義如下所示:
type?Recommender?interface?{Name()?stringframework.Filterframework.PrePrepareframework.Prepareframework.PostPrepareframework.PreRecommendframework.Recommendframework.PostRecommendframework.Observe }//?Phase:?Filter type?Filter?interface?{//?Filter?將過濾無法通過目標推薦器推薦的資源Filter(ctx?*RecommendationContext)?error }//?Phase:?Prepare type?PrePrepare?interface?{CheckDataProviders(ctx?*RecommendationContext)?error }type?Prepare?interface?{CollectData(ctx?*RecommendationContext)?error }type?PostPrepare?interface?{PostProcessing(ctx?*RecommendationContext)?error }type?PreRecommend?interface?{PreRecommend(ctx?*RecommendationContext)?error }//?Phase:?Recommend type?Recommend?interface?{Recommend(ctx?*RecommendationContext)?error }type?PostRecommend?interface?{Policy(ctx?*RecommendationContext)?error }//?Phase:?Observe type?Observe?interface?{Observe(ctx?*RecommendationContext)?error }整個推薦過程分成了四個階段:Filter、Prepare、Recommend、Observe,階段的輸入是需要分析的 Kubernetes 資源,輸出是推薦的優化建議。接口中的?RecommendationContext?保存了一次推薦過程中的上下文,包括推薦目標、RecommendationConfiguration 等信息,我們可以根據自身需求增加更多的內容。
比如資源推薦就實現了 Recommender 接口,主要做了下面 3 個階段的處理:
Filter 階段:過濾沒有 Pod 的工作負載
Recommend 推薦:采用 VPA 的滑動窗口算法分別計算每個容器的 CPU 和內存并給出對應的推薦值
Observe 推薦:將推薦資源配置記錄到?crane_analytics_replicas_recommendation?指標
除了核心的智能推薦功能之外,Crane 還有很多高級特性,比如可以根據實際的節點利用率的動態調度器、基于流量預測的彈性 HPA 等等。
智能調度器
Crane?除了提供了智能推薦功能之外,還提供了一個調度器插件?Crane-scheduler?可以實現智能調度和完成拓撲感知調度與資源分配的工作。
動態調度器
K8s 的原生調度器只能通過資源的 requests 值來調度 pod,這很容易造成一系列負載不均的問題:
對于某些節點,實際負載與資源請求相差不大,這會導致很大概率出現穩定性問題。
對于其他節點來說,實際負載遠小于資源請求,這將導致資源的巨大浪費。
為了解決這些問題,動態調度器根據實際的節點利用率構建了一個簡單但高效的模型,并過濾掉那些負載高的節點來平衡集群。
動態調度器依賴于 prometheus 和 node-exporter 收集匯總指標數據,它由兩個組件組成:Node-annotator?定期從 Prometheus 拉取數據,并以 annotations 的形式在節點上用時間戳標記它們。
Dynamic plugin?直接從節點的 annotations 中讀取負載數據,過濾并基于簡單的算法對候選節點進行評分。
動態調度器提供了一個默認值調度策略,配置文件如下所示:
#?policy.yaml apiVersion:?scheduler.policy.crane.io/v1alpha1kind:?DynamicSchedulerPolicyspec:syncPolicy:##cpu?usage-?name:?cpu_usage_avg_5mperiod:?3m-?name:?cpu_usage_max_avg_1hperiod:?15m-?name:?cpu_usage_max_avg_1dperiod:?3h##memory?usage-?name:?mem_usage_avg_5mperiod:?3m-?name:?mem_usage_max_avg_1hperiod:?15m-?name:?mem_usage_max_avg_1dperiod:?3hpredicate:##cpu?usage-?name:?cpu_usage_avg_5mmaxLimitPecent:?0.65-?name:?cpu_usage_max_avg_1hmaxLimitPecent:?0.75##memory?usage-?name:?mem_usage_avg_5mmaxLimitPecent:?0.65-?name:?mem_usage_max_avg_1hmaxLimitPecent:?0.75priority:##cpu?usage-?name:?cpu_usage_avg_5mweight:?0.2-?name:?cpu_usage_max_avg_1hweight:?0.3-?name:?cpu_usage_max_avg_1dweight:?0.5##memory?usage-?name:?mem_usage_avg_5mweight:?0.2-?name:?mem_usage_max_avg_1hweight:?0.3-?name:?mem_usage_max_avg_1dweight:?0.5hotValue:-?timeRange:?5mcount:?5-?timeRange:?1mcount:?2我們可以根據實際需求自定義該策略配置,默認策略依賴于以下指標:
cpu_usage_avg_5m
cpu_usage_max_avg_1h
cpu_usage_max_avg_1d
mem_usage_avg_5m
mem_usage_max_avg_1h
mem_usage_max_avg_1d
這幾個指標我們這里是通過記錄規則創建的,可以查看 Prometheus 的配置文件來了解詳細信息:
$?kubectl?get?cm?-n?crane-system?prometheus-server?-oyaml apiVersion:?v1 data:alerting_rules.yml:?|{}alerts:?|{}allow-snippet-annotations:?"false"prometheus.yml:?|global:evaluation_interval:?1mscrape_interval:?1mscrape_timeout:?10srule_files:-?/etc/config/recording_rules.yml-?/etc/config/alerting_rules.yml-?/etc/config/rules-?/etc/config/alertsscrape_configs:-?job_name:?prometheusstatic_configs:-?targets:-?localhost:9090#?......recording_rules.yml:?|groups:-?interval:?3600sname:?costs.rulesrules:#???......-?interval:?30sname:?scheduler.rules.30srules:-?expr:?100?-?(avg?by?(instance)?(irate(node_cpu_seconds_total{mode="idle"}[90s]))*?100)record:?cpu_usage_active-?expr:?100*(1-node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)record:?mem_usage_active-?interval:?1mname:?scheduler.rules.1mrules:-?expr:?avg_over_time(cpu_usage_active[5m])record:?cpu_usage_avg_5m-?expr:?avg_over_time(mem_usage_active[5m])record:?mem_usage_avg_5m-?interval:?5mname:?scheduler.rules.5mrules:-?expr:?max_over_time(cpu_usage_avg_5m[1h])record:?cpu_usage_max_avg_1h-?expr:?max_over_time(cpu_usage_avg_5m[1d])record:?cpu_usage_max_avg_1d-?expr:?max_over_time(mem_usage_avg_5m[1h])record:?mem_usage_max_avg_1h-?expr:?max_over_time(mem_usage_avg_5m[1d])record:?mem_usage_max_avg_1drules:?|{} kind:?ConfigMap metadata:name:?prometheus-servernamespace:?crane-system在調度的 Filter 階段,如果該節點的實際使用率大于上述任一指標的閾值,則該節點將被過濾。而在 Score 階段,最終得分是這些指標值的加權和。
在生產集群中,可能會頻繁出現調度熱點,因為創建 Pod 后節點的負載不能立即增加。因此,我們定義了一個額外的指標,名為?hotValue,表示節點最近幾次的調度頻率,并且節點的最終優先級是最終得分減去 hotValue。
我們可以在 K8s 集群中安裝?Crane-scheduler?作為第二個調度器來進行驗證:
$?helm?repo?add?crane?https://finops-helm.pkg.coding.net/gocrane/gocrane $?helm?upgrade?--install?scheduler?-n?crane-system?--create-namespace?--set?global.prometheusAddr="http://prometheus-server.crane-system.svc.cluster.local:8080"?crane/scheduler安裝后會創建一個名為?scheduler-config?的 ConfigMap 對象,里面包含的就是調度器的配置文件,我們會在配置中啟用 Dynamic 動態調度插件:
$?kubectl?get?cm?-n?crane-system?scheduler-config?-oyaml apiVersion:?v1 data:scheduler-config.yaml:?|apiVersion:?kubescheduler.config.k8s.io/v1beta2kind:?KubeSchedulerConfigurationleaderElection:leaderElect:?falseprofiles:-?schedulerName:?crane-schedulerplugins:filter:enabled:-?name:?Dynamicscore:enabled:-?name:?Dynamicweight:?3pluginConfig:-?name:?Dynamicargs:policyConfigPath:?/etc/kubernetes/policy.yaml kind:?ConfigMap metadata:name:?scheduler-confignamespace:?crane-system安裝完成后我們可以任意創建一個 Pod,并通過設置?schedulerName: crane-scheduler?屬性明確指定使用該調度器進行調度,如下所示:
apiVersion:?apps/v1 kind:?Deployment metadata:name:?cpu-stress spec:selector:matchLabels:app:?cpu-stressreplicas:?1template:metadata:labels:app:?cpu-stressspec:schedulerName:?crane-schedulerhostNetwork:?truetolerations:-?key:?node.kubernetes.io/network-unavailableoperator:?Existseffect:?NoSchedulecontainers:-?name:?stressimage:?docker.io/gocrane/stress:latestcommand:?["stress",?"-c",?"1"]resources:requests:memory:?"1Gi"cpu:?"1"limits:memory:?"1Gi"cpu:?"1"直接創建上面的資源對象,正常創建的 Pod 就會通過?Crane Scheduler?調度器進行調度了:
Events:Type????Reason?????Age???From?????????????Message----????------?????----??----?????????????-------Normal??Scheduled??22s???crane-scheduler??Successfully?assigned?default/cpu-stress-cc8656b6c-hsqdg?to?node2Normal??Pulling????22s???kubelet??????????Pulling?image?"docker.io/gocrane/stress:latest"如果想默認使用該動態調度器,則可以使用該調度器去替換掉默認的調度器即可。
拓撲感知調度
Crane-Scheduler 和 Crane-Agent 配合工作可以完成拓撲感知調度與資源分配的工作。Crane-Agent 從節點采集資源拓撲,包括 NUMA、Socket、設備等信息,匯總到?NodeResourceTopology?這個自定義資源對象中。
CPU 拓撲感知Crane-Scheduler 在調度時會參考節點的?NodeResourceTopology?對象獲取到節點詳細的資源拓撲結構,在調度到節點的同時還會為 Pod 分配拓撲資源,并將結果寫到 Pod 的 annotations 中。Crane-Agent 在節點上 Watch 到 Pod 被調度后,從 Pod 的 annotations 中獲取到拓撲分配結果,并按照用戶給定的 CPU 綁定策略進行 CPUSet 的細粒度分配。
Crane 中提供了四種 CPU 分配策略,分別如下:
none:該策略不進行特別的 CPUSet 分配,Pod 會使用節點 CPU 共享池。
exclusive:該策略對應 kubelet 的 static 策略,Pod 會獨占 CPU 核心,其他任何 Pod 都無法使用。
numa:該策略會指定 NUMA Node,Pod 會使用該 NUMA Node 上的 CPU 共享池。
immovable:該策略會將 Pod 固定在某些 CPU 核心上,但這些核心屬于共享池,其他 Pod 仍可使用。
首先需要在 Crane-Agent 啟動參數中添加?--feature-gates=NodeResourceTopology=true,CraneCPUManager=true?開啟拓撲感知調度特性。
然后修改 kube-scheduler 的配置文件(scheduler-config.yaml?) 啟用動態調度插件并配置插件參數:
apiVersion:?kubescheduler.config.k8s.io/v1beta2 kind:?KubeSchedulerConfiguration leaderElection:leaderElect:?true clientConnection:kubeconfig:?"REPLACE_ME_WITH_KUBE_CONFIG_PATH" profiles:-?schedulerName:?default-scheduler?#?可以改成自己的調度器名稱plugins:preFilter:enabled:-?name:?NodeResourceTopologyMatchfilter:enabled:-?name:?NodeResourceTopologyMatchscore:enabled:-?name:?NodeResourceTopologyMatchweight:?2reserve:enabled:-?name:?NodeResourceTopologyMatchpreBind:enabled:-?name:?NodeResourceTopologyMatch正確安裝組件后,每個節點均會生成?NodeResourceTopology?對象。
$?kubectl?get?nrt NAME????CRANE?CPU?MANAGER?POLICY???CRANE?TOPOLOGY?MANAGER?POLICY???AGE node1???Static?????????????????????SingleNUMANodePodLevel??????????35d可以看出集群中節點?node1?已生成對應的 NRT 對象,此時 Crane 的 CPU Manager Policy 為?Static,節點默認的 Topology Manager Policy 為?SingleNUMANodePodLevel,代表節點不允許跨 NUMA 分配資源。
使用以下實例進行調度測試:
apiVersion:?apps/v1 kind:?Deployment metadata:name:?nginx-deploymentlabels:app:?nginx spec:selector:matchLabels:app:?nginxtemplate:metadata:annotations:topology.crane.io/topology-awareness:?"true"?#?添加注解,表示Pod需要感知CPU拓撲,資源分配不允許跨NUMA。若不指定,則拓撲策略默認繼承節點上的topology.crane.io/topology-awareness標簽topology.crane.io/cpu-policy:?"exclusive"?#?添加注解,表示Pod的CPU分配策略為exclusive策略。labels:app:?nginxspec:containers:-?image:?nginxname:?nginxresources:limits:cpu:?"2"?#?需要limits.cpu值,如果要開啟綁核,則該值必須等于requests.cpu。memory:?2Gi應用后可以從 annotations 中查看 Pod 的拓撲分配結果,發現 Pod 在 NUMA Node0 上被分配了 2 個 CPU 核心。
$?kubectl?get?pod?-o?custom-columns=name:metadata.name,topology-result:metadata.annotations."topology\.crane\.io/topology-result" name????????????????????????????????topology-result nginx-deployment-754d99dcdf-mtcdp???[{"name":"node0","type":"Node","resources":{"capacity":{"cpu":"2"}}}]實現基于流量預測的彈性
Kubernetes HPA 支持了豐富的彈性擴展能力,Kubernetes 平臺開發者部署服務實現自定義 Metric 的服務,Kubernetes 用戶配置多項內置的資源指標或者自定義 Metric 指標實現自定義水平彈性。
EffectiveHorizontalPodAutoscaler(簡稱?EHPA)是 Crane 提供的彈性伸縮產品,它基于社區 HPA 做底層的彈性控制,支持更豐富的彈性觸發策略(預測,觀測,周期),讓彈性更加高效,并保障了服務的質量。
提前擴容,保證服務質量:通過算法預測未來的流量洪峰提前擴容,避免擴容不及時導致的雪崩和服務穩定性故障。
減少無效縮容:通過預測未來可減少不必要的縮容,穩定工作負載的資源使用率,消除突刺誤判。
支持 Cron 配置:支持 Cron-based 彈性配置,應對大促等異常流量洪峰。
兼容社區:使用社區 HPA 作為彈性控制的執行層,能力完全兼容社區。
Effective HPA 兼容社區的 Kubernetes HPA 的能力,提供了更智能的彈性策略,比如基于預測的彈性和基于 Cron 周期的彈性等。在了解如何使用 EHPA 之前,我們有必要來詳細了解下 K8s 中的 HPA 對象。通過此伸縮組件,Kubernetes 集群可以利用監控指標(CPU 使用率等)自動擴容或者縮容服務中的 Pod 數量,當業務需求增加時,HPA 將自動增加服務的 Pod 數量,提高系統穩定性,而當業務需求下降時,HPA 將自動減少服務的 Pod 數量,減少對集群資源的請求量,甚至還可以配合 Cluster Autoscaler 實現集群規模的自動伸縮,節省 IT 成本。
不過目前默認的 HPA 對象只能支持根據 CPU 和內存的閾值檢測擴縮容,但也可以通過 custom metric api 來調用 Prometheus 實現自定義 metric,這樣就可以實現更加靈活的監控指標實現彈性伸縮了。
默認情況下,HPA 會通過?metrics.k8s.io?這個接口服務來獲取 Pod 的 CPU、內存指標,CPU 和內存這兩者屬于核心指標,metrics.k8s.io?服務對應的后端服務一般是 metrics-server,所以在使用 HPA 的時候需要安裝該應用。
如果 HPA 要通過非 CPU、內存的其他指標來伸縮容器,我們則需要部署一套監控系統如 Prometheus,讓 Prometheus 采集各種指標,但是 Prometheus 采集到的 metrics 指標并不能直接給 K8s 使用,因為兩者數據格式是不兼容的,因此需要使用到另外一個組件?prometheus-adapter,該組件可以將 Prometheus 的 metrics 指標數據格式轉換成 K8s API 接口能識別的格式,另外我們還需要在 K8s 注冊一個服務(即?custom.metrics.k8s.io),以便 HPA 能通過?/apis/?進行訪問。
需要注意的是 Crane 提供了一個?metric-adapter?組件,該組件和?prometheus-adapter?都基于?custom-metric-apiserver?實現了 Custom Metric 和 External Metric 的?ApiService,在安裝 Crane 時會將對應的?ApiService?安裝為 Crane 的?metric-adapter,所以它會和?prometheus-adapter?沖突,因為 Prometheus 是當下最流行的開源監控系統,所以我們更愿意使用它來獲取用戶的自定義指標,那么我們就需要去安裝?prometheus-adapter,但是在安裝之前需要刪除 Crane 提供的?ApiService。
#?查看當前集群?ApiService $?kubectl?get?apiservice?|grep?crane-system v1beta1.custom.metrics.k8s.io??????????crane-system/metric-adapter????????????????????True??????????????????????3h51m v1beta1.external.metrics.k8s.io????????crane-system/metric-adapter????????????????????True??????????????????????3h51m#?刪除?crane?安裝的?ApiService $?kubectl?delete?apiservice?v1beta1.custom.metrics.k8s.io $?kubectl?delete?apiservice?v1beta1.external.metrics.k8s.io然后通過 Helm Chart 來安裝 Prometheus Adapter:
$?helm?repo?add?prometheus-community?https://prometheus-community.github.io/helm-charts $?helm?repo?update #?指定有?prometheus?地址 $?helm?upgrade?--install?prometheus-adapter?-n?crane-system?prometheus-community/prometheus-adapter?--set?image.repository=cnych/prometheus-adapter,prometheus.url=http://prometheus-server.crane-system.svc,prometheus.port=8080當?prometheus-adapter?安裝成功后我們再將 ApiService 改回 Crane 的?metric-adapter,應用下面的資源清單即可:
apiVersion:?apiregistration.k8s.io/v1 kind:?APIService metadata:name:?v1beta1.custom.metrics.k8s.io spec:service:name:?metric-adapternamespace:?crane-systemgroup:?custom.metrics.k8s.ioversion:?v1beta1insecureSkipTLSVerify:?truegroupPriorityMinimum:?100versionPriority:?100 --- apiVersion:?apiregistration.k8s.io/v1 kind:?APIService metadata:name:?v1beta1.external.metrics.k8s.io spec:service:name:?metric-adapternamespace:?crane-systemgroup:?external.metrics.k8s.ioversion:?v1beta1insecureSkipTLSVerify:?truegroupPriorityMinimum:?100versionPriority:?100應用了上面的對象后,ApiService 改回了 Crane 的?metric-adapter,那么就不能使用?prometheus-adapter?的自定義 Metrics 功能,我們可以通過 Crane 的?metric-adapter?提供的?RemoteAdapter?功能將請求轉發給?prometheus-adapter。
修改?metric-adapter?的配置,將?prometheus-adapter?的 Service 配置成 Crane Metric Adapter 的?RemoteAdapter。
$?kubectl?edit?deploy?metric-adapter?-n?crane-system apiVersion:?apps/v1 kind:?Deployment metadata:name:?metric-adapternamespace:?crane-system spec:template:spec:containers:-?args:#?添加外部?Adapter?配置-?--remote-adapter=true-?--remote-adapter-service-namespace=crane-system-?--remote-adapter-service-name=prometheus-adapter-?--remote-adapter-service-port=443 #?......這是因為 Kubernetes?限制一個 ApiService 只能配置一個后端服務,為了在一個集群內使用 Crane 提供的 Metric 和?prometheus-adapter?提供的 Metric,Crane 支持了?RemoteAdapter?來解決該問題:
Crane Metric-Adapter 支持配置一個 Kubernetes Service 作為一個遠程 Adapter
Crane Metric-Adapter 處理請求時會先檢查是否是 Crane 提供的 Local Metric,如果不是,則轉發給遠程 Adapter
下面我們來部署一個示例應用,用來測試自定義指標的容器彈性伸縮。如下所示的應用暴露了 Metric 展示每秒收到的 http 請求數量。
#?sample-app.yaml apiVersion:?apps/v1 kind:?Deployment metadata:name:?sample-app spec:selector:matchLabels:app:?sample-apptemplate:metadata:labels:app:?sample-appspec:containers:-?image:?luxas/autoscale-demo:v0.1.2name:?metrics-providerresources:limits:cpu:?500mrequests:cpu:?200mports:-?containerPort:?8080 --- apiVersion:?v1 kind:?Service metadata:name:?sample-app spec:ports:-?name:?httpport:?80targetPort:?8080selector:app:?sample-apptype:?NodePort當應用部署完成后,我們可以通過命令檢查?http_requests_total?指標數據:
$?curl?http://$(kubectl?get?service?sample-app?-o?jsonpath='{?.spec.clusterIP?}')/metrics #?HELP?http_requests_total?The?amount?of?requests?served?by?the?server?in?total #?TYPE?http_requests_total?counter http_requests_total?1然后我們需要在 Prometheus 中配置抓取?sample-app?的指標,我們這里使用如下所示命令添加抓取配置:
$?kubectl?edit?cm?-n?crane-system?prometheus-server #?添加抓取?sample-app?配置 -?job_name:?sample-appkubernetes_sd_configs:-?role:?podrelabel_configs:-?action:?keepregex:?default;sample-app-(.+)source_labels:-?__meta_kubernetes_namespace-?__meta_kubernetes_pod_name-?action:?labelmapregex:?__meta_kubernetes_pod_label_(.+)-?action:?replacesource_labels:-?__meta_kubernetes_namespacetarget_label:?namespace-?source_labels:?[__meta_kubernetes_pod_name]action:?replacetarget_label:?pod配置生效后我們可以在 Prometheus Dashboard 中查詢對應的指標:
為了讓 HPA 能夠用到 Prometheus 采集到的指標,prometheus-adapter?通過使用 promql 語句來獲取指標,然后修改數據格式,并把重新組裝的指標和值通過自己的接口暴露。而 HPA 會通過?/apis/custom.metrics.k8s.io/?代理到?prometheus-adapter?的 service 上來獲取這些指標。
如果把 Prometheus 的所有指標到獲取一遍并重新組裝,那 adapter 的效率必然十分低下,因此 adapter 將需要讀取的指標設計成可配置,讓用戶通過 ConfigMap 來決定讀取 Prometheus 的哪些監控指標。
我們這里使用 Helm Chart 方式安裝的?prometheus-adapter,其默認的 Rule 配置如下所示:
$?kubectl?get?cm?-n?crane-system?prometheus-adapter?-oyaml apiVersion:?v1 data:config.yaml:?|rules:-?seriesQuery:?'{__name__=~"^container_.*",container!="POD",namespace!="",pod!=""}'seriesFilters:?[]resources:overrides:namespace:resource:?namespacepod:resource:?podname:matches:?^container_(.*)_seconds_total$as:?""metricsQuery:?sum(rate(<<.Series>>{<<.LabelMatchers>>,container!="POD"}[5m]))by?(<<.GroupBy>>)#?......?其他規則省略 kind:?ConfigMap metadata:name:?prometheus-adapternamespace:?crane-systemPrometheus adapter 的配置文件格式如上所示,它分為兩個部分,第一個是?rules,用于 custom metrics,另一個是?resourceRules,用于 metrics,如果你只用 Prometheus adapter 做 HPA,那么?resourceRules?就可以省略。
我們可以看到?rules?規則下面有很多的查詢語句,這些查詢語句的作用就是盡可能多的獲取指標,從而讓這些指標都可以用于 HPA。也就是說通過?prometheus-adapter?可以將 Prometheus 中的任何一個指標都用于 HPA,但是前提是你得通過查詢語句將它拿到(包括指標名稱和其對應的值)。也就是說,如果你只需要使用一個指標做 HPA,那么你完全就可以只寫一條查詢,而不像上面使用了好多個查詢。整體上每個規則大致可以分為 4 個部分:
Discovery:它指定 Adapter 應該如何找到該規則的所有 Prometheus 指標
Association:指定 Adapter 應該如何確定和特定的指標關聯的 Kubernetes 資源
Naming:指定 Adapter 應該如何在自定義指標 API 中暴露指標
Querying:指定如何將對一個獲多個 Kubernetes 對象上的特定指標的請求轉換為對 Prometheus 的查詢
我們這里使用的 sample-app 應用的指標名叫?http_requests_total,通過上面的規則后會將?http_requests_total?轉換成 Pods 類型的 Custom Metric,可以獲得類似于?pods/http_requests?這樣的數據。
執行以下命令,通過 Custom Metrics 指標查詢方式,查看 HPA 可用指標詳情。
$?kubectl?get?--raw?"/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests"?|?jq?. {"kind":?"MetricValueList","apiVersion":?"custom.metrics.k8s.io/v1beta1","metadata":?{"selfLink":?"/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/http_requests"},"items":?[{"describedObject":?{"kind":?"Pod","namespace":?"default","name":?"sample-app-6876d5585b-wv8fl","apiVersion":?"/v1"},"metricName":?"http_requests","timestamp":?"2022-10-27T11:19:05Z","value":?"18m","selector":?null}] }接下來我們就可以來測試下基于流量預測的容器彈性伸縮,這就需要用到 Crane 的 EHPA 對象了,我們可以使用上面的?pods/http_requests?自定義指標來實現彈性功能。
許多業務在時間序列上天然存在周期性的,尤其是對于那些直接或間接為“人”服務的業務。這種周期性是由人們日常活動的規律性決定的。例如,人們習慣于中午和晚上點外賣;早晚總有交通高峰;即使是搜索等模式不那么明顯的服務,夜間的請求量也遠低于白天時間。對于這類業務相關的應用來說,從過去幾天的歷史數據中推斷出次日的指標,或者從上周一的數據中推斷出下周一的訪問量是很自然的想法。通過預測未來 24 小時內的指標或流量模式,我們可以更好地管理我們的應用程序實例,穩定我們的系統,同時降低成本。EHPA 對象可以使用 DSP 算法來預測應用未來的時間序列數據,DSP 是一種預測時間序列的算法,它基于 FFT(快速傅里葉變換),擅長預測一些具有季節性和周期的時間序列。
創建一個如下所示的 EHPA 資源對象,并開啟預測功能:
#?sample-app-ehpa.yaml apiVersion:?autoscaling.crane.io/v1alpha1 kind:?EffectiveHorizontalPodAutoscaler metadata:name:?sample-app-ehpaannotations:#?metric-query.autoscaling.crane.io?是固定的前綴,后面是?前綴.Metric名字,需跟?spec.metrics?中的?Metric.name?相同,前綴支持?pods、resource、externalmetric-query.autoscaling.crane.io/pods.http_requests:?"sum(rate(http_requests_total[5m]))?by?(pod)" spec:#?ScaleTargetRef?是對需要縮放的工作負載的引用scaleTargetRef:apiVersion:?apps/v1kind:?Deploymentname:?sample-app#?minReplicas?是可以縮小到的縮放目標的最小副本數minReplicas:?1#?maxReplicas?是可以擴大到的縮放目標的最大副本數maxReplicas:?10#?scaleStrategy?表示縮放目標的策略,值可以是?Auto?或?ManualscaleStrategy:?Auto# metrics 包含用于計算所需副本數的規范。metrics:#?在使用預測算法預測時,你可能會擔心預測數據不準帶來一定的風險,EHPA?在計算副本數時,不僅會按預測數據計算,同時也會考慮實際監控數據來兜底,提升彈性的安全性,所以可以定義下面的?Resource?監控數據來兜底#?-?type:?Resource-?type:?Podspods:metric:name:?http_requeststarget:type:?AverageValueaverageValue:?500m?#?當出現了小數點,K8s 又需要高精度時,會使用單位 m 或k。例如1001m=1.001,1k=1000。#?prediction?定義了預測資源的配置,如果未指定,則默認不啟用預測功能prediction:predictionWindowSeconds:?3600?#?PredictionWindowSeconds?是預測未來指標的時間窗口predictionAlgorithm:algorithmType:?dsp?#?指定dsp為預測算法dsp:sampleInterval:?"60s"?#?監控數據的采樣間隔為1分鐘historyLength:?"7d"?#?拉取過去7天的監控指標作為預測的依據在上面的資源對象中添加了一個?metric-query.autoscaling.crane.io/pods.http_requests: "sum(rate(http_requests_total[5m])) by (pod)"?的 注解,這樣就可以開啟自定義指標的預測功能了。
相應的在規范中定義了?spec.prediction?屬性,用來指定預測資源的配置,其中的?predictionWindowSeconds?屬性用來指定預測未來指標的時間窗口,predictionAlgorithm?屬性用來指定預測的算法,比如我們這里配置的?algorithmType: dsp?表示使用 DSP(Digital Signal Processing)算法進行預測,該算法使用在數字信號處理領域中常用的的離散傅里葉變換、自相關函數等手段來識別、預測周期性的時間序列,關于該算法的實現原理可以查看官方文檔?https://gocrane.io/zh-cn/docs/tutorials/timeseriees-forecasting-by-dsp/?的相關介紹,或者查看源碼以了解背后原理,相關代碼位于?pkg/prediction/dsp?目錄下。此外在?prediction.predictionAlgorithm.dsp?下面還可以配置 dsp 算法的相關參數,比如我們這里配置的?sampleInterval: "60s"?表示監控數據的采樣間隔為 1 分鐘,historyLength: "7d"?表示拉取過去 7 天的監控指標作為預測的依據,此外還可以配置預測方式等。
然后核心的配置就是?spec.metrics?了,用來指定計算所需副本數的規范,我們這里指定了基于?Pods?指標的計算方式。
-?type:?Podspods:metric:name:?http_requeststarget:type:?AverageValueaverageValue:?500m上面的配置表示當?pods/http_requests?的自定義指標平均值達到 500m 后就可以觸發 HPA 縮放,這里有一個點需要注意自定義指標的?pods.metric.name?的值必須和 annotations 注解?metric-query.autoscaling.crane.io/pods.<metric name>?指標名保持一致。
EHPA 對象水平彈性的執行流程如下所示:
EffectiveHPAController?創建?HorizontalPodAutoscaler?和?TimeSeriesPrediction?對象
PredictionCore?從 Prometheus 獲取歷史 metric 通過預測算法計算,將結果記錄到?TimeSeriesPrediction
HPAController?通過 metric client 從 KubeApiServer 讀取 metric 數據
KubeApiServer?將請求路由到 Crane 的 Metric-Adapter。
HPAController?計算所有的 Metric 返回的結果得到最終的彈性副本推薦。
HPAController?調用 scale API 對目標應用擴/縮容。
整體流程如下所示:
直接應用上面的 EPHA 對象即可:
$?kubectl?apply?-f?sample-app-ehpa.yaml effectivehorizontalpodautoscaler.autoscaling.crane.io/sample-app-ehpa?created $?kubectl?get?ehpa NAME??????????????STRATEGY???MINPODS???MAXPODS???SPECIFICPODS???REPLICAS???AGE sample-app-ehpa???Auto???????1?????????10???????????????????????1??????????17s由于我們開啟了自動預測功能,所以 EPHA 對象創建后會創建一個對應的?TimeSeriesPrediction?對象:
$?kubectl?get?tsp NAME???????????????????TARGETREFNAME???TARGETREFKIND???PREDICTIONWINDOWSECONDS???AGE ehpa-sample-app-ehpa???sample-app??????Deployment??????3600??????????????????????3m50s $?kubectl?get?tsp?ehpa-sample-app-ehpa?-oyaml apiVersion:?prediction.crane.io/v1alpha1 kind:?TimeSeriesPrediction metadata:name:?ehpa-sample-app-ehpanamespace:?default spec:predictionMetrics:-?algorithm:algorithmType:?dspdsp:estimators:?{}historyLength:?7dsampleInterval:?60sexpressionQuery:expression:?sum(http_requests{})resourceIdentifier:?pods.http_requeststype:?ExpressionQuerypredictionWindowSeconds:?3600targetRef:apiVersion:?apps/v1kind:?Deploymentname:?sample-appnamespace:?default status:conditions:-?lastTransitionTime:?"2022-10-27T13:01:14Z"message:?not?all?metric?predictedreason:?PredictPartialstatus:?"False"type:?ReadypredictionMetrics:-?ready:?falseresourceIdentifier:?pods.http_requests在 status 中可以看到包含?not all metric predicted?這樣的信息,這是因為應用運行時間較短,可能會出現無法預測的情況。同樣也會自動創建一個對應的 HPA 對象:
$?kubectl?get?hpa NAME???????????????????REFERENCE???????????????TARGETS????MINPODS???MAXPODS???REPLICAS???AGE ehpa-sample-app-ehpa???Deployment/sample-app???16m/500m???1?????????10????????1??????????69m然后我們可以使用?ab?命令對 sample-app 做一次壓力測試,正常也可以觸發該應用的彈性擴容。
$?kubectl?get?svc?sample-app NAME?????????TYPE???????CLUSTER-IP???????EXTERNAL-IP???PORT(S)????????AGE sample-app???NodePort???10.104.163.144???<none>????????80:31941/TCP???3h59m #?對?nodeport?服務做壓力測試 $?ab?-c?50?-n?2000?http://192.168.0.106:31941/ $?kubectl?get?hpa NAME???????????????????REFERENCE???????????????TARGETS??????MINPODS???MAXPODS???REPLICAS???AGE ehpa-sample-app-ehpa???Deployment/sample-app???7291m/500m???1?????????10????????10?????????71m $?kubectl?describe?hpa?ehpa-sample-app-ehpa Name:???????????????????????ehpa-sample-app-ehpa #?...... Metrics:????????????????????(?current?/?target?)"http_requests"?on?pods:??8350m?/?500m Min?replicas:???????????????1 Max?replicas:???????????????10 Deployment?pods:????????????10?current?/?10?desired Conditions:Type????????????Status??Reason????????????Message----????????????------??------????????????-------AbleToScale?????True????ReadyForNewScale??recommended?size?matches?current?sizeScalingActive???True????ValidMetricFound??the?HPA?was?able?to?successfully?calculate?a?replica?count?from?pods?metric?http_requestsScalingLimited??True????TooManyReplicas???the?desired?replica?count?is?more?than?the?maximum?replica?count Events:Type????Reason?????????????Age???From???????????????????????Message----????------?????????????----??----???????????????????????-------Normal??SuccessfulRescale??57s???horizontal-pod-autoscaler??New?size:?4;?reason:?pods?metric?http_requests?above?targetNormal??SuccessfulRescale??42s???horizontal-pod-autoscaler??New?size:?8;?reason:?pods?metric?http_requests?above?targetNormal??SuccessfulRescale??27s???horizontal-pod-autoscaler??New?size:?10;?reason:?pods?metric?http_requests?above?target我們可以使用如下所示命令來查看 EHPA 自動生成的 HPA 對象的資源清單:
$?kubectl?get?hpa.v2beta2.autoscaling?ehpa-sample-app-ehpa?-oyaml apiVersion:?autoscaling/v2beta2 kind:?HorizontalPodAutoscaler metadata:name:?ehpa-sample-app-ehpanamespace:?default spec:maxReplicas:?10metrics:-?pods:metric:name:?http_requeststarget:averageValue:?500mtype:?AverageValuetype:?PodsminReplicas:?1scaleTargetRef:apiVersion:?apps/v1kind:?Deploymentname:?sample-app #?......?省略其他部分可以觀測到已經創建出基于自定義指標預測的 Metric:?http_requests,由于生產環境的復雜性,基于多指標的彈性(CPU/Memory/自定義指標)往往是生產應用的常見選擇,因此 Effective HPA 通過預測算法覆蓋了多指標的彈性,達到了幫助更多業務在生產環境落地水平彈性的成效。
除此之外 EHPA 對象還支持基于 cron 的自動縮放,除了基于監控指標,有時節假日和工作日的工作負載流量存在差異,簡單的預測算法可能效果不佳。然后可以通過設置周末 cron 來支持更大數量的副本來彌補預測的不足。對于一些非 web 流量的應用,比如一些應用不需要在周末使用,可以把工作負載的副本數減少到 1,也可以配置 cron 來降低你的服務成本。
QOS 增強與混部
除了上面介紹的主要功能之外,crane 還具有很多 QoS 增強功能,QoS 相關能力保證了運行在 Kubernetes 上的 Pod 的穩定性。crane 具有干擾檢測和主動回避能力,當較高優先級的 Pod 受到資源競爭的影響時,Disable Schedule、Throttle 以及 Evict 將應用于低優先級的 Pod,以保證節點整體的穩定,目前已經支持節點的 cpu/內存 負載絕對值/百分比作為水位線,在發生干擾進行驅逐或壓制時,會進行精確計算,將負載降低到略低于水位線即停止操作,防止誤傷和過渡操作。
同時,crane 還支持自定義指標適配整個干擾檢測框架,只需要完成排序定義等一些操作,即可復用包含精確操作在內的干擾檢測和回避流程。
此外 crane 還具有預測算法增強的彈性資源超賣能力,將集群內的空閑資源復用起來,同時結合 crane 的預測能力,更好地復用閑置資源,當前已經支持 cpu 和內存的空閑資源回收。同時具有彈性資源限制功能,限制使用彈性資源的 workload 最大和最小資源使用量,避免對高優業務的影響和饑餓問題。
同時具備增強的旁路 cpuset 管理能力,在綁核的同時提升資源利用效率。
總結
2022 年,騰訊云原生 FinOps Crane 項目組,結合行業及產業的發展趨勢,聯動中國產業互聯網發展聯盟、中國信通院、中國電子節能技術協會、FinOps 基金會及中國內外眾多生態合作伙伴,開展及推動技術標準、國內聯盟、國際開源、雙碳升級等多維度的成果落地,輸出了系列白皮書和標準指南,旨在助力企業和生態更良性發展和應用先進技術,達成降本增效,節能減排目標方向。
Crane 能力全景圖我們可以自己在 K8s 集群中安裝 crane 來獲取這些相關功能,此外這些能力也都會在騰訊云 TKE 的原生節點產品?Housekeeper?中提供,新推出的 TKE Housekeeper 是騰訊云推出的全新 K8s 運維范式,可以幫助企業像管理 Workload 一樣聲明式管理 Node 節點,高效解決節點維護、資源規劃等各種各樣的運維問題。
毫無疑問,Crane 已經是 K8s?集群中用于云資源分析和經濟的最佳 FinOps 平臺了。目前,騰訊云 Crane 已進入 CNCF LandScape,這意味著 Crane 已成為云原生領域的重要項目。面向未來,騰訊云還將持續反饋開源社區、共建開源生態,幫助更多企業通過云原生全面釋放生產力,加速實現數字化和綠色化雙轉型。
本文轉載自:「Github愛好者」,原文:https://url.hi-linux.com/Pn5lR,版權歸原作者所有。歡迎投稿,投稿郵箱: editor@hi-linux.com。
最近,我們建立了一個技術交流微信群。目前群里已加入了不少行業內的大神,有興趣的同學可以加入和我們一起交流技術,在 「奇妙的 Linux 世界」 公眾號直接回復 「加群」 邀請你入群。
你可能還喜歡
點擊下方圖片即可閱讀
Helm Dashboard: 一款超好用的 Kubernetes 包管理器 Helm 可視化工具
點擊上方圖片,『美團|餓了么』外賣紅包天天免費領
更多有趣的互聯網新鮮事,關注「奇妙的互聯網」視頻號全了解!
總結
以上是生活随笔為你收集整理的Crane: 腾讯开源一款基于 FinOps 超强大云资源分析与成本优化平台的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是php-fpm
- 下一篇: Deep Mind用AlphaZero开