Amazon Elasticsearch Service (AES) で手動スナップショット取得の仕組みをCloudformationで一気にデプロイします。かつCurator使って古いスナップショットは自動的に削除する設定になっています。スナップショット取るだけで意外に大変です。
PythonスクリプトはこちらのAWSのドキュメントにあるものベースにしてます。
Curator を使用した Amazon Elasticsearch Service でのデータの更新 - Amazon Elasticsearch Service
- やりたいこと
- 手動スナップショットの必要性
- 参考URLはあるが
- 作業前提
- 実行方法
- バックアップ取ってみる
- やっていること
- スナップショットの復元
- 参考
- [Tipsメモ] Kibanaのインデックス以外をリストアする
やりたいこと
これを作ります。スクリプトはAWSのドキュメントにあるものを、ほぼそのまま使っているので、読めばすぐわかるレベルだと思います。コメントも残ってます。
手動スナップショットの必要性
2019年7月に以下のように自動スナップショットが強化され、1時間毎のスナップショットが14日間 S3に保管されるようになりました。
これだけでも、複数ノード同時障害によるデータロスト時にも障害1時間前の状況までもどせる状態になりとても便利です。
ただ、自動スナップショットはマネージドのS3バケットに取得されるため、ドメインが削除されると一緒に全てが削除されてしまいます。
また、ドメインの複製を作成したい場合など、スナップショットを別ドメインにリストアはできないなどの制約もあります。
Kibanaの定義やIndexのマップ等を別ドメインで使いたいというニーズは結構あると思います。そのためには自動スナップショットに合わせて手動のスナップショットも並列で取得すると良いです。
参考URLはあるが
実績あるサービスだけあって、この辺りは公式でも情報があります。
Curator を使用した Amazon Elasticsearch Service でのデータの更新 - Amazon Elasticsearch Service
ただ、これをそのままLambdaにコピペしても動きません。Pythonのサンプルスクリプトに使われているライブラリは別途Lambdaでインポートできるように設定が必要です。
また、手動スナップショットを行うにはIAM等の設定が必要です。ここにマニュアルありますが、慣れてないと何やっていいかわからないと思います。
Amazon Elasticsearch Service インデックススナップショットの使用 - Amazon Elasticsearch Service
この記事では、このプログラム(を少し調整したもの)が動く環境作るのを目標にします。
作業前提
この記事で実施している操作の前提です。
作業端末側
最低、以下がインストールされているLinuxやMacマシン。(ちなみに、私はwsl2で作業してます)
- Python3
- Docker
- Git
- AWS CLI
AWS側
- Amazon Elasticsearch ServiceをVPCアクセスタイプでデプロイ済み
実行方法
Githubからダウンロード
Githubから以下のリポジトリをダウンロードします。
$ git clone git@github.com:yomon8/aes-snapshot-sample.git
$ cd aes-snapshot-sample/
設定ファイル調整
設定ファイルに変数を入力します。
$ cp settings.sh{.sample,} $ vim settings.sh
以下のような項目があるので、環境に合わせて設定入れます。
# CloudformationのStack名 readonly STACK_NAME=es-snapshot-sample # Cloudformationのパッケージをアップロードするバケット readonly STACK_S3_BUCKET=bucket-name readonly STACK_S3_PREFIX=es-snapshot-sample # AESのホスト名(AESはVPCアクセスを前提に作ってます) readonly AES_HOST=vpc-xxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com # AESにアクセス可能なSubnetを指定 readonly LAMBDA_SUBNET_ID=subnet-xxxxxxxxxxxxxxxxxxxxxx # AESにアクセス可能なSGを指定 readonly LAMBDA_SECURITY_GROUP_ID=sg-xxxxxxxxxxxxxxxxxxx # AESのスナップショットの保管先の名前 readonly SNAPSHOT_REPOSITORY_NAME=your-repo # AESのスナップショットの名前のPrefix readonly SNAPSHOT_PREFIX=your-snapshot
Cloudformationデプロイ
後はデプロイ用のスクリプト叩いたら終わりです。初回はLayerのソフトウェアダウンロードするのに結構時間かかります。私の環境で10分かからないくらいです。
$ ./deploy.sh ~省略~
Snapshotリポジトリの登録
deploy.sh
を実行すると以下のようなメッセージが最後に表示されます。
1. 最初に一回、以下のコマンドを実行します. aws lambda invoke --function-name aes-snapshot-sample-AESRegistSnapshotRepositoryFun-1SHIY9NWSSH8B:live /dev/null
メッセージの通り、コマンドを実行するとリポジトリ登録用のLambdaが実行されます。
$ aws lambda invoke --function-name aes-snapshot-sample-AESRegistSnapshotRepositoryFun-1SHIY9NWSSH8B:live /dev/null { "StatusCode": 200, "ExecutedVersion": "1" }
リポジトリが登録されたか確認してみます。 my-repo
というリポジトリが登録されています。
GET _cat/repositories?v id type cs-automated s3 my-repo s3
バックアップ取ってみる
この時点ではリポジトリ登録しただけなのでスナップショットはありません。以下のAPI叩いてもスナップショット表示されないはずです。
GET _cat/snapshots/my-repo
スナップショットを取得するため deploy.sh
でもう一つメッセージが表示されると思います。
2. スナップショットを手動で取得するには、以下のコマンドを実行します. なお、こちらのLambdaはスケジュール実行も設定されています. aws lambda invoke --function-name aes-snapshot-sample-AESRotateSnapshotFunction-1GB4JKXMNZ8KQ:live /dev/null
こちらで表示されているコマンドを実行するとバックアップが取得できます。
$ aws lambda invoke --function-name aes-snapshot-sample-AESRotateSnapshotFunction-1GB4JKXMNZ8KQ:live /dev/null { "StatusCode": 200, "ExecutedVersion": "1" }
GET _cat/snapshots/my-repo?v id status start_epoch start_time end_epoch end_time duration indices successful_shards failed_shards total_shards my-snapshot-2019-11-13-12-35 SUCCESS 1573647456 12:17:36 1573647456 12:17:36 459ms 1 1 0 1
S3にもスナップショットのデータ入ったこと確認できます。
なお、バックアップの方はCloudWatch Eventで時間起動するように設定されていますので、上記のようにコマンド実行しなくても1日一回動きます。
template.yaml
の以下の部分でスケジュール調整できます。スケジュール以外もスクリプトはありもの持ってきただけなので調整して使ってください。
Events: Rule: Type: Schedule Properties: Schedule: cron(5 16 * * ? *)
やっていること
やっていることは deploy.sh
の中身見てもらえばわかると思います。
elasticsearchやCuratorはDockerでダウンロード、ビルドしてLambda Layerとしてアップロードしています。
#!/bin/bash # 設定ファイルの読み込み source ./settings.sh # Lambda Layerとして必要なPythonライブラリをダウンロード docker run --rm -v $(pwd)/layer/python:/python python:3.7.5-alpine pip install -t /python requests-aws4auth elasticsearch elasticsearch-curator # Cloudformation でデプロイ aws cloudformation package --template-file ./template.yaml --output-template-file ./package.yaml \ --s3-bucket ${STACK_S3_BUCKET} \ --s3-prefix ${STACK_S3_PREFIX} aws cloudformation deploy --template-file ./package.yaml --capabilities CAPABILITY_IAM \ --stack-name ${STACK_NAME} \ --parameter-overrides \ AESHost=${AES_HOST} \ LambdaSubnetId=${LAMBDA_SUBNET_ID} \ LambdaSecurityGroupId=${LAMBDA_SECURITY_GROUP_ID} \ SnapshotRepositoryName=${SNAPSHOT_REPOSITORY_NAME} \ SnapshotPrefix=${SNAPSHOT_PREFIX} # メッセージ表示 echo "" echo "1. 最初に一回、以下のコマンドを実行します." echo aws lambda invoke --function-name $(aws cloudformation describe-stacks --stack-name ${STACK_NAME} --query 'Stacks[].Outputs[?OutputKey == `RegistSnapshotFunctionName`].OutputValue' --output text):live /dev/null echo "" echo "2. スナップショットを手動で取得するには、以下のコマンドを実行します." echo " なお、こちらのLambdaはスケジュール実行も設定されています." echo aws lambda invoke --function-name $(aws cloudformation describe-stacks --stack-name ${STACK_NAME} --query 'Stacks[].Outputs[?OutputKey == `RotateSnapshotFunctionName`].OutputValue' --output text):live /dev/null echo ""
スナップショットの復元
同じようにスナップショットが保管されているS3をリポジトリとして登録すれば、後は以下のリンクの手順で簡単にリストアできます。
参考
[Tipsメモ] Kibanaのインデックス以外をリストアする
よくあるのが、Kibana以外をリストアしたい場合。以下のように実行するとKibana以外のインデックスをリストアできます。indicesのパラメータ変更すれば特定のindexのみリストアしたり色々できます。
POST _snapshot/リポジトリ名/スナップショット名/_restore {"indices": "*,-.kibana_1"}
Snapshot And Restore | Elasticsearch Reference [7.4] | Elastic
Amazon Elasticsearch Service インデックススナップショットの使用 - Amazon Elasticsearch Service