본문 바로가기
리눅스/Part2. Ch01. 클라우드 기반 컨테이너 운영

05. (실습) Amazon ECS에 어플리케이션 배포

by Engineer-Lee 2022. 12. 8.
반응형

AWS 자원 어떻게 구성해야 하나요?

웹 호스팅을 위한 AWS 클라우드 아키텍처

 

 

 

 

AWS 클라우드 쉽게 사용해보기 -> PaaS 처럼 써보기

Poll앱을 쉽게 배포해보기

- 샘플 프로젝트 : https://github.com/go4real/Django-Poll-App
- 컴퓨팅 환경: Amazon ECS + AWS Fargate à 서버리스 환경
* AWS Elastic Beanstalk 사용 대비 서비스 확장에 따른 자유도가 높음
- 빌드/배포 : AWS Copilot CLI

 

AWS Copilot CLI는 아래와 같이 프로비저닝해야 하는 많은 자원들을 생성해준다.

 

 

 

 

 

 

 

 


실습자료: https://github.com/go4real/linux_campus

1단계. 실행 환경 구성 (Part2/Ch01_06/01_environment_setup.md)

- AWS Copilot CLI 설치
- Copilot CLI 실행 권한 설정
(Role 생성 + Policy 적용)
- AWS CLI 설치
- Docker desktop 설치
- Project 코드가 없는 경우 코드 새로 받기
git clone https://github.com/go4real/Django-Poll-App.git
git checkout ecs-base

 

 

1. AWS Copilot cli 설치

https://aws.github.io/copilot-cli/docs/getting-started/install/
```
curl -Lo copilot https://github.com/aws/copilot-cli/releases/latest/download/copilot-linux && chmod +x copilot && sudo mv copilot /usr/local/bin/copilot && copilot --help 명령어 입력
```


+ copilot 자동 완성 기능 설정
```
source <(copilot completion bash)
copilot completion bash > copilot.sh
sudo mv copilot.sh /etc/bash_completion.d/copilot
```

 

 

2. AWS EC2에 적용할 IAM role 생성 및 적용

aws 서비스와 ec2를 선택 후 다음을 누른다.

Administrator Access 권한을 부여하고 다음을 누른다.

 

역할 이름을 ECSDemo로 설정하고 역할을 생성한다.

 

동작중인 ec2 인스턴스의 IAM 역할 수정을 한다.

 

이 작업을 통해 ec2 인스턴스 내에서는 AWS CLI를 수행할때 관리자 권한으로 실행된다.

 

 


3. AWS CLI 설치

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html
```
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```

 

 


4. AWS CLI 설정  (ap-northeast-2)

```
aws configure
```

 

 


5. Docker Desktop

https://docs.docker.com/engine/install/ubuntu/
https://docs.docker.com/engine/install/linux-postinstall/
```
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker   # vs remote server 재시작 또는 sudo reboot
```

6. Git에서 새로 코드를 받으시는 분들

```
git clone https://github.com/go4real/Django-Poll-App.git
cd Django-Poll-App
git checkout ecs-base
```

 

 


 

2단계. 애플리케이션 구성 (Part2/Ch01_06/02_app_provisioning.md)

- Copilot 애플리케이션: 서비스와 환경의 집합
- 추가 단계: PostgresDB 배포

 

 

1. ECS 앱 생성  프로젝트 루트에서 실행

```
copilot init
# Application name: poll-app


## poll-db 서비스 생성
# Workload type: Backend Service
# Service name: poll-db
# Dockerfile: Use an existing image instead
# Image: postgres
```

Deploy는 뒤에 몇가지 수정 작업을 거친 후에 할 것이기에 NO를 입력한다.

 


2. copilot 디렉토리 내용 확인

+ postgres 포트 설정 
+ copilot/poll-db/manifest.yml
...
image:
  location: postgres
  port: 5432    # 공개할 포트정보 추가
...
```

포트 정보를 추가로 입력한다.

 


3. dev 환경 생성

```
copilot env init 
# Environment name: dev
# Credential source: [profile default]
# 다른 항목은 기본설정 사용
```

+ 3분 이상 시간 소요  --> AWS Web Console에서 인프라 생성 내용 확인 (ECS, CloudFormation 등)

 


4. poll-db 서비스 배포 

```
copilot deploy
```
+ AWS Console에서 배포 상태 확인
+ 오류 확인 : Error: Database is uninitialized and superuser password is not specified.
+ ctrl+c로 copilot 실행 종료

 


5. Database 초기 실행 정보 설정

+ copilot/poll-db/manifest.yml
...
variables:                    # Pass environment variables as key value pairs.
  POSTGRES_DB: poll
  POSTGRES_USER: fast
  POSTGRES_PASSWORD: 1234qwer
...

 


6. deploy 실행 

```
copilot deploy
# ✘ execute svc deploy: deploy service poll-db to environment dev: deploy service: stack poll-app-dev-poll-db is currently being updated and cannot be deployed to
```

 


7. Circuitbreaker 에서 기본 서비스 시작 재시도 횟수 10번 실패

+ 수분 이상 소요


8. 배포작업 자동 롤백 및 CloudFormation 종료 

 


9. 다시 deploy 진행

```
copilot deploy
```
+ 서비스 배포 완료 확인 

 

 


 

3단계. 백엔드 서비스 구성 (Part2/Ch01_06/ 03_backend_deploy.md)

- poll-backend 서비스 구성
- poll-db 서비스에 데이터베이스 연결 구성

 

 

1. 프로젝트 루트 위치에 Dockerfile.backend 파일 생성

```
FROM python:3.8-slim-buster

ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE 1

