Infrastructure as Code(IaC)는 인프라를 일관성 있고 반복 가능하게 관리해 오늘날 DevOps 환경에 널리 도입되고 있습니다. IaC를 사용해 인프라를 코드로 정의하면 변경 사항을 추적하고 롤백할 수 있고요. 환경을 쉽게 복제하며, 구성 오류도 줄일 수 있습니다. 이로써 인프라를 프로비저닝하고 관리하는 방식을 더 효율화할 수 있고요. 구성 드리프트, 운영자 실수, 정보 손실 등 문제도 해결할 수 있죠.

시중에는 Terraform, Pulumi, Nitric 등 다양한 IaC 도구가 있는데요. AWS의 CloudFormation(이하 CFN)도 유용한 IaC 도구입니다. CFN을 사용하면, 별도 상태 저장소를 설정하거나 유지할 필요가 없고요. AWS에서 CFN을 직접 개발했기에 AWS 서비스와 원활하게 통합할 수 있습니다. 또 DependsOn 속성을 사용해 명시적으로 의존성을 지정할 수 있고요.

업계를 둘러보면 AWS 클라우드에서 인프라를 관리하는 조직이 많은데요. 이러한 조직에서 CFN으로 IaC를 구축하면 위 장점을 누릴 수 있습니다. 이 글에서는 GitLab과 AWS의 CFN을 연동해 Lambda를 배포하는 방법을 알아보겠습니다.

AWS의 GitLab 접근 권한 설정

GitLab과 AWS의 CFN을 연동하려면, AWS에서 GitLab에 접근하도록 CodeConnections를 먼저 설정해야 합니다. 순서는 다음과 같습니다.

  1. 개발자 도구 > 설정 > 연결에서 연결 생성 버튼을 클릭합니다.

    AWS 개발자 도구 설정 화면 | 인포그랩 GitLab
    AWS 개발자 도구 설정 화면

  2. 연결 생성 > 공급자 선택에서 GitLab을 선택하고, GitLab 연결 생성에서 연결 이름을 입력합니다. 그다음, GitLab에 연결 버튼을 클릭하면 GitLab으로 리다이렉트됩니다.

    AWS 개발자 도구 연결 생성 화면 | 인포그랩 GitLab
    AWS 개발자 도구 연결 생성 화면

  3. 아래 화면이 뜨면 Authorize 버튼을 클릭합니다.

    AWS Connector for GitLab 권한 부여 관련 창 | 인포그랩 GitLab
    AWS Connector for GitLab 권한 부여 관련 창

  4. GitLab에 연결 > GitLab 연결 설정에서 연결 이름을 입력하고, 연결 버튼을 클릭합니다.

    AWS 개발자 도구에서 GitLab 연결을 설정하는 화면 | 인포그랩 GitLab
    AWS 개발자 도구에서 GitLab 연결을 설정하는 화면

  5. 연결 설정 > 상태사용 가능이라고 뜨면, AWS에서 GitLab에 접근할 수 있습니다.

    AWS에서 GitLab에 접근하도록 GitLab 연결 설정을 마무리한 결과 | 인포그랩 GitLab
    AWS에서 GitLab에 접근하도록 GitLab 연결 설정을 마무리한 결과

CFN 스택과 연동할 GitLab 프로젝트 생성

