본문 바로가기

AWS

[CICD / ECS] CodePipeline으로 ECS Fargate 배포 자동화 #4 - buildspec.yml, appspec.yml, taskdef.json 설정

반응형

해당 부분에서는 Secret 설정 및 변수 설정 등을 진행하며, appspec.yml과 buildspec.yml, taskdef.json 파일 생성 등에 대해 다룰 것이다.

 

Git에서 형상 변화가 일어나면 CodePipeline이 이를 감지하고, Build → Deploy 까지 배포 자동화 프로세스를 구현하기 위해 스크립트 파일을 잘 작성해야 한다.

 

또한 생성한 컨테이너 이미지나 빌드 아티팩트들이 S3 혹은 Container Registry에 저장될 수 있도록 Buildspec.yml에서 잘 설정해주어야 한다.

 

1. Secrets Manager 생성

간단하게 APP_NAME 및 ECR_REPOSITORY_URI 시크릿을 생성해준다.

그 외, 데이터베이스의 암호 등을 이 시크릿 매니저를 통해 설정해 줄 수 있으며 주기적으로 패스워드 또한 AWS 람다 서비스와 연동하여 변경이 가능하다.

2. CodeBuild 부분에서 수행될 buildspec.yml 설정

buildspec.yml은 AWS에서 제공하는 관리형 CI 툴인 CodeBuild에서 인식하는 파일이다.

환경 변수는 이전에 설명했던 것처럼 CLUSTER_NAME, SERVICE_NAME, TASK_DEF_NAME, Region은 variables를 통해 설정하고, 소스코드에 노출되어선 안되는 값에 대해서는 Secrets-manager 등을 활용할 수 있다.

실습인 만큼 그닥 예민하지 않은 정보이지만 사용해보기 위해 APP_NAME 등을 Secrets-manager에 저장하였다.

pre_build는 빌드하기 전에 수행하는 명령어들을 나열하였으며, build, post_build 등에 대한 phases에 각각의 명령어들을 설정할 수 있다.

우선 pre_build 부분에는 ECR에 로그인하는 부분이 필요하며, build 부분에서는 Dockerfile을 build 하는 부분, post_build에서는 ECR Repository에 Push 하는 작업이 필요하다.

sed 명령어를 통해서 taskdef.json에 있는 ECR_REPO_URI나 버전, Account ID 등을 sed 명령어로 치환하였고, 리디렉션을 통해 taskdef.json 파일과 appspec.yml 파일을 저장한 뒤 Artifact로 S3에 넘겨줄 것이다.

이 파일들은 CodeDeploy에서 사용될 것이기 때문에 Deploy 수행 이전에 원하는대로 값이 잘 변경되는지 확인이 필요하다.

 

- buildspec.yml

version: 0.2

env:
  # You can use env at variables, Parameter-store, secrets-manager
  # need to add IAM Policy to CodeBuild Role
  variables:
    CLUSTER_NAME: "node-dev-apne2-cluster"
    SERVICE_NAME: "nodejs_app_svc"
    TASK_DEF_NAME: "nodejs_app"
    Region: "ap-northeast-2"
    # Web Console : AccountID

  secrets-manager:
    ECR_REPOSITORY_URI: NODEJS_APP_SECRET:ECR_REPOSITORY_URI
    APP_NAME : NODEJS_APP_SECRET:APP_NAME

phases:
  install:
    runtime-versions:
      docker: 18

  pre_build:
    commands:
      - echo Current Build number is v${CODEBUILD_BUILD_NUMBER}
      - echo current working dir
      - pwd
      - echo Logging to Amazon ECR
      - aws --version
      - aws ecr get-login-password --region $Region | docker login --username AWS --password-stdin ${AccountID}.dkr.ecr.${Region}.amazonaws.com

  build:
    commands:
      # Build
      - echo Docker build ...
      - docker build -t ${APP_NAME}:v${CODEBUILD_BUILD_NUMBER} .

  post_build:
    commands:
      # Tag, Push
      - echo Docker Tag, Pushz
      - docker tag ${APP_NAME}:v${CODEBUILD_BUILD_NUMBER} ${ECR_REPOSITORY_URI}:v${CODEBUILD_BUILD_NUMBER}
      - docker push ${ECR_REPOSITORY_URI}:v${CODEBUILD_BUILD_NUMBER}

      # taskdef.json
      - cat scripts/taskdef.json | sed -e "s|<ACCOUNT_ID>|${AccountID}|g" -e "s|<ECR_REPO_URI>|${ECR_REPOSITORY_URI}|g" -e "s|<VERSION>|v${CODEBUILD_BUILD_NUMBER}|g" > taskdef.json
      
      # 만약 VPC 설정을 안하였을 경우, 주석 처리 가능
      # appspec.yml
      
      # 치환
      - cat scripts/appspec.yml > appspec.yml
      

artifacts:
 files:
  - appspec.yml
  - taskdef.json

 

- taskdef.json

{
  "executionRoleArn": "arn:aws:iam::<ACCOUNT_ID>:role/ECSTaskExecutionRole",
  "containerDefinitions": [{
    "name": "nodejs_app",
    "image": "<ECR_REPO_URI>:<VERSION>",
    "essential": true,
    "portMappings": [{
      "protocol": "tcp",
      "hostPort": 8080,
      "containerPort": 8080
    }]
  }]
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "networkMode": "awsvpc",
  "cpu": "256",
  "memory": "512",
  "family": "nodejs_app_taskdef"
}

 

- appspec.yml

<TASK_DEFINITION>은 CodeDeploy가 Source Artifact로 받은 작업 정의 파일을 등록한 뒤 작업 정의의 arn으로 알아서 치환해주므로 그대로 둔다.

필자는 Fargate의 배포 위치를 VPC의 특정 서브넷 및 보안 그룹에 종속시켰기 때문에 아래처럼 VPC 설정값을 추가해주었다.

이 값들 또한 buildspec.yml에서 동적으로 치환할 수 있을 것으로 본다.

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "<TASK_DEFINITION>"
        LoadBalancerInfo:
          ContainerName: "nodejs_app" # Edit here
          ContainerPort: 8080
        PlatformVersion: "LATEST"
        NetworkConfiguration:
          AwsvpcConfiguration:
            Subnets: ["subnet-05e6e358bfcce6868", "subnet-08bec4aaec4e77526"] # Edit here
            SecurityGroups: ["sg-06363646d6eece2d9"]  # Edit here
            AssignPublicIp: "DISABLED"

 

 

이제 이 파일들을 통해 자동화 빌드 및 배포 과정이 구현될 것이다.

반응형