RUN apt-get update \
  && apt-get install -y gcc libpq-dev python-dev \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install -r requirements.txt
COPY . .

EXPOSE 8000
ENTRYPOINT [ "sh", "./docker-entrypoint.sh" ]
```

 


2. 프로젝트 루트 위치에 docker-entrypoint.sh 파일 생성

+ 앱 실행 전에 스키마 변경 내용을 반영하는 migrate 커맨드 실행
```
#!/bin/bash

# Apply database migrations
echo "Apply database migrations"
python manage.py migrate

# Start server
echo "Starting server"
gunicorn --bind 0.0.0.0:8000 --workers 3 pollme.wsgi:application
```

 

 

3. Database 엔드포인트 설정

+ pollme/settings.py
```
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('POSTGRES_DB'),
        'USER': os.environ.get('POSTGRES_USER'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        #'HOST': os.environ.get('POSTGRES_HOST'),
        'HOST': "poll-db.{}".format(os.environ.get('COPILOT_SERVICE_DISCOVERY_ENDPOINT')),
        'PORT': '5432',
    }
}
```

 


4. Poll backend 서비스 생성

```
copilot init
# Workload type: Backend Service
# Service name: poll-backend
# Dockerfile: ./Dockerfile.backend
```

 


5. 포트 정보 추가 및 데이터베이스 접속을 위한 환경 변수 설정

+ copilot/poll-backend/manifest.yml

image:
  # Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/backend-service/#image-build
  build: Dockerfile.backend
  # Port exposed through your container to route traffic to it.
  port: 8000   # 포트정보 추가

variables:                    # Pass environment variables as key value pairs.
  POSTGRES_DB: poll     # DB관련 환경변수 추가 
  POSTGRES_USER: fast
  POSTGRES_PASSWORD: 1234qwer

 

 

6. Poll backend 서비스 배포

copilot deploy

 


7. AWS Web Console에서 Poll backend 서비스 배포 상태 확인 





 

4단계. 프론트엔드 서비스 구성 (Part2/Ch01_06/04_frontend_deploy.md)

- poll-frontend서비스 구성
- nginx로 reverse proxy 구성
동적 컨텐츠: poll-backend 서비스로 라우팅
정적 컨텐츠: 직접 제공

 

 

1. nginx 설정에 환경 변수 사용을 위해 template 사용

+ nginx/config/nginx.conf 내용 수정
```
events {
  worker_connections  4096;  ## Default: 1024
}
http {
    charset utf-8;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
```

 


2. nginx/templates/default.conf.template 파일 생성

```
server {
    listen      80;
    server_name localhost; # IP 또는 FQDN으로 변경. 실습에서는 AWS 콘솔에서 IP 확인
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    location /static/ {
        alias /data/static/; # Django 프로젝트의 static 파일 위치. 실습에서는 Dockerfile에서 지정.
    }

    location / {
        # 실습에서는 host의 private ip 사용 ($ ip address show eth0)
        #proxy_pass              http://app:8000;  
        proxy_pass              http://poll-backend.${COPILOT_SERVICE_DISCOVERY_ENDPOINT}:8000;  
        proxy_set_header        Host $host;
    }
}
```

 


3. 프로젝트 루트 위치에 Dockerfile.frontend 파일 생성


```
FROM nginx
COPY nginx/templates /etc/nginx/templates/
COPY nginx/config/nginx.conf /etc/nginx/nginx.conf
COPY static /data/static

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
```

 


4. Poll frontend 서비스 생성

```
copilot init

# Workload type: Load Balanced Web Service
# Service name: poll-frontend
# Dockerfile: ./Dockerfile.frontend
```

 


5. ELB 헬스체크를 지원하기 위해 헬스체크용 미들웨어 구성

- polls/middleware.py 파일 생성
```
from django.http import HttpResponse


class HealthCheckMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.path == "/health":
            return HttpResponse("ok")
        response = self.get_response(request)
        return response
```

 

- pollme/settings.py 수정
```
MIDDLEWARE = [
    'polls.middleware.HealthCheckMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
...
```

 


6. poll-frontend 서비스에 health check 경로 설정

```
http:
  # Requests to this path will be forwarded to your service.
  # To match all requests you can use the "/" path.
  path: '/'
  # You can specify a custom health check path. The default is "/".
  healthcheck: '/health'
```

 


7. Poll frontend 서비스 배포

copilot deploy


8. AWS Web Console에서 Poll frontend 서비스 배포 상태 확인 

+ 400 오류 확인 --> 트러블 슈팅

 

9. 배포된 Poll 앱 확인 

+ Invalid HTTP_HOST header 오류 확인 --> 트러블 슈팅


10. pollme/settings.py 수정

```
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

ALLOWED_HOSTS = ['.elb.amazonaws.com']
```

 


11. Poll backend 서비스 빌드/배포

copilot deploy


12. Test

+ 배포된 Poll 앱 확인 
+ 테스트: 회원 가입 및 로그인 


시간 관계상 강의에 포함 못한 Copilot 기능들

비밀키 관리

- Postgres 패스워드를 암호화 à $ copilot secret init

Database 서버 구성

- Aurora Serverless à $ copilot storage init

CI/CD 파이프라인 구성

- Code Pipeline à $ copilot pipeline init

 

반응형