grafana version upgrade 방법

Jaemyeong.Lee·2022년 9월 5일
1

현재 사용중인 grafana 를 version upgrade 를 해야 겠다는 생각을 하고 어떤 방법이 좋을지 찾아보니 2가지 방법을 찾았습니다.

  1. 기존 grafana 에 신규 버전을 설치하면 version upgrade 가 자동으로 되는 방법
  2. grafana http api 를 사용하는 방법

첫번째 방법은 롤백을 위해 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 도 있긴 하나 수작업으로 등록을 해도 가능한 갯수입니다.

  • Datasources
  • Folders
  • Dashboards

grafana http api 를 확인해보니 위 3가지 모두 지원이 됩니다. 아래 http api 를 사용하면 됩니다.

이제 http api 를 활용해서 migration 을 진행해보겠습니다.

  • 예제 소스 실행을 위해서는 mac or linux 환경이 필요합니다.
  • 스크립트 실행을 위해서는 jq 명령어가 필요합니다.

우선 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 로 등록하는 스크립트 입니다.

  • datasource 중에 id/password(basic auth) 가 필요한 datasource 는 migration 할때 password 를 입력해줘야 합니다.

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 로 등록하는 스크립트 입니다.

  • folder 는 기존 grafana 에서 추출한 json data 에 별다른 조치없이 바로 POST 로 insert/update 가 됩니다.
#!/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가지 조치가 필요합니다.

  • dashboard 관리하는데 folder 를 사용한 경우 dashboard 와 folder 사이에 mapping 관계에 자동으로 할당되는 folder id 가 사용되기 때문에, new grafana 에 신규 등록된 folder id 를 찾아서 변경해주는 작업이 필요합니다.
  • dashboard 등록에는 dashboard import api 를 사용하기 하기 때문에 import data 구조에 맞게 json data 를 변경해줘야 합니다.
#!/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 스크립트를 약간 수정해서 사용하면 되는데요. 아래 스크립트를 참고하세요.

  • dashboard json data 구조에 맞게 변경해주는 작업이 필요합니다.
#!/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 방법을 소개해 드렸습니다.

.감사합니다.

0개의 댓글