현재 사용중인 grafana 를 version upgrade 를 해야 겠다는 생각을 하고 어떤 방법이 좋을지 찾아보니 2가지 방법을 찾았습니다.
첫번째 방법은 롤백을 위해 grafana database file 인 /var/lib/grafana/grafana.db 파일을 백업하고 신규 버전 grafana 를 설치하면 grafana 가 알아서 upgrade 를 해준다고 합니다.
자세한 내용은 아래 링크를 참고하세요.
https://grafana.com/docs/grafana/v9.0/setup-grafana/upgrade-grafana/
위 가이드에 따르면 grafana 에서 version upgrade 를 알아서 해준다니 쉬운 방법인거 같습니다.
하지만 제가 원하는 upgrade 방식은 아닌데요. 저는 기존 grafana 에 영향이 없어야 하고, 제가 원할때 수시로 upgrade 를 할 수 있는 방법이 필요합니다.
그러고 보니 제가 원하는건 upgrade 라기 보다는 migration 이라고 해야겠네요.
migration 방법으로 2번째 방법인 grafana http api 를 사용해보겠습니다.
먼저 관련 http api 에 어떤게 있는지 확인해보겠습니다.
https://grafana.com/docs/grafana/latest/developers/http_api/
현재 사용중인 grafana 에서 migration 해야 할 항목에 어떤게 있는지 확인해 보니 아래 3가지만 migration 하면 될거 같습니다. Users 도 있긴 하나 수작업으로 등록을 해도 가능한 갯수입니다.
grafana http api 를 확인해보니 위 3가지 모두 지원이 됩니다. 아래 http api 를 사용하면 됩니다.
이제 http api 를 활용해서 migration 을 진행해보겠습니다.
- 예제 소스 실행을 위해서는 mac or linux 환경이 필요합니다.
- 스크립트 실행을 위해서는 jq 명령어가 필요합니다.
- jq 설치 방법: https://stedolan.github.io/jq/download/
우선 grafana 2개(old, new) 를 설치해야 합니다. helm chart 를 이용해서 다른 버전을 설치해주면 되고요, old grafana 는 기존에 사용하던게 있다면 그걸 사용하고, 테스트를 위해서라면 old grafana UI 에 접속해서 datasource, folder, dashboard 를 몇개 생성해줍니다.
helm repo add grafana https://grafana.github.io/helm-charts
helm install grafana/grafana:old_version
helm install grafana/grafana:new_version
우선 Basic auth 와 중복되는 내용을 환경변수를 설정해줍니다.
export OLD_BASIC_AUTH=$(echo -ne "admin:admin" | base64 --wrap 0)
export OLD_URI=http://localhost:3000
export NEW_BASIC_AUTH=$(echo -ne "admin:admin" | base64 --wrap 0)
export NEW_URI=http://localhost:3000
그리고 http api 를 사용하기 위해 grafana 에 apikey 를 생성하고 환경변수로 설정해줍니다.
curl -X POST $OLD_URI/api/auth/keys -H "Content-Type: application/json" -H "Authorization: Basic $OLD_BASIC_TOKEN" -d '{"name":"apikeycurl", "role": "Admin", "secondsToLive": 86400}'
export OLD_BEARER_TOKEN=위에서 조회된 내용을 넣어준다.
curl -X POST $NEW_URI/api/auth/keys -H "Content-Type: application/json" -H "Authorization: Basic $NEW_BASIC_TOKEN" -d '{"name":"apikeycurl", "role": "Admin", "secondsToLive": 86400}'
export NEW_BEARER_TOKEN=위에서 조회된 내용을 넣어준다.
grafana api key 는 다시 생성할때는 grafana UI 에서 기존 key 를 먼저 삭제해 줍니다.
먼저 datasource 를 migration 해보겠습니다. old grafana 에서 datasource 목록을 가져와서 new grafana 로 등록하는 스크립트 입니다.
grafana 에서 http api 로 password 조회를 안해주네요. 기존 password 를 모를 경우 좀 난감한데요. 그래서 저는 아예 표준화도 할겸 target 에 신규 id/password 를 생성해서 새로 입력하는 방식으로 진행하기로 합니다.
#!/bin/bash
set +x
# get old datasources
curl -X GET "${OLD_URI}/api/datasources" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > datasources.json
jq -c '.[].id' datasources.json |
# jq -c '.[] | select(.id == 183) | .id' datasources.json |
while read id;
do
echo "";
echo id=${id}
# get old datasource
cat /dev/null > z_datasource.json
curl -s -X GET "${OLD_URI}/api/datasources/${id}" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > z_datasource.json
# basic auth password setup
cat /dev/null > z_datasource_new.json
jq -c '.' z_datasource.json | jq -c '. | if (.basicAuth == true and .type == "loki") then (.secureJsonData.basicAuthPassword |= "admin") elif (.basicAuth == true and .type == "elasticsearch") then (.basicAuthUser |= "admin" | .secureJsonData.basicAuthPassword |= "admin") else . end' | jq . > z_datasource_new.json
# create new datasource
curl -g -X POST "${NEW_URI}/api/datasources" -H "Content-Type: application/json" -H "Authorization: Bearer ${NEW_BEARER_TOKEN}" -d @z_datasource_new.json
done
# get new datasources
curl -X GET "${NEW_URI}/api/datasources" -H "Content-Type: application/json" -H "Authorization: Bearer ${NEW_BEARER_TOKEN}" | jq . > datasources_new.json
datasource 는 name 필드를 이용해서 insert 할때 중복 여부를 체크합니다.
같은 name 의 datasource 를 migration 할때는 기존 datasource 를 먼저 삭제해줍니다.
다음으로 folder 를 이용해서 dashboard 를 관리한다면 folder 를 먼저 migration 해야 합니다. folder 를 new grafana 로 등록하는 스크립트 입니다.
#!/bin/bash
set +x
# get old folder
curl -X GET "${OLD_URI}/api/folders" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > folders.json
# create new folder
jq -c '.[]' folders.json |
while read keydata;
do
echo "";
curl -g -X POST "${NEW_URI}/api/folders" -H "Content-Type: application/json" -H "Authorization: Bearer ${NEW_BEARER_TOKEN}" -d "${keydata}";
done
# get new folder
curl -X GET "${NEW_URI}/api/folders" -H "Content-Type: application/json" -H "Authorization: Bearer ${NEW_BEARER_TOKEN}" | jq . > folders_new.json
folder 는 name 필드를 이용해서 insert/update 를 수행합니다. name 이 중복이면 update 를 수행합니다.
이제 마지막으로 dashboard 를 migration 하는 스크립트 입니다.
dashboard 는 아래 2가지 조치가 필요합니다.
#!/bin/bash
set +x
# get old dashboards
curl -X GET "${OLD_URI}/api/search?type=dash-db" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > dashboards.json
jq -c '.[].uid' dashboards.json |
# jq -c '.[] | select(.uid == "_oT-WeoGk") | .uid' dashboards.json |
while read keydata;
do
echo "====="
# uid 에서 따옴표("") 를 제거해준다.
uid=$(echo $keydata | sed -e "s/\"//g");
echo uid=${uid}
# 임시파일 삭제
cat /dev/null > z_dashboard.json
cat /dev/null > z_dashboard_new.json
# dashboard 상세 정보를 가져온다.
curl -s -X GET "${OLD_URI}/api/dashboards/uid/${uid}" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > z_dashboard.json
# 변경된 folderId 를 가져온다.
folderUid=$(jq -c '.' dashboards.json | jq -c '.[] | select(.uid == "'${uid}'") | .folderUid' | sed -e "s/\"//g")
echo folderUid=${folderUid}
if [ ${folderUid} == "null" ] ; then
folderId=null
else
folderId=$(jq -c '.' folders_new.json | jq -c '.[] | select(.uid == "'${folderUid}'") | .id' | sed -e "s/\"//g")
fi
echo folderId=${folderId}
# json 구조를 import 에 맞게 변경하고, 변경된 folderId 와 "overwrite":true 를 추가한다.
jq -c '.' z_dashboard.json | jq -c '.dashboard.id |= null | {"dashboard":.dashboard, "overwrite":true, "folderId":'${folderId}'}' > z_dashboard_new.json
# import dashboard
curl -g -X POST "${NEW_URI}/api/dashboards/import" -H "Content-Type: application/json" -H "Authorization: Bearer ${NEW_BEARER_TOKEN}" -d @z_dashboard_new.json
done
# get new dashboards
curl -X GET "${NEW_URI}/api/search?type=dash-db" -H "Content-Type: application/json" -H "Authorization: Bearer ${NEW_BEARER_TOKEN}" | jq . > dashboards_new.json
dashboard 는 folder name + dashboard name 으로 중복 체크를 해서 insert/update 를 해줍니다.
이제 migration 작업이 완료되었습니다. new grafana UI 에 접속해서 migration 이 제대로 되었는지 확인하면 됩니다. 기존에 사용중인 grafana 에서 migration 해야 할 항목이 더 있다면 해당 항목의 http api 를 사용해서 migration 을 수행하면 됩니다.
추가로 dashboard json data 만 export 해서 사용하고 싶다면 dashbaord migration 스크립트를 약간 수정해서 사용하면 되는데요. 아래 스크립트를 참고하세요.
#!/bin/bash
set +x
# get old dashboards
curl -X GET "${OLD_URI}/api/search?type=dash-db" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > dashboards.json
jq -c '.[].uid' dashboards.json |
# jq -c '.[] | select(.id == 356) | .uid' dashboards.json |
while read keydata;
do
# uid 에서 따옴표("") 를 제거해준다.
uid=$(echo $keydata | sed -e "s/\"//g");
echo uid=${uid}
# 임시파일 삭제
cat /dev/null > z_dashboard.json
# dashboard 상세 정보를 가져온다.
curl -s -X GET "${OLD_URI}/api/dashboards/uid/${uid}" -H "Content-Type: application/json" -H "Authorization: Bearer ${OLD_BEARER_TOKEN}" | jq . > z_dashboard.json
# json 구조를 형태에 맞게 변경한다.
jq -c '.' z_dashboard.json | jq -c '.dashboard' | jq . > ./dashboards_export/${uid}.json
i=`expr $i + 1`
done
이상으로 grafana version upgrade 를 위해서 grafana http api 를 활용한 data migration 방법을 소개해 드렸습니다.
.감사합니다.