在 AWS Elasticsearch Service 使用 snapshot 功能做 migration

Luyo
verybuy-dev
Published in
7 min readJul 10, 2018

今天在研究 Kibana 時,一個衝動就把 .kibana 的 index 的刪了,公司同仁辛苦建好的 Visualization、Dashboard 等等資料 Save Objects 資料全部 GG,當下心都涼了。我們用的是 AWS 的 Elasticsearch Service,雖然每天都有備份,要還原資料並不難,但因為 AWS ES 的 .kibana 這個 index 具特殊權限,沒有辦法徹底砍掉重練,所以照理說是沒救了……但好險下午我手動建了一個 Snapshot,所以還有救!即使如此我還是花了一番功夫才把 Kibana 的設定資料救回來。

雖然我這個需求一般狀況是不太會碰到,但其實解決方法剛好就是我順便想研究的 AWS 的 Elasticsearch 的 snapshot 搬家方法,因為 Elasticsearch Service 沒有辦法跨版本升級,必須透過 snapshot 的做法搬到另一個新的 domain,趁這個機會趕快把實作方法記錄起來。

AWS 的文件在此:https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains-snapshots.html

但眾所周知,AWS 的文件是難讀到一個鬼打牆堪稱悲劇中的悲劇,所以不意外地我看了一遍又一遍、辜狗了一遍又一遍、在心中暗幹了一遍又一遍最後才終於破關。

建立 snapshot repository 及產生 snapshot

先講基本觀念,ES 的 snapshot 架構有兩層,第一層是 repository,第二層才是 snapshot 名稱,所以 URI 會長成這樣:

/_snapshot/repository/snapshot-name

AWS Elasticsearch Service 的手動快照系統會把資料存到你指定的 S3 bucket 之中,一個 repository 名稱對應一個 bucket 來源,你可以設定好個幾 repository 對應到同一個 bucket 來源,你就會看到這些相同來源的 repository 裡面的 snapshot 都是同樣的那幾個,這樣講可能比較好理解,但實作上其實沒什麼意義。

設定 S3 bucket 及相關權限

這部分照著文件的 Manual Snapshot Prerequisites 部分做,沒有什麼太大的問題,當然會有很多小問題,例如在建立 IAM role 的時候,一定要你先選一個相關的 AWS 服務,但裡面根本找不 Elasticsearch Service 的選項,所以只好先隨便選一個,等建好再去改掉。

基本上這部分要做五件事:

  1. 開一個 S3 bucket
  2. 建立一個 IAM policy
  3. 建立一個 IAM role,套用上一步建立的 policy
  4. 修改這個 IAM role 的 trust relationship
  5. 給予你自己 AWS 帳號對應的權限

至於這些 policy 及權限內容請參考文件,這邊就不詳述了。

註冊 snapshot repository

這裡會遇到的問題是你必須要有可以設定 Http Authorization 資料的 Http request 工具 (這些 header 要自己生也不是不行但可能會麻煩到你想哭),我是用 Postman,參考 Use Postman to Call an API 這份文件去把 Authorization 設定好,然後在 body 的部份貼上 json 內容並選擇 JSON (application/json) 格式。request 的 method 及 URI 為:

PUT https://elasticsearch-domain.region.es.amazonaws.com/_snapshot/my-snapshot-repo

request body 內容為:

{
"type": "s3",
"settings": {
"bucket": "s3-bucket-name",
"region": "region",
"role_arn": "arn:aws:iam::123456789012:role/TheServiceRole"
}
}

記得把粗體部分換成你自己的設定,只要前一個段落的權限有設定好,應該不會有什麼大問題。

注意,到這邊只是「註冊」snapshot repository 而已喔,還沒有真的建立 snapshot。

建立 snapshot

因為上一部分的 request 會需要你的 credential key pair 所以必須用可以設定 Authorization 的工具,這邊開始就不需要設定 Authorization,所以直接用 Kibana 的 DevTools 來送 request 就可以了 (當然你要用 Postman 也可以)。

以下是建立 snapshot 的 request,若在 DevTools 就不用加 domain name:

PUT /_snapshot/my-snapshot-repo/snapshot-name

my-snapshot-repo 是你剛剛建立的 snapshot repository 名稱;snapshot-name 就是這次的 snapshot 名稱,一樣請自己取。

若順利的話,S3 那邊就會慢慢跑出 snapshot 的相關檔案了,但跑完會需要好一陣子。

確認 snapshot

送以下 request 會列出所有的 repositories:

GET /_snapshot/_all?pretty

若你也是用 Elasticsearch Service,就會看到兩個,一個是 cs-automated,另一個是你剛剛建立的 repository。此時再送以下 request:

GET /_snapshot/my-snapshot-repo/_all?pretty

會顯示這個 repository 裡所有的 snapshot,理論上這裡你就會看到剛剛建立的 snapshot 名稱及內容囉。

還原 snapshot

這裡就是最容易鬼打牆的部分了。

我們剛剛都在同一個 domain 下設定 repository、做 snapshot,到底要怎麼把資料還原到一個新開的 Elasticsearch domain?文件完全沒有說!

花了好一番功夫我才理解,原來我們要在這個新的 domain 重新設定一次 snapshot repository!

請往上拉到「註冊 repository」那個部分,然後在你的新 domain 做一次,就可以讓它抓到 S3 bucket 的 snapshot repository 資料了!你可以用上面「確認 snapshot」部分的 request 來確認 repository 的內容是否正確。

還原 snapshot 的 request 如下 (從 DevTools 送即可):

POST /_snapshot/my-snapshot-repo/snapshot-name/_restore

若只想還原特定的 index,可以用:

POST /_snapshot/my-snapshot-repo/snapshot-name/_restore
{
"indices": "my-index"
}

另外,像我這次想從 5.x 升級到 6.x,就遇到 index 規格太舊無法匯入的問題,就只能回去把程式碼升級,重建 index 再重新匯入了。

以上,希望可以幫到被 AWS 文件迷惑的朋友們。

最後補充我怎麼還原所有 Kibana 的 Saved Objects 資料。因為 Elasticsearch Service 無法完全砍掉 .kibana 這個 index,所以我做了以下步驟:
1. 在 EC2 開了一台機器起來 (不要開太低規格會跑不動 ES)
2. 灌好 Elasticsearch、Kibana (記得灌 java)
3. 安裝 S3 Repository Plugin
4. 設定 aws credential key pair
5. 註冊 S3 snapshot repository
6. 把 .kibana index 設定成 close
7. 還原 snapshot 的資料
8. 匯出 Save Ojbects json 檔案
9. 回到原本的 domain 匯入 Save Objects 檔案,結束
就是這麼麻煩,千萬不要隨便砍掉你的 Elasticsearch Service 的 .kibana index。

--

--