运维监控报表太麻烦?用 Grafana-Reporter 一键搞定!

引言

为什么要部署这样的一个组件呢?前几天的早上,我们这边提出了一个需求,能否把 Grafana 的 Dashboard 生成为 PDF 文件呢,然后再发送到相应的邮件或者聊天软件,这样做的好处是,比较好玩吧,新鲜,好看,哈哈,开玩笑的。

既然提出了这样的需求,那肯定是咱有这个实力的,哈哈,自卖自夸。但总之,这个需求还是挺有意思的。我喜欢挑战,喜欢新技术。

这边折腾了会,就发现了 Grafan-reporter 这样一款组件。

介绍

Github地址:https://github.com/IzakMarais/reporter,对中文不支持,dashboard 中含有中文字符会报错。

首先介绍一下Grafana Image Renderer,它是一个用于将Grafana仪表盘转换为静态图像的插件。它提供了在Grafana中生成PNG、JPEG和SVG格式图像的功能,这些图像可以用于导出仪表盘的快照、生成报告、在文档中嵌入等用途。通过Grafana Image Renderer插件,用户可以通过简单的HTTP请求将特定的Grafana仪表盘转换为静态图像。用户可以指定要转换的仪表盘、图像的宽度和高度等参数,并通过HTTP响应获取图像的二进制数据。该插件在处理图像时还支持渲染时过滤器的应用,例如应用时间范围、自定义变量、主题等,以确保生成的图像准确地显示所需的数据和样式。

Grafana Image Renderer插件可以与其他工具和系统集成,例如将生成的图像嵌入到报告生成工具、文档管理系统或自定义的应用程序中。这样,用户就能够方便地分享、保存和展示Grafana仪表盘的快照,而无需访问Grafana本身。

Grafana Reporter 是一个基于Grafana的插件,用于生成和导出报告。它允许用户将Grafana中的监控数据和仪表盘内容导出为报告,以便与团队成员、管理层或其他人共享。Grafana Reporter支持导出为PDF、PNG、SVG和CSV等格式,可以定制报告的样式、布局和内容。用户可以设定报告的时间范围、图表和指标,并在报告中包含注释、摘要和其他信息。Grafana Reporter使用户能够以可视化和易读的方式展示和分享他们的监控数据。 

部署

本环境采用 Kubernetes 安装,因为我喜欢用 Kubernetes,我看网上的文章几乎没有使用 Kubernetes 安装的。你也可以使用 Docker 或者 Docker-compose,又或者源码编译安装。

这边的监控采用的是 kube-prometheus-stack 的 Helm chart 安装,这边的重点不在安装 Prometheus,所以就直接跳过了。

因为有些信息比较敏感,这边的域名都做了修改。

部署 Grafana-reporter

这边使用 StatefulSet 部署,他这边需要指定下我们的 Grafana 的地址,还有我们的 Localtime 也需要修改为本地的。

复制
apiVersion: apps/v1 kind: StatefulSet metadata: name: grafana-reporter namespace: monitoring labels: app: grafana-reporter spec: replicas: 1 selector: matchLabels: app: grafana-reporter serviceName: grafana-reporter template: metadata: labels: app: grafana-reporter spec: hostNetwork: true containers: - name: grafana-reporter image: izakmarais/grafana-reporter imagePullPolicy: Always ports: - containerPort: 8686 args: - "-proto=https://" - "-ip=grafana.example.com" - "-ssl-check=true" # 如果 Grafana 使用了自签名证书,我这边因为有证书,所以就true了 volumeMounts: - name: localtime mountPath: /etc/localtime readOnly: true volumes: - name: localtime hostPath: path: /etc/localtime type: File1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.

我们还需要创建一个 Service:

复制
apiVersion: v1 kind: Service metadata: name: grafana-reporter namespace: monitoring labels: app: grafana-reporter spec: selector: app: grafana-reporter ports: - protocol: TCP port: 8686 targetPort: 8686 type: ClusterIP1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

再来一个 Ingress:

