ABOUT ME

Today
Yesterday
Total
  • [프로젝트02] AWS ECS CI/CD
    교육/코드스테이츠 2023. 1. 26. 05:16

    Project 2 / Team H

    AWS ECS를 사용하는 서비스의 CI/CD 구축 프로젝트

     

    Github

    회고록(8주차-프로젝트)

    Achievement Goals

    Day 1

    ● WAS, DBDocker Image로 빌드하여 컨테이너화

     컨테이너화한 WASECRPush

     Docker Compose를 이용해, WASDB를 한번에 실행

     WAS 이미지 빌드 및 push 자동화를 구현

     

    Day 2

     WAS mongoDB 이미지를 ECS를 통해 배포

     WAS 이미지의 배포 자동화를 구현

     WAS와 연결된 로드 밸런서에 HTTPS를 적용

     

    Day 3-4

     프론트엔드의(제공받은) 배포를 자동화

     CDN을 통해 캐싱 및 HTTPS를 적용

     프론트엔드와 WAS를 연결

     

    진행 순서

    1. fastify server app 만들기

    npm install fastify-cli -g

    fastify generate .

    npm i

    npm run start

     

    주의사항: npm start명령으로 fastify 서버를 시작하면 로컬호스트 주소로 동작하므로 AWS에 컨테이너를 띄워도 접속할 수 없다. 따라서, package.json에서 -a 옵션으로 0.0.0.0 주소로 시작할 수 있도록 해야한다.

    로컬호스트는 배포할 경우 노출이 되지 않는다

     

    출처: https://github.com/fastify/fastify-cli

     

    2. ECRDocker image 배포하기

    Github action에서 Deploy to Amazone ECS 템플릿을 활용하여 ECS 배포

    도커파일 생성

    레포지포리 내의 최상위 디렉토리에 생성해준다.

    #Dockerfile
    FROM node:16-alpine
    WORKDIR /usr/src/app
    COPY package*.json ./
    RUN npm install
    COPY . .
    EXPOSE 3000
    CMD [ "npm", "start" ]
    
    # 앱 디렉터리 생성 - 컨테이너 디렉토리
    # 호스트 계정에 있는 package.json, package-lock.json 파일을 컨테이너 현재 디렉토리 안에 복사
    # 앱 의존성 설치
    # 호스트 계정(' . ')에 있는 소스파일 전체를 dockerfile과 동일한 위치한 컨테이너 위치에 복사
    # 포트 3000연결 확인
    # 컨테이너 running시 실행
    
    도커 이미지 실행
    docker build -t was:1.0
    
    도커 컨테이너 실행
    docker run --name project02 -p 3000:3000 was:1.0

     

    깃헙 액션으로 AWS ECR에 이미지 빌드 자동화

    yaml파일 만들기

    name: KJH Push to ECR
    on:
      push:
        branches: [ "main" ]
    
    jobs:
      deploy:
        name: Deploy
        runs-on: ubuntu-latest
        
        steps:
        - name: Checkout repo
          uses: actions/checkout@v3
    
        - name: KJH Configure AWS credentials
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.KJH_AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.KJH_AWS_SECRET_ACCESS_KEY }}
            aws-region: ap-northeast-2
    
        - name: KJH Login to Amazon ECR
          id: login-ecr
          uses: aws-actions/amazon-ecr-login@v1
    
        - name: KJH Build, tag, and push image to Amazon ECR
          id: build-image
          env:
            ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
            REPOSITORY: project_02
            IMAGE_TAG: ${{ github.sha }}
    
          run: |
            docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./helloworld
            docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
            docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

    모든 이름에 KJH를 붙여 팀원과 파일을 구분해주었다

    Configure AWS credentials 의 aws-access-key-id와 aws-secret-access-key의 값을 환경변수로 설정 해준다.

    키페어를 받기 위해서는 aws콘솔 로그인 - 우측 상단 아이디 클릭 - 보안자격 증명 - 엑세스 키 에서 받을 수 있다.

    키페어를 받은 후 레포지토리 Setting에 들어가서 Secrets and variables -> actions 에서 만들어준다.

     

    형식

    name: AWS_ACCESS_KEY_ID

    Value: 키 값

    ECR 레포지토리 만들기

    프라이빗 레퍼지토리를 생성한다.

    생성 후 우측 상단에 푸쉬명령 보기 클릭

    먼저 AWS CLI를 사용하기 위해서 인증 토큰을 터미널에 인증한다

    순차적으로 2~4번을 터미널에 입력하면 된다

    코드 푸쉬하면 깃허브 액션이 실행되며 오류가 없을 경우 ECR로 이미지가 전송된다

    AWS credentials에서 키 값으로 인한 몇번의 오류가 있었다

    시크릿 키 설정시 주의하기

    데이터베이스 만들기

    도커 명령어로 컨테이너 만들 경우 --env가 앞에 있을 경우 적용이 안돼, 뒤쪽에 넣었다 

    #Docker 명령어
    docker run --name some-mongo --env MONGO_ININDB_ROOT_USERNAME=root --env MONGO_ININDB_ROOT_PASSWORD=example –p 27017:27017 –d mongo:latest
    
    #Docker-compose
    version: '3.1'
    
    services:
    
      mongo:
        image: mongo
        restart: always
        ports:
          - "27017:27017"
        environment:
          MONGO_INITDB_ROOT_USERNAME: root
          MONGO_INITDB_ROOT_PASSWORD: example
    
      was:
        image: was:1.0
        ports:
          - "3000:3000"

     

    ECR에 저장된 웹 서버 이미지를 ECS로 배포

    테스크 데피니션, 컨테이너

    사진01

    ECR에 올린 이미지에 URL을 복사한 후 등록하여 컨테이너 설정

    사용할 포트 설정

    데이터베이스에 환경 설정을 Task Definition을 만들면서 설정 가능하다

    AWS Secrets Manager

    보안 암호 유형: 다른 유형의 보안 암호 선택

    자동 교체는 적용하지 않았다

    /값 페어: 다음의 키/값들을 입력한다

    사진02

    키는 실제로 애플리케이션에서 사용할 환경 변수 이름이다

    값 유형은 ValueFrom 으로 설정한다

    값은 Secrets Manager에 저장되어 있는 보안 암호의 키/값의 ARN으로 지정하며 다음과 같은 형식이다

    arn:aws:secretsmanager:region:ap-northeast-2:509484456337:secret:was-secret-G8xPVg:USERNAME::

     

    Secret키를 이용하기 위해서는 IAM도 같이 설정해야한다

    역할 - 역할 만들기 후 권한을 설정해주면 된다

     

    클러스터 및 서비스 생성

    클러스터는 보안그룹과 서브넷만 신경써서 만들면 된다

    사용할 작업정의와 개정을 선택한다

    이용할 테스크의 수량을 지정한다

    로드밸런싱 부분에서 ALB, NLB를 선택한다

    ALB는 로드밸런서, 리스너, 타겟 그룹을 만들 수 있다

    NLB는 기존 로드밸런서, 리스너, 타겟 그룹을 만들고 설정해줘야한다

     

    워크플로우 설정

    작업 정의 JSON 파일을 Git repository에 추가한다

    작업 정의 파일을 기반으로, ECR로의 배포를 자동화할 수 있습니다. JSON 형식의 작업 정의를 Git Repository에 적당한 곳에 위치한다

    작업 정의 파일에 민감 정보가 포함되어 있는지 여부를 확인한다

    가장 최근 개정을 이용하면 되고 한번 선택하면 알아서 업데이트 된다.

     

    GitHub Action에 Deploy to Amazon ECS라는 workflow를 검색하고 환경 설정을 제대로 넣어두면, 배포가 자동화된다

    기존의 ECR로의 빌드/push 작업 자동화 workflow가 있는 경우에 해당 내용이 중복이므로, 기존 workflow는 지워야 한다

    name: KJH build was image and push to ecr repository
    
    on:
      push:
        branches: [ "main" ]
        
    env:
      AWS_REGION: ap-northeast-2                 # set this to your preferred AWS region, e.g. us-west-1
      ECR_REPOSITORY: project_02           # set this to your Amazon ECR repository name
      ECS_SERVICE: was-svc                # set this to your Amazon ECS service name
      ECS_CLUSTER: helloworld-was-cluster                # set this to your Amazon ECS cluster name
      ECS_TASK_DEFINITION: ./devops-03-P2-TeamB/helloworld-was-task-definition3:1.json # set this to the path to your Amazon ECS task definition
                                                   # file, e.g. .aws/task-definition.json
      CONTAINER_NAME: helloworld-was-container3           # set this to the name of the container in the
                                                   # containerDefinitions section of your task definition
    
    permissions:
      contents: read
    
    jobs:
      deploy:
        name: KJH Deploy
        runs-on: ubuntu-latest
        environment: production
    
    
        steps:
        - name: KJH Checkout repo
          uses: actions/checkout@v3
    
        - name: KJH Configure AWS credentials
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.KJH_AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.KJH_AWS_SECRET_ACCESS_KEY }}
            aws-region: ap-northeast-2
    
        - name: KJH Login to Amazon ECR
          id: login-ecr2
          uses: aws-actions/amazon-ecr-login@v1
    
        - name: KJH Build, tag, and push docker image to Amazon ECR
          id: build-image
          env:
            ECR_REGISTRY: ${{ steps.login-ecr2.outputs.registry }}
            ECR_REPOSITORY: project_02
            IMAGE_TAG: ${{ github.sha }}
          run: |
            docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./devops-03-P2-TeamB
            docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
            echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
        - name: KJH Fill in the new image ID in the Amazon ECS task definition
          id: task-def
          uses: aws-actions/amazon-ecs-render-task-definition@v1
          with:
            task-definition: ${{ env.ECS_TASK_DEFINITION }}
            container-name: ${{ env.CONTAINER_NAME }}
            image: ${{ steps.build-image.outputs.image }}
    
        - name: KJH Deploy Amazon ECS task definition
          uses: aws-actions/amazon-ecs-deploy-task-definition@v1
          with:
            task-definition: ${{ steps.task-def.outputs.task-definition }}
            service: ${{ env.ECS_SERVICE }}
            cluster: ${{ env.ECS_CLUSTER }}
            wait-for-service-stability: true

     

    ECS CI/CD 환경 구축

    서버 애플리케이션 HTTPS 적용

    HTTPS 적용을 위해서는, 구입한 도메인의 인증서가 필요하다 

    인증서 발급은 간단히 할 수 있다 발급 후 CNAME 이름/값 확인 - 라우트53에서 레코드 생성 클릭

    발급 후 이메일 인증!!!

     

    DNS 주소에 따른 트래픽을 로드 밸런서로 보내려면 Route 53을 이용해야 한다

     

    ACM에서 레코드를 생성 안할 경우

    Route53 - 호스트 영역 - 구매한 도메인 선택  - 레코드 생성 - 단순 레코드 정의 - 레코드 생성

    AWS Certificate Manager(ACM)에서 발급받은 인증서를 로드 밸런서 구성에서 HTTPS 프로토콜을 선택하면 인증서 적용

    설정 후 로드벨런서 리스너의 443포트와 80포트를 열어주었다

    HTTPS 443포트에는 ACM인증서를 추가로 설정했다

     

    CloudFront와 프론트엔드가 담긴 S3 버킷을 연결하고, HTTPS를 적용

    GIT을 통해 Frontend 레포지토리 포크

    S3 버킷 생성 후 정적 웹 사이트 호스팅 활성화 - 권한 버킷 정책 편집

    buildspec.yml 작성

    version: 0.2
    
    phases:
      pre_build:
        commands:
          - npm install
      build:
        commands:
          - npm run build
    
    artifacts:
      files:
        - '**/*'
      base-directory: ./build

    package.json에서 start 및 build 명령 확인한 후 실행 할 도메인 입력

    현재 정적 웹서버는 HTTP를 통해 제공되고 있으므로, WAS의 엔드포인트 역시 HTTP 프로토콜이어야 한다

    이후 프론트엔드 HTTPS 적용시에는 WAS 역시 HTTPS로의 연결이 필요하다

     

    CodePipeline + CodeBuild를 통해 배포 자동화 구현(35일차 참고)

     

     

    프론트엔드 HTTPS 적용

    Route 53을 이용해 트래픽이, CDN(CloudFront)에 연결한다

    CloudFront를 이용하여, S3 정적 웹사이트를 캐싱한다

    설정했던 것들을 기록해 봤다

    Codepipeline을 이용한 프론트엔드 자동화

     

    =======================================================

    fastify 설치 공식문서

    https://www.fastify.io/

     

    fastufy cli

    https://github.com/fastify/fastify-cli

     

    Amazon ECR Private에 이미지를 빌드 푸시

    https://github.com/aws-actions/amazon-ecr-login

     

    mongo docker hub

    https://hub.docker.com/_/mongo

Designed by Tistory.