天天看點

Prometheus2.6.0監控——部署篇

大家好,我是Linux運維工程師 Linke 。技術過硬,從不挖坑~

這篇文檔來記錄一下我新部署的監控軟體Prometheus ,grafana 和 alatermanager 放在下一篇文章中~~

記得剛剛上了 k8s 時,我還是用的老套筒式監控,當時不知道有prometheus這個東西,2017年的時候,prometheus大概還不為業内所用,是以不知道。。。好吧,這是我不知道的理由~

當時pod狀态、副本數等都是python寫的監控插件,因為當時主監控服務用的小米監控——open-falcon 。 open-falcon 總體還是不錯的,用的也可以,我個人感覺比zabbix 、 nagios 強多了,但是監控 k8s 就有些吃力了,大部分監控都要自己再開發。我也就這麼一直晃悠的用,維護起來很操蛋的。而且容器中跑java應用的話,jvm用小米的那套重量太大,是以幹脆我就不監控 jvm 了,pod 因為 OOM 挂了我就加記憶體。直到有一天,有個應用不管怎麼加都挂,于是就和同桌研究怎麼監控 JVM ,然後他看到有人用 prometheus 監控 k8s ,而且能拿到 jvm ,然後我們就研究使用這個。上線後,k8s 各名額監控完美抓取,媽媽再也不用擔心我的學習了。

下面開始進入部署環節,還是老樣子,不扯原理,無非就是資料從哪裡來,到哪裡去,沒啥好說的,用兩把就都知道了。

不監控 k8s 的話,感覺還是 open-falcon 使的友善,因為我到現在還沒時間看如何回調接口。也沒找到。自定義監控倒是研究明白了,因為 prometheus沒有端口監控,草不操蛋,然後我自己寫了個,看這個文檔:

https://blog.csdn.net/qq_31547771/article/details/103263288

本文介紹在 k8s 上部署 prometheus ,源碼安裝的俺也沒試過。

前提先要有個 kubernates 叢集,當然能撸到這篇文檔的同行們我相信早已擁有了自己的 k8s 叢集。沒有也沒關系,兄弟我提供一條龍服務,請看文檔:

https://blog.csdn.net/qq_31547771/article/details/100699573
伺服器劃分
k8s叢集角色 ip 排程
master101 192.168.7.101 不跑業務應用
master102 192.168.7.102 不跑業務應用
master103 192.168.7.103 不跑業務應用
node104 192.168.7.104 排程 prometheus 到此節點,不跑其他應用
node105 192.168.7.105 跑其他業務應用

其餘節點都如 node105 ,跑業務應用

另外本例中還加入了一組 es 的監控

192.168.7.41

192.168.7.42

192.168.7.43

k8s操作節點配置prometheus的yaml檔案

我把用來操作 k8s 的系統叫做 k8s 操作節點,這裡我用的是 192.168.7.101 ,生産環境不建議使用 master 節點做操作節點,建議單獨弄一個系統,裝了 kubelet ,使用 k8s 的秘鑰檔案連接配接 k8s 。

下面所有的檔案都放在 /home/scripts/prometheus 路徑下

先編輯第一個主要檔案: configmap.yaml

這個檔案是 prometheus 主服務要使用的,監控規則、監控分組等都寫在這個檔案中了。

如果閑報警規則和監控組寫到一個檔案太多,可以把 rules.yaml 檔案移出去,加一個 rule_files: - “/etc/prometheus/prometheus.rules.yml” ,指定到一個檔案。但要記得挂載進去。本例中,我是寫到一起的、

