Kubernetes1.16下部署Prometheus+node-exporter+Grafana+AlertManager 監控系統


Prometheus 持久化安裝

我們prometheus采用nfs掛載方式來存儲數據,同時使用configMap管理配置文件。並且我們將所有的prometheus存儲在kube-system

#建議將所有的prometheus yaml文件存在一塊
mkdir /opt/prometheus -p && cd /opt/prometheus

#生成配置文件

cat >> prometheus.configmap.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: kube-system
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090']
EOF

# 配置文件解釋(這里的configmap實際上就是prometheus的配置)
上面包含了3個模塊global、rule_files和scrape_configs

其中global模塊控制Prometheus Server的全局配置
scrape_interval:表示prometheus抓取指標數據的頻率,默認是15s,我們可以覆蓋這個值
evaluation_interval:用來控制評估規則的頻率,prometheus使用規則產生新的時間序列數據或者產生警報

rule_files模塊制定了規則所在的位置,prometheus可以根據這個配置加載規則,用於生產新的時間序列數據或者報警信息,當前我們沒有配置任何規則,后期會添加

scrape_configs用於控制prometheus監控哪些資源。由於prometheus通過http的方式來暴露它本身的監控數據,prometheus也能夠監控本身的健康情況。在默認的配置有一個單獨的job,叫做prometheus,它采集prometheus服務本身的時間序列數據。這個job包含了一個單獨的、靜態配置的目標;監聽localhost上的9090端口。
prometheus默認會通過目標的/metrics路徑采集metrics。所以,默認的job通過URL:http://localhost:9090/metrics采集metrics。收集到時間序列包含prometheus服務本身的狀態和性能。如果我們還有其他的資源需要監控,可以直接配置在該模塊下即可

然后創建該資源對象:

[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml
configmap/prometheus-config created
[root@k8s-01 prometheus]#  kubectl get configmaps -n kube-system |grep prometheus
prometheus-config                    1      163m

配置文件創建完成,如果以后我們有新的資源需要被監控,我們只需要將ConfigMap對象更新即可,現在我們開始創建prometheus的Pod資源

[root@k8s-01 prometheus]# cat > prometheus.deploy.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: kube-system
  labels:
    app: prometheus
spec:
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      serviceAccountName: prometheus
      containers:
      - image: prom/prometheus:v2.4.3
        name: prometheus
        command:
        - "/bin/prometheus"
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/prometheus"
        - "--storage.tsdb.retention=30d"
        - "--web.enable-admin-api"  # 控制對admin HTTP API的訪問,其中包括刪除時間序列等功能
        - "--web.enable-lifecycle"  # 支持熱更新,直接執行localhost:9090/-/reload立即生效
        ports:
        - containerPort: 9090
          protocol: TCP
          name: http
        volumeMounts:
        - mountPath: "/prometheus"
          subPath: prometheus
          name: data
        - mountPath: "/etc/prometheus"
          name: config-volume
        resources:
          requests:
            cpu: 100m
            memory: 512Mi
          limits:
            cpu: 100m
            memory: 512Mi
      securityContext:
        runAsUser: 0
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: prometheus
      - configMap:
          name: prometheus-config
        name: config-volume



---
apiVersion: v1
kind: Service
metadata:
  namespace: kube-system
  name: prometheus
  labels:
    app: prometheus
spec:
  type: NodePort
  selector:
    app: prometheus
  ports:
  - name: http
    port: 9090

EOF

我們在啟動程序的時候,除了指定prometheus.yaml(configmap)以外,還通過storage.tsdb.path指定了TSDB數據的存儲路徑、通過storage.tsdb.rentention設置了保留多長時間的數據,還有下面的web.enable-admin-api參數可以用來開啟對admin api的訪問權限,參數web.enable-lifecyle用來開啟支持熱更新,有了這個參數之后,prometheus.yaml(configmap)文件只要更新了,通過執行localhost:9090/-/reload就會立即生效

我們添加了一行securityContext,,其中runAsUser設置為0,這是因為prometheus運行過程中使用的用戶是nobody,如果不配置可能會出現權限問題

NFS搭建步驟

for i in k8s-01 k8s-02 k8s-03;do ssh root@$i "yum install nfs-utils rpcbind -y";done
接着我們在任意一台機器上搭建nfs,其他的服務器主要是掛載

我這里使用192.168.0.200

NFS服務器操作如下
mkdir -p /home/kvm
systemctl start rpcbind
systemctl enable rpcbind
systemctl enable nfs
echo "/home/kvm  *(rw,no_root_squash,sync)" >>/etc/exports



其他k8s節點直接啟動rpcbind並且掛載目錄就可以
systemctl start rpcbind
systemctl enable rpcbind
mkdir /data/k8s -p
mount -t nfs 10.4.82.138:/home/kvm /data/k8s

prometheus.yaml文件對應的ConfigMap對象通過volume的形式掛載進Pod,這樣ConfigMap更新后,對應的pod也會熱更新,然后我們在執行上面的reload請求,prometheus配置就生效了。除此之外,對了將時間數據進行持久化,我們將數據目錄和一個pvc對象進行了綁定,所以我們需要提前創建pvc對象

[root@k8s-01 prometheus]# cat >prometheus-volume.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: prometheus
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    server: 192.168.0.200
    path: /home/kvm/k8s-vloume

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: prometheus
  namespace: kube-system
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

EOF

#nfs 
server nfs服務器ip
path  掛載點,提前掛在好,確保可以寫入

這里通過一個簡單的NFS作為存儲后端創建一個pv & pvc

[root@k8s-01 prometheus]# kubectl create -f prometheus-volume.yaml
persistentvolume/prometheus created
persistentvolumeclaim/prometheus created

我們這里還需要創建rbac認證,因為prometheus需要訪問k8s集群內部的資源

cat >>prometheus-rbac.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - services
  - endpoints
  - pods
  - nodes/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - nodes/metrics
  verbs:
  - get
- nonResourceURLs:
  - /metrics
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: kube-system
EOF

由於我們要獲取的資源,在每一個namespace下面都有可能存在,所以我們這里使用的是ClusterRole的資源對象,nonResourceURLs是用來對非資源型metrics進行操作的權限聲明

創建rbac文件
[root@k8s-01 prometheus]# kubectl create -f prometheus-rbac.yaml
serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created

我們將ConfigMap volume rbac 創建完畢后,就可以創建prometheus.deploy.yaml了,運行prometheus服務

[root@k8s-01]# kubectl create -f prometheus.deploy.yaml
deployment.extensions/prometheus created

[root@k8s-01 prometheus]# kubectl get pod -n kube-system |grep prometheus
prometheus-847494df74-zbz9v      1/1     Running   0          148m


#這里1/1 狀態為Running即可

現在我們prometheus服務狀態是已經正常了,但是我們在瀏覽器是無法訪問prometheus的 webui服務。那么我們還需要創建一個service

cat >>prometeheus-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: kube-system
  name: prometheus
  labels:
    app: prometheus
spec:
  type: NodePort
  selector:
    app: prometheus
  ports:
  - name: http
    port: 9090

EOF
[root@k8s-01prometheus]# kubectl create -f prometeheus-svc.yaml
service/prometheus created

[root@k8s-01 prometheus]# kubectl get svc -n kube-system |grep prometheus
prometheus   NodePort    10.1.183.250   <none>        9090:30129/TCP           148m

這里定義的端口為3xxxx,我們直接在瀏覽器上任意節點輸入ip+端口即可

 

 

 

 

 

 

我們可以查看一下當前監控規則

默認prometheus會監控自己

Status-->Targets

 

 

 我們查看一下數據,是否收集到數據

 

 

 

 

Prometheus監控Kubernetes 集群節點及應用

 

對於Kubernetes的集群監控一般我們需要考慮一下幾方面

  • Kubernetes節點的監控;比如節點的cpu、load、fdisk、memory等指標
  • 內部系統組件的狀態;比如kube-scheduler、kube-controller-manager、kubedns/coredns等組件的運行狀態
  • 編排級的metrics;比如Deployment的狀態、資源請求、調度和API延遲等數據指標

監控方案

Kubernetes集群的監控方案主要有以下幾種方案

  • Heapster:Herapster是一個集群范圍的監控和數據聚合工具,以Pod的形式運行在集群中

kubernetes_monitoring_heapster.png-19.1kB

Kubelet/cAdvisor之外,我們還可以向Heapster添加其他指標源數據,比如kube-state-metrics

Heapster已經被廢棄,使用metrics-server代替

  • cAvisor:cAdvisor是Google開源的容器資源監控和性能分析工具,它是專門為容器而生,本身也支持Docker容器,Kubernetes中,我們不需要單獨去安裝,cAdvisor作為kubelet內置的一部分程序可以直接使用
  • Kube-state-metrics:通過監聽API Server生成有關資源對象的狀態指標,比如Deployment、Node、Pod,需要注意的是kube-state-metrics只是簡單的提供一個metrics數據,並不會存儲這些指標數據,所以我們可以使用Prometheus來抓取這些數據然后存儲
  • metrics-server:metrics-server也是一個集群范圍內的資源數據局和工具,是Heapster的代替品,同樣的,metrics-server也只是顯示數據,並不提供數據存儲服務。

不過kube-state-metricsmetrics-server之前還有很大不同的,二者主要區別如下

1.kube-state-metrics主要關注的是業務相關的一些元數據,比如Deployment、Pod、副本狀態等
2.metrics-service主要關注的是資源度量API的實現,比如CPU、文件描述符、內存、請求延時等指標

資源度量API


監控集群節點

首先需要我們監控集群的節點,要監控節點其實我們已經有很多非常成熟的方案了,比如Nagios、Zabbix,甚至可以我們自己收集數據,這里我們通過prometheus來采集節點的監控指標,可以通過node_exporter獲取,node_exporter就是抓取用於采集服務器節點的各種運行指標,目前node_exporter幾乎支持所有常見的監控點,比如cpu、distats、loadavg、meminfo、netstat等,詳細的監控列表可以參考github repo

這里使用DeamonSet控制器來部署該服務,這樣每一個節點都會運行一個Pod,如果我們從集群中刪除或添加節點后,也會進行自動擴展

[root@k8s-01 prometheus]# cat >>prometheus-node-exporter.yaml<<EOF
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: kube-system
  labels:
    name: node-exporter
    k8s-app: node-exporter
spec:
  selector:
    matchLabels:
      name: node-exporter
  template:
    metadata:
      labels:
        name: node-exporter
        app: node-exporter
    spec:
      hostPID: true
      hostIPC: true
      hostNetwork: true
      containers:
      - name: node-exporter
        image: prom/node-exporter:v0.16.0
        ports:
        - containerPort: 9100
        resources:
          requests:
            cpu: 0.15
        securityContext:
          privileged: true
        args:
        - --path.procfs
        - /host/proc
        - --path.sysfs
        - /host/sys
        - --collector.filesystem.ignored-mount-points
        - '"^/(sys|proc|dev|host|etc)($|/)"'
        volumeMounts:
        - name: dev
          mountPath: /host/dev
        - name: proc
          mountPath: /host/proc
        - name: sys
          mountPath: /host/sys
        - name: rootfs
          mountPath: /rootfs
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: dev
          hostPath:
            path: /dev
        - name: sys
          hostPath:
            path: /sys
        - name: rootfs
          hostPath:
            path: /

EOF

創建node-exporter並檢查pod

[root@k8s-01prometheus]# kubectl create -f prometheus-node-exporter.yaml
daemonset.extensions/node-exporter created


[root@k8s-01 prometheus]# kubectl get pod -n kube-system -o wide|grep node
node-exporter-bsdkl              1/1     Running   0          36m    192.168.122.217   k8s-02   <none>           <none>
node-exporter-f8wrt              1/1     Running   0          36m    192.168.122.2     k8s-01   <none>           <none>
node-exporter-gjhvz              1/1     Running   0          36m    192.168.122.165   k8s-03   <none>           <none>
 

#這里我們可以看到,我們有3個節點,在所有的節點上都啟動了一個對應Pod進行獲取數據

node-exporter.yaml文件說明

由於我們要獲取的數據是主機的監控指標數據,而我們的node-exporter是運行在容器中的,所以我們在Pod中需要配置一些Pod的安全策略

hostPID:true
hostIPC:true
hostNetwork:true

#這三個配置主要用於主機的PID namespace、IPC namespace以及主機網絡,這里需要注意的是namespace是用於容器隔離的關鍵技術,這里的namespace和集群中的namespace是兩個完全不同的概念

另外我們還需要將主機/dev/proc/sys這些目錄掛在到容器中,這些因為我們采集的很多節點數據都是通過這些文件來獲取系統信息

比如我們在執行top命令可以查看當前cpu使用情況,數據就來源於/proc/stat,使用free命令可以查看當前內存使用情況,其數據來源是/proc/meminfo文件

另外如果是使用kubeadm搭建的,同時需要監控master節點的,則需要添加下方的相應容忍

      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule

node-exporter容器相關啟動參數

        args:
        - --path.procfs     #配置掛載宿主機(node節點)的路徑
        - /host/proc
        - --path.sysfs      #配置掛載宿主機(node節點)的路徑
        - /host/sys
        - --collector.filesystem.ignored-mount-points
        - '"^/(sys|proc|dev|host|etc)($|/)"'

在我們的yaml文件中加入了hostNetwork:true會直接將我們的宿主機的9100端口映射出來,從而不需要創建service 在我們的宿主機上就會有一個9100的端口

容器的9100--->映射到宿主機9100

      hostNetwork: true
      containers:
      - name: node-exporter
        image: prom/node-exporter:v0.16.0
        ports:
        - containerPort: 9100

上面我們檢查了Pod的運行狀態都是正常的,接下來我們要查看一下Pod日志,以及node-exporter中的metrics

使用命令kubectl logs -n 命名空間 node-exporter中Pod名稱檢查Pod日志是否有額外報錯

[root@k8s-01 prometheus]# kubectl logs -n kube-system node-exporter-
node-exporter-bsdkl  node-exporter-f8wrt  node-exporter-gjhvz  
[root@k8s-01 prometheus]# kubectl logs -n kube-system node-exporter-bsdkl 
time="2019-12-05T05:50:42Z" level=info msg="Starting node_exporter (version=0.16.0, branch=HEAD, revision=d42bd70f4363dced6b77d8fc311ea57b63387e4f)" source="node_exporter.go:82"
time="2019-12-05T05:50:42Z" level=info msg="Build context (go=go1.9.6, user=root@a67a9bc13a69, date=20180515-15:52:42)" source="node_exporter.go:83"
time="2019-12-05T05:50:42Z" level=info msg="Enabled collectors:" source="node_exporter.go:90"
time="2019-12-05T05:50:42Z" level=info msg=" - arp" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - bcache" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - bonding" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - conntrack" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - cpu" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - diskstats" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - edac" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - entropy" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - filefd" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - filesystem" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - hwmon" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - infiniband" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - ipvs" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - loadavg" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - mdadm" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - meminfo" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - netdev" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - netstat" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - nfs" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - nfsd" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - sockstat" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - stat" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - textfile" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - time" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - timex" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - uname" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - vmstat" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - wifi" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - xfs" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg=" - zfs" source="node_exporter.go:97"
time="2019-12-05T05:50:42Z" level=info msg="Listening on :9100" source="node_exporter.go:111"
#接下來,我們在任意集群節點curl 9100/metrics
[root@k8s-01 prometheus]# curl 127.0.0.1:9100/metrics|head 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0.000239179
go_gc_duration_seconds{quantile="0.25"} 0.000322674
go_gc_duration_seconds{quantile="0.5"} 0.000361148
go_gc_duration_seconds{quantile="0.75"} 0.000416324
go_gc_duration_seconds{quantile="1"} 0.000513074
go_gc_duration_seconds_sum 0.006654219
go_gc_duration_seconds_count 18
# HELP go_goroutines Number of goroutines that currently exist.
100 64669  100 64669    0     0  2235k      0 --:--:-- --:--:-- --:--:-- 2339k
curl: (23) Failed writing body (135 != 15652)
只要metrics可以獲取到數據說明node-exporter沒有問題

服務發現

我們這里三個節點都運行了node-exporter程序,如果我們通過一個Server來將數據收集在一起,用靜態的方式配置到prometheus就會顯示一條數據,我們得自己在指標中過濾每個節點的數據,配置比較麻煩。 這里就采用服務發現

在Kubernetes下,Prometheus通過Kubernetes API基礎,目前主要支持5種服務發現,分別是nodeServerPodEndpointsIngress

需要我們在Prometheus配置文件中,添加如下三行

    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
      - role: node

#通過制定Kubernetes_sd_config的模式為node,prometheus就會自動從Kubernetes中發現所有的node節點並作為當前job監控的目標實例,發現的節點/metrics接口是默認的kubelet的HTTP接口

 

 

 

接下來我們更新配置文件

[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# kubectl get svc -n kube-system |grep prometheus
prometheus   NodePort    10.1.183.250   <none>        9090:30129/TCP           169m
[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
#熱更新刷新配置(需要等待一小會)

接着訪問我們的地址

http://192.168.122.217:30129/targets

這個端口要和service對上

現在我們可以看到已經獲取到我們的Node節點的IP,但是由於metrics監聽的端口是10250而並不是我們設置的9100,所以提示我們節點屬於Down的狀態

 

 

 

這里我們就需要使用Prometheus提供的relabel_configs中的replace能力了,relabel可以在Prometheus采集數據之前,通過Target實例的Metadata信息,動態重新寫入Label的值。除此之外,我們還能根據Target實例的Metadata信息選擇是否采集或者忽略該Target實例。這里使用__address__標簽替換10250端口為9100

這里使用正則進行替換端口

    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:9100'
        target_label: __address__
        action: replace

 

 

 

接下來我們更新一下配置

curl的時候可以多更新幾次,順便等待一會

[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# 

 

 

現在在狀態就正常了

 

目前狀態已經正常,但是還有一個問題就是我們的采集數據只顯示了IP地址,對於我們監控分組分類不是很方便,這里可以通過labelmap這個屬性來將Kubernetes的Label標簽添加為Prometheus的指標標簽

    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:9100'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)

 

 

添加了一個action為labelmap,正則表達式是__meta_kubernetes_node(.+)的配置,這里的意思就是表達式中匹配的數據也添加到指標數據的Label標簽中去。

[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload

 

 

實際上就是獲取我們的標簽

[root@k8s-01 ~]# kubectl get nodes --show-labels
NAME     STATUS   ROLES    AGE   VERSION   LABELS
k8s-01   Ready    master   30d   v1.16.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-01,kubernetes.io/os=linux,node-role.kubernetes.io/master=
k8s-02   Ready    <none>   30d   v1.16.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-02,kubernetes.io/os=linux
k8s-03   Ready    <none>   30d   v1.16.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-03,kubernetes.io/os=linux
[root@k8s-01 ~]# 

對於Kubernetes_sd_configs下面可用的元標簽如下

  • __meta_kubernetes_node_name: 節點對象的名稱
  • _meta_kubernetes_node_label: 節點對象中的每個標簽
  • _meta_kubernetes_node_annotation: 來自節點對象的每個注釋

_meta_kubernetes_node_address: 每個節點地址類型的第一個地址(如果存在) 關於kubernetes_sd_configs更多信息可以查看官方文檔: kubernetes_sd_config

#prometheus configmap 監控完整配置如下,可以直接拷貝
root@k8s-01 prometheus]# cat prometheus.configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: kube-system
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090']
    
    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:9100'
        target_label: __address__
        action: replace
      - action: labelmap
        regex: __meta_kubernetes_node_label_(.+)
      
    - 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  

我們還可以去Graph里面看一下數據

 

 

我們這里也可以自定義規則

 

容器監控

cAdvisor是一個容器資源監控工具,包括容器的內存,CPU,網絡IO,資源IO等資源,同時提供了一個Web頁面用於查看容器的實時運行狀態。

cAvisor已經內置在了kubelet組件之中,所以我們不需要單獨去安裝,cAdvisor的數據路徑為/api/v1/nodes//proxy/metrics

action 使用labelkeep或者labeldrop則可以對Target標簽進行過濾,僅保留符合過濾條件的標簽

    - 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

 

 

ls_config配置的證書地址是每個Pod連接apiserver所使用的地址,基本上寫死了。並且我們在配置文件添加了一個labelmap標簽。在最下面使用了一個正則替換了cAdvisor的一個metrics地址

證書是我們Pod啟動的時候kubelet給pod注入的一個證書,所有的pod啟動的時候都會有一個ca證書注入進來

如要想要訪問apiserver的信息,還需要配置一個token_file

修改完成之后,我們需要configmap並且使用curl進行熱更新(過程比較慢,需要等待會)

[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload

 

 

現在我們可以到Graph路徑下面查詢容器的相關數據

這里演示查詢集群中所有Pod的CPU使用情況,查詢指標container_cpu_usage_seconds_total並且查詢1分鍾之內的數據

這里演示一下使用函數rate和不使用函數的一個過濾功能

container_cpu_usage_seconds_total{image!=" ",pod_name!=" "}
rate(container_cpu_usage_seconds_total{image!=" ",pod_name!=" "}[1m])

執行下方命令,過濾1分鍾內的數據

rate(container_cpu_usage_seconds_total{image!=" ",pod_name!=" "}[1m])

 

 

還可以使用sum函數,pod在1分鍾內的使用率,同時將pod名稱打印出來

sum by (pod)(rate(container_cpu_usage_seconds_total{image!=" ", pod_name!=" "}[1m] ))

 

 

Api-Service 監控

apiserver作為Kubernetes最核心的組件,它的監控也是非常有必要的,對於apiserver的監控,我們可以直接通過kubernetes的service來獲取

[root@k8s-01 prometheus]# kubectl get svc --all-namespaces 
NAMESPACE              NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   10.1.0.1       <none>        443/TCP                  31d
ingress-nginx          ingress-nginx               ClusterIP   10.1.216.99    <none>        80/TCP,443/TCP           24h
kube-system            kube-dns                    ClusterIP   10.1.0.10      <none>        53/UDP,53/TCP,9153/TCP   30d
kube-system            kubelet                     ClusterIP   None           <none>        10250/TCP                25h
kube-system            prometheus                  NodePort    10.1.183.250   <none>        9090:30129/TCP           4h38m
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.1.100.76    <none>        8000/TCP                 30d
kubernetes-dashboard   kubernetes-dashboard        NodePort    10.1.158.92    <none>        443:30001/TCP            30d


上面的service是我們集群的apiserver內部的service的地址,要自動發現service類型的服務,需要使用roleEndpointskubernetes_sd_configs (自動發現),我們只需要在configmap里面在添加Endpoints類型的服務發現

   - job_name: 'kubernetes-apiserver'
     kubernetes_sd_configs:
     - role: endpoints

 

 

刷新配置文件

[root@k8s-01 prometheus]# kubectl get svc -n kube-system 
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                  AGE
kube-dns     ClusterIP   10.1.0.10      <none>        53/UDP,53/TCP,9153/TCP   30d
kubelet      ClusterIP   None           <none>        10250/TCP                25h
prometheus   NodePort    10.1.183.250   <none>        9090:30129/TCP           4h43m
[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# 

更新完成后,我們可以看到kubernetes-apiserver下面出現了很多實例,這是因為我們這里使用的Endpoints類型的服務發現,所以prometheus把所有的Endpoints服務都抓取過來了,同樣的我們要監控的kubernetes也在列表中。

 

 

這里我們使用keep動作,將符合配置的保留下來,例如我們過濾default命名空間下服務名稱為kubernetes的元數據,這里可以根據__meta_kubernetes_namespace__mate_kubertnetes_service_name2個元數據進行relabel

    - job_name: kubernetes-apiservers
      kubernetes_sd_configs:
      - role: endpoints
      relabel_configs:
      - action: keep
        regex: default;kubernetes;https
        source_labels:
        - __meta_kubernetes_namespace
        - __meta_kubernetes_service_name
        - __meta_kubernetes_endpoint_port_name
      scheme: https
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        insecure_skip_verify: true
      bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
 
         
#參數解釋
action: keep  #保留哪些標簽
regex: default;kubernetes;https  #匹配namespace下的default命名空間下的kubernetes service 最后https協議
可以通過`kubectl describe svc kubernetes`查看到

刷新配置

#這個過程比較慢,可能要等幾分鍾,可以多reload幾次
[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# 

 

 

接下來我們還是前往Greph上查看采集到的數據

sum(rate(apiserver_request_count[1m]))

#這里使用的promql里面的rate和sun函數,意思是apiserver在1分鍾內請求的數

 

 

如果我們要監控其他系統組件,比如kube-controller-manager、kube-scheduler的話就需要單獨手動創建service,因為apiserver服務默認在default,而其他組件在kube-steam這個namespace下。其中kube-sheduler的指標數據端口為10251,kube-controller-manager對應端口為10252

 

Service 監控

apiserver實際上是一種特殊的Service,現在配置一個專門發現普通類型的Service

這里我們對service進行過濾,只有在service配置了prometheus.io/scrape: "true"過濾出來

    - 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

繼續重復步驟,刷新配置

[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# 

Serivce自動發現參數說明 (並不是所有創建的service都可以被prometheus發現)

#1.參數解釋
relabel_configs:
-source_labels:[__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep 
regex: true  保留標簽
source_labels: [__meta_kubernetes_service_annotation_prometheus_io_cheme]

這行配置代表我們只去篩選有__meta_kubernetes_service_annotation_prometheus_io_scrape的service,只有添加了這個聲明才可以自動發現其他service

#2.參數解釋
  - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
    action: replace
    target_label: __address__
    regex: ([^:]+)(?::\d+)?;(\d+)
    replacement: $1:$2
#指定一個抓取的端口,有的service可能有多個端口(比如之前的redis)。默認使用的是我們添加是使用kubernetes_service端口

#3.參數解釋
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
    action: replace
    target_label: __scheme__
    regex: (https?)
#這里如果是https證書類型,我們還需要在添加證書和token

我們可以看到這里的服務的core DNS,為什么那么多service只有coreDNS可以被收集到呢?

 

 

 

上面也說了,我們有過濾條件,只有復合條件的才進行過濾

core DNS serviceYaml 文件包含true參數,所以會被匹配到

 

 

繼續重復步驟,刷新配置

[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.1.183.250:9090/-/reload
[root@k8s-01 prometheus]# 

當我們再次查看,發現狀態完成

 

 

 

 

Grafana是一個跨平台的開源的度量分析和可視化工具,可以通過將采集的數據查詢然后可視化的展示,並及時通知。

Grafana 安裝並監控k8s集群

由於Prometheus自帶的web Ui圖標功能相對較弱,所以一般情況下我們會使用一個第三方的工具來展示這些數據

Grafana介紹

grafana 是一個可視化面包,有着非常漂亮的圖片和布局展示,功能齊全的度量儀表盤和圖形化編輯器,支持Graphite、Zabbix、InfluxDB、Prometheus、OpenTSDB、Elasticasearch等作為數據源,比Prometheus自帶的圖標展示功能強大很多,更加靈活,有豐富的插件

我們這里使用deployment持久化安裝grafana

cat >>grafana_deployment.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grafana
  namespace: kube-system
  labels:
    app: grafana
    k8s-app: grafana
spec:
  selector:
    matchLabels:
      k8s-app: grafana
      app: grafana
  revisionHistoryLimit: 10
  template:
    metadata:
      labels:
        app: grafana
        k8s-app: grafana
    spec:
      containers:
      - name: grafana
        image: grafana/grafana:5.3.4
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 3000
          name: grafana
        env:
        - name: GF_SECURITY_ADMIN_USER
          value: admin
        - name: GF_SECURITY_ADMIN_PASSWORD
          value: jiangwenhui
        readinessProbe:
          failureThreshold: 10
          httpGet:
            path: /api/health
            port: 3000
            scheme: HTTP
          initialDelaySeconds: 60
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 30
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /api/health
            port: 3000
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        resources:
          limits:
            cpu: 300m
            memory: 1024Mi
          requests:
            cpu: 300m
            memory: 1024Mi
        volumeMounts:
        - mountPath: /var/lib/grafana
          subPath: grafana
          name: storage
      securityContext:
        fsGroup: 472
        runAsUser: 472
      volumes:
      - name: storage
        persistentVolumeClaim:
          claimName: grafana
EOF

 

這里使用了grafana 5.3.4的鏡像,添加了監控檢查、資源聲明,比較重要的變量是GF_SECURITY_ADMIN_USERGF_SECURITY_ADMIN_PASSWORD為grafana的賬號和密碼。

由於grafana將dashboard、插件這些數據保留在/var/lib/grafana目錄下,所以我們這里需要做持久化,同時要針對這個目錄做掛載聲明,由於5.3.4版本用戶的userid和groupid都有所變化,所以這里添加了一個securityContext設置用戶ID

image_1ddnv749l17k7ucdel1m4v17jjea.png-56.5kB

現在我們添加一個pv和pvc用於綁定grafana

cat >>grafana_volume.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: grafana
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    server: 192.168.0.200
    path: /home/kvm/k8s-vloume
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: grafana
  namespace: kube-system
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

EOF

這里配置依舊使用NFS進行掛載使用

現在我們還需要創建一個service,使用NodePort

cat >>grafana_svc.yaml<<EOF
apiVersion: v1
kind: Service
metadata:
  name: grafana
  namespace: kube-system
  labels:
    app: grafana
spec:
  type: NodePort
  ports:
    - port: 3000
  selector:
    app: grafana
EOF

由於5.1(可以選擇5.1之前的docker鏡像,可以避免此類錯誤)版本后groupid更改,同時我們將/var/lib/grafana掛載到pvc后,目錄擁有者可能不是grafana用戶,所以我們還需要添加一個Job用於授權目錄

cat > grafana_job.yaml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: grafana-chown
  namespace: kube-system
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: grafana-chown
        command: ["chown", "-R", "472:472", "/var/lib/grafana"]
        image: busybox
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: storage
          subPath: grafana
          mountPath: /var/lib/grafana
      volumes:
      - name: storage
        persistentVolumeClaim:
          claimName: grafana
EOF

這里使用一個busybox鏡像將/var/lib/grafana目錄修改為權限472

#需要先創建pv和pvc  (這里是需要安裝順序來創建)
[root@k8s-01 prometheus]# kubectl create -f grafana_volume.yaml
persistentvolume/grafana created
persistentvolumeclaim/grafana created
[root@k8s-01 prometheus]# kubectl create -f grafana_job.yaml
job.batch/grafana-chown created
[root@k8s-01 prometheus]# kubectl apply -f grafana_deployment.yaml
deployment.apps/grafana created
[root@k8s-01 prometheus]# kubectl create -f grafana_svc.yaml

創建完成后我們打開grafana的dashboard界面

[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# kubectl get pod,svc -n kube-system |grep grafana
pod/grafana-59bd6c446d-4jjnf         1/1     Running     0          7m39s
pod/grafana-chown-w562v              0/1     Completed   0          14m
service/grafana      NodePort    10.1.63.182    <none>        3000:30636/TCP           13m
[root@k8s-01 prometheus]# 

然后我們在任意集群中的節點訪問端口為30636

這里的集群密碼就是上面我們創建deployment里面設置的變量,我這里用戶設置為admin密碼jiangwenhui

 

 登陸到grafana就顯示到了我們的引導界面

 

 

登陸到grafana就顯示到了我們的引導界面

第一次創建grafana需要添加數據源

 

 類型選擇prometheus

這里的地址我們填寫下面的url

http://prometheus.kube-system.svc.cluster.local:9090

這里的prometheus代表service名稱

kube-system代表命名空間

 

 

 

 

 數據源添加完畢后,接下來添加New dashboard

 

 這里我們可以自定義模板,或者可以使用別人寫好的模板 (寫好的模板后面是需要我們自己修改的)

 

 grafana提供了很多模板,類似和docker鏡像倉庫一下。導入模板也極其簡單。點擊上方的Dashboard

 

 

這里面的模板都是公共的,可以免費使用

 

 

點進去任意一個模板后,我們可以看到ID,復制ID然后在返回grafana

我這里添加一個監控Kubernetes集群。顯示整體群集CPU、內存、磁盤使用情況以及單個pod統計信息。

https://grafana.com/grafana/dashboards/8588

 

 

 

點擊導入模板

 

 在這里我們輸入8588或者url,會自動跳轉到配置頁面

https://grafana.com/grafana/dashboards/8588

 

 

選擇好數據源之后,我們在點擊Import即可

 

 

這里就會將模板8588給我們導入進行

這里就會獲取我們prometheus里面的數據了

 

 

現在的模板還沒有進行保存,我們要點擊保存一下

 

 

現在就保存下來了

 

 目前我們導入模板之后是無法直接使用滴

 

 

這里無法顯示是由於模板定義的標簽,我們prometheus並沒有這個數據元,所以說我們要對模板進行修改!

在修改之前我們先設置一下時區,grafana默認走的是瀏覽器時區,但是prometheus使用的是UTC時區

 

 

修改默認模板 (我這里使用的是8588模板,下面模板修改請根據我的操作步驟進行操作)

grafana模板修改

前面的步驟必須和我相同,否則這里可能會無法出現值

首先我們進行編輯 Cluster memory usage (集群內存使用率)

 

 

計算方式就是(整個集群的內存-(整個集群剩余的內存以及Buffer和Cached))/整

(sum(node_memory_MemTotal_bytes) - sum(node_memory_MemFree_bytes + node_memory_Buffers_bytes+node_memory_Cached_bytes)) / sum(node_memory_MemTotal_bytes) * 100

 

 

這里要說明一點,這里填寫的是PromSQL,也就是說是可以在prometheus查詢到的。 如果查詢不到grafana也是會獲取不到數據的

這里在prometheus是可以獲取到的

 

 

Cluster memory usage 配置如下 (集群內存使用率)

sum(sum by (container_name)( rate(container_cpu_usage_seconds_total{image!=""}[1m] ) )) / count(node_cpu_seconds_total{mode="system"}) * 100

 

 

Cluster filesystem usage 集群文件系統使用率

(sum(node_filesystem_size_bytes{device="tmpfs"}) - sum(node_filesystem_free_bytes{device="tmpfs"}) ) / sum(node_filesystem_size_bytes{device="tmpfs"}) * 100

 

 

這里我們就獲取到數據了

 

 

 接下來我們配置集群中Pod cpu使用率

sum by (pod)(rate(container_cpu_usage_seconds_total{image!=" ", pod_name!=" "}[1m]))

下面顯示的地方配置

{{ pod }}

 

 

 集群pod 內存使用率

sort_desc(sum (container_memory_usage_bytes{image!=" ", pod_name!=" "}) by(pod))

下面顯示的名稱同樣也是{{ pod }}

 

 

最后我們配置一下Pod 網絡監控

1.入口流量
sort_desc(sum by (pod) (rate (container_network_receive_bytes_total{name!=""}[1m]) ))

2.出口流量
sort_desc(sum by (pod) (rate (container_network_transmit_bytes_total{name!=""}[1m]) ))

#監控時間為1分鍾

 

 

 

 

效果圖如下 記得點擊保存

 

 

 

 

所有的PromSQL都是可以在prometheus獲取到數據的!

 

Prometheus AlertManager 實戰

AlerManager 簡介

Prometheus包含了一個報警模塊,那就是AlertManager,主要用於接受Prometheus發送的告警信息,它支持豐富的告警通知渠道,而且很容易做到告警信息進行去重,降噪,分組等,是一個前衛的告警通知系統

prometheus-architecture.png-94.6kB

安裝 AlerManager

prometheus配置文件官方文檔

https://prometheus.io/docs/alerting/configuration/

首先,我們需要先指定配置文件 ,這里我們還是創建一個ConfigMap資源對象

[root@k8s-01 prometheus]# cat >> prometheus-alert-conf.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: alert-config
  namespace: kube-system
data:
  config.yml: |-
    global:
      # 在沒有報警的情況下聲明為已解決的時間
      resolve_timeout: 5m
      # 配置郵件發送信息
      smtp_smarthost: 'smtp.163.com:465'
      smtp_from: '18676791057@163.com'
      smtp_auth_username: '18676791057@163.com'
      smtp_auth_password: '授權密碼'
      smtp_hello: '163.com'
      smtp_require_tls: false
    # 所有報警信息進入后的根路由,用來設置報警的分發策略
    route:
      # 這里的標簽列表是接收到報警信息后的重新分組標簽,例如,接收到的報警信息里面有許多具有 cluster=A 和 alertname=LatncyHigh 這樣的標簽的報警信息將會批量被聚合到一個分組里面
      group_by: ['alertname', 'cluster']
      # 當一個新的報警分組被創建后,需要等待至少group_wait時間來初始化通知,這種方式可以確保您能有足夠的時間為同一分組來獲取多個警報,然后一起觸發這個報警信息。
      group_wait: 30s

      # 當第一個報警發送后,等待'group_interval'時間來發送新的一組報警信息。
      group_interval: 5m

      # 如果一個報警信息已經發送成功了,等待'repeat_interval'時間來重新發送他們
      repeat_interval: 5m

      # 默認的receiver:如果一個報警沒有被一個route匹配,則發送給默認的接收器
      receiver: default

      # 上面所有的屬性都由所有子路由繼承,並且可以在每個子路由上進行覆蓋。
      routes:
      - receiver: email
        group_wait: 10s
        match:
          team: node
    receivers:
    - name: 'default'
      email_configs:
      - to: '290070744@qq.com'
        send_resolved: true
    - name: 'email'
      email_configs:
      - to: '290070744@qq.com'
        send_resolved: true

EOF

授權密碼申請,這里以163郵箱為例

 

 

我們現在創建alertmanager的配置文件

 

[root@k8s-01 prometheus]# kubectl create -f prometheus-alert-conf.yaml
configmap/alert-config created
[root@k8s-01 prometheus]#  kubectl get cm -n kube-system
NAME                                 DATA   AGE
alert-config                         1      8s
coredns                              1      37d
extension-apiserver-authentication   6      37d
kube-flannel-cfg                     2      37d
kube-proxy                           2      37d
kubeadm-config                       2      37d
kubelet-config-1.16                  1      37d
prometheus-config                    1      6d21h
[root@k8s-01 prometheus]# 
#這里已經顯示我們創建好的alert-config

現在我們在之前的prometheus pod的yaml文件中添加這個容器

這里我們將上面創建的aler-config這個configmap資源對象volume的形式掛載到/etc/alertmanager目錄下去,然后在啟動參數中指定--config.file=/etc/alertmanager/config.yml

      - name: alermanager
        image: prom/alertmanager:v0.15.3
        imagePullPolicy: IfNotPresent
        args:
        - "--config.file=/etc/alertmanager/config.yml"
        - "--storage.path=/alertmanager/data"
        ports:
        - containerPort: 9093
          name: http
        volumeMounts:
        - mountPath: "/etc/alertmanager"
          name: alertcfg
        resources:
          requests:
            cpu: 100m
            memory: 256Mi
          limits:
            cpu: 200m
            memory: 1024Mi
  ...
      - name: alertcfg
        configMap:
          name: alert-config

在0.15版本,alertmanager的WORKDIR發生了變化,變成/etc/alertmanager默認情況下存儲路徑--storage.path是相對目錄data/,因此alertmanager會在我們上面掛載的ConfigMap中去創建這個目錄,所以會報錯,這里通過--storage.path參數來解決

[root@k8s-01 prometheus]# kubectl apply -f  prometheus.deploy.yaml
deployment.apps/prometheus configured
#更新deployment

查看一下pod啟動狀態

[root@k8s-01 prometheus]# kubectl get pod -n kube-system |grep prometheus
prometheus-65856969cd-29rqf      2/2     Running     1          49s

AlertManager容器啟動之后,我們還需要在Prometheus中配置下AlertManager的地址,讓Prometheus能夠訪問AlertManager

    alerting:
      alertmanagers:
        - static_configs:
          - targets: ["localhost:9093"]

 

 

接下來更新一下Prometheus配置文件

[root@k8s-01 prometheus]# 
[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml
configmap/prometheus-config configured
[root@k8s-01 prometheus]# kubectl get pod -n kube-system -o wide |grep prometheus 
prometheus-65856969cd-29rqf      2/2     Running     1          3m58s   10.244.1.70       k8s-02   <none>           <none>
[root@k8s-01 prometheus]# curl -X POST http://10.244.1.70:9090/-/reload
#確保更新配置沒有報錯(刷新比較慢可以等等)
現在prometheus alertmanager並沒有告警的規則,還需要我們添加報警規則

Prometheus 報警規則

上面我們將prometheus和alertmanager進行了關聯,但是現在並沒有報警規則,所以這里還需要配置一些報警規則。讓prometheus觸發報警

#首先在prometheus.configmap.yaml文件中添加報警規則,下面的文件就是prometheus報警的規則文件
    rule_files:
    - /etc/prometheus/rules.yml

 

 

報警規則允許基於Prometheus表達式語言來定義報警規則條件,並在出發報警時發送給外部

我們上面已經將/etc/promtehus進行掛載了,所以這里只需要修改prometheus-configmap就可以了。

  rules.yml: |
    groups:
    - name: test-rule
      rules:
      - alert: NodeMemoryUsage
        expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes+node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 50
        for: 1m
        labels:
          team: node
        annotations:
          summary: "{{ $labels.instance }}:High Memory Usage detected"
          description: "{{ $labels.instance }}: Memory usage us avive 50% (current value is :: {{ $value }})"



#配置相關參數說明
  rules.yml: |
    groups:
    - name: test-rule
      rules:  #規則
      - alert: NodeMemoryUsage #報警名稱(內存報警)
        expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 50 #規則表達式
        for: 1m  #等待1分鍾執行查詢條件
        labels:
          team: node   #當我們觸發報警后,帶有team=node的標簽,並且這里走的是我們alertmanager node標簽,這里對應的就是我們的email接收器
        annotations:  #指定另外一組標簽,不會將這個標簽當做我們告警的身份標示(不會在我們報警信息里操作)這里主要是用於額外的展示,例如發送給郵件里面>的報警信息
          summary: "{{ $labels.instance }}:High Memory Usage detected"   #label標簽,instance代表節點名稱
          description: "{{ $labels.instance }}: Memory usage us avive 50% (current value is :: {{ $value }})" #描述:相當於報警信息 $value代表當前值

expr所執行的命令是可以在prometheus上獲取到數據的

 

 

[root@k8s-01 prometheus]# kubectl apply -f prometheus.configmap.yaml 
configmap/prometheus-config configured
[root@k8s-01 prometheus]# kubectl get pod -n kube-system -o wide |grep prometheus 
prometheus-65856969cd-29rqf      2/2     Running     1          14m     10.244.1.70       k8s-02   <none>           <none>
[root@k8s-01 prometheus]# curl -X POST http://10.244.1.70:9090/-/reload
[root@k8s-01 prometheus]# curl -X POST http://10.244.1.70:9090/-/reload

 

報警說明

本次報警大概意思是當服務器內存百分比大於80的時候,就進行報警,並且通過labels標簽關聯team:node (這里team=node是在我們alertmanager里面配置的接收器,默認是default),並且報警內容添加主機和當前內存使用率

接下來我們訪問prometheus,點擊alerts,就可以看到我們添加的NodeMemoryUsage

我這里將腳本改成>50

當前值已經大於我們設置的50%,現在已經出發報警

 

 

郵件內容如下

 

alertManager Ui界面

我們可以在郵件內容中看到包含View in AlertManager的鏈接,這是alertmanager自帶的Ui界面。我們可以使用NodePort進行訪問

這里需要修改一下prometheus的service

cat >>prometeheus-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: prometheus
  namespace: kube-system
  labels:
    app: prometheus
spec:
  selector:
    app: prometheus
  type: NodePort
  ports:
    - name: web
      port: 9090
      targetPort: http
    - name: alertmanager
      port: 9093
      targetPort: 9093
EOF

我們查看一下node-port端口

[root@k8s-01 prometheus]# kubectl get svc -n kube-system |grep prometheus
prometheus   NodePort    10.1.183.250   <none>        9090:30129/TCP,9093:31882/TCP   6d23h

訪問alertmanager端口為9093=31882 (集群任一節點訪問即可)

 

 

 在上面的圖片,我們可以看到hostname為k8s-01,02一直在報警,如果不想接收這個IP報警。可以點擊Slience

 

 

注意Prometheus有8小時時區問題

這時候報警匹配為k8s-01的host,在2個小時內。不進行報警,我們點擊創建就可以。在Comment輸入提交內容就可以了

這里可以直接編輯,或者直接讓它過期

 

 

這里我們已經看不到k8s-01的報警內容了

 

 

點擊Silences可以看到被禁用的監控

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM