從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中的直接獲取,沒必要再經過其它途徑。node
Metrics-Server收集指標數據的方式是從各節點上kubelet提供的Summary API 收集數據,收集Node和Pod核心資源指標數據,主要是內存和cpu方面的使用狀況,並將收集的信息存儲在內存中,因此當經過kubectl top不能查看資源數據的歷史狀況,其它資源指標數據則經過prometheus採集了。python
k8s中不少組件是依賴於資源指標API的功能 ,好比kubectl top 、hpa,若是沒有一個資源指標API接口,這些組件是無法運行的;git
新一代監控系統由核心指標流水線和監控指標流水線協同組成github
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
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
web
# 在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
docker
默認會從kubelet的基於HTTP的10255端口獲取指標數據,但出於安全通訊目的,kubeadm在初始化集羣時會關掉10255端口,致使沒法正常獲取數據shell
# 第一個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採集到的metrics並不能直接給k8s用,由於二者數據格式不兼容,所以還須要另一個組件(kube-state-metrics)
,將prometheus的metrics數據格式轉換成k8s API接口能識別的格式,轉換之後,由於是自定義API,因此還須要用Kubernetes aggregator
在主API服務器中註冊,以便直接經過/apis/來訪問。後端
如上圖,每一個被監控的主機均可以經過專用的exporter
程序提供輸出監控數據的接口,並等待Prometheus
服務器週期性的進行數據抓取。若是存在告警規則,則抓取到數據以後會根據規則進行計算,知足告警條件則會生成告警,併發送到Alertmanager
完成告警的彙總和分發。當被監控的目標有主動推送數據的需求時,能夠以Pushgateway
組件進行接收並臨時存儲數據,而後等待Prometheus
服務器完成數據的採集。centos
node_exporter
:收集主機的指標數據,如平均負載、CPU、內存、磁盤、網絡等等多個維度的指標數據。Prometheus把API Server做爲服務發現系統發現和監控集羣中的全部可被監控對象
這裏須要特別說明的是, Pod 資源須要添加下列註解信息才能被 Prometheus 系統自動發現並抓取其內建的指標數據。
僅指望Prometheus爲後端生成自定義指標時,僅部署Prometheus服務便可,甚至不須要持久功能
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)# 下載相關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
監聽 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
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提供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
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
自動彈性伸縮工具 Auto Scaling:
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 # 支持更多自定義資源指標的擴容
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
用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)支持從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副本數量的指標列表,每一個指標單獨計算,取全部計算結果的最大值做爲最終副本數量
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
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
編輯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自定義指標,須要定義規則
將 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