IaaS/퍼블릭클라우드

(AWS) CloudFormation UserData, cfn-init, cfn-signal 에 대해

armyost 2022. 1. 19. 16:47
728x90

UserData 란?

  • AWS 콘솔을 통해 User Data를 EC2 시작시에 적용할 수 있다. 
  • 또한 CF를 통해 포함시켜 적용할 수 있다. 
  • 중요한것은 모든 Script는 Fn::Base64를 통해서 통과한다는 것이다.
  • UserData는 /var/log/cloud-init-output.log에 로깅된다


사용법

Resources:
  MyInstances:
    Properties:
      AvailabilityZone: us-east-1a
      UserData:
        Fn::Base64: |
          #!/bin/bash -xe
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd
          echo "Hello world! from user data" ? /var/www/html/index.html

 

cfn-init 이란?

AWS::CloudFormation::Init 은 Resource의 메타데이터이다.

cfn-init 스크립트를 통해 EC2 환경설정이 가독성이 향상된다.

/var/log/cfn-init.log에 로깅한다.

 

Userdata는 CLI가 나열되어 있는 반면에 cfn-init은 메타데이터의 조합으로 이루어져 있다. 각자 장단점이 있으며 잘 조합해서 써야한다.

 

사용법은 다음과 같다.

cfn-init --stack|-s stack.name.or.id \
         --resource|-r logical.resource.id \
         --region region \
         --access-key access.key \
         --secret-key secret.key \
         --role rolename \
         --credential-file|-f credential.file \
         --configsets|-c config.sets \
         --url|-u service.url \
         --http-proxy HTTP.proxy \
         --https-proxy HTTPS.proxy \
         --verbose|-v

 

 

cfn-signal 이란?

cfn-init을 통해서 적절하게 환경설정이 되었는지 CF에 알리기 위해 cfn-signal 스크립트를 사용할 수 있다.그리고 WaitCondition을 통해 cfn-signal에서 cfn-signal이 올때까지 CF Template진행을 막을 수 있다. 

 

사용법은 다음과 같다.

cfn-signal --success|-s signal.to.send \
        --access-key access.key \
        --credential-file|-f credential.file \
        --exit-code|-e exit.code \
        --http-proxy HTTP.proxy \
        --https-proxy HTTPS.proxy \
        --id|-i unique.id \
        --region AWS.region \
        --resource resource.logical.ID \
        --role IAM.role.name \
        --secret-key secret.key \
        --stack stack.name.or.stack.ID \
        --url AWS CloudFormation.endpoint

 

 

최종적적으로 다음과 같은 YAML이 생성된다.



Resources:
  MyInstance:
    Properties:
      UserData:
        Fn::Base64:
          !Sub |
            #!/bin/bash -xe
            # Get the latest CloudFormation package
            yum update -y aws-cfn-bootstrap
            # Start cfn-init
            /opt/aws/bin/cfn-init -s $(AWS::StackId) -r MyInstance --region $(AWS::Region) ||
            error_exit 'Faild to run cfn-init'
            # Start cfn-signal to the wait condition
            /opt/aws/bin/cfn-signal -e $? --stack $(AWS::StackId) --resource SampleWaitCondition --region ${AWS::Region}
    MetaData:
      Comment: Install a simple Apache HTTP page
      AWS::CloudFormation::Init:
        config:
          packages:
            yum:
              httpd: []
            files:
              "/var/www/html/index.html";
                content: |
                  <h1>Hello World From EC2 instance!</h1>
                  <p>This was created using cfn-init</p>
                mode: '000644'
              commands:
                hello:
                  command: "echo 'hello world'"
              Services:
                sysvinit:
                  httpd:
                    enabled: 'true'
                    ensureRunning: 'true'

    SampleWaitCondition:
      CreationPolicy:
        ResourceSignal:
          Timeout: PT2M
          Count: 1
      Type: AWS::CloudFormation::WaitCondition

 

CF와 EC2 간의 통신은 다음과 같은 순서로 이루어진다. 

cfn 구조를 사용할때 주의사항

  • 사용하려는 AMI가 AWS CloudFormation helper 스크립트가 설치된 것인지 확인하라. 만약 AMI가 helper 스크립트가 없다면 다운로드 해야한다.
  • cfn-init과 cfn-signal 커맨드가 성공적으로 돌아가는지 검증하라. /var/log/cloud-init.log, /var/log/cfn-init.log를 참고하기 바란다.(혹시 CF가 생성중에 Fail되어 FailBack될 수 있으니 rollback on failure 모드를 비활성화하라)
  • 인스턴스가 NAT게이트웨이 등을 통해 인터넷구간에 접촉해있어야 한다.