デプロイと同時にEC2インスタンスを起動する

早朝に軽くジョギングして体温を上げているものの、日中は冷房の効いた部屋にいるので身体が冷えて仕方ありません。自律神経がぶっ壊れるわ、夏はつらい。

必要なときだけ使う

クラウドサービスは「使わない時は停止する」というのが一般的です。
使った分だけコストが発生する、従量課金の良いところですね。
しかし、毎回起動するのは非常に億劫ですし、そんなことを気にしながら作業はしたくないものです。

EC2を起動したい時とは

EC2も同様で、テスト環境等は必要なときだけ起動したいものです。
自動化するために、まず「EC2を起動したい時とは」から考えました。
いろいろあるけど、デプロイのときが一番多いのかなぁ。
というか起動していないとデプロイすらできないし。

そんなこんなで、デプロイ時にEC2を起動する、を目指してみたという話です。

構成図

f:id:tydk27:20200807115120p:plain

CloudWatch EventsCodePipelineの状態変更を検知します。
イベントは以下のような形式で飛んでくるので、detail以下を読み取れば良さそう。

{
    "version": "0",
    "id": "1",
    "detail-type": "CodePipeline Pipeline Execution State Change",
    "source": "aws.codepipeline",
    "account":"123456789012",
    "time":"2020-01-01T00:00:00Z",
    "region": "us-east-1",
    "resources": [
        "arn:aws:codepipeline:us-east-1:123456789012:hoge-pipe"
    ],
    "detail": {
        "pipeline": "hoge-pipe",
        "version": "1",
        "state": "STARTED",
        "execution-id": "1"
    }
}

詳しくは公式ドキュメントに書いてありますので、こちらもどうぞ。

docs.aws.amazon.com

ただ、これだとデプロイ対象のインスタンスがわからない(CodeDeployのEventsで取れたらなぁ)
仕方ないので、パイプライン名とインスタンスIDを紐付けた情報をLambda側で持つことにしてみました。

リポジトリ

github.com

Pythonです。AWS SAMを利用しました。

コードの中身ですが、

やっていることはこれだけ。

response = boto3.client('ec2').describe_instance_status(
    InstanceIds=instances,
    IncludeAllInstances=True
)

target = []
for instance in response['InstanceStatuses']:
    state_code = instance['InstanceState']['Code']
    if state_code != 80:  # not stopped
        continue

    target.append(instance['InstanceId'])

boto3.client('ec2').start_instances(
    InstanceIds=target
)

使い方

$ git clone git@github.com:tydk27/ageage-ec2.git && cd ageage-ec2
$ vim src/instances.json # パイプライン名とインスタンスIDを直書き
$ sam deploy -g

パイプライン名とインスタンスIDの紐付けは、DynamoDBとかを使うのもありですよね。
最初は直書きでも良いと思うけど、後々地獄を見ることになりそうですし。
というか他に何か方法はないのかなぁ、絶賛模索中。

まとめ

思いついた時にさっと実装できるのが、クラウドの良さですよね。
そういうところをもっと布教していきたい(主に社内に)