cat > configmap.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: monitor
data:
  #被引用到/etc/prometheus/prometheus.yml
  prometheus.yml: |
    global:
      #每15s采集一次資料和15s做一次告警檢測
      scrape_interval:     15s
      evaluation_interval: 15s
    #指定加載的告警規則檔案
    rule_files:
    - /etc/prometheus/rules.yml
    #将報警送至何地進行報警
    alerting:
      alertmanagers:
        - static_configs:
          - targets: ["192.168.7.107:9093"]
    #指定prometheus要監控的目标
    scrape_configs:
    - job_name: 'k8s-node'
      scrape_interval: 10s
      static_configs:
      - targets: 
        - '192.168.7.101:31672'
        - '192.168.7.102:31672'     
        - '192.168.7.103:31672'     
        - '192.168.7.104:31672'     
        - '192.168.7.105:31672'     
    - job_name: 'es-node'
      scrape_interval: 10s
      static_configs:
      - targets: 
        - '192.168.7.41:31672'
        - '192.168.7.42:31672'     
        - '192.168.7.43:31672'
    #自定義擷取監控資料,每個 job_name 都是獨立的,以下的文法難的一逼,可能隻有老天爺知道
    - job_name: 'tomcat-pods'
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape, __meta_kubernetes_service_annotation_prometheus_io_jvm_scrape]
        regex: true;true
        action: keep
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_app_metrics_patn]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__meta_kubernetes_pod_ip, __meta_kubernetes_service_annotation_prometheus_io_app_metrics_port]
        action: replace
        target_label: __address__
        regex: (.+);(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_pod_host_ip]
        action: replace
        target_label: kubernetes_host_ip
    - job_name: 'kubernetes-apiservers'
      kubernetes_sd_configs:
      - role: endpoints
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
        action: keep
        regex: default;kubernetes;https

    - job_name: 'kubernetes-nodes'
      kubernetes_sd_configs:
      - role: node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics

    - job_name: 'kubernetes-cadvisor'
      kubernetes_sd_configs:
      - role: node
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
      relabel_configs:
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      - target_label: __address__
        replacement: kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        target_label: __metrics_path__
        replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor

    - 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

    - job_name: 'kubernetes-services'
      kubernetes_sd_configs:
      - role: service
      metrics_path: /probe
      params:
        module: [http_2xx]
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
        action: keep
        regex: true
      - source_labels: [__address__]
        target_label: __param_target
      - target_label: __address__
        replacement: blackbox-exporter.example.com:9115
      - source_labels: [__param_target]
        target_label: instance
      - action: labelmap
        regex: __meta_kubernetes_service_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_service_name]
        target_label: kubernetes_name

    - job_name: 'kubernetes-ingresses'
      kubernetes_sd_configs:
      - role: ingress
      relabel_configs:
      - source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
        regex: (.+);(.+);(.+)
        replacement: ${1}://${2}${3}
        target_label: __param_target
      - target_label: __address__
        replacement: blackbox-exporter.example.com:9115
      - source_labels: [__param_target]
        target_label: instance
      - action: labelmap
        regex: __meta_kubernetes_ingress_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_ingress_name]
        target_label: kubernetes_name
    - job_name: 'kubernetes-pods'
      kubernetes_sd_configs:
      - role: pod
      relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name
  # 監控規則檔案,被引用到/etc/prometheus/rules.yml
  rules.yml: |
    groups:
    - name: test-rule
      rules:

      ############# k8s-Node監控 #############
      - alert: k8s-node狀态異常
        expr: up{job="k8s-node"} != 1
        for: 3m
        labels:
          severity: 非常嚴重
        annotations:
          summary: "k8s節點可能宕了"
          description: "{{$labels.instance}}: Node節點狀态異常"
      - alert: k8s-node節點CPU使用率
        expr: (1 - avg(irate(node_cpu_seconds_total{job="k8s-node",mode="idle"}[1m])) by (instance)) * 100  > 95
        for: 3m
        labels:
          severity: 一般
        annotations:
          summary: "Node節點CPU使用率超過95%"
          description: "{{$labels.instance}}: Node節點目前CPU使用率為: {{ $value }}"
      - alert: k8s-node節點根磁盤使用率
        expr: (node_filesystem_size_bytes{mountpoint="/",job="k8s-node"} - node_filesystem_avail_bytes{mountpoint="/",job="k8s-node"}) / node_filesystem_size_bytes{mountpoint="/",job="k8s-node"} * 100 > 70
        for: 3m
        labels:
          team: k8s-node
        annotations:
          summary: "根磁盤使用率為: {{ $value }}"
          description: "Node伺服器[[ {{$labels.instance}} ]] 的 {{$labels.mountpoint}} 磁盤空間使用率超過70%,超過85%後pod将遷移,請盡快處理"
      - alert: k8s-node節點記憶體使用率
        expr: (node_memory_MemTotal_bytes{job="k8s-node"} - (node_memory_Buffers_bytes{job="k8s-node"} + node_memory_Cached_bytes{job="k8s-node"} + node_memory_MemFree_bytes{job="k8s-node"})) / node_memory_MemTotal_bytes{job="k8s-node"} * 100 > 95
        for: 3m
        labels:
          team: k8s-node
        annotations:
          summary: "目前記憶體使用率超過95%"
          description: "Node伺服器[[ {{$labels.instance}} ]]  記憶體使用率為: {{ $value }}"
          
      ############# es-Node監控 #############
      - alert: es-node狀态異常
        expr: up{job="es-node"} != 1
        for: 3m
        labels:
          severity: 非常嚴重
        annotations:
          summary: "elasticsearch節點可能宕了"
          description: "{{$labels.instance}}: elasticsearch節點狀态異常"
      - alert: es-node節點資料磁盤使用率
        expr: (node_filesystem_size_bytes{mountpoint="/data",job="es-node"} - node_filesystem_avail_bytes{mountpoint="/data",job="es-node"}) / node_filesystem_size_bytes{mountpoint="/data",job="es-node"} * 100 > 70
        for: 3m
        labels:
          severity: 嚴重
        annotations:
          summary: "/data 磁盤使用率為: {{ $value }}"
          description: "Node伺服器[[ {{$labels.instance}} ]] 的 {{$labels.mountpoint}} 磁盤空間使用率超過70%,超過85%後pod将遷移,請盡快處理"
EOF
           

我這麼負責,這裡要說一下某些沒加注釋的地方

  • alert: 報警組

    expr: 報警規則設定,這裡的資料源在 prometheus 的 UI 界面都能搜尋到,并且在 UI 界面都可以用文法取到想要的值,監控規則必須得在 UI 界面能一樣運作取值,否則無法監控。例如 up{job=“es-node”} 直接在 UI 界面輸入是可以拿到值的。

    for:觸發報警後等待時間

    labels: 設定報警級别,此處還有别的功能,沒研究

    annotations: 報警資訊的描述,這裡可以從報警資訊中過濾想要的内容,使報警内容更加易讀

    summary: 翻譯一下,總結; 概括; 概要; 如我上面所寫,你懂得。

    description: 翻譯一下,描述,描寫,說明,你懂得。這兩個随便怎麼用都行。

    建議報警規則按照各個類型分開,以服務種類劃分,本人跟監控打了三年交道,我覺得越細越好、因為各種服務有各種自己的門檻值,它可以讓磁盤到 90% 再報警,但另一個80%就得報警,是以越細越好。跑題了。。。

rbac 檔案

這個檔案不得了,有了他,就可以連接配接到 k8s master ,擷取到 k8s 的叢集資訊,即獲得 k8s api ,這個檔案不用改,直接拿去用。

cat > rbac-setup.yaml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: monitor
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: monitor
EOF
           

pod 的配置檔案 prometheus-deploy.yaml

來吧,下面讓我們一鼓作氣建立完,然後是啟動 pod 的配置檔案 prometheus-deploy.yaml ,有兩點需要注意:

1、修改一下資料目錄的挂在點為自己的路徑,主控端此資料路徑給 777 權限。

2、我給 prometheus 的 pod 加了排程方式,隻能在有 prometheus 标簽的節點上啟動,即下面的這個配置

nodeSelector:
    nodetype: prometheus
           

具體怎麼做,請看這篇文檔:

https://blog.csdn.net/qq_31547771/article/details/100742202

這個檔案。。。能撸到此文的,相信對 k8s 的 yaml 檔案已經相當熟悉了。不熟悉的話,Linke 在這兒有詳解:

https://blog.csdn.net/qq_31547771/article/details/102526403
cat > prometheus-deploy.yaml << EOF
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    name: prometheus-deployment
  name: prometheus
  namespace: monitor
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - image: prom/prometheus:v2.6.0
        name: prometheus
        command:
        - "/bin/prometheus"
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/home/prometheus"
        - "--storage.tsdb.retention=15d"
        - "--web.enable-lifecycle"
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: "/home/prometheus"
          name: data
        - mountPath: "/etc/prometheus"
          name: config-volume
        - mountPath: "/etc/localtime"
          readOnly: false
          name: localtime
        resources:
          requests:
            cpu: 500m
            memory: 3180Mi
          limits:
            cpu: 1000m
            memory: 4180Mi
      serviceAccountName: prometheus    
      nodeSelector:
        nodetype: prometheus
      volumes:
      - name: data
        hostPath:
          path: "/opt/prometheus/data"
      - name: config-volume
        configMap:
          name: prometheus-config
      - name: localtime
        hostPath:
          path: "/etc/localtime"
          type: File
EOF
           

然後是對外(叢集外部通路)用的 service 配置檔案

prometheus-service.yaml ,即使用 nodeport 将端口映射到叢集外,然後用浏覽器通路。

cat > prometheus-service.yaml << EOF
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus
  namespace: monitor
spec:
  type: NodePort
  ports:
  - port: 9090
    targetPort: 9090
    nodePort: 30003
  selector:
    app: prometheus
EOF
           

最後是建立 namespace 的配置檔案 monitor_namespace.yaml

以上 service 和 pod 都規劃到 monitor 命名空間中

cat > monitor_namespace.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
   name: monitor
   labels:
     name: monitor
EOF
           

然後是。然後prometheus就啟動了。。順序, 先建立命名空間——> 建立 confimap ——> 建立 rbac ——> 啟動 prometheus pod ——> 建立 prometheus service

kubectk create -f monitor_namespace.yaml
kubectk create -f configmap.yaml
kubectk create -f rbac-setup.yaml
kubectk create -f prometheus-deploy.yaml
kubectk create -f prometheus-service.yaml
kubectl get po -n monitor
           

一頓操作下去,檢視prometheus pod 是否啟動正常。然後浏覽器輸入 192.168.7.104:30003 ,就可以通路 prometheus 的 UI 界面了。在這裡可以搜尋關鍵字,如輸入 pod ,會自動補充,但是下面還要啟動一個 kube-state-metrics 才能抓到 pod 的資料。 是以,接的往下看。

Prometheus2.6.0監控——部署篇

下面這兩個圖是 我現在的,上面的 confimap.yaml 我把多餘的都删了,否則太多。箭頭指出來的,是這個文檔例子中 confimap 會顯示的

點選 Alerts ,就可以看到自己設定的報警規則,可以嘗試觸發一個報警,看看這頁的狀态。

Prometheus2.6.0監控——部署篇
Prometheus2.6.0監控——部署篇

現在已經有了cadvisor、heapster、metric-server,幾乎容器運作的所有名額都能拿到,但是下面這種情況卻無能為力抓不到, k8s 的 pod 資料,還需要啟動一個從k8s中掏資料的元件,即 kube-state-metrics ,這個插件其實就是将 k8s api 中的 pod 資料取出來,然後處理成了 prometheus 監控資料的格式。

直接從 github 把這個項目下載下傳下來:

https://github.com/kubernetes/kube-state-metrics

将一個版本的下載下傳下來,如果有的資料抓不到,或者有問題,就換個版本。我這裡用的是 kube-state-metrics:v1.3.1 ,去年裝的,一直沒時間更新。

将項目下載下傳來了後,解壓開 tar 包後,我們用 k8s 啟動,是以隻需要項目中的 kubernetes 目錄和下面的是以 yaml 檔案就可以了,然後将各個檔案中的 namespace: 的值改成 monitor ,不改也可以 。然後挨個建立一下:

cd kubernetes
for i in *;do kubectk create -f $i ;done
kubectl get po -n monitor
           

等待一分鐘,此時再重新整理一下浏覽器,然後在Graph 那一頁搜尋: pod ,會補出抓到的pod 資料。如圖,我們選擇 kube_pod_info

Prometheus2.6.0監控——部署篇
Prometheus2.6.0監控——部署篇

然後可以使用 prometheus 的文法将資料縮小範圍,監控也是這個意思,自己多測幾遍就懂了:

Prometheus2.6.0監控——部署篇

未完,請見下面兩篇文章。

Prometheus監控之Grafana——部署篇

https://blog.csdn.net/qq_31547771/article/details/103433097

Prometheus監控之altermanager——部署篇

https://blog.csdn.net/qq_31547771/article/details/103433737