Elasticsearch 7.9 から OpenSearch 1.3 に移行した話
前提
この記事は、
- AWS で Elasticsearch を運用していること
- OpenSearch へ移行する計画があること
を前提に書かれています。
また、筆者の主観によるところが大きいので、あくまで参考程度にとどめるようにすることをお勧めします。
Elasticsearch および OpenSearch Service に関する勉強中、くらいの認識が良いと思います。
概要
基本的に AWS 上で Elasticsearch 7.9 から OpenSearch 1.3 へ移行する場合は、インプレースアップグレードを選択するケースが多いはずです。とても便利な方法なので、採用できる環境ではそれを全力でおすすめします。
一方この記事では、インプレースではない方法でアップグレードした際の手順や気付きをログとして残します。
やったこと
- 共有スナップショットリポジトリの登録
- スナップショットの取得と復元
- エンドポイントの差し替え
共有スナップショットリポジトリの登録
まず前提として Elasticsearch 7.9 と OpenSearch 1.3 の間には互換性があり、ほとんどの場合はデータスナップショットをそのまま利用できます。正確には一部の API や Kibana の挙動に注意が必要ですが、OpenSearch が Elasticsearch 7.10 からフォークされたという経緯を考えると納得感があります。少なくとも私が携わったプロダクトでは問題なく移行できました。
スナップショットリポジトリの登録には API を叩く必要があるので、ここでは awscurl を使います。以下のようにインストールしておきましょう。
# Linux の場合
$ pip3 install awscurl
# Mac の場合
$ brew install awscurl
Homebrew を使っていない場合は pip を使うと良いでしょう。awscurl を使う際は ~/.aws/credentials などにアクセスキーを設定しておく必要があります。
スナップショットの保存先には S3 を利用するので、あらかじめ S3 バケットと、OpenSearch Service から S3 にアクセスするためのロールを作成します。例えば以下のようなポリシーを設定しておくと良いでしょう。
// 信頼ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "es.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
// S3 アクセスポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": ["${S3_BUCKET_ARN}"]
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": ["${S3_BUCKET_ARN}/*"]
}
]
}
続いてスナップショット用のリポジトリを登録します。awscurl で以下のように実行します。
# スナップショットリポジトリを作る
$ awscurl --service es \
--region ${YOUR_REGION} \
-XPUT \
-H "Content-Type: application/json" \
-d "{
\"type\": \"s3\",
\"settings\": {
\"bucket\": \"${S3_BUCKET}\",
\"base_path\": \"snapshots/es79-to-os13\",
\"role_arn\": \"${SNAPSHOT_ROLE_ARN}\",
\"compress\": true
}
}" \
"${SOURCE_ENDPOINT}/_snapshot/${REPOSITORY_NAME}"
完了したら、ちゃんと登録されているかを確認します。
# リポジトリの確認
$ awscurl --service es \
--region ${YOUR_REGION} \
"${SOURCE_ENDPOINT}/_cat/repositories?v"
id type
cs-automated s3
opensearch-snapshots s3
このように REPOSITORY_NAME(ここでは opensearch-snapshots)が登録されていることを確認します。同じ手順を移行先ドメインでも実施し、その際は 必ず同じバケットと base_path を指定してください。
スナップショットの取得と復元
今回遭遇したケースでは、移行先のドメインにすでに .kibana_1 のようなインデックスが存在しており、それによって「重複はダメ」というエラーが発生しました。そのため、ここではスナップショットに .kibana* を含めない設定を入れています。
$ awscurl --service es \
--region "${AWS_REGION}" \
-XPUT \
-H "Content-Type: application/json" \
-d '{
"indices": "*,-.kibana*",
"ignore_unavailable": true,
"include_global_state": false
}' \
"${SOURCE_ENDPOINT}/_snapshot/${REPOSITORY_NAME}/${SNAPSHOT_NAME}"
このコマンドを実行すると既存インデックスのスナップショットが S3 に保存されていきます。(環境変数部分は各プロジェクトに合わせて適宜変更してください)実行すると以下のようなレスポンスが返ります。
{"acknowledged":true}
スナップショットの作成には時間がかかるので、以下のコマンドでステータスを確認しましょう。
$ awscurl --service es \
--region "${AWS_REGION}" \
"${SOURCE_ENDPOINT}/_snapshot/${REPOSITORY_NAME}/${SNAPSHOT_NAME}?pretty"
スナップショットが完成したら復元です。移行先のドメインを間違えないように気を付けます。
$ awscurl --service es \
--region "${AWS_REGION}" \
-XPOST \
-H "Content-Type: application/json" \
-d '{
"indices": "*,-.kibana*",
"ignore_unavailable": true,
"include_global_state": false
}' \
"${DESTINATION_ENDPOINT}/_snapshot/${REPOSITORY_NAME}/${SNAPSHOT_NAME}/_restore"
進行状況は以下のコマンドで確認できます。
$ awscurl --service es \
--region "${AWS_REGION}" \
"${DESTINATION_ENDPOINT}/_cat/recovery?v"
完了したらインデックスの復元は終了です。
気をつけるべきこと
重複するインデックスが存在するとエラーになる
ドキュメントにも記載されていますが、.kibana_1 などのインデックスは AWS の OpenSearch Service であれば最初から存在します。この状態で「すべてのインデックスを復元」しようとすると重複エラーになるため、除外パターンを指定するか、事前に削除するなどの対応が必要です。
ダウンタイムなしでの差し替えはできない
今回のように「インデックスをコピーする」という前提にすると、当然コピー後に作成されたインデックスは反映されません。メンテナンス時間を確保するか、追随用の仕組みを別途用意する必要があります。
互換性に注意する
例えば Elasticsearch 7.9 からいきなり OpenSearch 3.x に上げるのは危険です。互換性のない変更が入っている可能性があるため、3 系にしたい場合は 1.x → 2.x → 3.x のように段階を踏むことをおすすめします。
まとめ
こんな大掛かりな作業をしなくて済むように、普段から計画的なアップグレードを実施していきましょう。
Discussion