運用手順書を作っていると、たまにこうなりませんか。
「この画面を開いて、このボタンを押して、この値をコピペして、この画面に戻って……」
しかも頑張ってスクショを貼っても、数か月後にはAWSマネジメントコンソールのUIが変わっていて、手順書が静かに死んでいる。辛いです。
そこで今回は、運用手順をできるだけ 「AWS CLIで完結させつつ、CLI実行に必要なARNやIDはCDKからSSM Parameter Storeに流しておくというやり方を書きます。
技術的には地味です。でも、手順書運用はだいぶラクになります。
まず、GUIベースの運用手順書は辛い
GUI ベースの手順書がしんどい理由は、だいたいこのへんです。
- スクリーンショットの更新コストが高い
- コンソールUIの変更に弱い
- プロジェクト間で使い回ししにくい
- 手作業が増えてヒューマンエラーが起きやすい
- 自動化へ育てにくい
要するに、「今は読めるけど、来年にはメンテ不能になりがち」です。
ほな全部CLIでやればええやんけ
そう思ってAWS CLIに寄せていくと、かなり快適になります。
- 手順書がテキストで済む(Git管理しやすい)
- 差分管理しやすい
- コピペで実行しやすい
ここまではいい話です。
でも、CLI化すると別の地獄が始まる
例えばVPC Endpoint Serviceの承認をCLIでやりたいとします。
その瞬間、
- VPC Endpoint Service ID
- VPC Endpoint ID
あたりが必要になります。
実行コマンド自体は、最後だけ見るとそこまで難しくありません。
aws ec2 accept-vpc-endpoint-connections \
--service-id vpce-svc-0123456789abcdef0 \
--vpc-endpoint-ids vpce-0123456789abcdef0
問題は、その service-id と vpc-endpoint-id をどう取るかです。
例えば、まずサービス ID を調べて、
aws ec2 describe-vpc-endpoint-service-configurations \
--query 'ServiceConfigurations[*].[ServiceName,ServiceId]' \
--output table
次に pending な接続を調べて、
aws ec2 describe-vpc-endpoint-connections \
--filters Name=vpc-endpoint-state,Values=pendingAcceptance \
--query 'VpcEndpointConnections[*].[ServiceId,VpcEndpointId,VpcEndpointState]' \
--output table
ようやく本命の承認コマンドを打てます。
aws ec2 accept-vpc-endpoint-connections \
--service-id vpce-svc-0123456789abcdef0 \
--vpc-endpoint-ids vpce-0123456789abcdef0
これがBackup系の手順になると、少なくとも以下パラメータの取得が必要になります。
- バックアップ対象リソースARN
- Backup Vault ARN
- IAM Role ARN
- Recovery point ARN
つまり何が起きるかというと、
CLIを実行するために必要な値を取得するためのCLI
を先に実行し始めます。
これ、地味にきついです。その場では解決しても、気づくと手順書がこうなります。
- ID を取得するCLIを実行する
- 出力結果から値を探す
- その値を次のCLIに埋める
- また別の値が足りなくなる
CLI化したはずなのに、読みにくいし、間違えるし、結局あまりうれしくない。
スクリプトを作れば済む話ですが、下手に運用手順書をスクリプト化すると、
「メンテできないスクリプトが散乱する事態」不可避です。多分。
そこでCDKから「手順書用の値」を配る
ここで考えたのが
手順に必要なパラメータをCDKで SSM Parameter Store に出しておく
というやり方です。
イメージとしては、運用手順ごとにプレフィックスを決めます。
/ops/backup//ops/restore//ops/vpc-endpoint-approval/
そしてCDK側で、その手順に必要な値をその配下へ保存します。
import * as ssm from 'aws-cdk-lib/aws-ssm';
// 実際にはparameter.tsでプレフィックスを一元管理
const backupPrefix = '/manuals/backup/'
new ssm.StringParameter(this, 'BackupRoleArnParam', {
parameterName: '${backupPrefix}/role-arn/backup',
stringValue: roleBackup.roleArn,
});
new ssm.StringParameter(this, 'BackupVaultArnParam', {
parameterName: '${backupPrefix}/vault-arn',
stringValue: backupVault.backupVaultArn,
});
new ssm.StringParameter(this, 'BackupResourceArnParam', {
parameterName: '${backupPrefix}/target-resource-arn/s3/app',
stringValue: s3App.bucketArn,
});
ポイントは、「インフラを作る時点で分かっている値」はCDK側で配ってしまうことです。
手順書では最初にまとめて取得する
運用手順書側では、最初にそのプレフィックス配下のパラメータをまとめて取得します。
aws ssm get-parameters-by-path \
--path /ops/backup/ \
--recursive \
--query 'Parameters[*].[Name,Value]' \
--output table
こうしておくと、運用手順書は
- 必要なパラメータを取得する
- その値を使ってCLIを実行する
だけで済みます。
かなりスッキリする...かな?
何がうれしいのか
このやり方のうれしいところは、単にラクというだけではありません。
- 手順書にベタ書きのARNやIDを減らせる
- リソース名の変更に強くなる
- 環境ごとの差し替えがしやすい
- 手順書を別案件へ持っていきやすい
- 将来的にスクリプト化しやすい
特に大きいのは、手順書の責務 と 環境固有値の管理を分離できることです。
手順書は「どう操作するか」に集中し、環境固有のARNやIDはSSM側に寄せる。これだけでだいぶ見通しが良くなります。
もちろん、問題はある
万能ではありません。普通に課題はあります。
- SSMパラメータ名の設計をミスるとつらい
- CDK側に「どの値をどのプレフィックスへ出すか」という運用ルールが必要になる
- パラメータが増えると整理が必要になる
なので、何でもかんでもこれで解決ではないです。
ただ、少なくとも
GUI スクショ手順書を延命し続ける苦しみ
よりはかなり健全だと思っています。
まとめ
運用手順書を全部GUIベースで持つのは、更新コストも再利用性もかなり厳しいです。
そこで、
- 実行はAWS CLI
- 実行に必要な値はCDKからSSM Parameter Storeへ配布
という形にしておくと、手順書がかなりシンプルになります。
派手な仕組みではないですが、手順を複雑にせず、CLI化も両立する上では割といい落とし所かなと思います。
GUI手順書に苦しんでいる方がいれば、試す価値はある!(かも...)