iT邦幫忙

2024 iThome 鐵人賽

DAY 11
4
DevOps

後 Grafana 時代的自我修養系列 第 11

後 Grafana 時代的第十一天 - 關於 Grafana 的備份、恢復、遷移

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20240925/20149562bwOLFxYeTX.png

前言

兄弟,我相信我們在實務中接觸到的 Grafana 環境,大多數情況下都缺乏妥善的規劃。因此,當我們開始整理和維護 Grafana 時,往往會遇到各種大大小小的坑。例如,在升級 Grafana 版本時,有些資源(如 Alert、Panel 等)可能已被棄用,導致舊的設置無法直接在新版 Grafana 上運作。或者,由於許多資源綁定了 Grafana 特定的資源 UID,當該特定資源被移除時,所有依賴它的子資源將無法通過 UID 找到正確的對象。為了避免出現無法挽回的錯誤,我們必須事先做好完整的備份和還原準備,以確保能夠順利完成這項吃力不討好的環境搬遷任務。

使用 Database Dump vs JSON Output 備份的差異

在我們先前的建立高可用 Grafana 的章節中,我們了解到,Grafana 的內部依賴一個基於 SQL 的關聯資料庫作為持久層,所有數據都儲存在這個資料庫中。因此,從理論上來說,備份這個資料庫就等於備份了完整的 Grafana 資料。話雖如此,但在實務操作中,Grafana 的使用情境並不這麼簡單。幸好,我們可以通過 Grafana API 將資源以 JSON 形式輸出,從而實現另一種備份方式。這兩種備份方式的主要用途和差別如下:

Database Dump

優點:

  • 完整性:這種方式可以保留 Grafana 中的所有數據,包括所有的儀表板、數據源、通知渠道以及用戶數據和插件配置等,確保數據的完整性。
  • 一鍵恢復:dump 和 restore 操作通常是原子性的,即使你有大量的配置和數據,只需一次操作就可以完成所有的備份或恢復,非常適合災難恢復場景。

使用場景:

  • 完整備份和災難恢復:當你需要定期備份整個 Grafana 實例,並確保在災難發生後能快速恢復全部數據時,dump 整個數據庫是最可靠的方法。
  • 數據量大且操作頻繁:如果你的 Grafana 實例中有大量的配置和數據(如用戶、插件、儀表板等),而且這些配置變動頻繁,將整個數據庫 dump 出來可能會更高效。
  • 簡單直接:當你希望備份操作簡單直接,不需要考慮選擇性備份時,dump 數據庫是一個較好的選擇。

JSON Output

優點

  • 可讀性強:JSON 格式易於閱讀和理解,便於手動檢查和修改。例如,你可以輕鬆地查看和修改儀表板配置,或進行部分恢復。
  • 精細控制:你可以選擇性地備份特定的組件(如儀表板、數據源、通知渠道等),而不是整個數據庫。這在你只需要備份或恢復部分配置時非常有用。
  • 版本控制:JSON 文件很容易納入版本控制系統(如 Git),這樣你可以跟蹤不同版本之間的變化,並輕鬆回滾到之前的配置。
  • 跨環境遷移:因為 JSON 文件是與平台無關的格式,你可以輕鬆地將配置從一個 Grafana 實例遷移到另一個實例,無需考慮底層數據庫的結構。

使用場景:

  • 需要部分備份或恢復:當你只想備份特定的儀表板或配置時,JSON 格式非常適合。
  • 需要版本控制或跨環境遷移:當你需要將配置納入版本控制或從一個環境遷移到另一個環境時,使用 JSON 格式更靈活。
  • 便於檢查和修改:當你需要檢查或手動修改備份文件時,JSON 格式更加便捷。

Grafana 內部資源嚴重互相依賴

https://ithelp.ithome.com.tw/upload/images/20240925/20149562IP5FXWnN5l.png

首先,從 Grafana 的內部資源依賴關係圖中可以看出,Grafana 的內部資源之間存在高度耦合。假設有一天,一個仍然被其他資源依賴的 Datasource被誤刪,這將導致所有依賴該資料源 UID 的資源全部出現 "No Data" 錯誤。這樣的情況會直接導致 Dashboard、Panel 和 Alert 查詢失敗,等同於系統進入一段黑暗期:任何問題都不會觸發告警通知,即使發現服務出現問題,也無法使用 Dashboard 進行故障排除。這提醒我們,在 Grafana 中進行任何資源刪除操作時必須極其謹慎。

在同樣的誤刪資料源情境下,如果 Grafana 系統是以 JSON 格式進行配置管理,則可以通過易於理解的設置,快速定位被移除的資料源 UID,並一鍵將其全域替換為新的資料源 UID,從而迅速化解危機。而如果使用資料庫備份(Database dump)的方式進行恢復,最多只能恢復到刪除前的狀態,需要反覆測試和恢復,直到所有依賴的資源都處理妥當。這是因為 Grafana 的資料庫表之間的業務邏輯較為複雜,難以直觀理解,導致其在可讀性和細緻的可控性上存在不足。

Grafana Backup Tool 介紹

基於 Python 為底層的 Grafana Backup Tool 是一個用於備份和恢復 Grafana 配置的實用工具。它允許使用者輕鬆地將 Grafana 中的各種以 JSON 格式導出,並在需要時將其恢復。這款工具對於那些需要定期備份 Grafana 配置、進行版本控制或在不同環境間遷移配置的場景特別有用。

Support Components

使用 Grafana Backup Tool 可以備份的內容包含:

  • Folder
  • Folder Permissions
  • Library Elements
  • Dashboard (contains Alert)
  • Datasource
  • Alert Channel
  • Alert Rules
  • Teams
  • Team Members
  • Organization
  • User
  • Snapshots
  • Dashboard Versions (only backup, no restore)
  • Annotations

Grafana Backup 指令

Grafana Backup Tool 的指令提供了一個簡單的方式來讓我們執行備份和恢復操作。

以下是一些目前實現的指令:

Usage:
    grafana-backup save [--config=<filename>] [--components=<>] [--no-archive]
    grafana-backup restore [--config=<filename>] [--components=<>] <archive_file>
    grafana-backup delete [--config=<filename>] [--components=<>]
    grafana-backup tools [-h | --help] [--config=<filename>] [<optional-command>] [<optional-argument>]
    grafana-backup [--config=<filename>]
    grafana-backup [-h | --help]
    grafana-backup --version

由於我們利用 API 的方式作為與 Grafana Server 交互的方式,所以我們將額外提供相關 API Token、Service Account Token、使用者帳密等資訊。

主要能夠透過指令參數 —config=grafanaSettings.json 或環境變數來注入:

# grafanaSettings.json
{
  "general": {
    "debug": true,
    "verify_ssl": true,
    "backup_dir": "_OUTPUT_"
  },
  "grafana": {
    "url": "http://localhost:3000",
    "token": "{YOUR_GRAFANA_TOKEN}",
    "search_api_limit": 5000,
    "default_user_password": "00000000",
    "admin_account": "admin",
    "admin_password": "admin"
  }
}

# environment variables
GRAFANA_TOKEN={YOUR_GRAFANA_TOKEN}
GRAFANA_URL={YOUR_GRAFANA_URL}
GRAFANA_ADMIN_ACCOUNT={YOUR_GRAFANA_ADMIN_ACCOUNT}
GRAFANA_ADMIN_PASSWORD={YOUR_GRAFANA_ADMIN_PASSWORD}

其中以 grafana-backup save 和 grafana-backup restore 這兩個指令最為重要,它們也是 Grafana 以 JSON 格式備份的關鍵操作指令,接下來我們將實際操作看看。

實戰演練

如沒有 Python 相關套件環境,可以跟我一樣選擇 docker container 的方式執行 grafana-backup-tool 指令。

備份 Grafana 資源

首先,我們需要到 Grafana UI 側邊欄 Users and Accesee > Serviceaccounts 中建立一個 Service Account 給 Grafana Backup Tool,隨後我們就能產生出 Service Account Token 保存下來:

https://ithelp.ithome.com.tw/upload/images/20240925/20149562CuT2jnfWNz.png

接著將帳號密碼以及 Service Account Token 輸入指令執行 grafana-backup save,預設將會把所有 Grafana 資源輸出:

docker run --user $(id -u):$(id -g) --rm --name grafana-backup-tool \                                                                     (orbstack/default)
           -e GRAFANA_TOKEN=<GRAFANA_TOKEN> \
           -e GRAFANA_URL=<GRAFANA_URL> \
           -e GRAFANA_ADMIN_ACCOUNT=admin \
           -e GRAFANA_ADMIN_PASSWORD=<GRAFANA_ADMIN_PASSWORD> \
           -v ./backup:/opt/grafana-backup-tool/_OUTPUT_  \
           ysde/docker-grafana-backup-tool grafana-backup save
---
backup folders at: _OUTPUT_/folders/202408311406
backup datasources at: _OUTPUT_/datasources/202408311406
backup dashboards at: _OUTPUT_/dashboards/202408311406
backup alert_channels at: _OUTPUT_/alert_channels/202408311406
backup organizations at: _OUTPUT_/organizations/202408311406
backup users at: _OUTPUT_/users/202408311406
backup snapshots at: _OUTPUT_/snapshots/202408311406
backup dashboard_versions at: _OUTPUT_/dashboard_versions/202408311406
backup annotations at: _OUTPUT_/annotations/202408311406
backup library-elements at: _OUTPUT_/library-elements/202408311406
backup teams at: _OUTPUT_/teams/202408311406
backup team_members at: _OUTPUT_/team_members/202408311406
backup alert_rules at: _OUTPUT_/alert_rules/202408311406
backup contact_points at: _OUTPUT_/contact_points/202408311406
backup notification_policies at: _OUTPUT_/notification_policies/202408311406

將產生出來的壓縮檔解壓縮就能看到所有 JSON 格式的檔案:

tree ./backup/_OUTPUT_                                                                                                             (orbstack/default)
./backup/_OUTPUT_
├── dashboards
│   └── 202408311406
│       ├── UDdpyzz7z.dashboard
│       ├── dashboards_202408311406.txt
│       └── isFoa0z7k.dashboard
├── datasources
│   └── 202408311406
│       ├── P214B5B846CF3925F.datasource
│       ├── P8E80F9AEF21F6940.datasource
│       ├── bdwh2xielktmoc.datasource
│       ├── ddwh3bpiimrr4a.datasource
│       └── edwaj9in0rl6oa.datasource
├── folders
│   └── 202408311406
│       ├── adw3u5eidl7uoa.folder
│       ├── adw3u5eidl7uoa.folder_permission
│       └── folders_202408311406.txt
├── organizations
│   └── 202408311406
│       ├── 1.organization
│       └── organizations_202408311406.txt
└── users
    └── 202408311406
        ├── 1.user
        ├── 3.user
        └── users_202408311406.txt

其中一個輸出範例如下:

#_OUTPUT_/users/202408311406/1.user
{
  "id": 1,
  "uid": "adw3trl5csyyof",
  "name": "",
  "login": "admin",
  "email": "mike.hsu@gmail.com",
  "avatarUrl": "/avatar/c38142e68ae429a9319c9e39b846c724",
  "isAdmin": true,
  "isDisabled": false,
  "lastSeenAt": "2024-08-31T14:02:15Z",
  "lastSeenAtAge": "3 minutes",
  "authLabels": [],
  "theme": "",
  "orgId": 1,
  "isGrafanaAdmin": true,
  "isExternal": false,
  "isExternallySynced": false,
  "isGrafanaAdminExternallySynced": false,
  "updatedAt": "2024-08-28T01:42:13Z",
  "createdAt": "2024-08-27T16:21:27Z",
  "orgs": [
    {
      "orgId": 1,
      "name": "Main Org.",
      "role": "Admin"
    }
  ]
}

如此一來我們對於資源可讀性一目了然,也可以輕鬆的全域修改相關依賴及設定。

還原 Grafana 資源

同樣地,我們能透過 grafana-backup restore 指令指定我們想要還原的資源壓縮檔,輕鬆還原整個修正後的 Grafana 服務:

docker run --user $(id -u):$(id -g) --rm --name grafana-backup-tool \
           -e GRAFANA_TOKEN=<GRAFANA_TOKEN> \
           -e GRAFANA_URL=<GRAFANA_URL> \
           -e GRAFANA_ADMIN_ACCOUNT=admin \
           -e GRAFANA_ADMIN_PASSWORD=<GRAFANA_ADMIN_PASSWORD> \
           -v ./backup:/opt/grafana-backup-tool/_OUTPUT_  \
           ysde/docker-grafana-backup-tool grafana-backup restore /opt/grafana-backup-tool/_OUTPUT_/202408311406.tar.gz

定期備份 Grafana 資源 - Kubernetes Cronjob

當談到備份時,最理想的做法是將備份設置為一個自動化的例行任務,這樣可以確保在系統運行的任何時刻,我們都擁有最新的資料備份,從而在發生問題時能夠快速恢復。針對這一點,官方提供了一個非常實用的指南,教我們如何在 Kubernetes 中設置 CronJob 來自動執行定期備份。

這個 CronJob 不僅會自動備份數據,還會將備份文件壓縮後上傳到雲供應商的 Object Store 中,例如 AWS S3。這樣的設置不僅確保了數據的安全性和可靠性,還充分利用了雲存儲的冗餘性和擴展性。

apiVersion: v1
kind: ConfigMap
metadata:
  name: grafana-backup-tool
  namespace: grafana-backup-tool
data:
  GRAFANA_URL: "http://grafana.grafana.svc.cluster.local:80"
  GRAFANA_TOKEN: "{YOUR_GRAFANA_TOKEN}"
  GRAFANA_ADMIN_ACCOUNT: "backup"
  GRAFANA_ADMIN_PASSWORD: "{YOUR_GRAFANA_ADMIN_PASSWORD}"
  AWS_ENDPOINT_URL: "http://gitlab-minio-svc.gitlab.svc.cluster.local:9000"
  AWS_S3_BUCKET_NAME: "grafana-backup"
  AWS_S3_BUCKET_KEY: "daily"
  AWS_DEFAULT_REGION: "us-east-1"
  AWS_ACCESS_KEY_ID: "{YOUR_AWS_ACCESS_KEY_ID}"
  AWS_SECRET_ACCESS_KEY: "{YOUR_AWS_SECRET_ACCESS_KEY}"
---
# Run grafana-backup-tool daily and store backups in an S3
# compatible object storage such as minio
apiVersion: batch/v1
kind: CronJob
metadata:
  name: grafana-backup-tool
  namespace: grafana-backup-tool
  labels:
    app: grafana-backup-tool
spec:
  schedule: "0 4 * * *"
  jobTemplate:
    metadata:
      labels:
        app: grafana-backup-tool
    spec:
      template:
        spec:
          restartPolicy: "Never"
          containers:
            - name: grafana-backup-tool
              image: "ysde/docker-grafana-backup-tool:1.2.4"
              imagePullPolicy: Always
              envFrom:
                - configMapRef:
                    name: grafana-backup-tool

Database Backup 介紹

通常,在關聯式資料庫不論在 Saas 還是自建環境中都已經擁有成熟的備份方式,但在 Grafana 中常有個一個情境是:在從原本單體式 Grafana 的內嵌式 SQLite3 想要遷移到高可用的關聯式資要庫時,也必需要處理資料庫備份還原的情況。

SQLite Migration

Grafana 官方提供我們一套 Database Migrator 來幫助我們將內嵌的 SQLite 遷移到外部資料庫,就讓我們簡單操作一下。

Database Migrator 安裝:

git clone https://github.com/grafana/database-migrator.git

將 Kubernetes 中的 grafana.db 檔案輸出到本地:

kubectl cp <namespace>/<pod>:<PATH_TO_GRAFANA_DB>/grafana.db grafana.db 

執行設定檔:


./sqlitedump.sh grafana.db > grafana.sql

MySQL Backup

backup:
> mysqldump -u root -p[root_password] [grafana] > grafana_backup.sql

restore:
> mysql -u root -p grafana < grafana_backup.sql

Postgres Backup

backup:
> pg_dump grafana > grafana_backup

restore:
> psql grafana < grafana_backup

結論

在這篇文章中,我們探討了 Grafana 系統中常見的備份策略及其重要性,尤其是在面對未經妥善規劃的 Grafana 環境時,更需要謹慎處理升級和維護過程中的潛在風險。我們詳細比較了使用 Database Dump 和 JSON Output 進行備份的優缺點,以及這兩種方法在不同場景中的適用性。此外,我們介紹了 Grafana Backup Tool 的使用,這是一個強大工具能夠幫助我們輕鬆地備份和恢復 Grafana 的各種設定,並通過 Kubernetes CronJob 實現自動化的定期備份,以確保數據的安全性和可靠性。

無論我們選擇哪種備份方式,都應該根據實際情況和需求進行合理選擇,以確保在系統發生問題時能夠快速恢復,最小化業務中斷。通過將備份和恢復過程自動化,我們可以更好地保障系統的穩定運行,並減少手動操作的風險。


References:
https://github.com/ysde/grafana-backup-tool

https://grafana.com/docs/grafana/latest/administration/back-up-grafana/

https://github.com/grafana/database-migrator/tree/master

https://blog.ooopiz.com/post/2021/04/try-grafana-backup-tool/


上一篇
後 Grafana 時代的第十天 - 搭建 Grafana 高可用架構
下一篇
後 Grafana 時代的第十二天 - 探討 Grafana IaC 可行性方案
系列文
後 Grafana 時代的自我修養13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言