TIL| CI&CD

Tasha Han·2023년 9월 11일
0

용어정리

  • CI(Continuous Integration):
    자동적으로 중앙저장소에 통합하는 과정을 말한다 & 빌드 및 테스트 과정을 거쳐야 한다.

  • CD(Continuous Deployment):
    코드 변경사항이 자동적으로 배포되는 과정을 말한다. 수동 승인 없이 코드가 바로 사용자에게 제공된다.

  • ECR(Amazon Elastic Container Registry):

    • ECR은 도커 컨테이너 이미지를 쉽게 저장 관리 및 배포할 수 있는 완전관리형 도커 컨테이너 레지스트리다.
    • ECR은 AWS 내에서 실행되므로, AWS 서비스와 통합하여 컨테이너 이미지를 가져오거나 배포할 수 있다.
    • ECR은 높은 가용성과 확장성을 제공하며, 개발자는 컨테이너 이미지를 AWS에 안전하게 저장할 수 있다.
  • ECS(Amazon Elastic Container Service):

    • ECS는 확장성이 뛰어나고 고성능의 컨테이너 관리 서비스로, 도커 컨테이너를 쉽게 실행및 스케일링 할 수 있다. (스케일링이란 리소스의 크기나 용량을 조정하는 과정을 말한다)
    • ECS는 클러스터를 사용하여 컨테이너화된 어플리케이션을 관리하며, 해당 클러스터 내의 서비스 빛 작업을 정의하여 실행한다.
  • ECS Fargate:

    • AWS ECS의 서버리스 컴퓨트 엔진.
    • 클러스터나 서버를 직접 관리할 필요없이 컨테이너를 실행할 수 있다.

Workflow

1) 프로젝트 설정:

Nest.js 기반의 간단한 서버 어플리케이션을 생성

2) 환경 설정 파일:
alpha 및 prod에 대한 환경 설정 파일 작성 (예: .env.alpha, .env.prod).

3)Docker 설정:

  • Dockerfile 작성해서 Nest.js 애플리케이션을 컨테이너화.
    • Dockerfile은 도커 이미지를 생성하기 위한 스크립트 파일로 이 파일에는 어떤 이미지를 사용할 것인지 코드의 어떤 부분을 이미지 안으로 복사할 것인지, 어떤 의존성을 설치할것인지 어느 포트에 어떻게 배포할 것인지가 쓰여있다.
    • 필요한 경우 docker-compose.yml 파일을 작성하여 애플리케이션과 DB를 함께 실행한다. 각 phase별로 다른 Docker Compose 파일을 사용할 수 있다.✔️

4)GitHub Actions CI/CD 설정:

.github/workflows 디렉토리 내에 각 phase(alpha, prod)에 대한 별도의 YAML 파일을 생성합니다.
각 YAML 파일에는 다음 작업이 포함되어야 합니다:

  • Lint 체크
  • Test 실행 및 Coverage 리포트 생성
  • Docker 이미지 빌드
  • AWS ECR에 이미지 푸시
  • AWS ECS Fargate를 사용하여 이미지 배포
  • AWS 설정:

AWS IAM에서 배포에 사용할 IAM 사용자를 생성하고, 필요한 권한을 부여합니다.
GitHub Actions의 Secrets 메뉴를 사용하여 AWS 액세스 키, 비밀 키 등의 민감 정보를 저장합니다.✔️
AWS ECR에서 Docker 이미지를 저장할 레포지토리를 생성합니다.
AWS ECS에서 Fargate를 사용하여 서비스를 배포할 클러스터를 설정합니다.
문서화:

배포 파이프라인, 협업 정책, CI/CD 과정 등을 문서화하여 팀원들과 공유합니다.

AWS IAM

루트 계정 보호: 루트 계정은 가장 높은 권한을 가진 계정입니다. 루트 계정의 액세스 키를 절대 생성하지 말고, AWS Management Console에 로그인할 때만 사용하도록 하세요. MFA(Multi-Factor Authentication)를 활성화하여 루트 계정의 보안을 강화합니다.

개별 IAM 사용자 생성:

배포나 리소스 관리에 필요한 작업을 위해 별도의 IAM 사용자를 생성합니다.
이 사용자에게는 프로젝트에서 필요한 AWS 리소스에 접근할 수 있는 권한만 부여합니다.
AWS Management Console 액세스는 옵션으로 선택할 수 있습니다. 필요하다면 Console 액세스도 부여할 수 있지만, 웹 콘솔 대신 CLI나 SDK를 주로 사용한다면 프로그래밍 방식 액세스만 선택하는 것이 좋습니다.
관리형 정책 사용:

AWS에서 제공하는 관리형 정책을 활용하여 사용자에게 필요한 권한을 부여합니다. 예를 들어, EC2 인스턴스를 관리하는 경우 AmazonEC2FullAccess와 같은 정책을 사용할 수 있습니다.

GitHub Actions의 Secrets:

IAM 사용자의 액세스 키 ID와 비밀 액세스 키는 GitHub Actions의 Secrets에 저장하여 CI/CD 과정에서 사용합니다.

비용 모니터링:

