一、安装

Grafana 是一个可视化面板,有着非常漂亮的图表和布局展示,功能齐全的度量仪表盘和图形编辑器,支持Graphite、zabbix、InfluxDB、Prometheus、OpenTSDB、Elasticsearch 等作为数据源,比 Prometheus 自带的图表展示功能强大太多,更加灵活,有丰富的插件,功能更加强大。
镜像地址:https://hub.docker.com/r/grafana/grafana

编辑deployment配置清单:
grafana-deploy.yaml

  1. apiVersion: extensions/v1beta1
  2. kind: Deployment
  3. metadata:
  4. name: grafana
  5. namespace: kube-ops
  6. labels:
  7. app: grafana
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: grafana
  12. replicas: 1
  13. revisionHistoryLimit: 10
  14. template:
  15. metadata:
  16. labels:
  17. app: grafana
  18. spec:
  19. containers:
  20. - name: grafana
  21. image: grafana/grafana:6.5.0
  22. imagePullPolicy: IfNotPresent
  23. ports:
  24. - name: grafana
  25. containerPort: 3000
  26. env:
  27. - name: GF_SECURITY_ADMIN_USER
  28. value: admin
  29. - name: GF_SECURITY_ADMIN_PASSWORD
  30. value: admin321
  31. readinessProbe:
  32. failureThreshold: 10
  33. httpGet:
  34. path: /api/health
  35. port: 3000
  36. scheme: HTTP
  37. initialDelaySeconds: 60
  38. periodSeconds: 10
  39. successThreshold: 1
  40. timeoutSeconds: 30
  41. livenessProbe:
  42. failureThreshold: 10
  43. httpGet:
  44. path: /api/health
  45. port: 3000
  46. scheme: HTTP
  47. periodSeconds: 10
  48. successThreshold: 1
  49. timeoutSeconds: 1
  50. resources:
  51. requests:
  52. cpu: 100m
  53. memory: 256Mi
  54. limits:
  55. cpu: 100m
  56. memory: 256Mi
  57. volumeMounts:
  58. - name: storage
  59. mountPath: /var/lib/grafana
  60. subPath: grafana
  61. securityContext:
  62. fsGroup: 472
  63. runAsUser: 472
  64. volumes:
  65. - name: storage
  66. persistentVolumeClaim:
  67. claimName: grafana

这里配置securityContext的原因是从v5.1.0开始,grafana的运行用户ID(userid)和组ID(groupid)已经改成了472。而另外两个env是用来配置Grafana的管理员用户和密码。

配置持久化存储PVC:
grafana-volume.yaml

  1. apiVersion: v1
  2. kind: PersistentVolume
  3. metadata:
  4. name: grafana
  5. spec:
  6. capacity:
  7. storage: 1Gi
  8. accessModes:
  9. - ReadWriteOnce
  10. persistentVolumeReclaimPolicy: Recycle
  11. nfs:
  12. server: xxx.xx.xxx.xx
  13. path: /data/k8s/grafana
  14. ---
  15. apiVersion: v1
  16. kind: PersistentVolumeClaim
  17. metadata:
  18. name: grafana
  19. namespace: kube-ops
  20. spec:
  21. accessModes:
  22. - ReadWriteOnce
  23. resources:
  24. requests:
  25. storage: 1Gi

配置Service服务:
grafana-svc.yaml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: grafana
  5. namespace: kube-ops
  6. labels:
  7. app: grafana
  8. spec:
  9. selector:
  10. app: grafana
  11. type: NodePort
  12. ports:
  13. - name: grafana
  14. port: 3000

然后我们会发现Pod并没有正常启动:

  1. # kubectl get pod -n kube-ops
  2. NAME READY STATUS RESTARTS AGE
  3. grafana-d8cb7fd98-grqqf 0/1 CrashLoopBackOff 200 16h

查看其日志如下:

  1. Events:
  2. Type Reason Age From Message
  3. ---- ------ ---- ---- -------
  4. Warning BackOff 3m39s (x4398 over 16h) kubelet, 172.16.0.52 Back-off restarting failed container
  5. [root@ecs-5704-0003 ~]# kubectl logs grafana-d8cb7fd98-grqqf -n kube-ops
  6. GF_PATHS_DATA='/var/lib/grafana' is not writable.
  7. You may have issues with file permissions, more information here: http://docs.grafana.org/installation/docker/#migration-from-a-previous-version-of-the-docker-container-to-5-1-or-later
  8. mkdir: can't create directory '/var/lib/grafana/plugins': Permission denied

我们发现其报权限不足,虽然我们上面定义了其sercurityContext为472,但是container在挂载PVC的时候目录的userID和groupID并不是472,我们可以通过一个Job任务来更改其宿主:
grafana-chown-job.yaml

  1. apiVersion: batch/v1
  2. kind: Job
  3. metadata:
  4. name: grafana-chown
  5. namespace: kube-ops
  6. spec:
  7. template:
  8. metadata:
  9. name: grafana-chown
  10. spec:
  11. containers:
  12. - name: grafana-chown
  13. image: busybox
  14. imagePullPolicy: IfNotPresent
  15. command: ["chown", "-R", "472:472", "/var/lib/grafana"]
  16. volumeMounts:
  17. - name: storage
  18. subPath: grafana
  19. mountPath: /var/lib/grafana
  20. restartPolicy: Never
  21. volumes:
  22. - name: storage
  23. persistentVolumeClaim:
  24. claimName: grafana

注意:这里定义的PVC的名字和上面Grafana的Deployment中定义的必须一致。
然后我们生成Job的配置清单:

  1. # kubectl apply -f grafana-chown-job.yaml
  2. # kubectl get pod -n kube-ops
  3. NAME READY STATUS RESTARTS AGE
  4. grafana-chown-jfp77 0/1 Completed 0 4m22s
  5. grafana-d8cb7fd98-vm8hq 1/1 Running 5 5m41s

然后我们发现可以成功运行了。
image.png

二、配置

2.1、添加数据源

我们这个地方配置的数据源是 Prometheus,所以选择这个 Type 即可,给改数据源添加一个 name:prometheus-ds,最主要的是下面HTTP区域是配置数据源的访问模式。
访问模式是用来控制如何处理对数据源的请求的:

  • 服务器(Server)访问模式(默认):所有请求都将从浏览器发送到 Grafana 后端的服务器,后者又将请求转发到数据源,通过这种方式可以避免一些跨域问题,其实就是在 Grafana 后端做了一次转发,需要从Grafana 后端服务器访问该 URL。
  • 浏览器(Browser)访问模式:所有请求都将从浏览器直接发送到数据源,但是有可能会有一些跨域的限制,使用此访问模式,需要从浏览器直接访问该 URL。

由于我们这个地方 Prometheus 通过 NodePort 的方式的对外暴露的服务,所以我们这个地方是不是可以使用浏览器访问模式直接访问 Prometheus 的外网地址,但是这种方式显然不是最好的,相当于走的是外网,而我们这里 Prometheus 和 Grafana 都处于 kube-ops 这同一个 namespace 下面,是不是在集群内部直接通过 DNS 的形式就可以访问了,而且还都是走的内网流量,所以我们这里用服务器访问模式显然更好,数据源地址:http://prometheus-svc.kube-ops.svc:9090,然后其他的配置信息就根据实际情况了,比如 Auth 认证,我们这里没有,所以跳过即可,点击最下方的Save & Test提示成功证明我们的数据源配置正确:
image.png

2.2、添加Dashboard

Dashboard官方有很多模板,地址为:https://grafana.com/grafana/dashboards
然后可以搜索找自己想要的模板:
image.png
我们这里下载一个:https://grafana.com/grafana/dashboards/162/revisions
image.png
然后我们导入即可:
image.png
选择我们的数据源。
image.png
没有出数据的地方可能是promQL语句不对,或者是我们在我们采集的指标中没有模板中定义的,我们可以通过edit获得现有的promQL,然后到prometheus的grafa中调式语句。
image.png
image.png

CPU使用率的promQL:

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

文件系统使用率的promQL:

  1. (sum(node_filesystem_size_bytes{device="rootfs"}) - sum(node_filesystem_free_bytes{device="rootfs"}) ) / sum(node_filesystem_size_bytes{device="rootfs"}) * 100

Pod Network IO的promQL:

  1. sort_desc(sum by (pod_name) (rate (container_network_receive_bytes_total{name!="", pod_name!=""}[1m]) ))
  2. sort_desc(sum by (pod_name) (rate (container_network_transmit_bytes_total{name!="", pod_name!=""}[1m]) ))

2.3、报警

Grafana 支持很多种形式的报警功能,比如 email、钉钉、slack、webhook 等等.

2.3.1、email报警

要启用 email 报警需要在启动配置文件中/etc/grafana/grafan.ini开启 SMTP 服务,我们这里同样利用一个 ConfigMap 资源对象挂载到 grafana Pod 中:
grafana-cm.yaml

  1. metadata:
  2. name: grafana-config
  3. namespace: kube-ops
  4. data:
  5. grafana.ini: |
  6. [server]
  7. root_url = http://<你grafana的url地址>
  8. [smtp]
  9. enabled = true
  10. host = smtp.163.com:25
  11. user = ych_1024@163.com
  12. password = <邮箱密码>
  13. skip_verify = true
  14. from_address = ych_1024@163.com
  15. [alerting]
  16. enabled = true
  17. execute_alerts = true

上面配置了我的 163 邮箱,开启报警功能,当然我们还得将这个 ConfigMap 文件挂载到 Pod 中去:

  1. apiVersion: extensions/v1beta1
  2. kind: Deployment
  3. metadata:
  4. name: grafana
  5. namespace: kube-ops
  6. labels:
  7. app: grafana
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: grafana
  12. replicas: 1
  13. revisionHistoryLimit: 10
  14. template:
  15. metadata:
  16. labels:
  17. app: grafana
  18. spec:
  19. containers:
  20. - name: grafana
  21. image: grafana/grafana:6.5.0
  22. imagePullPolicy: IfNotPresent
  23. ports:
  24. - name: grafana
  25. containerPort: 3000
  26. env:
  27. - name: GF_SECURITY_ADMIN_USER
  28. value: admin
  29. - name: GF_SECURITY_ADMIN_PASSWORD
  30. value: admin321
  31. readinessProbe:
  32. failureThreshold: 10
  33. httpGet:
  34. path: /api/health
  35. port: 3000
  36. scheme: HTTP
  37. initialDelaySeconds: 60
  38. periodSeconds: 10
  39. successThreshold: 1
  40. timeoutSeconds: 30
  41. livenessProbe:
  42. failureThreshold: 10
  43. httpGet:
  44. path: /api/health
  45. port: 3000
  46. scheme: HTTP
  47. periodSeconds: 10
  48. successThreshold: 1
  49. timeoutSeconds: 1
  50. resources:
  51. requests:
  52. cpu: 100m
  53. memory: 256Mi
  54. limits:
  55. cpu: 100m
  56. memory: 256Mi
  57. volumeMounts:
  58. - name: storage
  59. mountPath: /var/lib/grafana
  60. subPath: grafana
  61. - name: config
  62. mountPath: /etc/grafana
  63. securityContext:
  64. fsGroup: 472
  65. runAsUser: 472
  66. volumes:
  67. - name: storage
  68. persistentVolumeClaim:
  69. claimName: grafana
  70. - name: config
  71. configMap:
  72. name: grafana-config

然后我们创建configmap并更新pod。

  1. # kubectl apply -f grafana-cm.yaml
  2. configmap/grafana-config created
  3. # kubectl apply -f grafana-deploy.yaml
  4. deployment.extensions/grafana configured

2.3.2、钉钉报警

(1)、生成钉钉机器人的webhook
(2)、测试
image.png
(3)、查看结果
image.png

2.3.3、添加报警

目前只有 Graph 支持报警功能,所以我们选择 Graph 相关图表,点击编辑,进入 Graph 编辑页面可以看到有一个 Alert 模块,切换过来创建报警:
image.png
参数说明:

  • 1、Alert 名称,可以自定义。
  • 2、执行的频率,这里我选择每60s检测一次。
  • 3、判断标准,默认是 avg,这里是下拉框,自己按需求选择。
  • 4、query(A,5m,now),字母A代表选择的metrics 中设置的 sql,也可以选择其它在 metrics中设置的,但这里是单选。1m代表从现在起往之前的五分钟,即1m之前的那个点为时间的起始点,now为时间的结束点,此外这里可以自己手动输入时间。
  • 5、设置的预警临界点,这里手动输入,和6是同样功能,6可以手动移动,两种操作是等同的。

然后配置报警发送的信息:
image.png

然后达到报警阈值就可以接收到报警了。