Route53 부터 CodePipeline 까지 CI/CD 이해하기

예리에르·2023년 8월 1일
2

AWS

목록 보기
2/3
post-thumbnail
post-custom-banner

계기

2월에 팀 개발 블로그를 CodePipeline을 통해 CI/CD를 구현했었다. 이후 관련 작업을 하지 않다 보니 어떻게 했던것인지 기억이 안날 뿐더러 기존에 있던 설정을 확인하고 입력하는 작업이어서 이해도가 부족했다. 그래서 예전에 개발한 팀 프로젝트 중 여전히 FileZilla를 통해 수동으로 배포되는 프로젝트가 있어서 학습 겸 CodePipeline CI/CD를 구축하기로 했다.

이러한 특성으로 수동이긴하나 이미 appspec.yml, DockerFile, update.sh 등 AWS의 배포에 필요한 기본파일들은 완성되어있었기 때문에, 해당 코드들을 이해하고 응용해서 구축하는 방향으로 글을 작성할까한다.

CodePipeline 구축하기.

buildspec.yml

먼저 CodeBuild를 만들기 위해서는 buildspec.yml이라는 파일이 필요하다. buildspec은 CodeBuild가 빌드를 실행하느데 사용하는 YAML 형식의 필드 명령 모음이다.

buildspec.yml은 소스 디렉터리의 루트에 배치해야하는데 예전에 이 사실을 몰랐을 때는 배포관련 폴더에 다 넣었다가 시간을 소비했던 기억이있다.

 // buildspec.yml
version: 0.2
phases:
  install:
    runtime-versions:
      nodejs: 16
    commands:
      - npm i npm@latest -g
  pre_build:
    commands:
      - npm install
  build:
    commands:
      - npm run build
artifacts:
  files:
    - 'deploy-live/**/*'
  name: dmp-training-center-front

대충 흐름을 봐도 여기서 올리려는 프로그램은 React 이기 때문에 React를 빌드하는 흐름에 맞춰 내용을 작성한 것을 알 수 있다.

여기서 궁금했던 점은 artifacts 였다.
전에는 막연히 빌드한 산출물이 들어가는 곳이겠네~~ 라고 생각했었다.

하지만 이번에는 코드 하나하나를 분석하면서 의미가 다르다는 것을 알게되었다. 추가로 나중에 Pipeline을 구성하면서 알게 되겠지만 CodeDeploy를 실행하기 위해서는 appspec.yml가 필요한데 설정화면에서 CodeBuild와 다르게 appspec.yml의 위치를 지정해주는 필드가 없다.

그런 생각을 꼬리를 따라가다 보면 더더욱 buildspec.yml의 artifacts의 이해가 필요하다고 생각했다.

artifacts.files

  • 빌드후 산출물과 CodeDeploy에 필요한 설정파일을 S3에 업로드 한다.

한줄로 정의 할 수있다고 생각한다. 현재 프로젝트는 deploy-live라는 폴더안에 appspec.yml, DockerFile, update.sh 설정파일이 들어가있고, dist라는 폴더안에 빌드 산출물이 들어가있다. 그래서 여기서는 deploy-live 안의 폴더 내용을 재귀적으로 가져가서 S3에 넣어줬다.

appspec.yml

version: 0.0
os: linux
files :
  - source : /
    destination : /*복사할 인스턴스 경로*/
hooks:
  ApplicationStart:
    - location: /update.sh
      timeout: 300
      runas: root

appspec.yml은 파일에 정의된 일련의 수명 주기 이벤트 후크로 배포를 관리하는데 사용한다.

files.source

  • 인스턴스에 복사할 수정의 파일 또는 디렉토리를 식별한다.
  • / 슬래시 하나인 경우 수정 버전의 모든 파일이 인스턴스에 복사된다.

files.destination

  • 인스턴스에서 파일이 복사되야 하는 위치를 식별한다.

update.sh

shell 스크립트로 인스턴스에 실행할 shell 스크립트를 적어준다.
지금 프로젝트는 Nginx와 React 빌드 산출물을 띄울 docker 1개를 띄울 것이다.

이번 기회를 통해 Docker에 대해 공부하게 되었는데, 가장 시간을 많이 할애했던 부분은 docker의 포트에 관한 내용이다.

Docker Container포트와 Host포트

docker 종료, 이미지 삭제, 이미지 제작은 검색을 통해 이해를 할 수 있었으나 이미 많이 떠있는 docker들의 포트를 보고 내가 띄우고 싶은 port는 어떻게 설정해야하고 어떤 의미가 있는지 고민이 많이 되었다.

"괜히 아무거나 적었다가 기존의 서비스에 영향을 주진 않을까? 기존에 설정된 포트는 어떤 기준으로 되었을까?"

생각으로 건들이지 못했는데 학습을 하면서 테스트로 elb를 띄어보고 포트도 새로 만들어보면서 이해도를 높일 수있었다.

포트에 관련된 글 중에서 도커에서 Container포트와 Host 포트의 개념 글을 보고 쉽게 이해할 수있었다. 😊😊

echo 도커 실행 8099:8080
sudo docker run -it -d -p 8099:8080 play-center/real

