실습3)

https://github.com/earth-space/Node.js-small-project-example

이 코드를 ECS에 배포해보세요.
단, 몽고디비 컨테이너는 프라이빗 서브넷에 존재하여야 한다.
그리고 nodejs의 http://<DNS이름>으로 접속했을때 서비스가 잘 제공되도록 해보세요.

 

https://eitherwho.tistory.com/80

 

56일차) 2025-03-20(앱 배포-java/js, 컨테이너화, dockerignore)

무중단 고가용성 앱 배포, 서비스를 끊기지 않게 제공다양한 앱 배포웹어플리케이션웹에서 동작하는 어플리케이션웹어플리케이션 프레임워크앱 제작 가이드 또는 툴자바 - spring(java + tomcat 서

eitherwho.tistory.com

풀이)

잘못만들어진 앱이기때문에, 일반적인 방법으로는 ECS에 배포하기가 쉽지 않다.

→ 서비스를 두개 만들어서 동일한 타겟그룹을 지정하고 하나는 3000, 다른 하나는 3001으로 연결시켜줄 수 밖에 없다.

# 이렇게 해도 chat(3001)이 정상적으로 동작하지 않음

1. mongo 태스크를 생성

- 로드밸런서를 생성한다면, NLB를 생성해야함. tcp로 헬스체크를 하기 위함

- 어차피 태스크를 한개만 생성할것이기 때문에 그냥 태스크를 정의 및 실행

  • 프라이빗에 존재하는 mongo 컨테이너의 동작여부를 알기 위해 퍼블릭서브넷에 bastion을 하나 생성

# 보안그룹은 모두 허용하는 정책

  • 프라이빗 서브넷에 태스크를 생성 = ECR에 있는 이미지를 pull = outbound 트래픽이 발생
    → NATGW를 생성해서 라우팅
  • NATGW 생성

  • 생성한 NATGW를 넥스트홉으로 하는 프라이빗 서브넷의 라우팅테이블에 정책 생성

  • 태스크 정의

# 가져다 쓸 이미지(따로 이미지를 push하지 않고 퍼블릭 ecr의 이미지 사용)

  • 태스크의 프라이빗 IP을 확인

# http로 통신은 하지 않지만, 적어도 mongodb가 띄워져있는건 확인 가능

2. nodejs 컨테이너 생성

root@aws-cli:~/sb_code# cd ..
root@aws-cli:~# git clone https://github.com/earth-space/Node.js-small-project-example
  • 수정해야 할 파일들

# app.js에서는 mongodb의 주소를 명시

# views/home.ejs에서는 alb의 리스너를 명시

 

1. app.js에서는 mongodb의 주소를 명시

root@aws-cli:~/Node.js-small-project-example# vi app.js

 

2. home.ejs에 넣을 alb의 주소가 필요하기때문에 alb를 생성

  • 로드밸런서 만드는 두가지 방법
    • 로드밸런서에서 alb를 생성 = ECS에서 서비스를 생성할때 '기존 로드밸런서'를 사용 가능
      : 타겟그룹에 ECS에서 생성한, 태스크를 자동으로 타겟그룹에 넣어줄 수 없음
    • ECS에서 서비스를 생성하면서 '새 로드밸런서를 생성'
      → ECS에서 만든 타겟그룹(자동으로 태스크가 포함) + 기존 로드밸런서

'기존로드밸런서'로 사용할 로드밸런서 생성

- 소스코드에 넣어주기 위함

  • 타겟그룹은 아무렇게나 (사용 안할 예정)

  • home.ejs에 넣어줄 주소

# 어차피 리스너도 안쓸것이고, 오히려 나중에 ECS에서 서비스를 만들때 새로운 리스너를 만들것이기 때문

root@aws-cli:~/Node.js-small-project-example# vi views/home.ejs

# chat서비스는 어차피 하나의 alb로는 구성이 불가능하기때문에 일단 비워둠 (ELB하나 더 써도 되지만 너무 비효율적)

  • 베이스 이미지

root@aws-cli:~/Node.js-small-project-example# pwd
/root/Node.js-small-project-example
root@aws-cli:~/Node.js-small-project-example# vi Dockerfile
FROM public.ecr.aws/docker/library/node:10.23-slim
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
CMD ["node","app.js"]
root@aws-cli:~/Node.js-small-project-example# docker build -t $ECR/nodejs:1 .
  • push하기 위한 레포 생성

root@aws-cli:~/Node.js-small-project-example# docker push $ECR/nodejs:1

3.  태스크 생성

  • nodejs 서비스 생성

 

# 만약에 chat 서비스도 구현하고 싶다면, 비슷한 방식으로 로드밸런서를 한개 더 만들어서 그 주소를 home.ejs파일에 넣어주고, ECR push후 push 된 이미지로 태스크를 개정한다음 똑같은 타겟그룹으로 된 다른 로드밸런서를 만들어주면 될 것 같다.

 

# 이 앱은 프론트와 백엔드가 하나로 합쳐진 앱. 브라우저가 백엔드를 직접 찾아가도록 만들어져있음.

 

# 원래는 브라우저 - 프론트 - 백엔드 - DB 이렇게 연결이 되어서 프론트와 백엔드사이에 리버스 프록시가 구성되어서, 브라우저가 백엔드를 찾아가는게 아니라, 프론트가 브라우저 대신 백엔드에 요청하고 응답값을 브라우저에게 반환을 해줘야함.