이어서 CFN 스택과 연동할 GitLab 프로젝트와 파일을 생성합니다. 순서는 다음과 같습니다.

  1. GitLab 프로젝트를 생성합니다.

    GitLab 프로젝트 생성 화면 | 인포그랩 GitLab
    GitLab 프로젝트 생성 화면

  2. 배포 파일(deploy.yaml)과 템플릿 파일(lambda.yaml)을 프로젝트에 추가합니다.

    • 배포 파일(또는 deployment file): CFN 스택을 관리하는 JSON 또는 YAML 형식의 파일입니다.

      ##예시 배포 파일
      template-file-path: lambda.yaml
      parameters: {}
      tags: {}
      • template-file-path : CFN 템플릿 파일을 지정합니다.
      • parameters : 스택의 리소스를 구성하는 키-값 페어를 포함합니다.
      • tags : 스택의 리소스를 식별하고 분류하는 데 사용합니다.
    • 템플릿 파일: CFN 스택을 구성할 AWS 리소스를 선언하는 JSON 또는 YAML 형식의 파일입니다.

      ##예시 템플릿 파일. Lambda를 생성합니다.
      AWSTemplateFormatVersion: '2010-09-09'
      Description: A CloudFormation template that creates a Lambda function.

      Resources:
      MyLambdaExecutionRole:
      Type: AWS::IAM::Role
      Properties:
      AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
      Principal:
      Service: [lambda.amazonaws.com]
      Action: ['sts:AssumeRole']
      Policies:
      - PolicyName: LambdaExecutionPolicy
      PolicyDocument:
      Version: '2012-10-17'
      Statement:
      - Effect: Allow
      Action:
      - logs:CreateLogGroup
      - logs:CreateLogStream
      - logs:PutLogEvents
      Resource: '*'

      MyLambdaFunction:
      Type: AWS::Lambda::Function
      Properties:
      Handler: index.handler
      Role: !GetAtt MyLambdaExecutionRole.Arn
      Code:
      ZipFile: |
      import json
      def handler(event, context):
      print("hello from Lambda")
      return {
      'statusCode': 200,
      'body': json.dumps('test')
      }
      Runtime: python3.8
      Timeout: 30


Git Sync IAM Role, 정책 생성

