2023年11月にAmazon Data Lifecycle Managerにプレスクリプト、ポストスクリプトの機能が追加されましたので試してみました。
Amazon Data Lifecycle Managerとは
AMIやEBSスナップショットの取得を自動化及び管理してくれる機能です。(以下DLMと記載)
DLMでのEBSスナップショット取得前後に任意の処理を実行したい場合にプレスクリプト、ポストスクリプトの機能を使用して実現できます。
DLMによるAMI取得ではプレスクリプト、ポストスクリプトの機能は使用できないので御注意下さい。
今回の検証の処理の流れ
検証では以下の処理が実行されるように実装します。
①DLMのプレスクリプトでOS内のアプリケーション(apache)を停止
②DLMによってEBSスナップショットを取得
③DLMのポストスクリプトでOS内のアプリケーション(apache)を起動
設定
設定手順を記載します。
EC2の起動とapacheのインストール
EC2のOSにはAmazonLinux2023を選択しました。
EC2起動後にOSにログインして以下のコマンドでapacheをインストールします。
yum -y install httpd
インストール後、apacheを起動させます。
systemctl start httpd
httpdのプロセスが起動していることを確認します。
[root@http-server ~]# ps -ef | grep httpd | grep -v grep
root 1467 1 0 14:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 1477 1467 0 14:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 1478 1467 0 14:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 1490 1467 0 14:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
apache 1507 1467 0 14:24 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
SSM AgentのインストールとEC2へのIAMロールの設定
DLMのプレスクリプト、ポストスクリプト機能を使用するにはSSM Agentが必要となります。
今回OSに選択したAmazonLinux2023では最初からSSM Agentが導入されていますが、SSM Agentが未導入のOSの場合は新規にインストールをして下さい。
また、AWS Systems Managerのエンドポイントへアクセスするためにインターネット経由又はVPCエンドポイントでの接続経路を確保する必要があることと、エンドポイントへのアクセス権限を付与するためIAMロールをEC2に設定します。
SSMドキュメントの作成
apacheを起動停止するためのSSMドキュメントを作成します。
AWSコンソールでSystems Managerを選択して左メニューの「ドキュメント」を選択します。
右側の「ドキュメントの作成」で「コマンドまたはセッション」を選択します。
ドキュメントの詳細で、以下を設定します。
名前:任意の名前を設定
ターゲットタイプ:/AWS::EC2::Instance を選択
ドキュメントタイプ:Command を設定
以下のコードを設定します。
---
schemaVersion: '2.2'
description: SSM Document Template for Amazon Data Lifecycle Manager Pre/Post script feature
parameters:
executionId:
type: String
default: None
description: (Required) Specifies the unique identifier associated with a pre and/or post execution
allowedPattern: ^(None|[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})$
command:
# Data Lifecycle Manager will trigger the pre-script and post-script actions during policy execution.
# 'dry-run' option is intended for validating the document execution without triggering any commands
# on the instance. The following allowedValues will allow Data Lifecycle Manager to successfully
# trigger pre and post script actions.
type: String
default: 'dry-run'
description: (Required) Specifies whether pre-script and/or post-script should be executed.
allowedValues:
- pre-script
- post-script
- dry-run
mainSteps:
- action: aws:runShellScript
description: Run Database freeze/thaw commands
name: run_pre_post_scripts
precondition:
StringEquals:
- platformType
- Linux
inputs:
runCommand:
- |
#!/bin/bash
###===============================================================================###
### Global variables
###===============================================================================###
START=$(date +%s)
# For testing this script locally, replace the below with OPERATION=$1.
OPERATION={{ command }}
# Add all pre-script actions to be performed within the function below
execute_pre_script() {
echo "INFO: Start execution of pre-script. httpd stop."
# httpd stop
systemctl stop httpd
# httpd stop check
HTTPD_COUNT=`ps -ef | grep httpd | grep -v grep | wc -l`
if [ ${HTTPD_COUNT} != 0 ]; then
echo "ERROR: httpd is not stopped."
exit 201
fi
}
# Add all post-script actions to be performed within the function below
execute_post_script() {
echo "INFO: Start execution of post-script. httpd start"
# httpd start
systemctl start httpd
# httpd start check
HTTPD_COUNT=`ps -ef | grep httpd | grep -v grep | wc -l`
if [ ${HTTPD_COUNT} = 0 ]; then
echo "ERROR: httpd is not started."
exit 202
fi
}
# Debug logging for parameters passed to the SSM document
echo "INFO: ${OPERATION} starting at $(date) with executionId: ${EXECUTION_ID}"
# Based on the command parameter value execute the function that supports
# pre-script/post-script operation
case ${OPERATION} in
pre-script)
execute_pre_script
;;
post-script)
execute_post_script
;;
dry-run)
echo "INFO: dry-run option invoked - taking no action"
;;
*)
echo "ERROR: Invalid command parameter passed. Please use either pre-script, post-script, dry-run."
exit 1 # return failure
;;
esac
END=$(date +%s)
# Debug Log for profiling the script time
echo "INFO: ${OPERATION} completed at $(date). Total runtime: $((${END} - ${START})) seconds."
ドキュメントのサンプルコードはAWS公式マニュアルにも記載があります。
DLMの設定
AWSコンソールでEC2を選択して左メニューの「ライフサイクルマネージャー」を選択します。
「カスタムポリシー」及び「EBSスナップショットポリシー」を選択します。ここで「EBS-backed AMIポリシー」を選択すると後続でプレスクリプト、ポストスクリプトが設定できません。
ターゲットリソースタイプで「インスタンス」を選択します。ここで「ボリューム」を選択すると後続でプレスクリプト、ポストスクリプトが設定できません。
説明で任意のポリシー名を入力します。
DLMに設定するIAMロールは公式サイトを御確認下さい。
ポリシーのステータスで設定完了後にこのDLMのポリシーをすぐに有効にするか無効にしておくかを選択できます。
ボリュームを除外でEBSスナップショットの対象から除外するボリュームを選択することもできます。
スケジュールの詳細でEBSスナップショットの取得頻度や実行時間、世代管理を設定します。
初回の実行は設定した開始時刻から1時間以内に実行される仕様なので御注意下さい。また、ここで設定する開始時刻はUTCである点にも注意が必要です。
EBSスナップショットに設定するタグを必要に応じて設定します。
ここでようやくプレスクリプト、ポストスクリプトの設定が出てきました。
この画面のように先ほど作成したSSMドキュメントを指定してスクリプトのタイムアウト値やスクリプト失敗時の再試行などを設定します。
その他のオプションで、EBSスナップショットに対して高速スナップショットを有効化したり別リージョンへのコピー、別AWSアカウントへの共有を自動化するかも選択できます。
DLM実行結果の確認
DLMで取得されたEBSスナップショットのタグを確認してみます。
aws:dlm:pre-scriptとaws:dlm:post-scriptのValueがSUCCESSになっています。
これはプレスクリプトとポストスクリプトが正常に実行されたことを示す結果です。
OS内のログでもapacheが停止起動されたことを確認しました。
[Sun Dec 10 16:51:06.180966 2023] [mpm_event:notice] [pid 1467:tid 1467] AH00492: caught SIGWINCH, shutting down gracefully ※apacheが停止したログ
[Sun Dec 10 16:51:09.212254 2023] [suexec:notice] [pid 8228:tid 8228] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Sun Dec 10 16:51:09.230848 2023] [lbmethod_heartbeat:notice] [pid 8228:tid 8228] AH02282: No slotmem from mod_heartmonitor
[Sun Dec 10 16:51:09.236298 2023] [mpm_event:notice] [pid 8228:tid 8228] AH00489: Apache/2.4.58 (Amazon Linux) configured -- resuming normal operations
[Sun Dec 10 16:51:09.236354 2023] [core:notice] [pid 8228:tid 8228] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND' ※apacheが起動したログ
まとめ
以上がDLMのプレスクリプト、ポストスクリプト実装の流れとなります。
EBSスナップショット取得前にEC2上のアプリケーションやデータベースに対して静止点を設ける場合、これまではOSのタスクスケジューラやcronでスクリプトを実行したりすることもありましたが、この機能を使用することによってDLM単体で静止点確保とスナップショット取得が完結できるようになりました。
DLMの進化に今後も期待したいと思います。