Help us understand the problem. What is going on with this article?

Elastic Beanstalkのインスタンスやボリュームのタグをデプロイ時に更新

なぜ

  • .ebextensionsで環境プロパティからインスタンスやボリュームにカスタムタグを追加している。管理ルールが変わりタグ更新が必要になったため、何気なく更新したらデプロイに失敗した。目的の環境プロパティをタグ以外の処で参照していた。
  • シンプルに.ebextensionsを修正する何のことでもないことだが、保守担当に説明すると承認が必要のこと。これは時間がかかりそうだ。

遠回り

改善策でサーバ構成もプログラムも遠回りしてはいけない。根本原因をつぶすのがベストだ。しかし、
承認とリリースまで1~2ヵ月はかかりそうなことと、以前からLambdaのイベントトリガーを試してみたかったことがあり今回は遠回りをする。

無題.png

Lambda

  • LambdaのRoleは事前登録しておく
Python3.8
import json
import boto3

def lambda_handler(event, context):
    evt = str(event)
    print(evt) #json parseできない文字列が飛んでくるため

    # eb-app, new-tag, old-tag //環境変数の利用をお勧め
    apps = [
        ["app1", "newapp1", "oldapp1"],
        ["app2", "newapp2", "oldapp2"],
        ["app3", "newapp3", "oldapp3"],
        ...
        ...
    ]
    newTag = ''
    oldTag = ''
    client = boto3.resource('ec2', region_name='ap-northeast-1')

    if evt.find('EbUpdateEnvironmentCron') > 0:
        #from cloudwatch cron EBインスタンスはすべてチェックしたい時
        #EbUpdateEnvironmentCron: イベント名

        for app in apps:
            newTag = app[1]
            oldTag = app[2]

            update_ec2tag(client, oldTag, newTag)

    else:
        #from cloudtail event
        #更新されたEB環境に絞る        

        for app in apps:
            if evt.find(app[0]) > -1:
                newTag = app[1]
                oldTag = app[2]
                break

        if len(newTag) > 1:
            update_ec2tag(client, oldTag, newTag)
        else:
            print('target not ')

    return {
        'statusCode': 200,
        'body': json.dumps('OK')
    }


#ec2タグ更新
def update_ec2tag(client, oldTag, newTag):
    print(str(newTag))

    newTags = [{'Key': 'Project', 'Value': newTag}]

    instances = client.instances.filter(
        Filters = [{'Name': 'tag:Project', 'Values': [oldTag]}]
    )

    for instance in instances:
        hasTag = 0
        for tag in instance.tags:
            if tag['Key'] == 'Project': #調整対象タグ
                hasTag += 1
            elif tag['Key'] == 'elasticbeanstalk:environment-id': #Elastic Beanstalkのインスタンのみにしたい
                hasTag += 1

        if hasTag == 2:
            client.create_tags(
                Resources=[instance.instance_id],
                Tags=newTags
            )

            #print(instance.instance_id)
            update_voltag(instance, newTags)

#volumeタグ更新
def update_voltag(instance, ptags):
    instId = instance.instance_id
    print(instId)

    for vol in instance.volumes.all():
        print('Updating tags for {}'.format(vol.id))
        vol.create_tags(Tags=ptags)

CloudWatch Events Rule

  • 名前: EbUpdateEnvironment -> Lambdaのトリガーに追加
  • イベントパターン
{
  "source": [
    "aws.elasticbeanstalk"
  ],
  "detail-type": [
    "AWS API Call via CloudTrail"
  ],
  "detail": {
    "eventSource": [
      "elasticbeanstalk.amazonaws.com"
    ],
    "eventName": [
      "UpdateEnvironment"
    ]
  }
}

おまけ

イベントトリガーをSQSにすると

def lambda_handler(event, context):
    for record in event['Records']:
        pval = record["body"] #ここにElastic Beanstalkのアプリ名
        print(str(pval))

イベント発行
例え、zabbixで環境更新を検知したとしてアクションで設定
Elastic Beanstalkのデプロイ -> zabbixでアイテムで更新検知&アクション(SQSキュー生成) -> Lambda実行
zabbixアイテム例:https://qiita.com/mkawanee/items/66fb507ab9bd53638f58

/usr/bin/aws sqs send-message --queue-url https://sqs.ap-northeast-1.amazonaws.com/12345678/infra-modify-tag \
--region ap-northeast-1 --profile awsX --message-body {EVENT.NAME}

参照

追記

CloudWatch EventでEBの環境名を拾って判断しているが、APIからはEnvironmentIdを使うため、環境名が入らない。EnvironmentNameをパラメータに追加すると、「'errorCode': 'InvalidParameterValueException'」になる。
とにかくログに環境名があればよいのでDescriptionに入れてみたらOK!

C#
var req = new UpdateEnvironmentRequest
{
    EnvironmentId = "e-xxxxxx",
    Description = "env-name-xxx",
    OptionSettings = {options}
};
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした