本文介紹如何將 Amazon Web Services(簡稱 AWS)ES 中的索引資料移轉至阿里雲 Elasticsearch。該方案採用快照遷移方式,將AWS ES 的快照資料存入 AWS S3,然後將快照資料移轉至阿里雲 OSS,最後在阿里雲 Elasticsearch 中恢複索引。
遷移方案
遷移基於Elasticsearch的快照機制,不依賴特定雲廠商:在源端AWS ES中建立快照並存入AWS S3儲存空間,將快照資料移轉至阿里雲OSS,再在目標端Elasticsearch中從OSS恢複索引。其中快照資料的跨雲搬遷也可使用線上遷移服務完成(同樣適用於騰訊雲COS中的ES快照資料),恢複環節使用ES的快照恢複功能。
ES快照僅支援恢複到同版本或更高版本的叢集,且精確到小版本號碼,詳見快照相容性。例如源端AWS ES為7.10.2時,目標端Elasticsearch選擇7.10.0會在恢複時報錯the snapshot was created with Elasticsearch version [7.10.2] which is higher than the version of this node [7.10.0],此時應選擇7.16.2等更高版本。

遷移過程分為四個階段,與下文四個步驟一一對應:
準備資源:源端AWS域、AWS S3儲存空間、IAM角色與策略,目標端Elasticsearch執行個體、OSS Bucket。
在AWS ES中註冊指向S3儲存空間的快照存放庫。
遷移首次全量快照:建立快照、提取至OSS、在Elasticsearch中註冊OSS存放庫並恢複索引。
遷移增量快照並切換:停止源端寫入、建立增量快照、增量提取至OSS、恢複並核對資料量後切換業務流量。
步驟一:準備遷移所需資源
遷移只能使用儲存在自有AWS S3儲存空間中的手動快照。AWS每天自動建立的快照保留14天且不能遷移到其他域,僅可用於恢複本域;手動快照按S3標準計費。開始遷移前,需完成以下準備。
準備源端AWS資源
建立AWS域。AWS OpenSearch Service已下線Elasticsearch 7.1.0.0等早期版本,請以控制台當前可選版本為準(本文以Elasticsearch 7.10.2為例),地區可任選(本文以us-east-1為例)。具體操作請參見建立Amazon OpenSearch Service域。
說明如果該域啟用了精細存取控制(Fine-grained access control)且主使用者類型為IAM,或存取原則僅允許IAM主體(如
es:ESHttp*僅授權給帳號根使用者),則無法直接用瀏覽器登入該域的Kibana控制台,會返回403User: anonymous is not authorized to perform: es:ESHttpGet。此時請統一使用帶AWS簽名(SigV4)的方式執行本文中AWS側的各條命令,例如複用步驟二中的Python用戶端。建立AWS S3儲存空間,用於存放手動快照,並記錄其AWS資源名稱(ARN)。該ARN在兩處會用到:IAM策略的Resource語句、註冊快照存放庫的Python用戶端。
ARN樣本如下。
arn:aws:s3:::eric-es-index-backups在AWS ES中準備待遷移的索引,本文樣本索引名稱為
movies。
建立IAM角色與策略
IAM角色用於為AWS ES授權訪問S3儲存空間,IAM策略用於限定該角色可執行檔操作,兩者需配套建立並綁定。
建立IAM角色,用於為AWS ES授權。註冊快照存放庫時需使用該角色,且只有具備該角色存取權限的IAM使用者才能註冊。
該角色信任關係中的
Service語句必須指定為es.amazonaws.com,如下所示。{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "es.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }在IAM控制台左側導覽列選擇Roles,找到目標角色後單擊Trust relationships頁簽,再單擊Edit trust relationship,即可查看和編輯信任策略。
說明在IAM控制台建立AWS服務角色時,Select role type下拉式清單中不包含AWS ES。可先選擇AWS EC2完成角色建立,再將
ec2.amazonaws.com修改為es.amazonaws.com。建立IAM策略並附加給上述IAM角色,用於限定該角色可對S3儲存空間執行的操作。
策略的Resource語句中需指定存放快照的S3儲存空間ARN。以下樣本指定了儲存空間
eric-es-index-backups。{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListBucket" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::eric-es-index-backups" ] }, { "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::eric-es-index-backups/*" ] } ] }建立完成後可在IAM控制台核對:左側導覽列選擇Policies,單擊策略名稱稱進入詳情頁,在Permissions頁簽的JSON視圖中確認策略內容與上述樣本一致,Policy summary中顯示該策略對S3授予Limited: List, Read, Write存取層級。
再在左側導覽列單擊Roles,選擇目標角色,在Permissions頁簽下確認策略已附加成功。
準備目標端阿里雲資源
建立Elasticsearch執行個體,地區為杭州,版本不低於源端AWS ES的具體小版本(源端為7.10.2時選擇7.16.2)。具體操作請參見建立Elasticsearch執行個體。
建立OSS Bucket,用於接收從S3遷移過來的快照資料。本文使用的Bucket地區為華東1(杭州)、儲存類型為標準儲存、讀寫權限為私人,其他參數保持預設,具體操作請參見建立儲存空間。
步驟二:在AWS ES中註冊快照存放庫
只有在AWS ES中註冊了指向S3儲存空間的快照存放庫,才能建立手動快照。註冊請求需使用步驟一:準備遷移所需資源中IAM角色信任關係所指定的使用者或角色進行AWS簽名(SigV4)。curl命令不支援AWS請求籤名,因此需使用以下Python用戶端完成註冊。
準備註冊指令碼
修改指令碼中注釋標註的參數值,並另存新檔snapshot.py。
各參數說明如下。
變數名
描述
region
建立快照存放庫所在的AWS地區。
host
AWS ES域的訪問地址。
aws_access_key_id
IAM憑證ID。
aws_secret_access_key
IAM憑證Key。
service
簽名使用的AWS服務識別,Amazon OpenSearch Service(含Elasticsearch版本)固定為
es。url
註冊快照存放庫的請求地址,格式為
https://{host}/_snapshot/{倉庫名稱},其中倉庫名稱需與後續建立、恢複快照時使用的名稱保持一致。payload
必須包含上文步驟一:準備遷移所需資源中,為IAM角色建立的S3儲存空間的名字和ARN。
重要建議在settings中增加
"base_path": "<自訂首碼>",讓本執行個體的快照檔案集中存放在該首碼下,避免與同一S3儲存空間中其他執行個體的快照混用同一路徑(詳見下文常見問題中的倉庫唯一性說明)。請記錄該首碼,後續在阿里雲ES中註冊OSS倉庫時,base_path必須與快照資料移轉到OSS後的實際首碼保持一致。如果要為快照存放庫啟用S3託管密鑰的伺服器端加密,請將
"server_side_encryption": true添加到settings JSON中。如果S3儲存空間在ap-southeast-1地區,請使用
"endpoint": "s3.amazonaws.com"替代"region": "ap-southeast-1"。
安裝依賴並執行註冊
安裝樣本Python用戶端所需的依賴。
樣本Python用戶端使用requests發送請求、使用requests-aws4auth完成AWS簽名,請在執行註冊操作的機器上(Python 3環境)安裝這兩個依賴。
pip install requests requests_aws4auth執行Python用戶端,註冊快照存放庫。執行成功後返回HTTP狀態代碼200及
{"acknowledged" : true}。python snapshot.py
驗證註冊結果
進入對應AWS ES的Kibana控制台,在Dev Tools頁面的Console中,執行以下命令,查看請求結果。如果該域啟用了精細存取控制或存取原則僅允許IAM主體,導致無法登入Kibana,請改用帶簽名的方式(如複用上述Python用戶端,把要求方法改為GET)執行同樣的命令。
GET _snapshot執行該命令後,返回登入的快照倉庫配置資訊。其中系統自動建立的倉庫名為
cs-automated;若該域開啟了靜態加密,則為cs-automated-enc。{ "eric-snapshot-repository": { "type": "s3", "settings": { "bucket": "eric-es-index-backups", "base_path": "eric-aws", "region": "us-east-1", "role_arn": "arn:aws:iam::xxx:role/eric-iam-role-es" } }, "cs-automated-enc": { "type": "s3" } }
步驟三:首次遷移全量快照
本步驟將源端現有資料整體遷移到目標端:在AWS ES中建立全量快照,把快照資料提取至阿里雲OSS,再在Elasticsearch中註冊OSS存放庫並恢複索引。
在AWS ES中建立全量快照
以下AWS側命令在AWS ES的Kibana控制台的Dev Tools中執行。如果該域無法通過瀏覽器登入Kibana,請改用帶SigV4簽名的請求執行同樣的命令。
為在
eric-snapshot-repository存放庫中的movies索引,建立名稱為snapshot_movies_1的快照。PUT _snapshot/eric-snapshot-repository/snapshot_movies_1 { "indices": "movies" }查看快照狀態,
state為SUCCESS表示快照建立完成。GET _snapshot/eric-snapshot-repository/snapshot_movies_1{ "snapshots": [ { "snapshot": "snapshot_movies_1", "uuid": "BlgKLvgoSpSgwBnbD4hIWg", "version_id": 7100299, "version": "7.10.2", "indices": [ "movies" ], "data_streams": [], "include_global_state": true, "state": "SUCCESS", "start_time": "2018-02-28T03:00:44.591Z", "start_time_in_millis": 1519786844591, "end_time": "2018-02-28T03:00:46.236Z", "end_time_in_millis": 1519786846236, "duration_in_millis": 1645, "failures": [], "shards": { "total": 5, "failed": 0, "successful": 5 } } ] }在AWS S3控制台確認快照檔案已產生。
快照建立成功後,在S3儲存桶eric-es-index-backups中可以看到產生的快照檔案,包括
indices檔案夾、index-0、index.latest、meta-BlgKLvgoSpSgwBhbD4hTWg.dat和snap-BlgKLvgoSpSgwBhbD4hTWg.dat等檔案。
將快照資料移轉至阿里雲OSS
從AWS S3提取快照資料至阿里雲OSS,詳細操作方法請參見從Amazon S3上的應用無縫切換至OSS。
遷移完成後,在OSS控制台確認快照資料已到位。
OSS儲存桶中可看到以下快照檔案:indices/(檔案夾)、index-0、index.latest、meta-BlgKLvgoSpSgwBhbD4hTWg.dat和snap-BlgKLvgoSpSgwBhbD4hTWg.dat。
在阿里雲ES中註冊OSS快照存放庫
建立快照存放庫。
重要在進行Elasticsearch快照遷移過程中,必須確保每個Elasticsearch執行個體使用獨立的快照倉庫或路徑。多執行個體共用同一倉庫將導致資料無法恢複,造成資料丟失風險。
進入目標Elasticsearch執行個體的Kibana控制台(登入Kibana控制台),在Dev Tools頁面的Console中,執行如下命令建立一個同名的快照存放庫。其中
base_path必須與快照資料移轉到OSS後的實際首碼一致(若AWS側倉庫未設定base_path、快照檔案位於儲存空間根目錄,則此處也不要設定base_path)。PUT _snapshot/eric-snapshot-repository { "type": "oss", "settings": { "base_path": "my/snapshot/directory", "endpoint": "http://oss-cn-hangzhou-internal.aliyuncs.com", "access_key_id": "your AccessKeyID", "secret_access_key": "your AccessKeySecret", "bucket": "eric-oss-aws-es-snapshot-s3", "compress": true } }查看名稱為
snapshot_movies_1的快照狀態。GET _snapshot/eric-snapshot-repository/snapshot_movies_1返回結果中
state為SUCCESS,表示Elasticsearch已能從OSS存放庫中讀到該快照。如果返回snapshot_missing_exception,請檢查base_path是否與快照資料在OSS中的實際首碼一致。說明記錄本次快照的起始時間和結束時間,遷移增量快照資料時需要用到。例如:
“start_time_in_millis”: 1519786844591
“end_time_in_millis”: 1519786846236
恢複索引並核對資料
在Elasticsearch的Kibana控制台執行以下命令恢複快照。
POST _snapshot/eric-snapshot-repository/snapshot_movies_1/_restore
{
"indices": "movies"
}執行以下命令,查看movies索引的可用性。
GET movies/_recovery恢複完成後,movies索引中的文檔數量與AWS ES域中一致。
也可在Elasticsearch的Kibana中通過Discover頁面選擇movies索引核對資料。本文樣本中恢複後返回3條文檔(The Manchurian Candidate、Mars Attacks!、U.S. Marshals),與源端相同。
步驟四:遷移增量快照並切換
首次全量快照遷移完成後,源端在此期間新寫入的資料需通過增量快照補齊。正式切換前請先停止所有會修改源端索引的服務,再執行本步驟,確保末次增量快照包含全部資料。以下以在源端新寫入2條文檔為例。
在 AWS ES 中建立增量快照
在AWS ES的
movies索引中寫入增量資料。本文樣本中新寫入2條文檔,寫入後
movies索引共5條文檔,_id分別為1~5。執行GET movies/_count可查看當前文檔數量,用於後續與目標端核對。建立增量快照。
執行以下命令手動建立快照,詳情請參見上文的在AWS ES中建立全量快照。
PUT _snapshot/eric-snapshot-repository/snapshot_movies_2 { "indices": "movies" }建立成功後,執行以下命令查看快照狀態。
GET _snapshot/eric-snapshot-repository/snapshot_movies_2在AWS S3控制台查看新增的快照檔案。
S3儲存空間中會列出快照倉庫的全部檔案,其中與
snapshot_movies_2對應的新增檔案為snap-CWhlF7ShQZaKQlJasPE70A.dat、index.latest、index-1和meta-CWhlF7ShQZaKQlJasPE70A.dat。
遷移增量快照資料至阿里雲OSS
從AWS S3提取增量快照資料至阿里雲OSS,仍使用OSSImport工具遷移。此時S3儲存空間中已包含首次快照的檔案,建議在設定檔local_job.cfg中將isSkipExistFile設定為true,僅遷移新增的快照檔案。
isSkipExistFile為布爾類型,預設值為false,表示覆蓋已有對象;設定為true時,根據對象的size和LastModifiedTime跳過已遷移的對象。當jobType為audit時該配置無效。
遷移完成後,OSS中會出現本次新增的快照檔案。
增量檔案遷移到OSS後,Elasticsearch會沿用已緩衝的倉庫內容,此時執行GET _snapshot/eric-snapshot-repository/_all可能仍然只能看到首次快照。請在Elasticsearch的Kibana控制台重新註冊同名OSS倉庫(先執行DELETE _snapshot/eric-snapshot-repository,再按步驟三中的PUT命令重新建立),確認新快照已可見後,再繼續恢複增量快照。
新增檔案為index-1、index.latest、meta-CWhIF7ShQZaKQUasPE70A.dat和snap-CWhIF7ShQZaKQUasPE70A.dat。
恢複增量快照並切換業務流量
恢複增量快照的命令與步驟三:首次遷移全量快照中相同,但需先關閉movies索引,恢複完成後再重新開啟movies索引。
關閉
movies索引POST /movies/_close查看
movies索引狀態,確認已變為close。索引關閉後不能使用GET movies/_stats查看(會返回index_closed_exception),請使用如下命令。GET _cat/indices/movies?v恢複增量快照
POST _snapshot/eric-snapshot-repository/snapshot_movies_2/_restore { "indices": "movies" }開啟
movies索引POST /movies/_open
恢複完成後,執行GET movies/_count核對文檔數量。本文樣本中目標端返回5,與源端AWS ES一致,此時可將業務流量切換至Elasticsearch執行個體。
常見問題
為什麼需要倉庫唯一性?
當多個Elasticsearch執行個體(包括源端和目標端執行個體)同時使用同一個快照倉庫時,會產生以下問題:
中繼資料衝突:Elasticsearch快照機制依賴於倉庫中的中繼資料檔案來管理快照資訊。多個執行個體同時操作同一倉庫會導致中繼資料被覆蓋或修改,使快照索引無法正確識別。
資料覆蓋風險:不同執行個體建立的快照可能會覆蓋彼此的資料檔案,導致部分快照資料丟失或損壞。
恢複失敗:當嘗試從共用倉庫恢複資料時,Elasticsearch無法確定哪些資料屬於哪個執行個體,導致恢複操作失敗或恢複錯誤資料。
因此,請為每個Elasticsearch執行個體使用獨立的快照倉庫,或在同一儲存空間中通過base_path劃分獨立路徑。如果確實需要多個叢集訪問同一倉庫,請只讓其中一個叢集擁有寫入許可權,其餘叢集在註冊倉庫時設定"readonly": true,以唯讀方式接入。
阿里雲ES從OSS上做快照恢複索引資料時報錯,為什嗎?
可能是因為快照資料在OSS上的路徑中包含以正斜線(/)結尾的空目錄名或其他特殊符號,例如在OSS控制台中可以看到名稱為“/”的異常層級。
阿里雲ES從OSS上做快照恢複索引資料時,不支援快照檔案路徑中包含此類符號。解決方案為通過用圖形化管理工具ossbrowser 2.0快速入門,將OSS的快照資料移到正常的檔案夾下。