본문 바로가기
docker-kub

ECS를 이용한 배포

by 오우지 2023. 1. 2.

1. 단일 컨테이너를 ECS에 배포하기

ECS를 사용하기 전에 직접 로컬에서 만든 이미지를 docker hub에 올리고 EC2 등의 서버에 ssh 접속을 통해 빌드 해 주는 방법도 있다.

하지만 너무 불편하다 또한 로드 밸런서를 사용하려고 한다면 새로운 서버가 생성될 때마다 배포를 해줘야 하는데 현실적으로 말이 안된다.

 

따라서 ECS를 사용하려고 한다. ECS는 클러스터, 컨테이너, 테스크, 서비스 네 가지 범주로 구분된다. 

 

ECS 설정을 하면서 각각의 레이어가 어떤것을 의미하는지 알아보자.

 

 

1. Container

컨테이너부터 만들어보자

네 가지 옵션이 있는데 우선 커스텀 옵션을 통해 단일 컨테이너를 배포해보자.

 

컨테이너를 만드는데 들어가는 설정들은 모두 docker run 시에 추가되는 옵션이라고 보면 된다. 예를 들어 포트포워딩, 볼륨 등의 옵션들이다. 세부 설정들은 Dockerfile에서 해줬을 텐데 그 외의 docker run 옵션들을 여기에서 추가해줄 수 있다. 

 

포트 아래에는 ECS를 위한 헬스체크 세팅, 도커에서 했던 것처럼 entrypoint 설정(작업루트 설정), 환경변수 등을 추가할 수 있다. 만약 docker run이 아닌 Dockerfile을 사용해 configure 해줬다면 딱히 입력할게 없다.

2. Task

말 그대로 작업에 대한 정의다. 어떤 네트워크 설정을 사용할 것인지, serverless 환경을 사용할 것인지 ec2 환경을 사용할 것인지 등등에 대한 정의를 이곳에서 해준다. docker run 이전에 이를 실행하는 서버 환경이라고 생각하면 된다. 하나의 테스크에는 여러 컨테이너가 실행될 수 있다.

 

3. Service

 

로드 밸런서에 대한 설정, 보안 그룹 설정 등 애플리케이션과 그를 포함하는 컨테이너를 실행하는 방법을 컨트롤 한다.

4. Cluster

클러스터는 다중 컨테이너 상황에서 해당 네트워크 구성을 어떻게 가져갈지에 대한 옵션이다. 로컬에서 도커를 이용해 가상화를 할 때 하나의 네트워크 안에 있으면 각각의 컨테이너 이름으로 컨테이너간에 환경변수 사용도 가능했는데 이걸 클러스터라고 생각하면 될 것 같다. 물론 ECS에서 컨테이너이름으로 환경변수로 사용하는건 지원이 안된다고 한다.

 

 

이렇게 설정을 다 해주고 Create를 누르면

열심히 만든다. 비싸겠다.

 

만약 이렇게 만든 클러스터에 넣는 이미지를 변경하고 싶다면 이미지가 인입되는 구간인 서비스를 업데이트 해줘야 한다.

 

도커 컴포즈를 이용하면 로컬에서 여러 컨테이너를 실행하기는 편리하지만 배포 환경에서는 그리 편리하지 않다. 특히나 ECS 같은 클러스터 환경에서는 더 그렇다. 위에서 말했듯이 도커 컴포즈에서 컨테이너 이름으로 네트워킹 할 수 있는 편리함은 ECS에서 지원되지 않는다. ECS가 동일 컴퓨터에서 실행된다는 보장이 없기 때문에 그렇다. 그 대신 ECS는 같은 클러스터 안에 있다면  localhost로 해당 ip를 찾아가는 기능을 제공한다. 멀티 컨테이너 환경을 가정하고 클러스터링을 해보자.


2. 다중 컨테이너를 ECS에 배포하기

 

로컬 개발환경을 위해 도커 컴포즈를 통해 구성해줬던 코드를 이제 클러스터 위에서 구성해주자 도커 컴포즈는 동일한 머신에서 다중 컨테이너를 관리하는데는 유용하지만 다중 서버 환경에서 사용하기엔 제약사항들이 있다. 따라서 위에서 이야기 한대로 각각의 컨테이너를 Task에 정의하고 클러스터로 묶어주면 다중서버 환경에서도 도커 컴포즈와 비슷한 서버 구성을 가져갈 수 있다.

 

기존의 도커 컴포즈 설정은 아래와 같았는데 이걸 ECS가 대신 해주게 설정한다고 생각하면 될 것 같다.

version: '3.8'
services:
  mongodb:
    image: 'mongo'
    volumes:
      - data:/data/db
    env_file:
      - ./env/mongo.env
  backend:
    build: ./backend
    ports:
      - '80:80'
    volumes:
      - ./backend:/app
      - /app/node_modules
    env_file:
      - ./env/backend.env
    depends_on:
      - mongodb

volumes:
  data:

 

