LoginSignup
0
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-01-20

なぜ

  • .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}
};
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0