資源指標: Metrics-Server
資源指標: Metric-Server介紹
從k8s v1.8之后, 引入了Metric-API
, 以前在使用heapster獲取資源指標時, heapster有自己的獲取路徑, 沒有通過apiServer, 所以之前資源指標的數據並不能通過apiServer直接獲取, 用戶和Kubernetes的其他組件必須通過master proxy的方式才能訪問到. 后來k8s引入了資源指標API(Metrics API),有了Metrics Server組件,也采集到了該有的數據,也暴露了api,但因為api要統一,如何將請求到api-server的/apis/metrics
請求轉發給Metrics Server呢,解決方案就是:kube-aggregator
, 於是資源指標的數據就從k8s的api中的直接獲取,不必再通過其它途徑。
- Metrics API 只可以查詢當前的度量數據,並不保存歷史數據
- Metrics API URI 為 /apis/metrics.k8s.io/,在 k8s.io/metrics 維護
- 必須部署 metrics-server 才能使用該 API,metrics-server 通過調用 Kubelet Summary API 獲取數據
Metrics-Server收集指標數據的方式是從各節點上kubelet提供的Summary API 收集數據,收集Node和Pod核心資源指標數據,主要是內存和cpu方面的使用情況,並將收集的信息存儲在內存中,所以當通過kubectl top不能查看資源數據的歷史情況,其它資源指標數據則通過prometheus采集了。
k8s中很多組件是依賴於資源指標API的功能 ,比如kubectl top 、hpa,如果沒有一個資源指標API接口,這些組件是沒法運行的;
新一代監控系統由核心指標流水線和監控指標流水線協同組成
- 核心指標流水線:由kubelet、metrics-server以及由API server提供的api組成;cpu累計利用率、內存實時利用率、pod的資源占用率及容器的磁盤占用率
- 監控流水線:用於從系統收集各種指標數據並提供給終端用戶、存儲系統以及HPA,他們包含核心指標以及許多非核心指標。非核心指標不能被k8s所解析
Metric-Server部署
下載yaml文件
for i in auth-delegator.yaml auth-reader.yaml metrics-apiservice.yaml metrics-server-deployment.yaml metrics-server-service.yaml resource-reader.yaml;do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/metrics-server/$i; done
因為有牆, 所以提前下載image鏡像, 當然也可以手動修改yaml相關文件
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.5
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.5 k8s.gcr.io/metrics-server-amd64:v0.3.5
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/addon-resizer:1.8.5
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/addon-resizer:1.8.5 k8s.gcr.io/addon-resizer:1.8.5
修改文件, 不然報錯
修改resource-reader.yaml
# 在resources下添加一行nodes/stats, 下列代碼為部分代碼
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:metrics-server
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
- ""
resources:
- pods
- nodes/stats #添加此行
- nodes
- namespaces
修改metrics-server-deployment.yaml
默認會從kubelet的基於HTTP的10255端口獲取指標數據,但出於安全通信目的,kubeadm在初始化集群時會關掉10255端口,導致無法正常獲取數據
# 第一個container metrics-server的command只留下以下三行
containers:
- name: metrics-server
image: k8s.gcr.io/metrics-server-amd64:v0.3.5
command:
- /metrics-server
- --kubelet-insecure-tls # 不驗證客戶端證書
- --kubelet-preferred-address-types=InternalIP # 直接使用節點IP地址獲取數據
# 第二個container metrics-server-nanny的command中內存和CPU修改為自己需要的具體的數值
command:
- /pod_nanny
- --config-dir=/etc/config
- --cpu=20m
- --extra-cpu=0.5m
- --memory=200Mi #{{ base_metrics_server_memory }}
- --extra-memory=50Mi
- --threshold=5
- --deployment=metrics-server-v0.3.5
- --container=metrics-server
- --poll-period=300000
- --estimator=exponential
- --minClusterSize=10
創建Metric-Server
# 進入到yaml文件目錄執行命令
kubectl apply -f ./
# 可以看到pod已經運行起來了
kubectl get pods -n kube-system |grep metrics-server
[root@master ~]# kubectl api-versions|grep metrics #已經可以看到metric的api了
metrics.k8s.io/v1beta1
[root@master ~]# kubectl proxy --port=8080
[root@master ~]# curl http://localhost:8080/apis/metrics.k8s.io/v1beta1
[root@master ~]# curl http://localhost:8080/apis/metrics.k8s.io/v1beta1/nodes
# kubectl可以使用了
[root@master ~]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 513m 25% 1348Mi 78%
node01 183m 18% 1143Mi 66%
自定義資源指標: Prometheus
Prometheus可以采集其它各種指標,但是prometheus采集到的metrics並不能直接給k8s用,因為兩者數據格式不兼容,因此還需要另外一個組件(kube-state-metrics)
,將prometheus的metrics數據格式轉換成k8s API接口能識別的格式,轉換以后,因為是自定義API,所以還需要用Kubernetes aggregator
在主API服務器中注冊,以便直接通過/apis/來訪問。
k8s-prometheus-adapter 項目
Prometheus
如上圖,每個被監控的主機都可以通過專用的exporter
程序提供輸出監控數據的接口,並等待Prometheus
服務器周期性的進行數據抓取。如果存在告警規則,則抓取到數據之后會根據規則進行計算,滿足告警條件則會生成告警,並發送到Alertmanager
完成告警的匯總和分發。當被監控的目標有主動推送數據的需求時,可以以Pushgateway
組件進行接收並臨時存儲數據,然后等待Prometheus
服務器完成數據的采集。
- 監控代理程序:如
node_exporter
:收集主機的指標數據,如平均負載、CPU、內存、磁盤、網絡等等多個維度的指標數據。 - kubelet(cAdvisor):收集容器指標數據,也是K8S的核心指標收集,每個容器的相關指標數據包括:CPU使用率、限額、文件系統讀寫限額、內存使用率和限額、網絡報文發送、接收、丟棄速率等等。
- API Server:收集API Server的性能指標數據,包括控制隊列的性能、請求速率和延遲時長等等
- etcd:收集etcd存儲集群的相關指標數據
- kube-state-metrics:該組件可以派生出k8s相關的多個指標數據,主要是資源類型相關的計數器和元數據信息,包括制定類型的對象總數、資源限額、容器狀態以及Pod資源標簽系列等。
Prometheus把API Server作為服務發現系統發現和監控集群中的所有可被監控對象
這里需要特別說明的是, Pod 資源需要添加下列注解信息才能被 Prometheus 系統自動發現並抓取其內建的指標數據。
- prometheus.io/scrape: 是否采集指標數據,true/false
- prometheus.io/path: 抓取指標數據時使用 的URL 路徑,常為 /metrics
- prometheus.io/port: 抓取指標數據時使用的套接字端口端口號
僅期望Prometheus為后端生成自定義指標時,僅部署Prometheus服務即可,甚至不需要持久功能
在k8s集群中部署Prometheus
github地址
https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/prometheus
需要部署的服務清單
node-exporter
: prometheus的export,收集Node級別的監控數據prometheus
: 監控服務端,從node-exporter拉數據並存儲為時序數據。kube-state-metrics
: 將prometheus中可以用PromQL查詢到的指標數據轉換成k8s對應的數據k8s-prometheus-adpater
: 聚合進apiserver,即一種custom-metrics-apiserver實現開啟Kubernetes aggregator功能
(參考上文metric-server)
安裝部署所有服務及插件
部署kube-state-metrics
# 下載相關yaml文件
for i in kube-state-metrics-deployment.yaml kube-state-metrics-rbac.yaml kube-state-metrics-service.yaml; do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/prometheus/$i; done
# 所有節點都要執行
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/addon-resizer:1.8.6
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/addon-resizer:1.8.6 k8s.gcr.io/addon-resizer:1.8.6
docker pull quay-mirror.qiniu.com/coreos/kube-state-metrics:v1.3.0
docker tag quay-mirror.qiniu.com/coreos/kube-state-metrics:v1.3.0 quay.io/coreos/kube-state-metrics:v1.3.0
# 查看提供的指標數據
curl 10.105.51.200:8080/metrics # 10.105.51.200 是Service的IP
部署Exporter及Node Exporter
監聽 9100 端口
事實上,每個節點本身就能通過kubelet或cAdvisor提供節點指標數據,因此不需要安裝node_exporter程序
for i in node-exporter-ds.yml node-exporter-service.yaml; do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/prometheus/$i; done
kubectl apply -f ./
curl 10.0.0.51:9100/metrics # 10.0.0.51是node01節點的IP
告警系統 Alertmanager
prometheus
根據告警規則將告警信息發送給alertmanager
,而后alertmanager
對收到的告警信息進行處理,包括去重、分組並路由到告警接收端
alertmanager使用了持久存儲卷,PVC , 這里只做測試, 所以把這部分修改了; 端口9093會有Web UI
for i in alertmanager-configmap.yaml alertmanager-deployment.yaml alertmanager-pvc.yaml alertmanager-service.yaml; do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/prometheus/$i; done
# 修改alertmanager-deployment.yaml的pvc設置
volumes:
- name: config-volume
configMap:
name: alertmanager-config
- name: storage-volume
emptyDir: {}
# persistentVolumeClaim:
# claimName: alertmanager
# 修改alertmanager-service.yaml
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 9093
nodePort: 30093
selector:
k8s-app: alertmanager
type: "NodePort"
kubectl apply -f ./
kubectl get deployments -n kube-system
# 瀏覽器可以直接訪問到Web UI
http://10.0.0.50:30093/#/alerts
部署prometheus服務
Prometheus提供Web UI,端口9090,需要存儲卷,通過volumeClaimTemplates提供, 這里只做測試, 所以把這部分修改了, 所以采用了馬哥的安裝部署方式
# 官方安裝yaml文件
for i in prometheus-configmap.yaml prometheus-rbac.yaml prometheus-service.yaml prometheus-statefulset.yaml; do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/prometheus/$i; done
# 馬哥安裝yaml文件
git clone https://github.com/iKubernetes/k8s-prom.git && cd k8s-prom #我只使用了這里邊的prometheus文件, 並且把namespace統一修改成了kube-system
[root@master prometheus]# ls
prometheus-cfg.yaml prometheus-deploy.yaml prometheus-rbac.yaml prometheus-svc.yaml
kubectl apply -f ./
# 查看Web UI:
http://10.0.0.50:30090
自定義指標適配器 k8s-prometheus-adapter
PromQL接口無法直接作為自定義指標數據源,它不是聚合API服務器
需要使用 k8s-prometheus-adapter
# 配置ssl證書
cd /etc/kubernetes/pki/
(umask 077;openssl genrsa -out serving.key 2048)
openssl req -new -key serving.key -out serving.csr -subj "/CN=serving"
openssl x509 -req -in serving.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out serving.crt -days 3650
k8s-prometheus-adapter默認部署在custom-metrics名稱空間,在該名稱空間創建secret對象
證書和私鑰鍵名為 serving.crt 和 serving.key
cd /etc/kubernetes/pki/
kubectl create namespace custom-metrics
kubectl create secret generic cm-adapter-serving-certs -n custom-metrics --from-file=serving.crt=./serving.crt --from-file=serving.key=./serving.key
git clone https://github.com/DirectXMan12/k8s-prometheus-adapter
cd k8s-prometheus-adapter/deploy/manifests/
# 編輯:custom-metrics-apiserver-deployment.yaml 第28行. 因為我的promethus部署在了kube-system名稱空間中
--prometheus-url=http://prometheus.prom.svc:9090/ -> --prometheus-url=http://prometheus.kube-system.svc:9090/
# 查看API
kubectl api-versions | grep custom
# 列出指標名稱
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq '.resources[].name'
# 查看pod內存占用率
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/kube-system/pods/*/memory_usage_bytes" | jq
HPA 自動彈性縮放
自動彈性伸縮工具 Auto Scaling:
- HPA,Horizontal Pod Autoscaler,兩個版本,HPA僅支持CPU指標;HPAv2支持資源指標API和自定義指標API
- CA,Cluster Autoscaler,集群規模自動彈性伸縮,能自動增減節點數量,用於雲環境
- VPA,Vertical Pod Autoscaler,Pod應用垂直伸縮工具,調整Pod對象的CPU和內存資源需求量完成擴展或收縮
- AR,Addon Resizer,簡化版本的Pod應用垂直伸縮工具,基於集群中節點數量調整附加組件的資源需求量
Horizontal Pod Autoscaling可以根據CPU利用率(內存為不可壓縮資源)
自動伸縮一個Replication Controller、Deployment 或者Replica Set中的Pod數量;
HPA自身是一個控制循環,周期由 controller-manager的 --horizontal-pod-autoscaler-sync-period選項定義,默認為30s
對於未定義資源需求量的Pod對象,HPA控制器無法定義容器CPU利用率,且不會為該指標采取任何操作
對於每個Pod的自定義指標,HPA僅能處理原始值而非利用率
默認縮容延遲時長為5min,擴容延遲時長為3min,目的是防止出現抖動
目前HPA只支持兩個版本,其中v1版本只支持核心指標的定義;
[root@master ~]# kubectl api-versions |grep autoscaling
autoscaling/v1 # 僅支持CPU一種資源指標的擴容
autoscaling/v2beta1 # 支持更多自定義資源指標的擴容
autoscaling/v2beta2 # 支持更多自定義資源指標的擴容
實驗一: HPA
用命令行的方式創建一個帶有資源限制的pod
kubectl run myapp --image=ikubernetes/myapp:v1 --replicas=1 --requests='cpu=50m,memory=100Mi' --limits='cpu=50m,memory=100Mi' --labels='app=myapp' --expose --port=80
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-cf57cd7b-2r6q2 1/1 Running 0 2m3s
下面我們讓myapp 這個pod能自動水平擴展
用kubectl autoscale,其實就是創建HPA控制器的
kubectl autoscale deployment myapp --min=1 --max=8 --cpu-percent=60
# --min:表示最小擴展pod的個數
# --max:表示最多擴展pod的個數
# --cpu-percent:cpu利用率
[root@master ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
myapp Deployment/myapp 0%/60% 1 8 1 4m14s
kubectl patch svc myapp -p '{"spec":{"type": "NodePort"}}'
kubectl get svc |grep myapp
# [root@master ~]# kubectl get svc |grep myapp
# myapp NodePort 10.99.246.253 <none> 80:31835/TCP 11m
#壓測命令
ab -c 100 -n 500000000 http://10.0.0.51:30304/index.html
[root@master manifests]# kubectl describe hpa |grep -A 3 "resource cpu"
resource cpu on pods (as a percentage of request): 81% (40m) / 60%
Min replicas: 1
Max replicas: 8
Deployment pods: 3 current / 3 desired
[root@master manifests]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-cf57cd7b-2lqdx 1/1 Running 0 14m
myapp-cf57cd7b-bwm4h 1/1 Running 0 3m19s
myapp-cf57cd7b-fc5ns 1/1 Running 0 91s
# 壓測結束五分鍾后, 資源恢復到初始值
[root@master manifests]# kubectl describe hpa |grep -A 3 "resource cpu"
resource cpu on pods (as a percentage of request): 0% (0) / 60%
Min replicas: 1
Max replicas: 8
Deployment pods: 1 current / 1 desired
[root@master manifests]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-cf57cd7b-2lqdx 1/1 Running 0 22m
實驗二: HPA v2
HPA(v2)支持從metrics-server中請求核心指標;從k8s-prometheus-adapter一類自定義API中獲取自定義指標數據, 多個指標計算時,結果中數值較大的勝出
規則一
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: myapp
spec:
scaleTargetRef: # 要縮放的目標資源
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 50
- type: Resource
resource:
name: memory
targetAverageValue: 50Mi
metrics,計算所需Pod副本數量的指標列表,每個指標單獨計算,取所有計算結果的最大值作為最終副本數量
- external: 引用非附屬於任何對象的全局指標,可以是集群之外的組件的指標數據,如消息隊列長度
- object: 引用描述集群中某單一對象的特定指標,如Ingress對象上的hits-per-second等
- pods: 引用當前被彈性伸縮的Pod對象的特定指標
- resource: 引用資源指標,即當前被彈性伸縮的Pod對象中容器的requests和limits中定義的指標
- type: 指標源的類型,可為Objects、Pods、Resource
規則二
ikubernetes/metrics-app 運行時會通過 /metrics路徑輸出 http_requests_total 和 http_requests_per_second 兩個指標
注釋 prometheus.io/scrape:"true" 使Pod對象能夠被 Promethues采集相關指標
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: metrics-app
name: metrics-app
spec:
replicas: 2
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: ikubernetes/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
curl 10.98.175.207/metrics # IP為上一個文件創建的service IP
創建HPA
Prometheus
通過服務發現機制發現新創建的Pod對象,根據注釋提供的配置信息識別指標並納入采集對象,而后由k8s-prometheus-adapter
將這些指標注冊到自定義API中,提供給HPA(v2)
控制器和調度器等作為調度評估參數使用
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: metrics-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: metrics-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Pods
pods:
metricName: http_requests_per_second
targetAverageValue: 800m # 800m 即0.8個/秒
# 壓測命令
while true; do curl 10.98.175.207/metrics &>/dev/null; sleep 0.1; done # IP為service IP
壓測結果
[root@master ~]# kubectl describe hpa metrics-app-hpa |grep -A 4 Metrics
Metrics: ( current / target )
"http_requests_per_second" on pods: 4350m / 800m
Min replicas: 2
Max replicas: 10
Deployment pods: 10 current / 10 desired
添加自定義指標 http_requests_per_second
編輯k8s-prometheus-adapter/deploy/manifests/custom-metrics-config-map.yaml
添加規則:
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>>)'
自定義規則參考文檔:
將prometheus指標升級為k8s自定義指標,需要定義規則
- https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/config-walkthrough.md
- https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/walkthrough.md
將 http_requests_total 命令為 http_requests_per_second 自定義指標
讓配置生效:
需要先應用 custom-metrics-config-map.yaml 然后手動刪除 custom-metrics 空間下 custom-metrics-apiserver-xxxx Pod
注意:修改config-map后,不刪除Pod,不會生效
測試:
kubectl get pods -w
curl 10.104.226.230/metrics
kubectl run client -it --image=cirros --rm -- /bin/sh
while true; do curl http://metrics-app; let i++; sleep 0.$RANDOM; done # 模擬壓力
測試需要達到數分鍾后才能看到自動擴容,原因是:默認縮容延遲時長為5min,擴容延遲時長為3min
參考鏈接
https://www.cnblogs.com/fawaikuangtu123/p/11296510.html
https://www.qingtingip.com/h_252011.html
https://www.servicemesher.com/blog/prometheus-operator-manual/
https://www.cnblogs.com/centos-python/articles/10921991.html
https://pdf.us/tag/docker