-
[프로젝트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, DB를 Docker Image로 빌드하여 컨테이너화
● 컨테이너화한 WAS를 ECR에 Push
● Docker Compose를 이용해, WAS와 DB를 한번에 실행
● 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. ECR에 Docker 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 설치 공식문서
fastufy cli
https://github.com/fastify/fastify-cli
Amazon ECR Private에 이미지를 빌드 푸시
https://github.com/aws-actions/amazon-ecr-login
mongo docker hub
'교육 > 코드스테이츠' 카테고리의 다른 글
[45일차] 도메인 주도 설계(DDD,Domain-Driven-Design) (0) 2023.01.31 [44일차] 마이크로서비스 구조와 특징 (0) 2023.01.30 [36일차] 환경변수 설정 및 배포 전략 (0) 2023.01.16 [35일차] 클라이언트, 서버 파이프라인 생성 (0) 2023.01.14 [34일차] Github Action 실습 정리 (0) 2023.01.12