CI / CD (Continuous Integration / Continuous Delivery·Deployment)

  • CI툴 - Jenkins, github-action, AWS CodeBuild, Gitlab Runner
  • CD툴 - k8s의 ArgoCD, AWS CodeDeploy
  • AWS CodePipeline - CodeBuild + CodeDeploy(ECS)
  • GitOps - 깃허브를 사용하는 DevOps


1. 깃허브 레포를 마련

https://github.com/oolralra/ecspipe

  • 내 깃허브 계정에 로그인 한다음 위 레포로 가서 fork (fork = 내 레포로 복제)

  • 브랜치가 무엇인지(master) 꼭 확인


  • 기존꺼 제거
root@aws-cli:~# docker image prune -fa
  • 디스크 30GB 추가후 재부팅
root@aws-cli:~# vgextend ubuntu-vg /dev/sdb
root@aws-cli:~# lvextend -l +100%FREE -n /dev/mapper/ubuntu--vg-ubuntu--lv
root@aws-cli:~# resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv


root@aws-cli:~# git clone https://github.com/leeseohoo/ecspipe.git

# 현재 개발환경은 VM이고, github의 레포지토리는 원격지다. 클론한 디렉토리의 .git이라는 경로에 원격지와 VM의 동기화 정보가 담겨 있다. 따라서 개발환경에서만 수정을 하고, 변경사항을 github에 push하는 방식으로 동기화가 안깨지게 해야한다.

 

요약 = github에서는 수정안하는게 좋음

root@aws-cli:~/ecspipe# vi index.html

# 소스코드를 수정해서 github에 push

# 이 소스코드에 변경사항이 생김

root@aws-cli:~/ecspipe# git add .
root@aws-cli:~/ecspipe# git commit -m "delete 11"
root@aws-cli:~/ecspipe# git config --global user.email sm01004@naver.com
root@aws-cli:~/ecspipe# git config --global user.name leeseohoo

  • origin = 내 원격지인 깃허브 레포
root@aws-cli:~/ecspipe# git remote -v
origin https://github.com/leeseohoo/ecspipe.git (fetch)
origin https://github.com/leeseohoo/ecspipe.git (push)


  • origin이라는 원격지의 master라는 브랜치에 현재 ecspipe라는 경로의 파일들을 push
root@aws-cli:~/ecspipe# git push origin master
  • push를 위한 깃허브인증이 필요 = 깃허브토큰이 필요함

 

root@aws-cli:~/ecspipe# git push origin master
Username for 'https://github.com': 토큰복붙
Password for 'https://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@github.com': 토큰복붙
root@aws-cli:~/ecspipe# git commit -m "test"

push할때 토큰이 만료 ♨

재로그인

ERROR: invalid tag "/test:1": invalid reference format

$ECR environment variable is empty or not set
export ECR=741448938532.dkr.ecr.ap-northeast-2.amazonaws.com

  • 이미지 빌드
root@aws-cli:~/ecspipe# docker build -t $ECR/test:1 .
  • 이미지 테스트
root@aws-cli:~/ecspipe# docker run -dp 8989:80 --name test $ECR/test:1

# 테스트 성공

  • ECR에 push
root@aws-cli:~/ecspipe# docker push $ECR/test:1

push한 이미지로 태스크 생성

  • 빌드스펙의 컨테이너이름과 태스크를 생성할때 컨테이너의 이름을 반드시 일치시키기


서비스 생성 = 배포(deployment)


  • 수동배포 성공
root@aws-cli:~/ecspipe# curl test-alb-404680567.ap-northeast-2.elb.amazonaws.com


AWS에서 수동배포가 아닌 자동배포를 해보자

CodeBuild

 


webhook


# 깃허브레포에서 ci절차가 담겨있는 buildspec.yml을 받아온다. 이 빌드스펙안에는 앱을 빌드해서 컨테이너이미지로 만들고, ECR에 push하는 절차가 담겨있다. 이런 절차를 수행하려면 당연히 '환경'이 필요한데, AWS codebuild 서비스에서는 이 환경을 자동으로 제공해준다.

# 이름이 다르면 직접 써준다.


생성 후 ECR 접근 단계에서 실패 ♨

이 codebuild 프로젝트에 ECR에 접근할 수 있는 권한이 없기 때문

→ IAM 에서 Role을 찾은다음 Policy를 부여

  • 정책을 Role에 부여


  • '빌드'를 할때마다 ECR의 test레포에서 태그가 늘어나는걸 확인

  • 빌드가 완료되어 추가된 '3' tag

  • buildspec의 환경변수 $CODEBUILD_BUILD_NUMBER


  • 이번에는 소스코드를 변경하여 github에 푸쉬하여, codebuild가 동작되는지 확인
root@aws-cli:~/ecspipe# echo ci-test >> index.html
root@aws-cli:~/ecspipe# git add .
root@aws-cli:~/ecspipe# git commit -m "edit index"
root@aws-cli:~/ecspipe# git push origin master


CodePipeline

  • 개정된 태스크를 확인


자율과제)

sb_code로 여러분들 레포로 fork해서 한번 ECS에 CI/CD를 구성해보세요.