复制
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: id-test-reporter namespace: monitoring spec: ingressClassName: nginx rules: - host: reporter.example.com http: paths: - backend: service: name: grafana-reporter port: number: 8686 path: / pathType: ImplementationSpecific tls: - hosts: - reporter.example.com secretName: hiwin-test-ph-com-tls1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.

Apply 所有;

复制
kubectl apply -f .1.

我们来看下它的页面:

图片

这就算成功了。

部署 Grafana-image-render

这边使用 StatefulSet 控制器部署:

复制
apiVersion: apps/v1 kind: StatefulSet metadata: name: grafana-image-renderer namespace: monitoring labels: app: grafana-image-renderer spec: serviceName: grafana-image-renderer-headless replicas: 1 selector: matchLabels: app: grafana-image-renderer template: metadata: labels: app: grafana-image-renderer spec: containers: - name: renderer image: grafana/grafana-image-renderer:latest ports: - containerPort: 8081 env: - name: RENDERER_CALLBACK_URL value: "https://grafana.example.com" # Grafana 服务地址1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.

service:

复制
apiVersion: v1 kind: Service metadata: name: grafana-image-renderer namespace: monitoring spec: selector: app: grafana-image-renderer ports: - protocol: TCP port: 8081 targetPort: 8081 type: ClusterIP --- apiVersion: v1 kind: Service metadata: name: grafana-image-renderer-headless namespace: monitoring spec: selector: app: grafana-image-renderer ports: - protocol: TCP port: 8081 targetPort: 8081 clusterIP: None1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

Ingress:

复制
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: grafana-image-renderer-ingress namespace: monitoring annotations: nginx.ingress.kubernetes.io/proxy-body-size: "50m" # 调整请求体大小限制 nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" nginx.ingress.kubernetes.io/limit-connections: "50" spec: ingressClassName: nginx rules: - host: render.example.com # 替换为您自己的域名 http: paths: - path: / pathType: ImplementationSpecific backend: service: name: grafana-image-renderer-headless # 这边使用的是 Headless 服务 port: number: 8081 tls: - hosts: - render.example.com secretName: example-com-tls1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.

Apply 部署:

复制
kubectl apply -f .1.

测试一些是否有问题:

图片

可以看到,没有问题。

在一开始的部署中,我是不知道还需要部署 Grafana-image-render,所以当时因为这个,一直不能生成 PDF 文件。行了,往前看。

配置 Grafana

接下来我们配置下 Grafana,我们需要为 Grafana 添加下变量:

复制
apiVersion: apps/v1 kind: StatefulSet metadata: labels: app.kubernetes.io/instance: kube-prometheus-stack app.kubernetes.io/name: grafana app.kubernetes.io/version: 11.3.1 helm.sh/chart: grafana-8.6.3 name: kube-prometheus-stack-grafana namespace: monitoring spec: persistentVolumeClaimRetentionPolicy: whenDeleted: Retain whenScaled: Retain podManagementPolicy: OrderedReady replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/instance: kube-prometheus-stack app.kubernetes.io/name: grafana serviceName: kube-prometheus-stack-grafana-headless template: metadata: annotations: checksum/config: e1e314c7fdc64d2ecfb41c8c9c1d43e5dbf8d4fc87a11b2373bfbba95ff86a24 checksum/dashboards-json-config: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b checksum/sc-dashboard-provider-config: ce3cfbda1358535f70c551752a34e1d92271c95272f1891dfef8d65a403063e4 checksum/secret: f89c841c5ea6371a733417993185fefcf0760914325c94b37519ea2e919222a5 kubectl.kubernetes.io/default-container: grafana labels: app.kubernetes.io/instance: kube-prometheus-stack app.kubernetes.io/name: grafana app.kubernetes.io/version: 11.3.1 helm.sh/chart: grafana-8.6.3 spec: automountServiceAccountToken: true containers: - env: - name: METHOD value: WATCH - name: LABEL value: grafana_dashboard - name: LABEL_VALUE value: "1" - name: FOLDER value: /tmp/dashboards - name: RESOURCE value: both - name: NAMESPACE value: ALL - name: REQ_USERNAME valueFrom: secretKeyRef: key: admin-user name: kube-prometheus-stack-grafana - name: REQ_PASSWORD valueFrom: secretKeyRef: key: admin-password name: kube-prometheus-stack-grafana - name: REQ_URL value: http://localhost:3000/api/admin/provisioning/dashboards/reload - name: REQ_METHOD value: POST image: quay.io/kiwigrid/k8s-sidecar:1.28.0 imagePullPolicy: IfNotPresent name: grafana-sc-dashboard securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /tmp/dashboards name: sc-dashboard-volume - env: - name: METHOD value: WATCH - name: LABEL value: grafana_datasource - name: LABEL_VALUE value: "1" - name: FOLDER value: /etc/grafana/provisioning/datasources - name: RESOURCE value: both - name: REQ_USERNAME valueFrom: secretKeyRef: key: admin-user name: kube-prometheus-stack-grafana - name: REQ_PASSWORD valueFrom: secretKeyRef: key: admin-password name: kube-prometheus-stack-grafana - name: REQ_URL value: http://localhost:3000/api/admin/provisioning/datasources/reload - name: REQ_METHOD value: POST image: quay.io/kiwigrid/k8s-sidecar:1.28.0 imagePullPolicy: IfNotPresent name: grafana-sc-datasources securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL seccompProfile: type: RuntimeDefault volumeMounts: - mountPath: /etc/grafana/provisioning/datasources name: sc-datasources-volume - env: - name: POD_IP valueFrom: fieldRef: apiVersion: v1 fieldPath: status.podIP - name: GF_SECURITY_ADMIN_USER valueFrom: secretKeyRef: key: admin-user name: kube-prometheus-stack-grafana - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: key: admin-password name: kube-prometheus-stack-grafana - name: GF_PATHS_DATA value: /var/lib/grafana/ - name: GF_PATHS_LOGS value: /var/log/grafana - name: GF_PATHS_PLUGINS value: /var/lib/grafana/plugins - name: GF_PATHS_PROVISIONING value: /etc/grafana/provisioning - name: GF_RENDERING_SERVER_URL # Grafana 将向该地址发送渲染请求,并由 Image Renderer 服务生成图片(例如 PNG、JPEG) value: https://render.example.com - name: GF_RENDERING_CALLBACK_URL # 当 Image Renderer 完成渲染任务后,它会将生成的图片或渲染结果回传给 Grafana value: https://grafana.example.com - name: GF_LOG_FILTERS value: rendering:debug image: docker.io/grafana/grafana:11.3.1 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /api/health port: 3000 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 30 name: grafana ports: - containerPort: 3000 name: grafana - containerPort: 9094 name: gossip-tcp - containerPort: 9094 name: gossip-udp readinessProbe: httpGet: path: /api/health port: 3000 scheme: HTTP periodSeconds: 10 timeoutSeconds: 1 volumeMounts: - mountPath: /etc/grafana/grafana.ini name: config subPath: grafana.ini - mountPath: /var/lib/grafana name: storage - mountPath: /tmp/dashboards name: sc-dashboard-volume - mountPath: /etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml name: sc-dashboard-provider subPath: provider.yaml - mountPath: /etc/grafana/provisioning/datasources name: sc-datasources-volume initContainers: - command: - chown - -R - 472:472 - /var/lib/grafana image: docker.io/library/busybox:1.31.1 imagePullPolicy: IfNotPresent name: init-chown-data securityContext: capabilities: add: - CHOWN runAsUser: 0 volumeMounts: - mountPath: /var/lib/grafana name: storage restartPolicy: Always securityContext: fsGroup: 472 runAsUser: 472 serviceAccountName: kube-prometheus-stack-grafana terminationGracePeriodSeconds: 30 volumes: - configMap: name: kube-prometheus-stack-grafana name: config - emptyDir: {} name: sc-dashboard-volume - configMap: name: kube-prometheus-stack-grafana-config-dashboards name: sc-dashboard-provider - emptyDir: {} name: sc-datasources-volume updateStrategy: rollingUpdate: partition: 0 type: RollingUpdate volumeClaimTemplates: - metadata: name: storage spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi storageClassName: alicloud-nas-subpath1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.74.75.76.77.78.79.80.81.82.83.84.85.86.87.88.89.90.91.92.93.94.95.96.97.98.99.100.101.102.103.104.105.106.107.108.109.110.111.112.113.114.115.116.117.118.119.120.121.122.123.124.125.126.127.128.129.130.131.132.133.134.135.136.137.138.139.140.141.142.143.144.145.146.147.148.149.150.151.152.153.154.155.156.157.158.159.160.161.162.163.164.165.166.167.168.169.170.171.172.173.174.175.176.177.178.179.180.181.182.183.184.185.186.187.188.189.190.191.192.193.194.195.196.197.198.199.200.201.202.203.204.205.206.207.208.209.210.211.212.213.214.215.216.217.218.219.220.221.222.223.224.225.226.227.228.229.230.231.232.233.234.

等待更新完成后,可以测试一些是否有问题。

测试

如何测试呢,不要着急,跟紧我的步骤。

首先我们需要先在 Grafana 中创建一个 SA (serviceaccount),用于授权和访问。

图片

图片

这边起个名字,再选择一个 Admin 的 Role :

图片

创建完成之后,再创建一个 Token,保存好:

图片

接下来我们还需要获取到 Grafana Dashboard 的 ID,这边选择一个你想要生成 PDF 文件的 Dashboard:

然后进入,注意如何选择:

复制
https://grafana.example.com/d/efa86fd1d0c121a26444b636a3f509a8/kubernetes-compute-resources-cluster?orgId=1&from=now-1h&to=now&timeznotallow=utc&var-datasource=default&var-cluster=&refresh=10s1.

域名后面的 d/ 到下一个 / 之间的就是我们需要的 ID

图片

接下来我们开始真正的测试:

完成格式为:

复制
https://reporter.example.com/api/v5/report/alertmanager-overview?apitoken=glsa_M4a256mzUizdmdGsSNK8SZW7h9QfvhGr_6616e37c1.

我们来解析下:

https://reporter.example.com/

• 这个是你的 Grafana-reporter 的域名

api/v5/report/

• 这个是固定的格式,不能改

alertmanager-overview

• 这个也就是你的 Grafana Dashboard 的 ID

?apitoken=glsa_M4a256mzUizdmdGsSNK8SZW7h9QfvhGr_6616e37c

• 这个就是你的 Grafana SA 生成的 Token

接下来我们访问下,看下是否有问题。

可以看到失败了,为什么呢?我们来排查下:

提前说明下,我这边 kubectl 的命令都配置了 Alias。如果你也需要,请查看这篇文章。

进入容器
复制
$ kgpo -nmonitoring NAME READY STATUS RESTARTS AGE alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 19d grafana-image-renderer-0 1/1 Running 0 156m grafana-image-renderer-1 1/1 Running 0 156m grafana-image-renderer-2 1/1 Running 0 156m grafana-reporter-0 1/1 Running 0 92m kube-prometheus-stack-grafana-0 3/3 Running 0 34m kube-prometheus-stack-kube-state-metrics-5b58cf95c8-blv79 1/1 Running 0 19d kube-prometheus-stack-operator-b48974f48-m59d2 1/1 Running 0 19d prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 19d $ kex grafana-reporter-0 -nmonitoring -- bash root@grafana-reporter-0:/# cd /tmp/ # 这个目录是它默认存放生成的 PDF 文件的位置 root@grafana-reporter-0:/tmp# ls e4b21f3b-b031-4fa2-9443-a37f1095261e root@grafana-reporter-0:/tmp# cd e4b21f3b-b031-4fa2-9443-a37f1095261e/ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e# ls images report.aux report.log report.tex root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e# cd images/ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# ls image2.png image3.png image5.png image6.png1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.

我们可以使用 file 这个命令查看一些这个文件的类型

复制
$ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# file image2.png bash: file: command not found1.2.

那就安装下这个命令;

复制
$ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# apt update Ign:1 http://deb.debian.org/debian stretch InRelease Ign:2 http://security.debian.org/debian-security stretch/updates InRelease Ign:3 http://deb.debian.org/debian stretch-updates InRelease Err:4 http://security.debian.org/debian-security stretch/updates Release 404 Not Found [IP: 151.101.2.132 80] Err:5 http://deb.debian.org/debian stretch Release 404 Not Found [IP: 199.232.46.132 80] Err:6 http://deb.debian.org/debian stretch-updates Release 404 Not Found [IP: 199.232.46.132 80] Reading package lists... Done E: The repository http://security.debian.org/debian-security stretch/updates Release does not have a Release file. N: Updating from such a repository cant be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details. E: The repository http://deb.debian.org/debian stretch Release does not have a Release file. N: Updating from such a repository cant be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details. E: The repository http://deb.debian.org/debian stretch-updates Release does not have a Release file. N: Updating from such a repository cant be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details.1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.

报错了,那就修改下。

问题是由于容器中的 apt 使用了一个过期的 Debian 软件源 (stretch),这些源已经不再维护或者被替换,因此无法正确获取包列表

复制
$ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# echo "deb http://archive.debian.org/debian stretch main contrib non-free" > /etc/apt/sources.list $ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# echo "deb http://archive.debian.org/debian-security stretch/updates main contrib non-free" >> /etc/apt/sources.list # 安装 $ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# apt update Ign:1 http://deb.debian.org/debian stretch InRelease Ign:2 http://security.debian.org/debian-security stretch/updates InRelease Ign:3 http://deb.debian.org/debian stretch-updates InRelease Err:4 http://security.debian.org/debian-security stretch/updates Release 404 Not Found [IP: 151.101.2.132 80] Err:5 http://deb.debian.org/debian stretch Release 404 Not Found [IP: 199.232.46.132 80] Err:6 http://deb.debian.org/debian stretch-updates Release 404 Not Found [IP: 199.232.46.132 80] Reading package lists... Done E: The repository http://security.debian.org/debian-security stretch/updates Release does not have a Release file. N: Updating from such a repository cant be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details. E: The repository http://deb.debian.org/debian stretch Release does not have a Release file. N: Updating from such a repository cant be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details. E: The repository http://deb.debian.org/debian stretch-updates Release does not have a Release file. N: Updating from such a repository cant be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details. $ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# echo "deb http://archive.debian.org/debian stretch main contrib non-free" > /etc/apt/sources.list $ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# echo "deb http://archive.debian.org/debian-security stretch/updates main contrib non-free" >> /etc/apt/sources.list $ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# apt update Ign:1 http://archive.debian.org/debian stretch InRelease Get:2 http://archive.debian.org/debian-security stretch/updates InRelease [59.1 kB] Get:3 http://archive.debian.org/debian stretch Release [118 kB] Get:4 http://archive.debian.org/debian stretch Release.gpg [3177 B] Get:5 http://archive.debian.org/debian-security stretch/updates/main amd64 Packages [782 kB] Get:6 http://archive.debian.org/debian-security stretch/updates/non-free amd64 Packages [14.1 kB] Get:7 http://archive.debian.org/debian-security stretch/updates/contrib amd64 Packages [1760 B] Get:8 http://archive.debian.org/debian stretch/main amd64 Packages [7080 kB] Get:9 http://archive.debian.org/debian stretch/contrib amd64 Packages [50.7 kB] Get:10 http://archive.debian.org/debian stretch/non-free amd64 Packages [78.3 kB] Fetched 8186 kB in 1s (6008 kB/s) Reading package lists... Done Building dependency tree Reading state information... Done 31 packages can be upgraded. Run apt list --upgradable to see them. $ root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# apt install -y file Reading package lists... Done Building dependency tree Reading state information... Done The following additional packages will be installed: libmagic-mgc libmagic1 The following NEW packages will be installed: file libmagic-mgc libmagic1 0 upgraded, 3 newly installed, 0 to remove and 31 not upgraded. Need to get 397 kB of archives. After this operation, 5265 kB of additional disk space will be used. Get:1 http://archive.debian.org/debian stretch/main amd64 libmagic-mgc amd64 1:5.30-1+deb9u3 [222 kB] Get:2 http://archive.debian.org/debian stretch/main amd64 libmagic1 amd64 1:5.30-1+deb9u3 [111 kB] Get:3 http://archive.debian.org/debian stretch/main amd64 file amd64 1:5.30-1+deb9u3 [64.2 kB] Fetched 397 kB in 0s (4579 kB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package libmagic-mgc. (Reading database ... 6831 files and directories currently installed.) Preparing to unpack .../libmagic-mgc_1%3a5.30-1+deb9u3_amd64.deb ... Unpacking libmagic-mgc (1:5.30-1+deb9u3) ... Selecting previously unselected package libmagic1:amd64. Preparing to unpack .../libmagic1_1%3a5.30-1+deb9u3_amd64.deb ... Unpacking libmagic1:amd64 (1:5.30-1+deb9u3) ... Selecting previously unselected package file. Preparing to unpack .../file_1%3a5.30-1+deb9u3_amd64.deb ... Unpacking file (1:5.30-1+deb9u3) ... Setting up libmagic-mgc (1:5.30-1+deb9u3) ... Setting up libmagic1:amd64 (1:5.30-1+deb9u3) ... Processing triggers for libc-bin (2.24-11+deb9u3) ... Setting up file (1:5.30-1+deb9u3) ... # 看一下这个文件 root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# ls image2.png image3.png image5.png image6.png root@grafana-reporter-0:/tmp/e4b21f3b-b031-4fa2-9443-a37f1095261e/images# file image2.png image2.png: ASCII text, with no line terminators1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.74.75.76.77.78.79.80.

可以看到,这是文本,不是 png 图片,所以问题是 grafana 没有成功调用到 Grafana-image-render,去生成相应的 PNG 图片。

我们这边再去看下我们的 Grafana 的 logs

复制
# 截取一部分 logs,看起来没有什么特别大的问题: logger=rendering renderer=http t=2024-12-26T10:41:49.307925807Z level=debug msg="calling remote rendering service" url="https://render.example.com?deviceScaleFactor=1.000000&domain=grafana.example.com&encoding=png&height=500&renderKey=lFiW6KBBhrA8vY2BQ9OOXdPSZUU2FL5b&timeout=60&timeznotallow=&url=https%3A%2F%2Fgrafana.example.com%2Fd-solo%2Falertmanager-overview%2F_%3Ffrom%3Dnow-1h%26height%3D500%26panelId%3D2%26theme%3Dlight%26to%3Dnow%26width%3D1000%26render%3D1&width=1000" logger=context userId=1 orgId=1 uname=admin t=2024-12-26T10:41:53.196481964Z level=info msg="Request Completed" method=GET path=/api/live/ws status=-1 remote_addr=127.0.0.1 time_ms=5 duratinotallow=5.670954ms size=0 referer= handler=/api/live/ws status_source=server logger=live t=2024-12-26T10:41:53.389851883Z level=info msg="Initialized channel handler" channel=grafana/dashboard/uid/efa86fd1d0c121a26444b636a3f509a8 address=grafana/dashboard/uid/efa86fd1d0c121a26444b636a3f509a8 logger=rendering renderer=http t=2024-12-26T10:42:18.992113007Z level=info msg=Rendering path="d-solo/alertmanager-overview/_?from=now-1h&height=500&panelId=6&theme=light&to=now&width=1000" userID=2 logger=rendering renderer=http t=2024-12-26T10:42:18.995074149Z level=info msg=Rendering path="d-solo/alertmanager-overview/_?from=now-1h&height=500&panelId=2&theme=light&to=now&width=1000" userID=2 logger=rendering renderer=http t=2024-12-26T10:42:19.010142812Z level=debug msg="calling remote rendering service" url="https://render.example.com?deviceScaleFactor=1.000000&domain=grafana.example.com&encoding=png&height=500&renderKey=ElH0jx7AYodbbkv2lEzvV7Qf1OkeiRac&timeout=60&timeznotallow=&url=https%3A%2F%2Fgrafana.example.com%2Fd-solo%2Falertmanager-overview%2F_%3Ffrom%3Dnow-1h%26height%3D500%26panelId%3D6%26theme%3Dlight%26to%3Dnow%26width%3D1000%26render%3D1&width=1000" logger=rendering renderer=http t=2024-12-26T10:42:19.011440398Z level=info msg=Rendering path="d-solo/alertmanager-overview/_?from=now-1h&height=500&panelId=5&theme=light&to=now&width=1000" userID=2 logger=rendering renderer=http t=2024-12-26T10:42:19.024147345Z level=debug msg="calling remote rendering service" url="https://render.example.com?deviceScaleFactor=1.000000&domain=grafana.example.com&encoding=png&height=500&renderKey=FGMPcxnruw1ZbPXEeH4v0BBrEeUSKvjR&timeout=60&timeznotallow=&url=https%3A%2F%2Fgrafana.example.com%2Fd-solo%2Falertmanager-overview%2F_%3Ffrom%3Dnow-1h%26height%3D500%26panelId%3D5%26theme%3Dlight%26to%3Dnow%26width%3D1000%26render%3D1&width=1000" logger=rendering renderer=http t=2024-12-26T10:42:19.031615719Z level=info msg=Rendering path="d-solo/alertmanager-overview/_?from=now-1h&height=500&panelId=3&theme=light&to=now&width=1000" userID=2 logger=rendering renderer=http t=2024-12-26T10:42:19.044274424Z level=debug msg="calling remote rendering service" url="https://render.example.com?deviceScaleFactor=1.000000&domain=grafana.example.com&encoding=png&height=500&renderKey=a47WWfW9PiO75DoNSHKwfdMwPSeTIiNo&timeout=60&timeznotallow=&url=https%3A%2F%2Fgrafana.example.com%2Fd-solo%2Falertmanager-overview%2F_%3Ffrom%3Dnow-1h%26height%3D500%26panelId%3D3%26theme%3Dlight%26to%3Dnow%26width%3D1000%26render%3D1&width=1000" logger=rendering renderer=http t=2024-12-26T10:42:19.105601469Z level=debug msg="calling remote rendering service" url="https://render.example.com?deviceScaleFactor=1.000000&domain=grafana.example.com&encoding=png&height=500&renderKey=KnO2tIXJg9EvhcbhfDjbadYxAqChU0eN&timeout=60&timeznotallow=&url=https%3A%2F%2Fgrafana.example.com%2Fd-solo%2Falertmanager-overview%2F_%3Ffrom%3Dnow-1h%26height%3D500%26panelId%3D2%26theme%3Dlight%26to%3Dnow%26width%3D1000%26render%3D1&width=1000"1.2.3.4.5.6.7.8.9.10.11.12.

我们来排查下,看一下我们的 Grafana 的 YAML 文件里面的 image-render 的地址,其它多余的就不看了,问题重要在这里,去 Google 了一会,发现我可能少一个路径 /render,这个是默认的,那我们就加上去,看下它是否 OK:

复制
k edit sts kube-prometheus-stack-grafana -nmonitoring ···· - name: GF_RENDERING_SERVER_URL value: https://render.example.com/render - name: GF_RENDERING_CALLBACK_URL value: https://grafana.example.com ····1.2.3.4.5.6.7.

访问下:

图片

可以看到,我们成功了,如果你这边还有问题,可以查看下 Grafana 和 Grafana-reporter 的 logs。

阅读剩余
THE END