CDKで管理しているAmazon Elasticsearch ServiceをAmazon OpenSearch Serviceへ移行してみた

こんにちは。サービスグループの武田です。CDKで管理しているAmazon Elasticsearch ServiceのドメインをAmazon OpenSearch Serviceへ移行するための手順をまとめました。
2021.09.28

こんにちは。サービスグループの武田です。

先日Amazon Elasticsearch ServiceがAmazon OpenSearch Serviceと名称が変更されました。

それに伴い、従来のElasticsearchに加え、新たにOpenSearchがエンジンとしてサポートされるようになりました。そこでこの機会に、CDKで管理しているシステムが利用しているESをOSに移行してみました。実はESからOSへの移行自体はそこまで難しいものではありません。マネジメントコンソールでぽちぽちすれば終わります。しかしCloudFormationで管理している場合、そう簡単ではありません(CDKは内部でCFnを生成している)。

なぜ簡単ではないかというと、CFnのリソースタイプがAWS::Elasticsearch::DomainからAWS::OpenSearchService::Domainへ変更されているためです。異なるリソースタイプのため同一論理IDのアップグレードができません。移行は次の手順を実施しました。

  1. CDKのコードをESモジュールからOSモジュールを使用するように変更
  2. マネジメントコンソールで更新するスタックのテンプレートをコピーし、ES Domainに関する部分を手で削除し、スタックを更新
    • あらかじめDomainリソースの削除ポリシーはRetainにしておく必要がある(デフォルトはRetain)
  3. CDKのコードをsynthし、OS Domainに関する部分をコピーし、2で更新したテンプレートに貼り付け、スタックへリソースをインポート
  4. CDKのコードをdeployしてAWS環境と一致させる
  5. CDKでエンジンバージョンをOpenSearchに変更しdeploy

1がCDKの移行。2から4がCloudFormationの移行。5がOpenSearchへの移行です。

CDKのソースコードを修正する

この手順は簡単です。まずはCDKのモジュールを入れ替えます。

$ npm install @aws-cdk/aws-opensearchservice
$ npm uninstall @aws-cdk/aws-elasticsearch

次にesモジュールに依存していた箇所をopensearchモジュールを使用するように修正します。ポイントは、エンジンバージョンは変えないこととインスタンスタイプ名を新しい名称に変更することの2点です。

-import * as es from '@aws-cdk/aws-elasticsearch';
+import * as opensearch from '@aws-cdk/aws-opensearchservice';

//中略

-    const esDomain = new es.Domain(this, 'Domain', {
+    const osDomain = new opensearch.Domain(this, 'Domain', {
       domainName: 'classmethod',
-      version: es.ElasticsearchVersion.V7_10,
+      version: opensearch.EngineVersion.ELASTICSEARCH_7_10,
       ebs: {
         volumeSize: 20,
       },
       capacity: {
-        dataNodeInstanceType: 't3.small.elasticsearch',
+        dataNodeInstanceType: 't3.small.search',
       },

この時点でデプロイしようとしても失敗します。前述したようにリソースタイプが内部的に変わっているため互換性のないアップグレードということで弾かれます。

ElasticsearchドメインをCloudFormationスタックから切り離す

リソースタイプが変わっているため、それに対応する必要があります。古いリソースタイプのスタックから切り離し、新しいリソースタイプのスタックにインポートすることで対応します。

まずはマネジメントコンソールなどから現在のスタックのテンプレートをコピーし、ローカルファイルに保存します。

次にElasticsearchドメインに関する部分を削除します。具体的には次のリソースです。

  • リソースタイプがAWS::Elasticsearch::Domainのリソース
  • ESのドメインアクセスポリシー
  • そのほか、ESドメインに依存しているリソース

今回移行したアプリケーションの場合、Lambda関数の環境変数にESのエンドポイントを設定しており、そこを一時的にハードコードに変更しました。移行するアプリケーションによって依存リソースは異なるため、地道に削除または修正して対応しましょう。

テンプレートが修正できたらスタックを更新します。

必要なパラメーターは入力済みのはずですので、そのまま次へ。

変更セットを確認しましょう。ESに関するものが削除され、依存していたその他のリソースも変更されていれば問題ないはずです。

スタックの更新が完了しました。ESは削除スキップされていますね。

ElasticsearchドメインをOpenSearchServiceリソースとしてスタックにインポート

続いて、今切り離したESドメインを今度はOpenSearchServiceリソースとしてスタックにインポートします。1で修正したCDKのコードをsynthして OpenSearchドメインに関する部分だけ をコピーし、2で修正したCFnテンプレートに貼り付け保存します。おそらく修正中のCFnテンプレートはYAML形式ですので、標準出力に出力されたsynth結果をコピーしましょう。outディレクトリの中身はJSON形式のためそのままは使えないはずです。

ここの注意点はAWS::OpenSearchService::Domainのリソースのみコピーすることです。アクセスポリシーも一緒にコピーしてしまうと、インポートする際にインポート不可能なリソースとしてエラーになってしまいます。差分が出てしまうことについては次のステップで解決するので気にせず進めましょう。

スタックの更新ではなく スタックへのリソースのインポート を選択します。

インポートするリソースの識別子を入力します。

問題なければ既存の論理IDに紐付けられるはずです。

インポートが無事に完了しました。

CDKとAWS環境を同期する

このままではアクセスポリシーや一部リソース(今回で言えばLambda関数の環境変数など)が、CDKのコードとAWS環境で不一致の状態になっています。そこでdeployして一致させましょう。そのままコマンドを叩いて完了するのを待つだけです。完了後は念のためAWS環境を確認しておくとよいでしょう。

ElasticsearchからOpenSearchへマイグレーション

それでは仕上げとしてドメインのエンジンを変更しましょう。事前に アップグレードの適格性を確認 しておくと安心してアップグレードできます。修正は1箇所のみでversionのパラメーターを変更するだけです。なおenableVersionUpgrade: trueの指定も必要ですので、指定していなかった場合はこれも追加します。

-      version: opensearch.EngineVersion.ELASTICSEARCH_7_10,
+      version: opensearch.EngineVersion.OPENSEARCH_1_0,

修正できたらdeployしましょう。マネジメントコンソールを見てみるとアップグレードを開始しています。

しばらく待っているとアップグレードが完了し、バージョンがOpenSearch 1.0に変更されました。

ダッシュボードにアクセスするとログイン画面が表示されました。KibanaのURLが_plugin/kibanaから_dashboardsに変わっていますが、以前のURLでもリダイレクトされるので問題はありません。

問題なさそうです!

まとめ

ElasticsearchをOpenSearchに移行する機会があったので手順をまとめてみました。単なるアップグレードならワンクリックで済むのですがCDK(CFn)で管理していると少し手順が複雑でした。誰かにお役に立てば幸いです。

参考サイト