目錄:
實踐1:基於autoscaling cpu指標的擴容與縮容
實踐2:基於prometheus自定義指標QPS的擴容與縮容php
Pod自動擴容/縮容(HPA)
Horizontal Pod Autoscaler(HPA,Pod水平自動伸縮),根據資源利用率或者自定義指標自動調整replication controller, deployment 或 replica set,實現部署的自動擴展和縮減,讓部署的規模接近於實際服務的負載。HPA不適於沒法縮放的對象,例如DaemonSet。 HPA主要是對pod資源的一個計算,對當前的副本數量增長或者減小。 HPA大概是這樣的,咱們須要建立一個hpa的規則,設置這樣的一個規則對pod實現一個擴容或者縮容,主要針對deployment,當你當前設置的資源利用率超出你設置的預值,它會幫你擴容縮容這些副本。
一、HPA基本原理
Kubernetes 中的 Metrics Server 持續採集全部 Pod 副本的指標數據。HPA 控制器經過 Metrics Server 的 API(Heapster 的 API 或聚合 API)獲取這些數據,基於用戶定義的擴縮容規則進行計算,獲得目標 Pod 副本數量。當目標 Pod 副本數量與當前副本數量不一樣時,HPA 控制器就向 Pod 的副本控制器(Deployment、RC 或 ReplicaSet)發起 scale 操做,調整 Pod 的副本數量,完成擴縮容操做。如圖所示。
在彈性伸縮中,冷卻週期是不能逃避的一個話題, 因爲評估的度量標準是動態特性,副本的數量可能會不斷波動。有時被稱爲顛簸, 因此在每次作出擴容縮容後,冷卻時間是多少。html
來看這張圖,首先hpa要建立一個規則,就像咱們以前建立ingress的規則同樣,裏面定義好一個擴容縮容的一個範圍而後指定好對象,指定好它的預值,hpa自己就是一個控制器,循環的控制器,它會不斷的從metrics server 中去獲取這個指標,判斷這個預值是否是到達你設置規則的預值,若是是的話,就會去執行這個scale幫你擴容這個副本,若是長期處於一個低使用率的狀況下,它會幫你縮容這個副本,這個metrics server的資源來源是來自於cadvisor去拿的,想一下cadvisor能夠提供那些指標,hpa能夠拿到的,好比cpu,內存的使用率,主要採集你這些的利用率,因此hpa在早期已經支持了對CPU的彈性伸縮java
Hpa就是k8s中這個pod水平擴容的一個控制器,可是要實現
Pod的擴容,他須要必定的條件,他要拿必定的指標,這裏是有預值的,他要判斷你的指標,是否是超出這個預值,對你進行縮容擴容,因此要想獲得這個指標,你還須要裝一個組件,metrics server,在以前呢這個組件的實現是由heapster heapstar如今已是慢慢棄用了,基本上不怎麼去使用heapstat了,因此metrics server來提供這些數據,提供這些資源的利用率。node
好比有三個副本,來實現三個pod的伸縮,因此有東西去斷定資源的利用率,好比基於cpu的,計算3個pod的資源利用率,例如3個pod的資源利用率是50%,拿到這個值以後,你就要去使用這個hpa,這個裏面會定義個預值,有個規則,這個預值設置60%,它會週期性的與cpu去匹配,若是超出這個60%,那麼就去擴容,這裏還有定義擴容pod副本的數量
好比我這組pod的訪問量是異常的,好比受到一些小***,個人cpu就超過50%,若是沒有限制去最大擴容到多大的副本,它會無限的增大,以前3個副本可能一下就增長了10個副本,甚至50個,那麼很快就能拖死整個集羣,因此在hpa中都設置3個指標,第一個設置,pod的區間值,這個最大能擴容多少個pod,最小是多少個pod,好比1-10,最小能夠建立1個,最大能夠建立10個,這是一個縮容擴容的一個範圍值,接下來就是一個預值的判斷,第三個就是操做哪一個對象,哪一組pod,這三個都是要在hpa中去判斷的linux
那麼在什麼狀況下,去縮容擴容
擴容就是資源不夠了超過這個60%了,可是在這個區間它是由個狀態轉化的,一個是擴容的狀態,一個是縮容的狀態,這兩個狀態就比如如今的資源利用率60%了,進行擴容了,有3個副本就擴容到10個副本了,這是沒問題的,而後立刻這個值下來了,以前是到了70%-80%了,如今一下到了20%,從10直接縮容到5個,這兩個是有狀態轉化的,因此hpa得基於保證說不可能狀態轉化的區間頻率過高,若是過高就會出現比如時好時壞,間歇性的突發,並非一直的突發,它會致使一會擴一會縮,最後致使這個應用不穩定,因此hpa就有一個冷卻的機制,第一次擴容以後,第二次要想擴容必須通過這個冷卻時間,那麼默認是3分鐘,縮容呢,第一次後,第二次縮容要等5分鐘以後,這就是一個默認的一個值,來保障你當前業務的穩定性,是經過kube-controller-manager組件啓動參數設置的nginx
在 HPA 中,默認的擴容冷卻週期是 3 分鐘,縮容冷卻週期是 5 分鐘。
能夠經過調整kube-controller-manager組件啓動參數設置冷卻時間:git
• --horizontal-pod-autoscaler-downscale-delay :擴容冷卻 • --horizontal-pod-autoscaler-upscale-delay :縮容冷卻
二、HPA的演進歷程
目前 HPA 已經支持了 autoscaling/v一、autoscaling/v2beta1和autoscaling/v2beta2 三個大版本 。
目前大多數人比較熟悉是autoscaling/v1,這個版本只支持CPU一個指標的彈性伸縮。
這個也比較簡單,建立一個規則,使用採集的組件就能用了,github
而autoscaling/v2beta1增長了支持自定義指標,除了cadvisor暴露的指標外,還支持自定義指標,好比像第三方提供的QPS,或者基於其餘的一些資源進行擴容,就是支持一些第三方的一些組件了。
autoscaling/v2beta2又額外增長了外部指標支持。
而產生這些變化不得不提的是Kubernetes社區對監控與監控指標的認識認識與轉變。從早期Heapster到Metrics Server再到將指標邊界進行劃分,一直在豐富監控生態。
因此有這些指標的變化,k8s對監控的認識進行了轉變,由於彈性伸縮,在k8s中含金量仍是比較高的,以前是沒有太好的方案,因此在這一塊也不是應用不少,而後再到社區對這一塊進行完善,如今應用的也逐漸增多了。
實例
V1版本就是一個cpu的一個限制,其實早期也會內存也進行開放,後期只針對cpu進行了限制,由於只暴露cpu,是由於暴露內存並非使用彈性伸縮的一個指標,由於像一個內存都會有一些應用去管理,好比java,內存都是有一個jvm去管理,因此使用內存擴容的一個指標,並非很好,因此只暴露了cpu的指標,cpu仍是比較準確的,pod,cpu利用率上來以後,負載高了,流量高了,因此這塊參考價值比較大的,因此只使用cpu,在這裏指定一個百分比就行。web
apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: php-apache namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 50:
v2beta2版本
就支持了不少的自定義的東西,好比resource,pods.object,external
能夠根據cpu作一些pod暴露指標方面的工做,也能夠針對第三方的一些指標,還有一些第三方的指標,像消息隊列之類的,
V2支持的更多了sql
2.5 基於CPU指標縮放
一、 Kubernetes API Aggregation
在 Kubernetes 1.7 版本引入了聚合層,容許第三方應用程序經過將本身註冊到kube-apiserver上,仍然經過 API Server 的 HTTP URL 對新的 API 進行訪問和操做。爲了實現這個機制,Kubernetes 在 kube-apiserver 服務中引入了一個 API 聚合層(API Aggregation Layer),用於將擴展 API 的訪問請求轉發到用戶服務的功能。
要使用v1版本基於cpu指標縮放,首先要開啓API的聚合,在k8s1.7版本中去引入的,它引入是想讓第三方的應用程序註冊進來,都能註冊到api中,去訪問這個api時就能調用這個組件了,這張圖,首先api的聚合時從API server去啓用的,上面看成API server ,下面看成組件,APIserver它自己就是之後端聚合層後面的,只不過它都在這個裏面實現了,實際上apiserver在聚合層後面,能夠把聚合層看成一個代理層,就像nginx代理web同樣,代理的話就能夠代理多個了,就不侷限於apiserver了,像metrics server,本身開發的一個組件也能註冊進來,而後讓他代理,它代理以後就能夠訪問api,從而訪問到這個組件了,那麼聚合層就像請求的url幫你轉發到後面的組件上,後面的組件都會對應api,根據註冊到聚合層的api轉發,簡而言之就是擴展api的功能,就是方便本身開發的組件,集成到這個api裏面,就像調用api同樣調用你的組件,其實這就是一個聚合層的目的,在k8s中若是使用kubeadm部署的,默認的聚合層已是啓用了,若是是二進制的部署方式去部署的,那麼要按二進制的方式去啓動聚合層,這個根據本身的環境去啓動,由於每一個人部署的二進制都不同。
須要在kube-APIServer中添加啓動參數,增長如下配置:
vi /opt/kubernetes/cfg/kube-apiserver.conf ... --requestheader-client-ca-file=/opt/kubernetes/ssl/ca.pem \ --proxy-client-cert-file=/opt/kubernetes/ssl/server.pem \ --proxy-client-key-file=/opt/kubernetes/ssl/server-key.pem \ --requestheader-allowed-names=kubernetes \ --requestheader-extra-headers-prefix=X-Remote-Extra- \ --requestheader-group-headers=X-Remote-Group \ --requestheader-username-headers=X-Remote-User \ --enable-aggregator-routing=true \ ...
第一行指定的根證書,就是訪問聚合層也要有必定的認證,不是誰的都能訪問,自己也有必定的安全機制存在,也就是一個可信任的ca
第二,三行代理的是客戶端的證書,大體的意思是放在聚合層進行認證的,來判斷你是否有機制來訪問
第四行的就是容許的名稱,這個是提供的證書裏面的,來判段這個名稱是否是可以訪問,這個我使用的是apiserver的證書,也可使用ca單獨爲這個生成一個新的證書
第五行,請求頭來判斷是否能夠訪問
第六行,就是啓動聚合層的路由
重啓這個字段[root@k8s-master1 ~]# vim /opt/kubernetes/cfg/kube-apiserver.conf
將開始聚合層的配置添加進入
[root@k8s-master1 ~]# systemctl restart kube-apiserver [root@k8s-master1 ~]# ps -ef |grep kube-apiserver
二、部署 Metrics Server
Metrics Server是一個集羣範圍的資源使用狀況的數據聚合器。做爲一個應用部署在集羣中。
Metric server從每一個節點上Kubelet公開的摘要API收集指標。
Metrics server經過Kubernetes聚合器註冊在Master APIServer中。
它必須能拿到cpu的利用率,有這個才能作對比,要不要擴容,因此要部署一個metrics server到集羣中,讓它爲hpa提供CPU的數據查詢,metrics server至關於一個聚合器,它那的數據就是cadvisor 的數據,它將那些數據每一個節點的數據進行聚合,這是它說作的事,由於你要擴容,並非一個副本去擴容,並非參考一個副本的指標,要參考你當前跑的pod的都要考慮,而每一個上面都有cadvisor,那訪問當前的pod,就只訪問到當前的利用率,而cadvisor也沒有什麼聚合的做用,要想對全部的pod的資源利用率作一個彙總,那麼上面就有這個metrics server了,以前是有heapstar去作的,如今是由metrics server去作的,幫你去彙總,而後hpa從這個彙總信息裏去拿總體cpu的利用率來判斷這個域,因此metrics server就是一個聚合器,
並且還會從每一個節點上kubelet收集這些指標,並經過k8s聚合器註冊在k8s中的apiserver中,因此metrics必須啓動聚合器,因此metrics就能主動的將本身註冊進去,註冊進去以後就能夠metrics暴露的一個名稱來請求metrics,會根據你攜帶的名稱幫你轉發到後面的metrics的pod
git clone https://github.com/kubernetes-incubator/metrics-server cd metrics-server/deploy/1.8+/ vi metrics-server-deployment.yaml # 添加2條啓動參數 ... containers: - name: metrics-server image: zhaocheng172/metrics-server-amd64:v0.3.1 command: - /metrics-server - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP ...
確保pod起來
[root@k8s-master1 1.8+]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-59fb8d54d6-7rmx2 1/1 Running 0 43m kube-flannel-ds-amd64-4jjmm 1/1 Running 0 43m kube-flannel-ds-amd64-9f9vq 1/1 Running 0 43m kube-flannel-ds-amd64-gcf9s 1/1 Running 0 43m metrics-server-64499fd8c6-xkc6c 1/1 Running 0 61s
部署起來先看看metrics-server有沒有正常工做,先看一下pod有沒有錯誤日誌,再看看有沒有註冊到聚合層
經過kubectl get apiservers,查看有沒有註冊到,這裏爲true纔算正常
[root@k8s-master1 1.8+]# kubectl get apiservices v1beta1.metrics.k8s.io kube-system/metrics-server True 19s
而後查看kubectl top node來查看node資源的利用率
[root@k8s-master1 1.8+]# kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% k8s-master1 517m 25% 1021Mi 62% k8s-node1 994m 49% 551Mi 33% k8s-node2 428m 10% 2466Mi 32%
也能夠經過kubectl top pod來查看pod的資源利用率
[root@k8s-master1 1.8+]# kubectl top pod -n kube-system NAME CPU(cores) MEMORY(bytes) coredns-59fb8d54d6-7rmx2 13m 14Mi kube-flannel-ds-amd64-4jjmm 15m 23Mi kube-flannel-ds-amd64-9f9vq 7m 15Mi kube-flannel-ds-amd64-gcf9s 9m 15Mi metrics-server-64499fd8c6-xkc6c 3m 14Mi /
也能夠經過metrics api 的標識來得到資源使用率的指標,好比容器的cpu和內存使用率,這些度量標準既能夠由用戶直接訪問,經過kubectl top命令,也能夠由集羣中的控制器pod autoscaler用於進行查看,hpa獲取這個資源利用率的時候它是經過接口的,它請求的接口就是api,因此也能夠根據api去獲取這些數據,
測試:能夠獲取這些數據,這些數據和top看到的都是同樣的,只不過這個是經過api 去顯示的,只不過是經過json去顯示的
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes [root@k8s-master1 1.8+]# kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes {"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/nodes"},"items":[{"metadata":{"name":"k8s-master1","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/k8s-master1","creationTimestamp":"2019-12-12T03:45:06Z"},"timestamp":"2019-12-12T03:45:03Z","window":"30s","usage":{"cpu":"443295529n","memory":"1044064Ki"}},{"metadata":{"name":"k8s-node1","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/k8s-node1","creationTimestamp":"2019-12-12T03:45:06Z"},"timestamp":"2019-12-12T03:45:00Z","window":"30s","usage":{"cpu":"285582752n","memory":"565676Ki"}},{"metadata":{"name":"k8s-node2","selfLink":"/apis/metrics.k8s.io/v1beta1/nodes/k8s-node2","creationTimestamp":"2019-12-12T03:45:06Z"},"timestamp":"2019-12-12T03:45:01Z","window":"30s","usage":{"cpu":"425912654n","memory":"2524648Ki"}}]}
將命令行輸出的格式轉換成json格式----jq命令[root@k8s-master1 1.8+]# kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes |jq
三、 autoscaing/v1 ( cpu指標實踐 )
autoscaling/v1版本只支持CPU一個指標。
首先部署一個應用並指出一個service,咱們一會測試一下進行流量壓測,cpu達到60%的預值而後就進行自動擴容副本,若是流量下來,而後就進行自動的縮容
[root@k8s-master1 hpa]# cat app.yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 5 selector: matchLabels: app: nginx strategy: {} template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx name: nginx resources: requests: cpu: 90m memory: 90Mi --- apiVersion: v1 kind: Service metadata: name: nginx spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80
建立HPA策略
用命令生成kubectl autoscale –help
這裏能夠查看到使用的命令用-o yaml輸出出來—dry-run過濾空的字段
kubectl autoscale deployment foo --min=2 --max=10 kubectl autoscale deployment nginx --min=2 --max=10 -o yaml --dry-run > hpa-v1.yaml [root@k8s-master1 hpa]# cat hpa-v1.yaml apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: nginx spec: maxReplicas: 6 minReplicas: 3 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx targetCPUUtilizationPercentage: 60 scaleTargetRef:表示當前要伸縮對象是誰 targetCPUUtilizationPercentage:當總體的資源利用率超過60%的時候,會進行擴容。 Maxreplicas:是最大擴容到的副本量 Minreplicas:是最小縮容到的副本量
查看擴容狀態
[root@k8s-master1 hpa]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx Deployment/nginx 0%/60% 3 6 3 52m
開啓壓測,進行對咱們的cluster IP進行測試
[root@k8s-master1 hpa]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 5h20m nginx ClusterIP 10.0.0.211 <none> 80/TCP 48m
安裝壓測命令
yum install httpd-tools -y [root@k8s-master1 hpa]# ab -n 1000000 -c 10000 http://10.0.0.211/index.html
測試cpu已經成功超出預值
[root@k8s-master1 hpa]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx Deployment/nginx 148%/60% 3 6 6 56m
最大的副本量是6個,如今已經成功自動擴容
[root@k8s-master1 hpa]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-969bfd4c9-g4zkc 1/1 Running 0 34m nginx-969bfd4c9-hlcmc 1/1 Running 0 51s nginx-969bfd4c9-mn2rd 1/1 Running 0 52m nginx-969bfd4c9-rk752 1/1 Running 0 34m nginx-969bfd4c9-zmmd8 1/1 Running 0 51s nginx-969bfd4c9-zz5gp 1/1 Running 0 51s
關閉壓測,過一會大概5分鐘以後就會自動的縮容。
[root@k8s-master1 hpa]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-969bfd4c9-g4zkc 1/1 Running 0 39m nginx-969bfd4c9-mn2rd 1/1 Running 0 57m nginx-969bfd4c9-rk752 1/1 Running 0 39m 工做流程:hpa -> apiserver -> kube aggregation -> metrics-server -> kubelet(cadvisor)
四、autoscaling/v2beta2(多指標)
爲知足更多的需求, HPA 還有 autoscaling/v2beta1和 autoscaling/v2beta2兩個版本。
這兩個版本的區別是 autoscaling/v1beta1支持了 Resource Metrics(CPU)和 Custom Metrics(應用程序指標),而在 autoscaling/v2beta2的版本中額外增長了 External Metrics的支持。
爲了知足更多的需求,hpa還有v2beat1和v2beat2兩個版本,這個跨度也比較大,這個能夠實現自定義指標
[root@k8s-master1 hpa]# kubectl get hpa.v2beta2.autoscaling -o yaml > hpa-v2.yaml apiVersion: v1 items: - apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: nginx namespace: default spec: maxReplicas: 6 minReplicas: 3 metrics: - resource: name: cpu target: averageUtilization: 60 type: Utilization type: Resource scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx
與上面v1版本效果同樣,只不過這裏格式有所變化。
v2還支持其餘另種類型的度量指標,:Pods和Object。
type: Pods pods: metric: name: packets-per-second target: type: AverageValue averageValue: 1k
type: Object object: metric: name: requests-per-second describedObject: apiVersion: networking.k8s.io/v1beta1 kind: Ingress name: main-route target: type: Value value: 2k
metrics中的type字段有四種類型的值:Object、Pods、Resource、External。
• Resource:指的是當前伸縮對象下的pod的cpu和memory指標,只支持Utilization和AverageValue類型的目標值。
• Object:指的是指定k8s內部對象的指標,數據須要第三方adapter提供,只支持Value和AverageValue類型的目標值。
• Pods:指的是伸縮對象Pods的指標,數據須要第三方的adapter提供,只容許AverageValue類型的目標值。另外就是pod暴露的指標,好比http的請求數,吞吐量,也就是http它自己暴露的出來的,可是暴露出來,它不能拿到這些指標,還須要藉助一些第三方的監控,也就是使用hpa這裏面值的判斷,這個提早是要經過kubectl apiservices裏面看到註冊進去,到聚合層,全部的hpa都是經過聚合層去拿到的,它實際上是請求的api到聚合層,而後聚合層幫你代理到後面的組件,好比像metics-service ,它去幫你拿的,而後每一個kubelet幫你收集的(cadvisor每一個pod的資源利用率,它幫你作一個聚合,聚合以後經過聚合器暴露出來,而後來查詢設定的pod的資源利用率,而且作了一個平均,這樣就能經過hpa就能拿到以後的目標值,而後hpa再幫你判斷,是否達到這個預值,到的話,幫你擴容。
基於pod的實例,pod自己暴露的指標,比較吞吐量,qps,若是目標是1k也會觸發
Hpa ->apiserver->agg->聚合層->prometheus-adapter而後它註冊到聚合層裏面來,prometheus自己就是一個監控系統,它能採集到全部pod暴露的指標,本身存儲起來,而且展現,adapter主要將本身註冊到聚合層裏面而且它能轉換這個監控指標apiserver相應的數據接口和prometheus的接口是不同的,adapter在這裏存在的關鍵是數據格式的轉化,對接的不單純的是prometheus或者其餘的監控系統,要想實現自定義指標完成數據的轉化和註冊,而後prometheus將每一個pod展現出來
• External:指的是k8s外部的指標,數據一樣須要第三方的adapter提供,只支持Value和AverageValue類型的目標值。
• 工做流程:hpa -> apiserver -> kube aggregation -> prometheus-adapter -> prometheus -> pods
2.6 基於Prometheus自定義指標縮放
資源指標只包含CPU、內存,通常來講也夠了。但若是想根據自定義指標:如請求qps/5xx錯誤數來實現HPA,就須要使用自定義指標了,目前比較成熟的實現是 Prometheus Custom Metrics。自定義指標由Prometheus來提供,再利用k8s-prometheus-adpater聚合到apiserver,實現和核心指標(metric-server)一樣的效果。
資源通常就包含cpu、內存就夠了,像公有云也是同樣都是基於cpu、內存保守型的維度來實現的,可是咱們可能會有一些特殊額需求,好比web的服務請求的QPS,或者這組web提供的這組數據,這也是很常見的需求,不過這類需求,並非不少,它實現沒那麼簡單,目前很成熟的方案就是用prometheus來自定義這些指標
它大概的流程是這樣的,api adapter註冊到apiserver中的經過apiservice就能夠看到,而後到prometheus,而後從pod中獲取到這些指標
一、部署Prometheus
Prometheus(普羅米修斯)是一個最初在SoundCloud上構建的監控系統。自2012年成爲社區開源項目,擁有很是活躍的開發人員和用戶社區。爲強調開源及獨立維護,Prometheus於2016年加入雲原生雲計算基金會(CNCF),成爲繼Kubernetes以後的第二個託管項目。
Prometheus 特色:
• 多維數據模型:由度量名稱和鍵值對標識的時間序列數據
• PromSQL:一種靈活的查詢語言,能夠利用多維數據完成複雜的查詢
• 不依賴分佈式存儲,單個服務器節點可直接工做
• 基於HTTP的pull方式採集時間序列數據
• 推送時間序列數據經過PushGateway組件支持
• 經過服務發現或靜態配置發現目標
• 多種圖形模式及儀表盤支持(grafana)
Prometheus組成及架構
• Prometheus Server:收集指標和存儲時間序列數據,並提供查詢接口
• ClientLibrary:客戶端庫
• Push Gateway:短時間存儲指標數據。主要用於臨時性的任務
• Exporters:採集已有的第三方服務監控指標並暴露metrics
• Alertmanager:告警
• Web UI:簡單的Web控制檯
部署:
這裏沒有詳細說prometheus的部署,要是須要就看我前面一篇發表的文章
這裏只須要部署一個服務端就能夠,能夠拿到pod的數據就能夠,這裏還有個pv的自動供給,因此這裏我提早部署好了,以前的文章我都寫過,這裏不作過多演示,
[root@k8s-master1 prometheus]# kubectl get pod,svc -n kube-system NAME READY STATUS RESTARTS AGE pod/coredns-59fb8d54d6-7rmx2 1/1 Running 0 25h pod/grafana-0 1/1 Running 0 18m pod/kube-flannel-ds-amd64-4jjmm 1/1 Running 0 25h pod/kube-flannel-ds-amd64-9f9vq 1/1 Running 0 25h pod/kube-flannel-ds-amd64-gcf9s 1/1 Running 0 25h pod/metrics-server-64499fd8c6-xkc6c 1/1 Running 0 24h pod/prometheus-0 2/2 Running 0 23m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/grafana NodePort 10.0.0.233 <none> 80:30007/TCP 18m service/kube-dns ClusterIP 10.0.0.2 <none> 53/UDP,53/TCP 25h service/metrics-server ClusterIP 10.0.0.67 <none> 443/TCP 24h service/prometheus NodePort 10.0.0.115 <none> 9090:30090/TCP 23m
訪問個人prometheus的30090,這裏我沒有部署node節點上的node_experiod的組件因此沒有采集到,這個由於用不到,我前面的文章部署有詳細說明,這裏不作這個
三、基於QPS指標實踐
部署一個應用:
[root@k8s-master1 hpa]# cat hpa-qps.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: metrics-app name: metrics-app spec: replicas: 3 selector: matchLabels: app: metrics-app template: metadata: labels: app: metrics-app annotations: prometheus.io/scrape: "true" prometheus.io/port: "80" prometheus.io/path: "/metrics" spec: containers: - image: zhaocheng172/metrics-app name: metrics-app ports: - name: web containerPort: 80 resources: requests: cpu: 200m memory: 256Mi readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5 livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: metrics-app labels: app: metrics-app spec: ports: - name: web port: 80 targetPort: 80 selector: app: metrics-app
該metrics-app暴露了一個Prometheus指標接口,能夠經過訪問service看到:
[root@k8s-master1 hpa]# curl 10.0.0.107/metrics HELP http_requests_total The amount of requests in total TYPE http_requests_total counter
http_requests_total 31。這一塊是我這個pod總共請求了多少的訪問,累計值
HELP http_requests_per_second The amount of requests per second the latest ten seconds
TYPE http_requests_per_second gauge
http_requests_per_second 0.5 這個是10秒以內的吞吐率,也就是有0.5個http請求,吞吐率和qps是不同的概念,qps是指一個範圍內求的一個量,可是他們都是求當前量化的一個指標
如今去查看prometheus有沒有請求到那三個pod的數據
經過http_requests_total,能夠看到咱們在yaml中去定義的name_app: metrics-app
以前的若是也想被prometheus採集到,那麼就須要去暴露這個指標,這是其一,其二就是採集這個指標,全部的pod的數據是經過yaml中的註解去實現的
app: metrics-app
annotations:
prometheus.io/scrape: "true"。讓它可以採集
prometheus.io/port: "80"。 訪問它的地址也就是url
prometheus.io/path: "/metrics"。 默認都是metrics
這三個註解的字段都是prometheus開頭的,因此要把這個指標拿走監控起來
Prometheus會掃描k8s中的pod有沒有暴露的指標,有的話,它會自動加入被監控端,而後將暴露出來,因此這就是prometheus對k8s的自動發現所能感知所監控到
如今採集到了而後就是部署custom metrics adapter
部署 Custom Metrics Adapter
可是prometheus採集到的metrics並不能直接給k8s用,由於二者數據格式不兼容,還須要另一個組件(k8s-prometheus-adpater),將prometheus的metrics 數據格式轉換成k8s API接口能識別的格式,轉換之後,由於是自定義API,因此還須要用Kubernetes aggregator在主APIServer中註冊,以便直接經過/apis/來訪問。
這個主要做用就是將本身註冊到api-server中,第二就是轉換成api能夠識別的數據,https://github.com/DirectXMan12/k8s-prometheus-adapter
該 PrometheusAdapter 有一個穩定的Helm Charts,咱們直接使用。
先準備下helm環境:
[root@k8s-master1 helm]# wget https://get.helm.sh/helm-v3.0.0-linux-amd64.tar.gz [root@k8s-master1 helm]# tar xf helm-v3.0.0-linux-amd64.tar.gz [root@k8s-master1 helm]# mv linux-amd64/helm /usr/bin
如今就可使用helm 了,安裝好helm,還能配置一個helm的倉庫
也就是它將adapter存放到這個倉庫裏面了
添加的話建議使用微軟雲的adapter的
[root@k8s-master1 helm]# helm repo add stable http://mirror.azure.cn/kubernetes/charts "stable" has been added to your repositories [root@k8s-master1 helm]# helm repo ls NAME URL stable http://mirror.azure.cn/kubernetes/charts
這樣的話,咱們就能使用helm install,安裝adapter了
由於adapter這個chart好比它要鏈接prometheus的地址,就是默認的chart並不能以前使用,還得把它改了,因此要指定它的地址和端口,直接經過set命令來替換chart默認的變量
部署prometheus-adapter,指定prometheus地址:
[root@k8s-master1 helm]# helm install prometheus-adapter stable/prometheus-adapter --namespace kube-system --set prometheus.url=http://prometheus.kube-system,prometheus.port=9090 NAME: prometheus-adapter LAST DEPLOYED: Fri Dec 13 15:22:42 2019 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: prometheus-adapter has been deployed. In a few minutes you should be able to list metrics using the following command(s): kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 [root@k8s-master1 helm]# helm list -n kube-system NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION prometheus-adapter kube-system 1 2019-12-13 15:22:42.043441232 +0800 CST deployed prometheus-adapter-1.4.0 v0.5.0
查看pod已經部署成功
[root@k8s-master1 helm]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-59fb8d54d6-7rmx2 1/1 Running 0 28h grafana-0 1/1 Running 0 3h30m kube-flannel-ds-amd64-4jjmm 1/1 Running 0 28h kube-flannel-ds-amd64-9f9vq 1/1 Running 0 28h kube-flannel-ds-amd64-gcf9s 1/1 Running 0 28h metrics-server-64499fd8c6-xkc6c 1/1 Running 0 27h prometheus-0 2/2 Running 0 3h35m prometheus-adapter-77b7b4dd8b-9rv26 1/1 Running 0 2m36s
檢查判斷pod是否工做正常,這裏已是註冊到聚合層了
[root@k8s-master1 helm]# kubectl get apiservice v1beta1.custom.metrics.k8s.io kube-system/prometheus-adapter True 13m
這樣就能經過一個原始的url去測試這個接口能不能用[root@k8s-master1 helm]# kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" |jq
建立hpa策略
[root@k8s-master1 hpa]# cat hpa-v5.yaml apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: metrics-app-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: metrics-app minReplicas: 1 maxReplicas: 10 metrics: - type: Pods pods: metric: name: http_requests_per_second target: type: AverageValue averageValue: 800m
查看建立成功的狀態,目前是沒有拿到這個值的。由於適配器還不知道你要什麼指標(http_requests_per_second),HPA也就獲取不到Pod提供指標。
ConfigMap在default名稱空間中編輯prometheus-adapter ,並seriesQuery在該rules: 部分的頂部添加一個新的:
[root@k8s-master1 hpa]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE metrics-app-hpa Deployment/QPS <unknown>/800m 3 6 0 16m nginx Deployment/nginx 0%/60% 3 6 3 24h
添加新的字段,來收集咱們想實現的QPS的值[root@k8s-master1 hpa]# kubectl edit cm prometheus-adapter -n kube-system
將這一塊放到rules下,,並且中間這個實際上是promsql,這個能夠執行的,並且和咱們的以前輸出的結果是同樣的,{裏面表示字段不爲空,更精確一些},這個主要是查詢出一系列數據,下面一段是管聯,將ns和pod關聯,來拿數據,都是對應的關係。
和前面的同樣,只不過前面的是http的訪問的累計值,如今咱們要轉換成一個速率,QPS的值是經過範圍以內,1分鐘以內採集了多少指標進行相加,再除以60秒,就是每秒的值, matches: "^(.*)_total",也舉手匹配前面的值進行替換,來提供 as: "${1}_per_second"的值,也就是QPS的值,用這個值爲http提供接口,
rules: - seriesQuery: 'http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}' resources: overrides: kubernetes_namespace: {resource: "namespace"} kubernetes_pod_name: {resource: "pod"} name: matches: "^(.*)_total" as: "${1}_per_second" metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
這個值是求的它的一個平均值,也就是2分鐘以內0.42http請求,每一次執行就就近執行的平均數
rate(http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}[2m])
由於咱們是多個pod,因此咱們須要相加對外提供一個指標,而後咱們再給一個by,給個標籤,這樣的話進行標籤去查詢
sum(rate(http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}[2m]))
使用by,定義標籤的名稱方便去查詢
sum(rate(http_requests_total{kubernetes_namespace!="",kubernetes_pod_name!=""}[2m])) by (kubernetes_pod_name)
測試api kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/http_requests_per_second"
目前已經收到咱們的值了
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE metrics-app-hpa Deployment/metrics-app 416m/800m 1 10 3 2m13s nginx Deployment/nginx 0%/60% 3 6 3 25h
壓測
Kubectl get svc metrics-app ClusterIP 10.0.0.107 <none> 80/TCP 3h15m ab -n 100000 -c 100 http://10.0.0.107/metrics
查看擴容狀態
[root@k8s-master1 hpa]# kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE metrics-app-hpa Deployment/metrics-app 414m/200m 1 10 10 8m36s nginx Deployment/nginx 0%/60% 3 6 3 26h [root@k8s-master1 hpa]# kubectl get pod NAME READY STATUS RESTARTS AGE metrics-app-b96659c9c-5jxsg 1/1 Running 0 3m53s metrics-app-b96659c9c-5lqpb 1/1 Running 0 5m24s metrics-app-b96659c9c-6qx2p 1/1 Running 0 2m21s metrics-app-b96659c9c-bqkbk 1/1 Running 0 3m53s metrics-app-b96659c9c-f5vcf 1/1 Running 0 2m21s metrics-app-b96659c9c-j24xn 1/1 Running 1 3h12m metrics-app-b96659c9c-vpl4t 1/1 Running 0 3h12m metrics-app-b96659c9c-wxp7z 1/1 Running 0 3m52s metrics-app-b96659c9c-xztqz 1/1 Running 0 3m53s metrics-app-b96659c9c-zhq5r 1/1 Running 0 5m24s nfs-client-provisioner-6f54fc894d-dbvmk 1/1 Running 0 5h40m nginx-969bfd4c9-g4zkc 1/1 Running 0 25h nginx-969bfd4c9-mn2rd 1/1 Running 0 25h nginx-969bfd4c9-rk752 1/1 Running 0 25h
等待一會大概5分鐘就會進行副本的縮容
小結: