菜单
文档breadcrumb arrow Grafana 文档breadcrumb arrow Observability as Codebreadcrumb arrow Foundation SDKbreadcrumb arrow 使用 CI/CD 自动化仪表盘配置
Grafana Cloud Enterprise 开源

使用 CI/CD 自动化仪表盘配置

介绍

手动管理 Grafana 仪表盘效率低下且容易出错。正如您在入门指南中看到的那样,我们可以使用 Grafana Foundation SDK 通过强类型代码定义仪表盘。然后,我们可以将它们提交到版本控制,并使用 GitHub Actions 自动部署它们。

本指南将引导您了解

  • 将 Grafana 仪表盘生成为代码
  • 将其格式化为 Kubernetes 风格的部署
  • 使用 GitHub Actions 部署仪表盘
  • 检查仪表盘是否存在,如果存在则更新

最后,您对仪表盘代码的每一次更改都将在 Grafana 实例中自动创建或更新,无需手动干预。

1. 生成仪表盘 JSON

在部署仪表盘之前,我们需要使用 Grafana Foundation SDK 在代码中定义它。我们在入门指南中已经运行了一个示例,但是为了符合 Grafana 公开的 Kubernetes 资源兼容 API,我们将对代码进行一些更改,以适当的格式输出仪表盘 JSON。

Go
package main

import (
	"encoding/json"
	"log"
	"os"

	"github.com/grafana/grafana-foundation-sdk/go/cog"
	"github.com/grafana/grafana-foundation-sdk/go/common"
	"github.com/grafana/grafana-foundation-sdk/go/dashboard"
)

type DashboardWrapper struct {
	APIVersion string              `json:"apiVersion"`
	Kind       string              `json:"kind"`
	Metadata   Metadata            `json:"metadata"`
	Spec       dashboard.Dashboard `json:"spec"`
}

type Metadata struct {
	Name string `json:"name"`
}

func main() {
	builder := dashboard.NewDashboardBuilder("My Dashboard").
		Uid("my-dashboard").
		Tags([]string{"generated", "foundation-sdk", "go"}).
		Refresh("5m").
		Time("now-1h", "now").
		Timezone(common.TimeZoneBrowser).
		WithRow(dashboard.NewRowBuilder("Overview"))

	dashboard, err := builder.Build()
	if err != nil {
		log.Fatalf("failed to build dashboard: %v", err)
	}

	dashboardWrapper := DashboardWrapper{
		APIVersion: "dashboard.grafana.app/v1beta1",
		Kind:       "Dashboard",
		Metadata: Metadata{
			Name: *dashboard.Uid,
		},
		Spec: dashboard,
	}

	dashboardJson, err := json.MarshalIndent(dashboardWrapper, "", "  ")
	if err != nil {
		log.Fatalf("failed to marshal dashboard: %v", err)
	}

	err = os.WriteFile("dashboard.json", dashboardJson, 0644)
	if err != nil {
		log.Fatalf("failed to write dashboard to file: %v", err)
	}

	log.Printf("Dashboard JSON:\n%s", dashboardJson)
}
typescript
import { DashboardBuilder, RowBuilder } from '@grafana/grafana-foundation-sdk/dashboard';
import * as fs from 'fs';

// Generate the dashboard JSON
const dashboard = new DashboardBuilder('My Dashboard')
  .uid('my-dashboard')
  .tags(['generated', 'foundation-sdk', 'typescript'])
  .refresh('5m')
  .time({ from: 'now-1h', to: 'now' })
  .timezone('browser')
  .withRow(new RowBuilder('Overview'))
  .build();

// Convert to Kubernetes-style format
const dashboardWrapper = {
  apiVersion: "dashboard.grafana.app/v1beta1",
  kind: "Dashboard",
  metadata: {
    name: dashboard.uid!
  },
  spec: dashboard
};

// Save the formatted JSON to a file
const dashboardJSON = JSON.stringify(dashboardWrapper, null, 2);
fs.writeFileSync('dashboard.json', dashboardJSON, 'utf8');

console.log(`Dashboard JSON:\n${}`);

此脚本

  • 生成 Grafana 仪表盘 JSON 文件
  • 将其包装为 Kubernetes 风格的 API 格式(apiVersionkindmetadataspec
  • 将其保存为 dashboard.json 文件用于部署

2. 使用 GitHub Actions 自动化部署

接下来,我们将设置 GitHub Actions 来: 从 dashboard.json 中提取仪表盘名称 检查仪表盘是否已存在于我们的 Grafana 实例中 如果存在则更新,如果不存在则创建

注意

以下 GitHub Action 配置假设您使用的是基于 Go 的仪表盘生成器。如果您使用的是 Foundation SDK 支持的其他语言,请相应地修改 Generate Dashboard JSON (生成仪表盘 JSON) 步骤。

.github/workflows/deploy-dashboard.yml

yaml
name: Deploy Grafana Dashboard

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Go 1.24.3
        uses: actions/setup-go@v5
        with:
          go-version: 1.24.3

      - name: Verify Go version
        run: go version

      - name: Download and Extract grafanactl
        run: |
          curl -L -o grafanactl-x86_64.tar.gz "https://github.com/grafana/grafanactl/releases/download/${{ vars.GRAFANACTL_VERSION }}/grafanactl_Linux_x86_64.tar.gz"
          tar -xzf grafanactl-x86_64.tar.gz
          chmod +x grafanactl
          sudo mv grafanactl /usr/local/bin/grafanactl

      - name: Generate Dashboard JSON
        working-directory: ./github-actions-example
        run: go run main.go

      - name: Deploy Dashboard with grafanactl
        env:
          GRAFANA_SERVER: ${{ vars.GRAFANA_SERVER }}
          GRAFANA_STACK_ID: ${{ vars.GRAFANA_STACK_ID }}
          GRAFANA_TOKEN: ${{ secrets.GRAFANA_TOKEN }}
        run: |
          if [ -f dashboard.json ]; then
            echo "dashboard.json exists, deploying dashboard."
            grafanactl resources push dashboards --path ./dashboard.json
          else
            echo "dashboard.json does not exist."
            exit 1
          fi
        working-directory: ./github-actions-example

3. 说明此 GitHub Action

此 GitHub Action 使用 Foundation SDK 和 grafanactl CLI 工具自动化部署 Grafana 仪表盘。

1. 检出并设置 Go

前几个步骤

  • 检出仓库以访问项目代码。
  • 使用 actions/setup-go Action 安装 Go 1.24.3。
  • 验证 Go 是否正确安装。

2. 下载并安装 grafanactl

此步骤使用 vars.GRAFANACTL_VERSION 中定义的版本从 GitHub 下载 grafanactl CLI。它解压 tarball,使其可执行,并将其移动到系统 PATH 中的位置。

3. 生成仪表盘 JSON

./github-actions-example 目录运行仪表盘生成器(main.go)。这应该会生成一个包含 Grafana 仪表盘定义的 dashboard.json 文件。

4. 使用 grafanactl 部署仪表盘

如果 dashboard.json 存在,则使用以下命令部署到您的 Grafana 实例中:

bash
grafanactl resources push dashboards --path ./dashboard.json

此命令使用以下环境变量针对 Grafana 进行身份验证:

  • GRAFANA_SERVER:您的 Grafana 实例 URL
  • GRAFANA_STACK_ID:您的 Grafana 技术栈 ID
  • GRAFANA_TOKEN:具有足够权限的 Grafana 服务账户令牌

使用的 GitHub 变量和密钥

这些在您仓库的 **Settings → Security → Secrets and variables → Actions** (设置 → 安全 → 密钥和变量 → Actions) 下配置。

  • vars.GRAFANACTL_VERSION:要安装的 grafanactl 版本
  • vars.GRAFANA_SERVER:您的 Grafana 实例 URL
  • vars.GRAFANA_STACK_ID:Grafana 中的技术栈 ID
  • secrets.GRAFANA_TOKEN:Grafana API 令牌

此 Action 确保每次推送到 main 分支时都会重新生成并将最新的仪表盘定义部署到 Grafana。

为什么要自动化?

自动化 Grafana 仪表盘部署消除了手动创建和更新仪表盘的需求,确保仪表盘在不同环境之间保持一致。通过将仪表盘定义为代码并通过 CI/CD(例如 GitHub Actions)进行管理,我们可以获得完整的版本控制,从而轻松跟踪随时间的变化并在需要时回滚。这也防止了重复,因为工作流会智能地检查仪表盘是否存在,然后再决定创建还是更新。通过这种完全自动化的 CI/CD 流水线,开发人员可以专注于改进他们的仪表盘,而不是手动上传 JSON 文件到 Grafana。

结论

通过将 Grafana Foundation SDK 与 GitHub Actions 集成,我们成功地自动化了 Grafana 仪表盘的整个生命周期。此设置允许我们以编程方式定义仪表盘,将其转换为 Kubernetes 兼容的格式,并自动部署它们。每次推送到仓库时,工作流都会确保仪表盘按需创建或更新。这不仅提高了效率,还确保了所有部署的仪表盘始终与最新的代码更改同步,从而减少了手动工作和潜在错误。