이제 CFN이 Git 리포지터리에서 스택을 업데이트할 수 있는 Git Sync IAM Role과 정책을 생성합니다. CFN 스택을 생성할 때, 자동으로 해당 Role을 생성하는 옵션이 있습니다. 그러나 자동으로 Role을 생성하면 ‘CodeConnections에 접근 권한이 없다’는 에러가 발생합니다. 따라서 Role을 수동으로 생성해야 합니다. Git Sync IAM Role과 정책 생성 순서는 다음과 같습니다.

  1. 이 페이지에 접속해 Role을 생성합니다. 신뢰할 수 있는 엔터티 선택에서 신뢰할 수 있는 엔터티 유형으로 사용자 지정 신뢰 정책을 선택합니다.

    AWS에서 Git Sync IAM Role을 생성하기 위해 신뢰할 수 있는 엔터티 유형을 선택하는 화면 | 인포그랩 GitLab
    AWS에서 Git Sync IAM Role을 생성하기 위해 신뢰할 수 있는 엔터티 유형을 선택하는 화면

    아래는 사용자 지정 신뢰 정책 예시입니다.

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "CfnGitSyncTrustPolicy",
    "Effect": "Allow",
    "Principal": {
    "Service": "cloudformation.sync.codeconnections.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
    }
    ]
    }
  2. 생성한 Role을 선택해 권한을 추가합니다. CFN-IaC-role > 권한 > 권한 추가에서 인라인 정책 생성을 선택합니다.

    AWS에서 생성한 Role의 권한을 추가하는 화면 | 인포그랩 GitLab
    AWS에서 생성한 Role의 권한을 추가하는 화면

  3. 권한 지정에서 JSON 편집기를 사용해 권한 설명문을 작성합니다.

    AWS에서 JSON 편집기로 권한 설명문을 작성하는 화면 | 인포그랩 GitLab
    AWS에서 JSON 편집기로 권한 설명문을 작성하는 화면

    아래는 권한 설명문 예시입니다.

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "SyncToCloudFormation",
    "Effect": "Allow",
    "Action": [
    "cloudformation:CreateChangeSet",
    "cloudformation:DeleteChangeSet",
    "cloudformation:DescribeChangeSet",
    "cloudformation:DescribeStackEvents",
    "cloudformation:DescribeStacks",
    "cloudformation:ExecuteChangeSet",
    "cloudformation:GetTemplate",
    "cloudformation:ListChangeSets",
    "cloudformation:ListStacks",
    "cloudformation:ValidateTemplate"
    ],
    "Resource": [
    "arn:aws:cloudformation:ap-northeast-2:373015672791:stack/*"
    ]
    },
    {
    "Sid": "PolicyForManagedRules",
    "Effect": "Allow",
    "Action": [
    "events:PutRule",
    "events:PutTargets"
    ],
    "Resource": "*",
    "Condition": {
    "StringEquals": {
    "events:ManagedBy": [
    "cloudformation.sync.codeconnections.amazonaws.com"
    ]
    }
    }
    },
    {
    "Sid": "PolicyForDescribingRule",
    "Effect": "Allow",
    "Action": "events:DescribeRule",
    "Resource": "*"
    }
    ]
    }

    JSON 설정에서 .Statement.Resource의 값인 arn:aws:cloudformation:ap-northeast-2:373015672791:stack/*은 사용자가 이용하는 리전에 따라 변경될 수 있습니다.

CFN IAM Role 생성

그다음, 스택에서 수행되는 모든 작업에 사용할 CFN IAM Role을 생성합니다. 앞서 생성한 Git Sync IAM Role은 CFN에서 Git Sync 하는 Role이고요. CFN IAM Role은 Git Sync 이후 CFN 내 스택을 AWS의 실제 리소스 작업(describe, create, update, delete 등)에 사용하는 Role입니다. CFN IAM Role 생성 순서는 다음과 같습니다.

  1. 이 페이지에 접속해 Role을 생성합니다. 신뢰할 수 있는 엔터티 선택에서 신뢰할 수 있는 엔터티 유형AWS 서비스를, 사용 사례CloudFormation을 각각 선택하고 다음 버튼을 클릭합니다.

    AWS에서 CFN IAM Role을 생성하기 위해 신뢰할 수 있는 엔터티 유형과 사용 사례를 선택하는 화면 | 인포그랩 GitLab
    AWS에서 CFN IAM Role을 생성하기 위해 신뢰할 수 있는 엔터티 유형과 사용 사례를 선택하는 화면

  2. 권한 추가 > 권한 정책에서 앞서 생성한 Role에 연결할 정책을 선택합니다.

    AWS에서 생성한 Role에 연결할 정책을 선택하는 화면 | 인포그랩 GitLab
    AWS에서 생성한 Role에 연결할 정책을 선택하는 화면

  3. 이름 지정, 검토 및 생성 > 역할 세부 정보에서 역할 이름설명을 각각 입력한 다음, Role을 생성합니다.

    AWS에서 Role의 역할 이름과 설명을 각각 입력하는 화면 | 인포그랩 GitLab
    AWS에서 Role의 역할 이름과 설명을 각각 입력하는 화면

CFN 스택 생성

이제 GitLab과 연동할 CFN 스택을 생성합니다. 순서는 다음과 같습니다.

  1. AWS CFN 페이지에 접속해 스택 생성 버튼을 클릭합니다.

    AWS에서 CFN 스택을 생성하는 화면 | 인포그랩 GitLab
    AWS에서 CFN 스택을 생성하는 화면

  2. 스택 생성 > 사전 조건 - 템플릿 준비에서 템플릿 준비기존 템플릿 선택을, 템플릿 지정에서 템플릿 소스Git에서 동기화하기 - 신규를 선택하고, 다음 버튼을 클릭합니다.

    AWS에서 CFN 스택을 생성할 때 템플릿 준비, 템플릿 소스를 지정하는 화면 | 인포그랩 GitLab
    AWS에서 CFN 스택을 생성할 때 템플릿 준비, 템플릿 소스를 지정하는 화면

  3. 생성할 스택의 세부 정보를 설정합니다. 스택 세부 정보 지정에서 아래 항목을 각각 입력 또는 선택하고, 다음 버튼을 클릭합니다.

    • 스택 이름: 스택 이름을 지정합니다.

    • 배포 파일 생성: 스택 배포 파일을 제공하는 방법을 선택합니다.

    • 템플릿 정의 리포지토리: Git 리포지터리와 동기화할 스택 템플릿의 리포지터리를 지정합니다.

    • 리포지토리 공급자 선택: 리포지터리 공급업체를 선택합니다.

    • 연결: 리포지터리와의 연결을 선택합니다. 기존 연결을 선택하거나 새 연결을 추가할 수 있습니다.

    • 리포지토리: 템플릿을 포함하는 Git 리포지터리를 선택합니다.

    • 브랜치: CFN이 템플릿을 동기화할 브랜치를 선택합니다.

    • 배포 파일 경로: 템플릿의 배포 파일 경로를 지정합니다.

    • 기존 IAM 역할: CFN이 Git 리포지터리에서 스택을 업데이트하는 데 필요한 IAM 역할입니다.

      AWS에서 CFN 스택 세부 정보를 설정하는 화면 | 인포그랩 GitLab
      AWS에서 CFN 스택 세부 정보를 설정하는 화면

  4. 스택에서 수행되는 모든 작업에 사용할 CFN의 IAM Role을 설정합니다. 스택 옵션 구성 > 권한 - 선택 사항 > IAM 역할에서 앞서 생성한 CFN IAM Role을 선택합니다.

    AWS에서 CFN의 IAM Role을 설정하는 화면 | 인포그랩 GitLab
    AWS에서 CFN의 IAM Role을 설정하는 화면

  5. 고급 옵션 > 다음 버튼을 누르고, 스택 생성 옵션 > 전송 버튼을 클릭해 스택 설정을 마무리합니다.

    AWS에서 CFN 스택 설정을 마무리하는 화면-1 | 인포그랩 GitLab
    AWS에서 CFN 스택 설정을 마무리하는 화면-1

    AWS에서 CFN 스택 설정을 마무리하는 화면-2 | 인포그랩 GitLab
    AWS에서 CFN 스택 설정을 마무리하는 화면-2

GitLab-CFN 스택 동기화, 리소스 생성 확인

Git Sync가 정상적으로 동작해 Lambda가 생성된 걸 다음 화면과 같이 확인할 수 있습니다.

AWS에서 Git Sync가 정상적으로 동작한 걸 보여주는 화면 | 인포그랩 GitLab
AWS에서 Git Sync가 정상적으로 동작한 걸 보여주는 화면

AWS에서 스택 이벤트가 정상 상태임을 확인하는 화면 | 인포그랩 GitLab
AWS에서 스택 이벤트가 정상 상태임을 확인하는 화면

Lambda가 생성된 걸 보여주는 화면 | 인포그랩 GitLab
Lambda가 생성된 걸 보여주는 화면

GitLab에서 템플릿 파일 수정→Lambda 업데이트

마지막으로 GitLab에서 템플릿 파일을 수정한 다음, Lambda를 업데이트해 배포를 완료합니다. 순서는 다음과 같습니다.

  1. 먼저 GitLab 리포지터리에 있는 템플릿 파일인 lambda.yaml 내용을 아래 화면과 같이 수정합니다.

     lambda.yaml 파일 내용 수정 사항 | 인포그랩 GitLab
    lambda.yaml 파일 내용 수정 사항

  2. 다음 화면에서 보듯 GitLab 파이프라인이 external로 동작합니다.

    GitLab 파이프라인이 external로 동작하는 걸 보여주는 화면 | 인포그랩 GitLab
    GitLab 파이프라인이 external로 동작하는 걸 보여주는 화면

  3. 해당 파이프라인을 클릭하면 AWS의 CFN 페이지로 이동해 아래 화면과 같이 진행 상황을 볼 수 있습니다.

    AWS의 CFN 페이지에서 이�벤트 진행 상황을 확인하는 화면 | 인포그랩 GitLab
    AWS의 CFN 페이지에서 이벤트 진행 상황을 확인하는 화면

  4. 정상적으로 업데이트가 반영된 걸 Lambda에서 다음 화면과 같이 확인할 수 있습니다. 이로써 GitLab과 AWS의 CFN을 연동해 Lambda 배포를 완료했습니다.

    Lambda 업데이트를 보여주는 화면 | 인포그랩 GitLab
    Lambda 업데이트를 보여주는 화면

기타 참고 사항

AWS의 GitLab 접근 권한 설정 시 Self-Managed GitLab 연결 방법

  1. 연결 생성 > 공급자 선택 에서 GitLab self-managed를 선택하고, 연결 설정에서 연결 이름URL을 각각 입력합니다. Self-Managed GitLab을 VPC로만 접속할 수 있으면 VPC 사용에 체크합니다. 그다음, GitLab self-managed에 연결 버튼을 클릭합니다.

    AWS에서 Self-Managed GitLab을 연결하기 위해 연결을 설정하는 화면 | 인포그랩 GitLab
    AWS에서 Self-Managed GitLab을 연결하기 위해 연결을 설정하는 화면

  2. 보류 중인 연결 업데이트를 클릭합니다.

    AWS에서 Self-Managed GitLab을 연결할 때 보류 중인 연결을 업데이트하는 화면 | 인포그랩 GitLab
    AWS에서 Self-Managed GitLab을 연결할 때 보류 중인 연결을 업데이트하는 화면

  3. GitLab에서 Personal Access Token을 발급받습니다. 발급받을 Personal Access Token의 Scope는 api를 선택합니다. 발급받은 Personal Access Token은 호스트를 승인할 때만 사용됩니다. 따라서 연결 생성 이후 삭제해야 합니다.

    GitLab에서 Personal Access Token을 발급받는 화면 | 인포그랩 GitLab
    GitLab에서 Personal Access Token을 발급받는 화면

  4. 발급받은 토큰을 개인용 액세스 토큰 제공에 입력하고, 계속 버튼을 클릭합니다.

    GitLab에서 발급받은 Personal Access Token을 AWS에 등록하는 화면 | 인포그랩 GitLab
    GitLab에서 발급받은 Personal Access Token을 AWS에 등록하는 화면

AWS의 GitLab 리포지터리 접근 권한 확인 방법

GitLab의 User Settings > Applications에 들어가면, AWS에서 GitLab 리포지터리에 접근·수정하는 권한이 부여된 걸 아래 화면과 같이 확인할 수 있습니다. 부여된 Scope 설명은 Scope 설명 링크에서 볼 수 있습니다.

AWS에서 GitLab 리포지터리에 접근·수정하는 권한이 부여된 걸 GitLab에서 확인하는 화면 | 인포그랩 GitLab
AWS에서 GitLab 리포지터리에 접근·수정하는 권한이 부여된 걸 GitLab에서 확인하는 화면

AWS CLI로 Connections 생성 시 유의 사항

AWS CLI의 CodeConnections로 Connections를 생성할 때, ARN도 CodeConnections로 생성됩니다. 그러나 관리되는 정책은 여전히 CodeStarConnections를 사용하는 문제가 있습니다(2024년 5월 10일 확인). 따라서 CLI로 Connections를 생성할 때, CodeConnections가 아닌 CodeStarConnections를 사용해야 합니다.

CFN 스택 세부 정보 설정 시 참고 사항

템플릿 정의 리포지토리에서 Git 리포지터리와 동기화할 스택 템플릿의 리포지터리를 지정할 때, Self-Managed GitLab을 연결하려면 다음 순서를 따릅니다.

  1. AWS CLI로 아래 명령을 수행해 Link 리포지터리를 생성합니다.

    aws codeconnections create-repository-link --connection-arn CONNECTION_ARN --owner-id REPO_PATH --repository-name LINK_NAME
    ##ex)
    aws codeconnections create-repository-link --connection-arn arn:aws:codeconnections:ap-northeast-2:373015672791:connection/0e2060e0-37f1-4b65-a726-a0aef25c5f48 --owner-id sandbox/sabo/lambda --repository-name lambda
  2. 템플릿 정의 리포지토리에서 연결된 Git 리포지토리 선택을 클릭합니다.
    리포지토리에서 링크된 GitLab 리포지터리 중 연결할 리포지터리를 선택합니다.

    AWS에서 CFN 스택 세부 정보를 설정할 때, Self-Managed GitLab을 연결하기 위해 리포지터리를 지정하는 화면 | 인포그랩 GitLab
    AWS에서 CFN 스택 세부 정보를 설정할 때, Self-Managed GitLab을 연결하기 위해 리포지터리를 지정하는 화면

맺음말

지금까지 GitLab과 AWS의 CFN을 연동해 Lambda를 배포하는 방법을 알아봤습니다. AWS 클라우드에서 인프라를 관리한다면, CFN이 업무를 효율적으로 수행하는 데 도움이 될 수 있습니다. DevOps 엔지니어라면 다양한 IaC 도구를 이해하고 다룰 줄 알아야 하는데요. 여러분이 IaC 지식을 쌓고, 관련 도구를 보는 시야를 넓히는 데 이 글이 도움이 되면 좋겠습니다.

참고 자료

  1. Working with AWS CloudFormation Git sync

인포그랩은 GitLab과 DevOps를 맞춤형으로 기술 지원합니다. GitLab(Omnibus/Cloud Native Hybrid) 구축 지원이 필요하시면 문의하기로 연락해 주십시오.