[AWS] EC2 태깅 Lambda를 ServerlessFramework로 구현했습니다.

TL;DR


  • 유효성 검사 환경과 같은 여러 구성원이 사용하는 경우 관리자 알 수없는 리소스가 발생할 수 있습니다.
  • Lambda에서 EC2를 시작할 때 태그를 지정하는 솔루션이 일반적이라고 생각하지만,
    복수의 환경/리전이 있으면 매번 등록하는 것도 번거롭다.
  • ServerlessFramework를 사용하여 누구나 쉽게 구현할 수 있습니다.

  • ※본고에서는 ServerlessFramework의 도입 순서는 접하고 있지 않기 때문에
    도입 방법은 공식 문서를 참조하십시오.

    1. Lambda 함수 준비


  • 시작자 정보를 태그하는 Lambda 함수 파일(코드는 아래에 설명되어 있음)을 준비합니다.
  • 이번은 IAM 유저와 AssumeRole 하고 있는 유저에게 대응시키고 있습니다.

  • handler.py
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    import boto3
    import logging
    import os
    
    # set the simple logging
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    region = os.environ['AWS_REGION']
    account = os.environ['AWS_ACCOUNT']
    
    
    def ec2_tagging(event, context):
        logger.info(event)
    
    # Requestor Check
        userType = event['detail']['userIdentity']['type']
        if userType == 'IAMUser':
            Owner = event['detail']['userIdentity']['userName']
        elif userType == 'AssumedRole':
            roleID = event['detail']['userIdentity']['sessionContext']['sessionIssuer']['userName']
            Owner = (event['detail']['userIdentity']['arn'].replace("arn:aws:sts::" + str(account) + ":assumed-role/"+str(roleID)+"/", ""))
        logger.info("Owner: " + Owner)
    
    # Target Resource Check
        instanceIDs = event['detail']['responseElements']['instancesSet']['items']
        logger.info(instanceIDs)
        instance_count = len(instanceIDs)
        try:
            for i in range(0, instance_count):
                instanceID = instanceIDs[i]['instanceId']
                logger.info("target: " + str(instanceID))
                ec2 = boto3.client('ec2')
                r = ec2.create_tags(
                    Resources=[instanceID],
                    Tags=[
                       {
                            'Key': 'Owner',
                            'Value': Owner
                        },
                    ]
                )
        except Exception as e:
            logger.error("error: " + str(e))
    

    2. Lambda 실행을 위한 IAM Role 생성


  • Lambda 실행에 필요한 다음 권한을 가진 IAM 역할을 준비합니다.
  • CloudwachLog에 로그 쓰기 권한
  • EC2에 태그를 부여 할 수있는 권한

  •   {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Action": [
                      "logs:CreateLogStream",
                      "logs:PutLogEvents"
                  ],
                  "Resource": [
                      "arn:aws:logs:*"
                  ],
                  "Effect": "Allow"
              },
              {
                  "Action": [
                      "ec2:CreateTags"
                  ],
                  "Resource": [
                      "*"
                  ],
                  "Effect": "Allow"
              }
          ]
      }
    

    3. serverless.yml 만들기


  • serverless.yml에서 Lambda 함수 설정을 정의합니다.
  • Lambda 함수 파일이 있는 디렉토리에 serverless.yml(내용은 후술)을 배치합니다.
  • 환경에 따라 수정이 필요한 매개 변수는 custom 블록에 정리되었으므로,
    AWS AccountID, 리전, 2단계에서 생성한 IAM 역할 이름 등을 수정합니다.

  • serverless.yml
    service: ${self:custom.service}
    
    provider:
      name: aws
      runtime: python3.6
      stage: ${opt:stage, self:custom.defaultStage}
      region: ${opt:region, self:custom.defaultRegion}
      memorySize: 128
      timeout: 60
      role: arn:aws:iam::${self:custom.account}:role/${self:custom.iam}
      environment:
        AWS_ACCOUNT: ${self:custom.account}
    
    custom:
      account: hoge        ## AWS AccountIDを入力してください。
      defaultStage: dev
      defaultRegion: fuga  ## Regionを入力してください。(e.g.ap-northeast-1)
      description: EC2 Auto Tagging Function
      service: Ec2AutoTag
      iam: piyo            ## Lambdaを実行するIAM Role名を入力してください。
    
    functions:
      Ec2AutoTag:
        name: ${self:custom.service}
        handler: handler.ec2_tagging
        description: ${self:custom.description}
        events:
          - cloudwatchEvent:
              event:
                source:
                  - "aws.ec2"
                detail-type:
                  - "AWS API Call via CloudTrail"
                detail:
                  eventSource:
                    - "ec2.amazonaws.com"
                  eventName:
                    - "RunInstances"
    

    4. deploy



    Lambda 함수 파일이 있는 디렉토리에서 배포 명령sls deploy을 실행하기만 하면 됩니다.
    $ ls -l
    total 8
    -rw-rw-r-- 1 ubuntu ubuntu 1453 Aug 29 02:56 handler.py
    -rw-rw-r-- 1 ubuntu ubuntu 1012 Aug 29 03:00 serverless.yml
    $
    $ sls deploy
    Serverless: Packaging service...
    Serverless: Excluding development dependencies...
    Serverless: Creating Stack...
    Serverless: Checking Stack create progress...
    .....
    Serverless: Stack create finished...
    Serverless: Uploading CloudFormation file to S3...
    Serverless: Uploading artifacts...
    Serverless: Uploading service .zip file to S3 (774 B)...
    Serverless: Validating template...
    Serverless: Updating Stack...
    Serverless: Checking Stack update progress...
    ...................
    Serverless: Stack update finished...
    Service Information
    service: Ec2AutoTag
    stage: dev
    region: ap-northeast-1
    stack: Ec2AutoTag-dev
    api keys:
      None
    endpoints:
      None
    functions:
      Ec2AutoTag: Ec2AutoTag-dev-Ec2AutoTag
    

    5. 확인



    인스턴스를 시작해 보면 시작자의 사용자 이름이 부여되는지 확인할 수 있었습니다.


    6. 마지막으로


  • ServerlessFramework에서 Lambda 등록을 쉽게 할 수 있습니다.
  • StackSet을 지원하면 멀티 리전에 한 번에 배포 할 수 있으며,
    보다 편리하게 사용할 수 있을 것 같다. (앞으로 조사 )

  • 참고


  • Serverless Framework Document
  • Serverless Framework Github
  • Serverless Framework 사용법 요약
  • 좋은 웹페이지 즐겨찾기