-p 옵션은 포트를 의미하는 걸로 호스트의 8099포트를 컨테이너의 8080포트에 연결하는 의미이다. 위 그림을 보면 이해가 쉬운데 우리는 AWS에 인스턴스를 띄우고 그 곳에서 shell 스크립트를 실행하고 있다. 그럼 즉 지금 시점에서 host는 인스턴스이고 인스턴의 8099포트는 컨테이너의 8080 포트와 연결되어 있고 접속할 수 있다.

포토의 설정은 host포트는 일반적으로 개방되어있고 중복만 되지 않으면 된다!
하지만, 컨테이너 포트는 경우가 다르다. 공통적으로 어느 포트를 고르든지 상관은 없지만 정해진 포트가 있는 경우가 있다.

MySQL(3306), MongoDB(27017), redis(6379), node(3000)등 특정 이미지는 포트가 정해진 경우가 있으니 이부분을 생각하며 포트를 설정 할 수있다.

도커 포트가 겹치는데 괜찮은가?

개념을 이해하고 현재 서비스의 docker들을 다시 살펴보았다. 그런데 생각해보니 인스턴스에 떠있는 컨테이너 포트가 같은게 많은데 괜찮은가..? 라는 생각을 하게 되었다.

(지금 생각해보면 부끄러운 질문이었다. 하지만 친절하게 대답해주신 팀장님 쵝오...🫣)

컨테이너가 배포되면 격리된 네트워크 환경에서 각각의 컨테이너의 인터페이스도 새롭게 할당되고 mac과 private IP도 부여받게 된다.

sudo docker run -it -d -p 8099:8080 play-center/real
sudo docker run -it -d -p 8077:8080 play-center/real

즉, 첫 번째는 8099 host포트로 띄운 컨테이너의 8080과 연결되어 있고 두번쨰는 8077 host포트로 띄운 컨테이너의 8080과 연결되어 있다.!!

좀 더 나아가면 여러개의 컨테이너를 묶어 서비스를 구축하는 docker compose도 있고, 컨테이너끼리 통신 할 수있는 docker network 까지 다양한 방식의 docker 사용방법이 있다.

프론트 엔드와 백엔드를 같이 배포하여 관리하는 경우 front에 nginx를 두고 정적처리를 하고 백엔드는 docker 안에서 네트워크로 연결하여 외부 노출을 줄여 도메인 공격을 막을 수도 있다.

(담에 구성하게 된다면 추가 포스팅을 하겠습니다 ㅎㅎ)

CodePipeline 정리

지금까지 CodePipeline을 구성하면서 학습했던 고민했던 내용을 정리해봤습니다. 흐름을 정리하면 git을 통해 trigger로 작용할 브랜치를 선정합니다. 그 브랜치가 push된다면 CodeCommit는 CodeBuild를 실행합니다.
buildspec.yml을 통해 만들어진 빌드 산출과 CodeDeploy의 설정파일은 S3넣어줍니다.
CodeDeploy는 버킷에 있는 appspec.yml으로 배포를 시작하고 update.sh를 통해 docker를 띄운다.

Route53에서 인스턴스까지 닿기.

실제 라이브로 제공되는 서비스에 배포환경을 바꾸는게 부담스럽다 보니 elb임시로 포트를 열어 확인(8077의 host포트를 열어 실습)해보면서 도메인에서 ec2까지 닿는 과정을 다시 학습하였다.

이번의 환경 구축은 이전 내용의 수동배포를 자동화 시키는 목적으로 해당 부분은 흐름을 이해하는 관점에 학습및 내용정리를 하였다.

Route53

Route53은 AWS에서 제공하는 DNS(Domain Name Service)이다.

등록한 도메인의 세부정보를 보게되면 elb가 연결되어있다.

ELB 로드 밸린서와 Target Group

ELB

하나의 웹 사이트를 호스팅하는 경우 Elastic Load Balancing(ELB)를 사용하여 웹사이트의 트래픽을 분산할 수 있다.

Target Group

로드밸런서와 연결될 인스턴스 그룹을 설정. 등록 대상에 대하여 헬시체크를 수행한다. 프로토콜과 포트 번호를 사용하여 등록된 대상으로 요청을 전송한다.

SSL이 적용되지 않는 경우 HTTPS로 리다이렉트 한다. HTTPS는 설정된 Target Group으로 요청.

TargetGroup을 확인하게되면 연결된 인스턴스와 포트를 알 수있다.

Route53, ELB, Target Group 정리

지금까지 이해한걸 간략하게 정리해보면 등록된 도메인에 ELB를 설정하여 트래픽을 분산한다. ELB는 Target Group을 통해 인스턴스와 연결되고 헬시체크도 한다.

후기

기존에 CodePipeline을 구축했기 때문에 쉽게 할 수 있을 것이라고 생각했다. 여전히 많은 부분에서 기존의 설정들을 참고했지만 이번에는 좀더 의미를 파악하고 설정했다고 생각한다. 코드의 뜻을 모르고 일단 붙여놓고 실습을 했었는데 이번에는 하나하나 검색하면서 모르는건 물어보면서 좀더 구체적으로 시스템을 이해하기 위해 노력했다.

아직 부족한 부분이 있지만 기회가 있으면 도입하고 구축하면서 다른 옵션을 알게되면 팀원과 공유하면서 AWS의 이해도를 높이기 위해 노력해야겠다.

profile
궁금한 프론트엔드 개발자의 개발일기😈 ✍️
post-custom-banner

0개의 댓글