혹시나 예상치 못한 리소스 사용으로 인한 과도한 비용이 발생하는 것을 방지하기 위해 AWS 비용 알람을 설정하는 것이 좋습니다.

기타사항

docker-compose까지 사용하는 이유
여러개의 도커 컨테이너를 함께 정의하고 실행하기 위한 도구
1. 다중 컨테이너 어플리케이션 관리
ex) 웹어플리케이션,DB, 캐시서버, 백그라운드 작업자등 여러 서비스가 함께 작동할 수 있다.
2. 환경 일관성: 전체 구조와 서비스 설정을 문서화하기 때문에 개발자간의 환경 차이를 최소화하고 개발, 스테이징, 프로덕션 등의 다양한 환경에서 동일한 설정으로 어플리케이션을 실행할 수 있다.
3. depends_on 옵션을 통해 서비스 간의 의존 관계와 실행 순서를 정의할 수 있다.
4. 변수 및 환경 구성: '.env'파일이나 환경 변수를 통해 설정값을 관리하도록 지원. 이를 통해 개발, 테스트, 프로덕션 등 다양한 환경에 맞게 설정값을 조정할 수 있다.
5. 네트워크 및 볼륨관리: 각 서비스간의 네트워크 연겨르 볼륨 마운트가 가능하다. (docker-compose에서 서비스간의 연결을 설정할때, 해당 서비스 이름을 도메인이름처럼 사용할 수 있다. 그래서 db를

#github actions
name: Deploy to EC2

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    # EC2 서버에 배포
    - name: Deploy to EC2
      uses: appleboy/ssh-action@master
      with:
        host: 3.39.216.163
        username: ubuntu
        key: ${{ secrets.SSH_PRIVATE }}
        script: |
          cd /home/ubuntu/cicd
          git pull origin main
          docker-compose -f docker-compose.prod.yml down
          docker-compose -f docker-compose.prod.yml build
          docker-compose -f docker-compose.prod.yml up -d
# docker-compose.prod.yml
version: '3.7'
services:
  nestjs-server:
    build:
      context: .
      dockerfile: Dockerfile
      target: production

    environment:
      - NODE_ENV=production #파일 캐싱, 에러 메시지 감추기 로컬로 지정하려면.env파일에 NODE_ENV=production 이렇게 하면 됨
    ports:
      - 3000:3000
    depends_on:
      - db
  db:
    image: postgres:latest
    container_name: postgres
    env_file:
      - .env
    environment:
      - POSTGRES_USER=${PROD_DB_USER}
      - POSTGRES_PASSWORD=${PROD_DB_PASSWORD}
      - POSTGRES_DB=${PROD_DB_NAME}
    ports:
      - ${PROD_DB_PORT}:${PROD_DB_PORT}
# docker-compose.alpha.yml
version: '3.7'
services:
  nestjs-server:
    build:
      context: .
      dockerfile: Dockerfile
      target: development # 알파 환경에서는 개발 빌드를 사용할 수 있습니다.

    environment:
      - NODE_ENV=development # dev 상태로 설정 : 파일캐싱방지, 디버그를 위한 상세한 에러 메시지 보이기 등
    ports:
      - 3000:3000
    depends_on:
      - db
  db:
    image: postgres:latest
    container_name: postgres-alpha # 컨테이너 이름을 알파 환경에 맞게 변경합니다.
    env_file:
      - .env # 알파 환경 설정을 포함하는 .env 파일을 사용합니다.
    environment:
      - POSTGRES_USER=${ALPHA_DB_USER}
      - POSTGRES_PASSWORD=${ALPHA_DB_PASSWORD}
      - POSTGRES_DB=${ALPHA_DB_NAME}
    ports:
      - ${ALPHA_DB_PORT}:${ALPHA_DB_PORT}

###################
# BUILD FOR LOCAL DEVELOPMENT
###################
# 1. 기본 이미지 설정
FROM node:18-alpine As development
# 2. 작업 디렉터리 설정
WORKDIR /usr/src/app
# 3. 앱 의존성 파일들 복사
# --chown=node:node 옵션은 파일의 소유권을 node 사용자와 그룹에 할당
COPY --chown=node:node package*.json ./
# 4. 앱 의존성 설치
# npm ci는 package-lock.json을 사용하여 정확한 버전의 패키지를 설치하는 명령어
RUN npm ci
# 5. 앱 소스 코드 복사
COPY --chown=node:node . .
# 이후에는 node 사용자로 전환
USER node

###################
# BUILD FOR PRODUCTION
###################

FROM node:18-alpine As build

WORKDIR /usr/src/app

COPY --chown=node:node package*.json ./

COPY --chown=node:node --from=development /usr/src/app/node_modules ./node_modules

COPY --chown=node:node . .

RUN npm run build

ENV NODE_ENV production

RUN npm ci --only=production && npm cache clean --force

USER node

###################
# PRODUCTION
###################

FROM node:18-alpine As production

COPY --chown=node:node --from=build /usr/src/app/node_modules ./node_modules
COPY --chown=node:node --from=build /usr/src/app/dist ./dist

CMD [ "node", "dist/main.js" ]
profile
개발 잘하고 싶다~(고래)

0개의 댓글