Closed7
定期的に全てのEC2インスタンスをオフにするLambdaを書く
現在isuconの練習をしていて、うっかりEC2インスタンスを上げっぱなしにしてしまうのを防ぎたい。
ちゃんと練習環境を作ろうとするとlargeとかxlargeのインスタンスを3つみたいな感じになる。これらを長時間起動し続けると(個人の勉強代としては)洒落にならない課金になってしまう。
まず手元にCDK環境を作る。
cdk initしよう|AWS CDK×LINE BOTハンズオン~アプリとインフラをコード管理しよう~
mkdir isucon-env-auto-stopper
cd isucon-env-auto-stopper
npx cdk init --language typescript
プロジェクト直下にLambda関数用のディレクトリとファイルを作成。
mkdir lambda-fns
touch lambda-fns/stop-ec2-instances.ts
業務で真面目にやるならCDKコードとLambdaアプリケーションコードはリポジトリを分けるか、npm workspacesを使ったモノレポ構成にするなどで別管理するが、今回は手早さを重視してCDKプロジェクトの下にLambdaコードを置いてしまう。
AWS SDK v3をインストールする。
npm i @aws-sdk/client-ec2
prettierを入れておく。
npm i -D prettier
configを作る。
touch .prettierrc.json
中身は以下。すべてデフォルト設定とする。
{}
CDKコード:
適当に、6時間置きにLambdaを実行するとした。
lib/isucon-env-auto-stopper-stack.ts
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
export class IsuconEnvAutoStopperStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const isuconEnvAutoStopperFn = new cdk.aws_lambda_nodejs.NodejsFunction(
this,
"isuconEnvAutoStopperFn",
{
entry: "lambda-fns/stop-ec2-instances.ts",
timeout: cdk.Duration.seconds(30),
},
);
isuconEnvAutoStopperFn.addToRolePolicy(
new cdk.aws_iam.PolicyStatement({
effect: cdk.aws_iam.Effect.ALLOW,
actions: ["ec2:DescribeInstances", "ec2:StopInstances"],
resources: ["*"],
}),
);
new cdk.aws_events.Rule(this, "isuconEnvAutoStopperRule", {
schedule: cdk.aws_events.Schedule.rate(cdk.Duration.hours(6)),
targets: [
new cdk.aws_events_targets.LambdaFunction(isuconEnvAutoStopperFn),
],
});
}
}
Lambdaコード:
lambda-fns/stop-ec2-instances.ts
import {
DescribeInstancesCommand,
EC2Client,
StopInstancesCommand,
} from "@aws-sdk/client-ec2";
const ec2Client = new EC2Client();
export const handler = async () => {
const describeOutput = await ec2Client.send(
new DescribeInstancesCommand({
Filters: [{ Name: "instance-state-name", Values: ["running"] }],
}),
);
const instances = describeOutput.Reservations?.map(
({ Instances }) => Instances,
).flat();
const instanceIds = instances?.map((instance) => instance?.InstanceId);
if (instanceIds == null) {
throw new Error("instanceIdsがundefinedです");
}
const instanceIdsWithoutUndefined = instanceIds.filter<string>(
(instanceId): instanceId is string => instanceId != null,
);
await ec2Client.send(
new StopInstancesCommand({
InstanceIds: instanceIdsWithoutUndefined,
}),
);
};
esbuildを入れておく。
npm i -D esbuild
デプロイ:
npx cdk deploy
以上。これでぐっすり寝れそう。
このスクラップは2023/08/28にクローズされました