먼저 백과 DB만 띄워보자. 로컬의 이미지를 빌드하기 전에 서버에서 몽고DB를 접근할 때 이전에는 같은 네트워크에 있었기 때문에 컴포즈 파일에서 지정한 mongodb라는 서비스 이름으로 각각의 url에 접근 가능했다. 하지만 ECS에서 이런 네이밍은 지원하지 않기 때문에

mongodb:27017/course-goals?authSource=admin

이랬던 url을 로컬 환경과 프로덕션 환경에서 동일하게 가져가기 위해

${process.env.MONGODB_URL}:27017/course-goals?authSource=admin

이렇게 설정해주고 로컬에서 환경변수도 직접 설정파일에서 설정해주고 이미지를 빌드해서 도커허브에 올려주자.

 

1. Cluster

클러스터라는 단어 자체가 다중 컨테이너를 전제로 한 단어다. 우선 클러스터를 생성해주자.

 

이전 버전의 ECS를 사용해 만들어줬다.

클러스터 구성은 다음과 같이 가져가준다.

 

 

2. Service

단일 컨테이너 상황에서는 docker run의 명령어를 대체할 컨테이너 정의부터 해줬다면 이제 도커 컴포즈를 대체할 테스크를 하나씩 정의해보자. 테스크를 만들면 그 안에 개별 컨테이너들을 설정해줄 수 있는데

우선 서버리스인 FARGATE를 이용해서 테스크를 하나 만들어주자.

최신 버전에서는 컨테이너를 다음과 같이 설정해주고
이전 버전에서는 다음과 같이 크기와 IAM역할부터 지정해준다. 순서야 어찌됐든 이 설정을 만날 수 있다.

이제 컨테이너를 추가해주자.

로컬에서는 nodemon을 이용해서 코드 변경사항을 개발 환경에 바로 적용되게 해줬지만, 운영환경에서 노드몬은 필요 없다. 운영 서버에서 IDE 깔아서 코드 수정할거 아니니까.

따라서, package.json에서 scripts 설정의 start에 설정되어 있는 nodemon app.js를 찾아서 실행해주는 역할을 하는 npm start 명령어가 아닌 다른 서버 시작 명령어 node, app.js를 실행해준다.

 

docker-compose에서 작성해줬던 환경변수도 파일이 아닌 환경변수 탭에 직접 입력해준다.

localhost는 같은 태스크 안에 있는 타 컨테이너와 연결하기 위함인데, 어플리케이션에서 환경에 따라 변경되어야 할 변수들은 모두 환경변수를 가져가줬고, 로컬에서는 도커 컴포즈에서는 env파일로 매핑, 운영 환경에서는 환경변수로 매핑줬다. 이로써 환경에 따라 설정 변경점 없이 두 환경에서 사용할 수 있다.

 

 

메인 db로 사용할 mongodb를 띄워보자. 이미지는 mongo의 공식 이미지를 사용한다. 환경변수도 mongo.env에 있는 설정들을 변수로 등록해준다.(몽고DB 초기 부팅시 ID와 PW를 지정해주는 환경변수)

도커컴포즈에선 몽고 데이터를 보존하기 위한 볼륨도 추가해줬지만 조금 있다가 처리해주도록 하고 컨테이너를 만들어보자

 

3. Task

이 테스크를 기반으로 서비스를 만들면 된다. 서비스는 위에서 말했듯 로드밸런싱, 보안그룹 등 컨테이너를 실행할 방법에 대한 설정이다.

로드밸런서를 세팅해주고 VPC에 연결해주면 온전한 컨테이너화된 어플리케이션을 띄울 수 있다.

로드밸런서는 어플리케이션 로드밸런서로 ECS가 포함된 VPC와 동일한 VPC를 선택해줘야 하고 

대상그룹은 컨테이너가 Fargate를 사용하기 때문에 IP주소로 잡고 만들어 줘야 한다.

 

로드밸런싱은 패스하고 서비스를 생성해주면 된다.

 

EFS볼륨을 사용해 ECS에서 띄워논 mongoDB의 볼륨을 외부 스토리지에 저장할 수 있다. 하지만 이런 방법은 스케일과 퍼포먼스, 백업등의 보안 작업에 있어서 단점이 있다. 이를 해결하기 위해선 클라우드 기반 MongoDB 서비스인 MongoDB Atlas를 쓰는 것이 합리적이다.

 

Atlas에서 클러스터를 하나 만들면 접속을 위한 다음과 같은 url이 나온다.

 

`mongodb+srv://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}@${process.env.MONGODB_URL}:/${process.env.MONGODB_NAME}?authSource=admin`

기본적으로 테스트 DB는 격리하는게 나을 것 같지만 우선은 DB 내에서 구분해보자.

이렇게 DB 연결부에 써주고 환경변수도 로컬에 정의하면 이제 아틀라스에서만 적용해주면 완료된다.

'docker-kub' 카테고리의 다른 글

kubernetes - intro  (0) 2023.01.28
docker - 멀티스테이지 빌드  (0) 2023.01.15
docker - Docker Compose, utility container  (0) 2022.11.13
docker - 멀티 컨테이너 어플리케이션  (0) 2022.10.30
docker - 네트워킹  (0) 2022.10.19