kubernetes之監控Operator部署Prometheus
什麼是Operator
Operator是由CoreOS開發的,用來擴充套件Kubernetes API,特定的應用程式控制器,它用來建立、配置和管理複雜的有狀態應用,如資料庫、快取和監控系統。Operator基於Kubernetes的資源和控制器概念之上構建,但同時又包含了應用程式特定的領域知識。建立Operator的關鍵是CRD(自定義資源)的設計。
Operator
是將運維人員對軟體操作的知識給程式碼化,同時利用 Kubernetes 強大的抽象來管理大規模的軟體應用。目前CoreOS
官方提供了幾種Operator
的實現,其中就包括我們今天的主角:Prometheus Operator
,Operator
- 資源:物件的狀態定義
- 控制器:觀測、分析和行動,以調節資源的分佈
當前CoreOS提供的以下四種Operator:
- etcd:建立etcd叢集
- Rook:雲原生環境下的檔案、塊、物件儲存服務
- Prometheus:建立Prometheus監控例項
- Tectonic:部署Kubernetes叢集
接下來我們將使用Operator建立Prometheus。
安裝
我們這裡直接通過 Prometheus-Operator 的原始碼來進行安裝,當然也可以用 Helm 來進行一鍵安裝,我們採用原始碼安裝可以去了解更多的實現細節。首頁將原始碼 Clone 下來:
git clone https://github.com/coreos/prometheus-operator cd prometheus-operator/contrib/kube-prometheus/manifests
進入到 manifests 目錄下面,這個目錄下面包含我們所有的資源清單檔案,直接在該資料夾下面執行建立資源命令即可:
kubectl apply -f .
部署完成後,會建立一個名為monitoring
的 namespace,所以資源物件對將部署在改名稱空間下面,此外 Operator 會自動建立4個 CRD 資源物件:
kubectl get crd |grep coreos alertmanagers.monitoring.coreos.com 2019-03-18T02:43:57Z prometheuses.monitoring.coreos.com 2019-03-18T02:43:58Z prometheusrules.monitoring.coreos.com 2019-03-18T02:43:58Z servicemonitors.monitoring.coreos.com 2019-03-18T02:43:58Z
可以在 monitoring 名稱空間下面檢視所有的 Pod,其中 alertmanager 和 prometheus 是用 StatefulSet 控制器管理的,其中還有一個比較核心的 prometheus-operator 的 Pod,用來控制其他資源物件和監聽物件變化的:
kubectl get pods -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 0 37m alertmanager-main-1 2/2 Running 0 34m alertmanager-main-2 2/2 Running 0 33m grafana-7489c49998-pkl8w 1/1 Running 0 40m kube-state-metrics-d6cf6c7b5-7dwpg 4/4 Running 0 27m node-exporter-dlp25 2/2 Running 0 40m node-exporter-fghlp 2/2 Running 0 40m node-exporter-mxwdm 2/2 Running 0 40m node-exporter-r9v92 2/2 Running 0 40m prometheus-adapter-84cd9c96c9-n92n4 1/1 Running 0 40m prometheus-k8s-0 3/3 Running 1 37m prometheus-k8s-1 3/3 Running 1 37m prometheus-operator-7b74946bd6-vmbcj 1/1 Running 0 40m
檢視建立的 Service:
kubectl get svc -n monitoring NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE alertmanager-main ClusterIP 10.110.43.207 <none> 9093/TCP 40m alertmanager-operated ClusterIP None <none> 9093/TCP,6783/TCP 38m grafana ClusterIP 10.109.160.0 <none> 3000/TCP 40m kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 40m node-exporter ClusterIP None <none> 9100/TCP 40m prometheus-adapter ClusterIP 10.105.174.21 <none> 443/TCP 40m prometheus-k8s ClusterIP 10.97.195.143 <none> 9090/TCP 40m prometheus-operated ClusterIP None <none> 9090/TCP 38m prometheus-operator ClusterIP None <none> 8080/TCP 40m
可以看到上面針對 grafana 和 prometheus 都建立了一個型別為 ClusterIP 的 Service,當然如果我們想要在外網訪問這兩個服務的話可以通過建立對應的 Ingress 物件或者使用 NodePort 型別的 Service,我們這裡為了簡單,直接使用 NodePort 型別的服務即可,編輯 grafana 和 prometheus-k8s 這兩個 Service,將服務型別更改為 NodePort:
kubectl edit svc grafana -n monitoring kubectl edit svc prometheus-k8s -n monitoring kubectl get svc -n monitoring NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ..... grafana NodePort 10.109.160.0 <none> 3000:31740/TCP 42m prometheus-k8s NodePort 10.97.195.143 <none> 9090:31310/TCP 42m
更改完成後,我們就可以通過去訪問上面的兩個服務了,比如檢視 prometheus 的 targets 頁面:
我們可以看到大部分的配置都是正常的,只有兩三個沒有管理到對應的監控目標,比如 kube-controller-manager 和 kube-scheduler 這兩個系統元件,這就和 ServiceMonitor 的定義有關係了,我們先來檢視下 kube-scheduler 元件對應的 ServiceMonitor 資源的定義:(prometheus-serviceMonitorKubeScheduler.yaml)
配置kube-scheduler
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
k8s-app: kube-scheduler
name: kube-scheduler
namespace: monitoring
spec:
endpoints:
- interval: 30s #30s獲取一次資訊
port: http-metrics # 對應service的埠名
jobLabel: k8s-app
namespaceSelector: # 表示去匹配某一名稱空間中的service,如果想從所有的namespace中匹配用any: true
matchNames:
- kube-system
selector: # 匹配的 Service 的labels,如果使用mathLabels,則下面的所有標籤都匹配時才會匹配該service,如果使用matchExpressions,則至少匹配一個標籤的service都會被選擇
matchLabels:
k8s-app: kube-scheduler
上面是一個典型的 ServiceMonitor 資原始檔的宣告方式,上面我們通過selector.matchLabels
在 kube-system 這個名稱空間下面匹配具有k8s-app=kube-scheduler
這樣的 Service,但是我們系統中根本就沒有對應的 Service,所以我們需要手動建立一個 Service:(prometheus-kubeSchedulerService.yaml)
apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-scheduler labels: k8s-app: kube-scheduler spec: selector: component: kube-scheduler ports: - name: http-metrics port: 10251 targetPort: 10251 protocol: TCP
其中最重要的是上面 labels 和 selector 部分,labels 區域的配置必須和我們上面的 ServiceMonitor 物件中的 selector 保持一致,selector
下面配置的是component=kube-scheduler
,為什麼會是這個 label 標籤呢,我們可以去 describe 下 kube-scheduelr 這個 Pod:
$ kubectl describe pod kube-scheduler-k8s-master -n kube-system Name: kube-scheduler-k8s-master Namespace: kube-system Priority: 2000000000 PriorityClassName: system-cluster-critical Node: k8s-master/172.16.138.40 Start Time: Tue, 19 Feb 2019 21:15:05 -0500 Labels: component=kube-scheduler tier=control-plane ......
我們可以看到這個 Pod 具有component=kube-scheduler
和tier=control-plane
這兩個標籤,而前面這個標籤具有更唯一的特性,所以使用前面這個標籤較好,這樣上面建立的 Service 就可以和我們的 Pod 進行關聯了,直接建立即可:
$ kubectl create -f prometheus-kubeSchedulerService.yaml $ kubectl get svc -n kube-system -l k8s-app=kube-scheduler NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-scheduler ClusterIP 10.103.165.58 <none> 10251/TCP 4m
建立完成後,隔一小會兒後去 prometheus 檢視 targets 下面 kube-scheduler 的狀態:
我們可以看到現在已經發現了 target,但是抓取資料結果出錯了,這個錯誤是因為我們叢集是使用 kubeadm 搭建的,其中 kube-scheduler 預設是繫結在127.0.0.1
上面的,而上面我們這個地方是想通過節點的 IP 去訪問,所以訪問被拒絕了,我們只要把 kube-scheduler 繫結的地址更改成0.0.0.0
即可滿足要求,由於 kube-scheduler 是以靜態 Pod 的形式執行在叢集中的,所以我們只需要更改靜態 Pod 目錄下面對應的 YAML (kube-scheduler.yaml
)檔案即可:
$ cd /etc/kubernetes/manifests 將 kube-scheduler.yaml 檔案中-command的--address地址更改成0.0.0.0 $ vim kube-scheduler.yaml apiVersion: v1 kind: Pod metadata: annotations: scheduler.alpha.kubernetes.io/critical-pod: "" creationTimestamp: null labels: component: kube-scheduler tier: control-plane name: kube-scheduler namespace: kube-system spec: containers: - command: - kube-scheduler - --address=0.0.0.0 - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true ....
修改完成後我們將該檔案從當前資料夾中移除,隔一會兒再移回該目錄,就可以自動更新了,然後再去看 prometheus 中 kube-scheduler 這個 target 是否已經正常了:
配置kube-controller-manager
我們來檢視一下kube-controller-manager的ServiceMonitor資源的定義:
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: k8s-app: kube-controller-manager name: kube-controller-manager namespace: monitoring spec: endpoints: - interval: 30s metricRelabelings: - action: drop regex: etcd_(debugging|disk|request|server).* sourceLabels: - __name__ port: http-metrics jobLabel: k8s-app namespaceSelector: matchNames: - kube-system selector: matchLabels: k8s-app: kube-controller-manager
上面我們可以看到是通過k8s-app: kube-controller-manager這個標籤選擇的service,但系統中沒有這個service。這裡我們手動建立一個:
建立前我們需要看確定pod的標籤:
$ kubectl describe pod kube-controller-manager-k8s-master -n kube-system Name: kube-controller-manager-k8s-master Namespace: kube-system Priority: 2000000000 PriorityClassName: system-cluster-critical Node: k8s-master/172.16.138.40 Start Time: Tue, 19 Feb 2019 21:15:16 -0500 Labels: component=kube-controller-manager tier=control-plane ....
建立svc
apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-controller-manager labels: k8s-app: kube-controller-manager spec: selector: component: kube-controller-manager ports: - name: http-metrics port: 10252 targetPort: 10252 protocol: TCP
建立完後,我們檢視targer
這裡和上面是同一個問題。讓我們使用上面的方法修改。讓我們修改kube-controller-manager.yaml:
apiVersion: v1 kind: Pod metadata: annotations: scheduler.alpha.kubernetes.io/critical-pod: "" creationTimestamp: null labels: component: kube-controller-manager tier: control-plane name: kube-controller-manager namespace: kube-system spec: containers: - command: - kube-controller-manager - --node-monitor-grace-period=10s - --pod-eviction-timeout=10s - --address=0.0.0.0 #修改 ......
修改完成後我們將該檔案從當前資料夾中移除,隔一會兒再移回該目錄,就可以自動更新了,然後再去看 prometheus 中 kube-controller-manager 這個 target 是否已經正常了:
配置coredns
coredns啟動的metrics埠是9153,我們檢視kube-system下的svc是否有這個埠:
kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE heapster ClusterIP 10.96.28.220 <none> 80/TCP 19d kube-controller-manager ClusterIP 10.99.208.51 <none> 10252/TCP 1h kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 188d kube-scheduler ClusterIP 10.103.165.58 <none> 10251/TCP 2h kubelet ClusterIP None <none> 10250/TCP 5h kubernetes-dashboard NodePort 10.103.15.27 <none> 443:30589/TCP 131d monitoring-influxdb ClusterIP 10.103.155.57 <none> 8086/TCP 19d tiller-deploy ClusterIP 10.104.114.83 <none> 44134/TCP 18d
這裡我們看到kube-dns沒有metrics的埠,但是metrics後端是啟動,所以我們需要把這個埠通過svc暴露出來。建立svc:
apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-prometheus-prometheus-coredns labels: k8s-app: prometheus-operator-coredns spec: selector: k8s-app: kube-dns ports: - name: metrics port: 9153 targetPort: 9153 protocol: TCP
這裡我們啟動一個svc,labels是k8s-app: prometheus-operator-coredns,所有我們需要修改DNS的serviceMonitor下的labels值。
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: k8s-app: coredns name: coredns namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 15s port: metrics jobLabel: k8s-app namespaceSelector: matchNames: - kube-system selector: matchLabels: k8s-app: prometheus-operator-coredns
建立檢視這兩個資源:
$ kubectl apply -f prometheus-serviceMonitorCoreDNS.yaml $ kubectl create -f prometheus-KubeDnsSvc.yaml $ kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-prometheus-prometheus-coredns ClusterIP 10.100.205.135 <none> 9153/TCP 1h
讓我們再去看 prometheus 中 coredns 這個 target 是否已經正常了:
上面的監控資料配置完成後,現在我們可以去檢視下 grafana 下面的 dashboard,同樣使用上面的 NodePort 訪問即可,第一次登入使用 admin:admin 登入即可,進入首頁後,可以發現已經和我們的 Prometheus 資料來源關聯上了,正常來說可以看到一些監控圖表了:
自定義監控項
除了 Kubernetes 叢集中的一些資源物件、節點以及元件需要監控,有的時候我們可能還需要根據實際的業務需求去新增自定義的監控項,新增一個自定義監控的步驟也是非常簡單的。
- 第一步建立一個 ServiceMonitor 物件,用於 Prometheus 新增監控項
- 第二步為 ServiceMonitor 物件關聯 metrics 資料介面的一個 Service 物件
- 第三步確保 Service 物件可以正確獲取到 metrics 資料
接下來演示如何新增 etcd 叢集的監控。
無論是 Kubernetes 叢集外的還是使用 Kubeadm 安裝在叢集內部的 etcd 叢集,我們這裡都將其視作叢集外的獨立叢集,因為對於二者的使用方法沒什麼特殊之處。
etcd 證書
對於 etcd 叢集一般情況下,為了安全都會開啟 https 證書認證的方式,所以要想讓 Prometheus 訪問到 etcd 叢集的監控資料,就需要提供相應的證書校驗。
由於我們這裡演示環境使用的是 Kubeadm 搭建的叢集,我們可以使用 kubectl 工具去獲取 etcd 啟動的時候使用的證書路徑:
$ kubectl get pods -n kube-system | grep etcd etcd-k8s-master 1/1 Running 2773 188d etcd-k8s-node01 1/1 Running 2 104d $ kubectl get pod etcd-k8s-master -n kube-system -o yaml ..... spec: containers: - command: - etcd - --advertise-client-urls=https://172.16.138.40:2379 - --initial-advertise-peer-urls=https://172.16.138.40:2380 - --initial-cluster=k8s-master=https://172.16.138.40:2380 - --listen-client-urls=https://127.0.0.1:2379,https://172.16.138.40:2379 - --listen-peer-urls=https://172.16.138.40:2380 - --cert-file=/etc/kubernetes/pki/etcd/server.crt - --client-cert-auth=true - --data-dir=/var/lib/etcd - --key-file=/etc/kubernetes/pki/etcd/server.key - --name=k8s-master - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt - --peer-client-cert-auth=true - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key - --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt - --snapshot-count=10000 - --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt image: registry.cn-hangzhou.aliyuncs.com/google_containers/etcd-amd64:3.2.18 imagePullPolicy: IfNotPresent livenessProbe: exec: command: - /bin/sh - -ec - ETCDCTL_API=3 etcdctl --endpoints=https://[127.0.0.1]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd/healthcheck-client.key get foo failureThreshold: 8 initialDelaySeconds: 15 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 15 name: etcd resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki/etcd name: etcd-certs ...... tolerations: - effect: NoExecute operator: Exists volumes: - hostPath: path: /var/lib/etcd type: DirectoryOrCreate name: etcd-data - hostPath: path: /etc/kubernetes/pki/etcd type: DirectoryOrCreate name: etcd-certs .....
我們可以看到 etcd 使用的證書都對應在節點的 /etc/kubernetes/pki/etcd 這個路徑下面,所以首先我們將需要使用到的證書通過 secret 物件儲存到叢集中去:(在 etcd 執行的節點)
$ kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key --from-file=/etc/kubernetes/pki/etcd/ca.crt secret/etcd-certs created
然後將上面建立的 etcd-certs 物件配置到 prometheus 資源物件中,直接更新 prometheus 資源物件即可:
nodeSelector: beta.kubernetes.io/os: linux replicas: 2 secrets: - etcd-certs
更新完成後,我們就可以在 Prometheus 的 Pod 中獲取到上面建立的 etcd 證書檔案了,具體的路徑我們可以進入 Pod 中檢視:
$ kubectl exec -it prometheus-k8s-0 /bin/sh -n monitoring Defaulting container name to prometheus. Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod. /prometheus $ ls /etc/prometheus/ config_out/ console_libraries/ consoles/ prometheus.yml rules/ secrets/ /prometheus $ ls /etc/prometheus/secrets/etcd-certs/ ca.crt healthcheck-client.crt healthcheck-client.key /prometheus $
建立 ServiceMonitor
現在 Prometheus 訪問 etcd 叢集的證書已經準備好了,接下來建立 ServiceMonitor 物件即可(prometheus-serviceMonitorEtcd.yaml)
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: etcd-k8s namespace: monitoring labels: k8s-app: etcd-k8s spec: jobLabel: k8s-app endpoints: - port: port interval: 30s scheme: https tlsConfig: caFile: /etc/prometheus/secrets/etcd-certs/ca.crt certFile: /etc/prometheus/secrets/etcd-certs/healthcheck-client.crt keyFile: /etc/prometheus/secrets/etcd-certs/healthcheck-client.key insecureSkipVerify: true selector: matchLabels: k8s-app: etcd namespaceSelector: matchNames: - kube-system
上面我們在 monitoring 名稱空間下面建立了名為 etcd-k8s 的 ServiceMonitor 物件,基本屬性和前面章節中的一致,匹配 kube-system 這個名稱空間下面的具有 k8s-app=etcd 這個 label 標籤的 Service,jobLabel 表示用於檢索 job 任務名稱的標籤,和前面不太一樣的地方是 endpoints 屬性的寫法,配置上訪問 etcd 的相關證書,endpoints 屬性下面可以配置很多抓取的引數,比如 relabel、proxyUrl,tlsConfig 表示用於配置抓取監控資料端點的 tls 認證,由於證書 serverName 和 etcd 中籤發的可能不匹配,所以加上了 insecureSkipVerify=true
直接建立這個 ServiceMonitor 物件:
$ kubectl create -f prometheus-serviceMonitorEtcd.yaml servicemonitor.monitoring.coreos.com/etcd-k8s created
建立 Service
ServiceMonitor 建立完成了,但是現在還沒有關聯的對應的 Service 物件,所以需要我們去手動建立一個 Service 物件(prometheus-etcdService.yaml):
apiVersion: v1 kind: Service metadata: name: etcd-k8s namespace: kube-system labels: k8s-app: etcd spec: type: ClusterIP clusterIP: None ports: - name: port port: 2379 protocol: TCP --- apiVersion: v1 kind: Endpoints metadata: name: etcd-k8s namespace: kube-system labels: k8s-app: etcd subsets: - addresses: - ip: 172.16.138.40 nodeName: etcd-k8s-master - ip: 172.16.138.41 nodeName: etcd-k8s-node01 ports: - name: port port: 2379 protocol: TCP
我們這裡建立的 Service 沒有采用前面通過 label 標籤的形式去匹配 Pod 的做法,因為前面我們說過很多時候我們建立的 etcd 叢集是獨立於叢集之外的,這種情況下面我們就需要自定義一個 Endpoints,要注意 metadata 區域的內容要和 Service 保持一致,Service 的 clusterIP 設定為 None,對改知識點不太熟悉的,可以去檢視我們前面關於 Service 部分的講解。
Endpoints 的 subsets 中填寫 etcd 叢集的地址即可,我們這裡是建立的是高可用測試叢集,我們建立的時候指定了node的主機IP地址(2個etcd也是不符合規範的。因為etcd是選舉制,2個就等於一個是一樣的。),直接建立該 Service 資源:
$ kubectl create -f prometheus-etcdService.yaml service/etcd-k8s created endpoints/etcd-k8s created
建立完成後,隔一會兒去 Prometheus 的 Dashboard 中檢視 targets,便會有 etcd 的監控項了:
資料採集到後,可以在 grafana 中匯入編號為3070
的 dashboard,獲取到 etcd 的監控圖表。
配置 PrometheusRule
現在我們知道怎麼自定義一個 ServiceMonitor 物件了,但是如果需要自定義一個報警規則的話呢?比如現在我們去檢視 Prometheus Dashboard 的 Alert 頁面下面就已經有一些報警規則了,還有一些是已經觸發規則的了:
但是這些報警資訊是哪裡來的呢?他們應該用怎樣的方式通知我們呢?我們知道之前我們使用自定義的方式可以在 Prometheus 的配置檔案之中指定 AlertManager 例項和 報警的 rules 檔案,現在我們通過 Operator 部署的呢?我們可以在 Prometheus Dashboard 的 Config 頁面下面檢視關於 AlertManager 的配置:
alerting: alert_relabel_configs: - separator: ; regex: prometheus_replica replacement: $1 action: labeldrop alertmanagers: - kubernetes_sd_configs: - role: endpoints namespaces: names: - monitoring scheme: http path_prefix: / timeout: 10s relabel_configs: - source_labels: [__meta_kubernetes_service_name] separator: ; regex: alertmanager-main replacement: $1 action: keep - source_labels: [__meta_kubernetes_endpoint_port_name] separator: ; regex: web replacement: $1 action: keep rule_files: - /etc/prometheus/rules/prometheus-k8s-rulefiles-0/*.yaml
上面 alertmanagers 例項的配置我們可以看到是通過角色為 endpoints 的 kubernetes 的服務發現機制獲取的,匹配的是服務名為 alertmanager-main,埠名未 web 的 Service 服務,我們檢視下 alertmanager-main 這個 Service:
kubectl describe svc alertmanager-main -n monitoring Name: alertmanager-main Namespace: monitoring Labels: alertmanager=main Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"alertmanager":"main"},"name":"alertmanager-main","namespace":"monitoring"},... Selector: alertmanager=main,app=alertmanager Type: ClusterIP IP: 10.110.43.207 Port: web 9093/TCP TargetPort: web/TCP Endpoints: 10.244.0.31:9093,10.244.2.42:9093,10.244.3.40:9093 Session Affinity: None Events: <none>
可以看到服務名正是 alertmanager-main,Port 定義的名稱也是 web,符合上面的規則,所以 Prometheus 和 AlertManager 元件就正確關聯上了。而對應的報警規則檔案位於:/etc/prometheus/rules/prometheus-k8s-rulefiles-0/
目錄下面所有的 YAML 檔案。我們可以進入 Prometheus 的 Pod 中驗證下該目錄下面是否有 YAML 檔案:
$ kubectl exec -it prometheus-k8s-0 /bin/sh -n monitoring Defaulting container name to prometheus. Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod. /prometheus $ ls /etc/prometheus/rules/prometheus-k8s-rulefiles-0/ monitoring-prometheus-k8s-rules.yaml /prometheus $ cat /etc/prometheus/rules/prometheus-k8s-rulefiles-0/monitoring-prometheus-k8s-rules.yaml groups: - name: k8s.rules rules: - expr: | sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace) record: namespace:container_cpu_usage_seconds_total:sum_rate - expr: | sum by (namespace, pod_name, container_name) ( rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m]) ) record: namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate ...........
這個 YAML 檔案實際上就是我們之前建立的一個 PrometheusRule 檔案包含的:
$ cat prometheus-rules.yaml apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: prometheus: k8s role: alert-rules name: prometheus-k8s-rules namespace: monitoring spec: groups: - name: k8s.rules rules: - expr: | sum(rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m])) by (namespace) record: namespace:container_cpu_usage_seconds_total:sum_rate - expr: | sum by (namespace, pod_name, container_name) ( rate(container_cpu_usage_seconds_total{job="kubelet", image!="", container_name!=""}[5m]) ) record: namespace_pod_name_container_name:container_cpu_usage_seconds_total:sum_rate .....
我們這裡的 PrometheusRule 的 name 為 prometheus-k8s-rules,namespace 為 monitoring,我們可以猜想到我們建立一個 PrometheusRule 資源物件後,會自動在上面的 prometheus-k8s-rulefiles-0 目錄下面生成一個對應的<namespace>-<name>.yaml
檔案,所以如果以後我們需要自定義一個報警選項的話,只需要定義一個 PrometheusRule 資源物件即可。至於為什麼 Prometheus 能夠識別這個 PrometheusRule 資源物件呢?這就需要檢視我們建立的 prometheus 這個資源物件了,裡面有非常重要的一個屬性 ruleSelector,用來匹配 rule 規則的過濾器,要求匹配具有 prometheus=k8s 和 role=alert-rules 標籤的 PrometheusRule 資源物件,現在明白了吧?
ruleSelector: matchLabels: prometheus: k8s role: alert-rules
所以我們要想自定義一個報警規則,只需要建立一個具有 prometheus=k8s 和 role=alert-rules 標籤的 PrometheusRule 物件就行了,比如現在我們新增一個 etcd 是否可用的報警,我們知道 etcd 整個叢集有一半以上的節點可用的話叢集就是可用的,所以我們判斷如果不可用的 etcd 數量超過了一半那麼就觸發報警,建立檔案 prometheus-etcdRules.yaml:
apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: labels: prometheus: k8s role: alert-rules name: etcd-rules namespace: monitoring spec: groups: - name: etcd rules: - alert: EtcdClusterUnavailable annotations: summary: etcd cluster small description: If one more etcd peer goes down the cluster will be unavailable expr: | count(up{job="etcd"} == 0) > (count(up{job="etcd"}) / 2 - 1) for: 3m labels: severity: critical
.....
$ kubectl create -f prometheus-etcdRules.yam
注意 label 標籤一定至少要有 prometheus=k8s 和 role=alert-rules,建立完成後,隔一會兒再去容器中檢視下 rules 資料夾:
$ kubectl exec -it prometheus-k8s-0 /bin/sh -n monitoring Defaulting container name to prometheus. Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod. /prometheus $ ls /etc/prometheus/rules/prometheus-k8s-rulefiles-0/ monitoring-etcd-rules.yaml monitoring-prometheus-k8s-rules.yaml
可以看到我們建立的 rule 檔案已經被注入到了對應的 rulefiles 資料夾下面了,證明我們上面的設想是正確的。然後再去 Prometheus Dashboard 的 Alert 頁面下面就可以檢視到上面我們新建的報警規則了:
配置報警
我們知道了如何去新增一個報警規則配置項,但是這些報警資訊用怎樣的方式去傳送呢?前面的課程中我們知道我們可以通過 AlertManager 的配置檔案去配置各種報警接收器,現在我們是通過 Operator 提供的 alertmanager 資源物件建立的元件,應該怎樣去修改配置呢?
首先我們將 alertmanager-main 這個 Service 改為 NodePort 型別的 Service,修改完成後我們可以在頁面上的 status 路徑下面檢視 AlertManager 的配置資訊:
$ kubectl edit svc alertmanager-main -n monitoring ...... selector: alertmanager: main app: alertmanager sessionAffinity: None type: NodePort .....
這些配置資訊實際上是來自於我們之前在prometheus-operator/contrib/kube-prometheus/manifests
目錄下面建立的 alertmanager-secret.yaml 檔案:
apiVersion: v1 data: alertmanager.yaml: Imdsb2JhbCI6IAogICJyZXNvbHZlX3RpbWVvdXQiOiAiNW0iCiJyZWNlaXZlcnMiOiAKLSAibmFtZSI6ICJudWxsIgoicm91dGUiOiAKICAiZ3JvdXBfYnkiOiAKICAtICJqb2IiCiAgImdyb3VwX2ludGVydmFsIjogIjVtIgogICJncm91cF93YWl0IjogIjMwcyIKICAicmVjZWl2ZXIiOiAibnVsbCIKICAicmVwZWF0X2ludGVydmFsIjogIjEyaCIKICAicm91dGVzIjogCiAgLSAibWF0Y2giOiAKICAgICAgImFsZXJ0bmFtZSI6ICJEZWFkTWFuc1N3aXRjaCIKICAgICJyZWNlaXZlciI6ICJudWxsIg== kind: Secret metadata: name: alertmanager-main namespace: monitoring type: Opaque
可以將 alertmanager.yaml 對應的 value 值做一個 base64 解碼:
echo Imdsb2JhbCI6IAogICJyZXNvbHZlX3RpbWVvdXQiOiAiNW0iCiJyZWNlaXZlcnMiOiAKLSAibmFtZSI6ICJudWxsIgoicm91dGUiOiAKICAiZ3JvdXBfYnkiOiAKICAtICJqb2IiCiAgImdyb3VwX2ludGVydmFsIjogIjVtIgogICJncm91cF93YWl0IjogIjMwcyIKICAicmVjZWl2ZXIiOiAibnVsbCIKICAicmVwZWF0X2ludGVydmFsIjogIjEyaCIKICAicm91dGVzIjogCiAgLSAibWF0Y2giOiAKICAgICAgImFsZXJ0bmFtZSI6ICJEZWFkTWFuc1N3aXRjaCIKICAgICJyZWNlaXZlciI6ICJudWxsIg== | base64 -d
解碼出來的結果 "global": "resolve_timeout": "5m" "receivers": - "name": "null" "route": "group_by": - "job" "group_interval": "5m" "group_wait": "30s" "receiver": "null" "repeat_interval": "12h" "routes": - "match": "alertname": "DeadMansSwitch" "receiver": "null"
我們可以看到內容和上面檢視的配置資訊是一致的,所以如果我們想要新增自己的接收器,或者模板訊息,我們就可以更改這個檔案:
global: resolve_timeout: 5m smtp_smarthost: 'smtp.qq.com:587' smtp_from: '[email protected]' smtp_auth_username: '[email protected]' smtp_auth_password: '***' smtp_hello: 'qq.com' smtp_require_tls: true templates: - "/etc/alertmanager-tmpl/wechat.tmpl" route: group_by: ['job', 'severity'] group_wait: 30s group_interval: 5m repeat_interval: 5m receiver: default routes: - receiver: 'wechat' group_wait: 10s match: alertname: CoreDNSDown receivers: - name: 'default' email_configs: - to: '[email protected]' send_resolved: true - name: 'wechat' wechat_configs: - corp_id: '***' to_party: '*' to_user: "**" agent_id: '***' api_secret: '***' send_resolved: true
將上面檔案儲存為 alertmanager.yaml,然後使用這個檔案建立一個 Secret 物件:
#刪除原secret物件 kubectl delete secret alertmanager-main -n monitoring secret "alertmanager-main" deleted #將自己的配置檔案匯入到新的secret kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml -n monitoring
我們添加了兩個接收器,預設的通過郵箱進行傳送,對於 CoreDNSDown 這個報警我們通過 wechat 來進行傳送,上面的步驟建立完成後,很快我們就會收到一條釘釘訊息:
同樣郵箱中也會收到報警資訊:
我們再次檢視 AlertManager 頁面的 status 頁面的配置資訊可以看到已經變成上面我們的配置資訊了:
AlertManager 配置也可以使用模板(.tmpl檔案),這些模板可以與 alertmanager.yaml 配置檔案一起新增到 Secret 物件中,比如:
apiVersion:v1 kind:secret metadata: name:alertmanager-example data: alertmanager.yaml:{BASE64_CONFIG} template_1.tmpl:{BASE64_TEMPLATE_1} template_2.tmpl:{BASE64_TEMPLATE_2} ...
模板會被放置到與配置檔案相同的路徑,當然要使用這些模板檔案,還需要在 alertmanager.yaml 配置檔案中指定:
templates: - '*.tmpl'
建立成功後,Secret 物件將會掛載到 AlertManager 物件建立的 AlertManager Pod 中去。
樣例:我們建立一個alertmanager-tmpl.yaml檔案,新增如下內容:
{{ define "wechat.default.message" }} {{ range .Alerts }} ========start========== 告警程式: prometheus_alert 告警級別: {{ .Labels.severity }} 告警型別: {{ .Labels.alertname }} 故障主機: {{ .Labels.instance }} 告警主題: {{ .Annotations.summary }} 告警詳情: {{ .Annotations.description }} 觸發時間: {{ .StartsAt.Format "2013-12-02 15:04:05" }} ========end========== {{ end }} {{ end }}
刪除原secret物件
$ kubectl delete secret alertmanager-main -n monitoring secret "alertmanager-main" deleted
建立新的secret物件
$ kubectl create secret generic alertmanager-main --from-file=alertmanager.yaml --from-file=alertmanager-tmpl.yaml -n monitoring secret/alertmanager-main created
過一會我們的微信就會收到告警資訊。當然這裡標籤定義的問題,獲取的值不全,我們可以根據實際情況自定義。
自動發現配置
我們想一個問題,如果在我們的 Kubernetes 叢集中有了很多的 Service/Pod,那麼我們都需要一個一個的去建立一個對應的 ServiceMonitor 物件來進行監控嗎?這樣豈不是又變得麻煩起來了?
為解決這個問題,Prometheus Operator 為我們提供了一個額外的抓取配置的來解決這個問題,我們可以通過新增額外的配置來進行服務發現進行自動監控。和前面自定義的方式一樣,我們想要在 Prometheus Operator 當中去自動發現並監控具有prometheus.io/scrape=true
這個 annotations 的 Service,之前我們定義的 Prometheus 的配置如下:
- job_name: 'kubernetes-service-endpoints' kubernetes_sd_configs: - role: endpoints relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] action: replace target_label: __scheme__ regex: (https?) - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] action: replace target_label: __address__ regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] action: replace target_label: kubernetes_name
要想自動發現叢集中的 Service,就需要我們在 Service 的annotation
區域新增prometheus.io/scrape=true
的宣告,將上面檔案直接儲存為 prometheus-additional.yaml,然後通過這個檔案建立一個對應的 Secret 物件:
$ kubectl create secret generic additional-configs --from-file=prometheus-additional.yaml -n monitoring secret/additional-configs created
建立完成後,會將上面配置資訊進行 base64 編碼後作為 prometheus-additional.yaml 這個 key 對應的值存在:
$ kubectl get secret additional-configs -n monitoring -o yaml apiVersion: v1 data: prometheus-additional.yaml: LSBqb2JfbmFtZTogJ2t1YmVybmV0ZXMtc2VydmljZS1lbmRwb2ludHMnCiAga3ViZXJuZXRlc19zZF9jb25maWdzOgogIC0gcm9sZTogZW5kcG9pbnRzCiAgcmVsYWJlbF9jb25maWdzOgogIC0gc291cmNlX2xhYmVsczogW19fbWV0YV9rdWJlcm5ldGVzX3NlcnZpY2VfYW5ub3RhdGlvbl9wcm9tZXRoZXVzX2lvX3NjcmFwZV0KICAgIGFjdGlvbjoga2VlcAogICAgcmVnZXg6IHRydWUKICAtIHNvdXJjZV9sYWJlbHM6IFtfX21ldGFfa3ViZXJuZXRlc19zZXJ2aWNlX2Fubm90YXRpb25fcHJvbWV0aGV1c19pb19zY2hlbWVdCiAgICBhY3Rpb246IHJlcGxhY2UKICAgIHRhcmdldF9sYWJlbDogX19zY2hlbWVfXwogICAgcmVnZXg6IChodHRwcz8pCiAgLSBzb3VyY2VfbGFiZWxzOiBbX19tZXRhX2t1YmVybmV0ZXNfc2VydmljZV9hbm5vdGF0aW9uX3Byb21ldGhldXNfaW9fcGF0aF0KICAgIGFjdGlvbjogcmVwbGFjZQogICAgdGFyZ2V0X2xhYmVsOiBfX21ldHJpY3NfcGF0aF9fCiAgICByZWdleDogKC4rKQogIC0gc291cmNlX2xhYmVsczogW19fYWRkcmVzc19fLCBfX21ldGFfa3ViZXJuZXRlc19zZXJ2aWNlX2Fubm90YXRpb25fcHJvbWV0aGV1c19pb19wb3J0XQogICAgYWN0aW9uOiByZXBsYWNlCiAgICB0YXJnZXRfbGFiZWw6IF9fYWRkcmVzc19fCiAgICByZWdleDogKFteOl0rKSg/OjpcZCspPzsoXGQrKQogICAgcmVwbGFjZW1lbnQ6ICQxOiQyCiAgLSBhY3Rpb246IGxhYmVsbWFwCiAgICByZWdleDogX19tZXRhX2t1YmVybmV0ZXNfc2VydmljZV9sYWJlbF8oLispCiAgLSBzb3VyY2VfbGFiZWxzOiBbX19tZXRhX2t1YmVybmV0ZXNfbmFtZXNwYWNlXQogICAgYWN0aW9uOiByZXBsYWNlCiAgICB0YXJnZXRfbGFiZWw6IGt1YmVybmV0ZXNfbmFtZXNwYWNlCiAgLSBzb3VyY2VfbGFiZWxzOiBbX19tZXRhX2t1YmVybmV0ZXNfc2VydmljZV9uYW1lXQogICAgYWN0aW9uOiByZXBsYWNlCiAgICB0YXJnZXRfbGFiZWw6IGt1YmVybmV0ZXNfbmFtZQo= kind: Secret metadata: creationTimestamp: 2019-03-20T03:38:37Z name: additional-configs namespace: monitoring resourceVersion: "29056864" selfLink: /api/v1/namespaces/monitoring/secrets/additional-configs uid: a579495b-4ac1-11e9-baf3-005056930126 type: Opaque
然後我們只需要在宣告 prometheus 的資源物件檔案中新增上這個額外的配置:(prometheus-prometheus.yaml)
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: labels: prometheus: k8s name: k8s namespace: monitoring spec: alerting: alertmanagers: - name: alertmanager-main namespace: monitoring port: web baseImage: quay.io/prometheus/prometheus nodeSelector: beta.kubernetes.io/os: linux replicas: 2 secrets: - etcd-certs resources: requests: memory: 400Mi ruleSelector: matchLabels: prometheus: k8s role: alert-rules securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 1000 additionalScrapeConfigs: name: additional-configs key: prometheus-additional.yaml serviceAccountName: prometheus-k8s serviceMonitorNamespaceSelector: {} serviceMonitorSelector: {} version: v2.5.0
新增完成後,直接更新 prometheus 這個 CRD 資源物件:
$ kubectl apply -f prometheus-prometheus.yaml prometheus.monitoring.coreos.com/k8s configured
隔一小會兒,可以前往 Prometheus 的 Dashboard 中檢視配置是否生效:
在 Prometheus Dashboard 的配置頁面下面我們可以看到已經有了對應的的配置資訊了,但是我們切換到 targets 頁面下面卻並沒有發現對應的監控任務,檢視 Prometheus 的 Pod 日誌:
$ kubectl logs -f prometheus-k8s-0 prometheus -n monitoring evel=error ts=2019-03-20T03:55:01.298281581Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:302: Failed to list *v1.Pod: pods is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list pods at the cluster scope" level=error ts=2019-03-20T03:55:02.29813427Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:301: Failed to list *v1.Service: services is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list services at the cluster scope" level=error ts=2019-03-20T03:55:02.298431046Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:300: Failed to list *v1.Endpoints: endpoints is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list endpoints at the cluster scope" level=error ts=2019-03-20T03:55:02.299312874Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:302: Failed to list *v1.Pod: pods is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list pods at the cluster scope" level=error ts=2019-03-20T03:55:03.299674406Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:301: Failed to list *v1.Service: services is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list services at the cluster scope" level=error ts=2019-03-20T03:55:03.299757543Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:300: Failed to list *v1.Endpoints: endpoints is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list endpoints at the cluster scope" level=error ts=2019-03-20T03:55:03.299907982Z caller=main.go:240 component=k8s_client_runtime err="github.com/prometheus/prometheus/discovery/kubernetes/kubernetes.go:302: Failed to list *v1.Pod: pods is forbidden: User \"system:serviceaccount:monitoring:prometheus-k8s\" cannot list pods at the cluster scope"
可以看到有很多錯誤日誌出現,都是xxx is forbidden
,這說明是 RBAC 許可權的問題,通過 prometheus 資源物件的配置可以知道 Prometheus 綁定了一個名為 prometheus-k8s 的 ServiceAccount 物件,而這個物件繫結的是一個名為 prometheus-k8s 的 ClusterRole:(prometheus-clusterRole.yaml)
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus-k8s rules: - apiGroups: - "" resources: - nodes/metrics verbs: - get - nonResourceURLs: - /metrics verbs: - get
上面的許可權規則中我們可以看到明顯沒有對 Service 或者 Pod 的 list 許可權,所以報錯了,要解決這個問題,我們只需要新增上需要的許可權即可:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus-k8s rules: - apiGroups: - "" resources: - nodes - services - endpoints - pods - nodes/proxy verbs: - get - list - watch - apiGroups: - "" resources: - configmaps - nodes/metrics verbs: - get - nonResourceURLs: - /metrics verbs: - get
更新上面的 ClusterRole 這個資源物件,然後重建下 Prometheus 的所有 Pod,正常就可以看到 targets 頁面下面有 kubernetes-service-endpoints 這個監控任務了:
$ kubectl apply -f prometheus-clusterRole.yaml clusterrole.rbac.authorization.k8s.io/prometheus-k8s configured
我們這裡自動監控了兩個 Service,這兩個都是coredns的,我們在 Service 中有兩個特殊的 annotations:
$ kubectl describe svc kube-dns -n kube-system Name: kube-dns Namespace: kube-system .... Annotations: prometheus.io/port=9153 prometheus.io/scrape=true
...
所以被自動發現了,當然我們也可以用同樣的方式去配置 Pod、Ingress 這些資源物件的自動發現。
資料持久化
上面我們在修改完許可權的時候,重啟了 Prometheus 的 Pod,如果我們仔細觀察的話會發現我們之前採集的資料已經沒有了,這是因為我們通過 prometheus 這個 CRD 建立的 Prometheus 並沒有做資料的持久化,我們可以直接檢視生成的 Prometheus Pod 的掛載情況就清楚了:
............ volumeMounts: - mountPath: /etc/prometheus/config_out name: config-out readOnly: true - mountPath: /prometheus name: prometheus-k8s-db - mountPath: /etc/prometheus/rules/prometheus-k8s-rulefiles-0 ......... volumes: - name: config secret: defaultMode: 420 secretName: prometheus-k8s - emptyDir: {}
我們可以看到 Prometheus 的資料目錄 /prometheus 實際上是通過 emptyDir 進行掛載的,我們知道 emptyDir 掛載的資料的生命週期和 Pod 生命週期一致的,所以如果 Pod 掛掉了,資料也就丟失了,這也就是為什麼我們重建 Pod 後之前的資料就沒有了的原因,對應線上的監控資料肯定需要做資料的持久化的,同樣的 prometheus 這個 CRD 資源也為我們提供了資料持久化的配置方法,由於我們的 Prometheus 最終是通過 Statefulset 控制器進行部署的,所以我們這裡需要通過 storageclass 來做資料持久化, 我們之前用rook已經搭建過storageclass。所以我們就可以直接用了。我們讓prometheus 的 CRD 資源物件(prometheus-prometheus.yaml)中新增如下配置:
storage: volumeClaimTemplate: spec: storageClassName: rook-ceph-block resources: requests: storage: 10Gi
注意這裡的 storageClassName 名字為上面我們建立的 StorageClass 物件名稱,然後更新 prometheus 這個 CRD 資源。更新完成後會自動生成兩個 PVC 和 PV 資源物件:
$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-dba11961-4ad6-11e9-baf3-005056930126 10Gi RWO Delete Bound monitoring/prometheus-k8s-db-prometheus-k8s-0 rook-ceph-block 1m pvc-dbc6bac5-4ad6-11e9-baf3-005056930126 10Gi RWO Delete Bound monitoring/prometheus-k8s-db-prometheus-k8s-1 rook-ceph-block 1m $ kubectl get pvc -n monitoring NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE prometheus-k8s-db-prometheus-k8s-0 Bound pvc-dba11961-4ad6-11e9-baf3-005056930126 10Gi RWO rook-ceph-block 2m prometheus-k8s-db-prometheus-k8s-1 Bound pvc-dbc6bac5-4ad6-11e9-baf3-005056930126 10Gi RWO rook-ceph-block 2m
現在我們再去看 Prometheus Pod 的資料目錄就可以看到是關聯到一個 PVC 物件上了。
....... volumeMounts: - mountPath: /etc/prometheus/config_out name: config-out readOnly: true - mountPath: /prometheus name: prometheus-k8s-db subPath: prometheus-db - mountPath: /etc/prometheus/rules/prometheus-k8s-rulefiles-0 name: prometheus-k8s-rulefiles-0 ......... volumes: - name: prometheus-k8s-db persistentVolumeClaim: claimName: prometheus-k8s-db-prometheus-k8s-0 .........
現在即使我們的 Pod 掛掉了,資料也不會丟失了。讓我們測試一下。
我們先隨便查一下資料
刪除pod
kubectl delete pod prometheus-k8s-1 -n monitorin kubectl delete pod prometheus-k8s-0 -n monitorin
檢視pod狀態
kubectl get pod -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-main-0 2/2 Running 0 2d alertmanager-main-1 2/2 Running 0 2d alertmanager-main-2 2/2 Running 0 2d grafana-7489c49998-pkl8w 1/1 Running 0 2d kube-state-metrics-d6cf6c7b5-7dwpg 4/4 Running 0 2d node-exporter-dlp25 2/2 Running 0 2d node-exporter-fghlp 2/2 Running 0 2d node-exporter-mxwdm 2/2 Running 0 2d node-exporter-r9v92 2/2 Running 0 2d prometheus-adapter-84cd9c96c9-n92n4 1/1 Running 0 2d prometheus-k8s-0 0/3 ContainerCreating 0 3s prometheus-k8s-1 3/3 Running 0 9s prometheus-operator-7b74946bd6-vmbcj 1/1 Running 0 2d
pod正在重新建立。等建立完成,我們再檢視一下資料
我們的資料是正常的,沒有丟失。