IT STUDY LOG

[AWS] 09. 컨테이너 배포 본문

devops bootcamp 4/클라우드 서비스 운영

[AWS] 09. 컨테이너 배포

roheerumi 2023. 4. 19. 17:23

# 학습 목표

  • Cloud와 Deployment의 의미를 각각 알고, 서비스를 남에게 배포할 수 있다.
  • 클라우드 컴퓨팅이 무엇인지 설명할 수 있다.
  • 애플리케이션 배포가 어떻게 변화되어 왔는지 이해할 수 있다.
  • AWS의 각 서비스가 어떤 목적에 부합하는지 이해할 수 있다.
  • S3의 목적과, 정적 웹 사이트 배포 방법을 이해할 수 있다.
  • EC2의 주요 용어를 이해할 수 있다. (AMI, 인스턴스, 인스턴스 유형, 스토리지 타입, 퍼블릭/프라이빗 IP)
  • EC2의 인스턴스 시작/중지/종료에 대해 이해할 수 있다.
  • RDS와 EC2에서의 MySQL 사용이 어떻게 다른지 이해할 수 있다.
  • CloudFront의 목적을 이해할 수 있다.
  • Auto Scaling의 특징 및 역할을 알 수 있다.
  • 로드 밸런서 중 ELB, 그 중에서 Application Load Balancer의 목적을 이해할 수 있다.
  • AWS 인프라 중 VPC에 대해서 이해할 수 있다.
  • Route 53의 목적을 이해하고, 도메인을 연결해 HTTPS로 배포할 수 있다.
  • 빌드 및 배포시 필요한 환경 설정을 할 수 있다.
  • 배포 시 발생하는 문제를 이해하고 고칠 수 있다.

 


# 학습 내용

1.  Amazon ECS/ECR

 

ECS

- ECS란 "Elastic Container Service"의 약어로, AWS에서 제공하는 컨테이너 오케스트레이션 서비스

 

ECS를 지원하는 세 가지 종류

ECS (EC2 launch type), EC2 launch type

- 가상 머신(VM) 위에서 컨테이너를 실행하는 방식

- EC2 인스턴스를 직접 관리해야 하므로, 조금 더 복잡한 설정이 필요

 

ECS (Fargate launch type), Fargate launch type

- 서버리스(serverless) 방식으로 컨테이너를 실행하는 방식

- EC2 인스턴스를 직접 관리하지 않아도 되기 때문에 간편하게 컨테이너를 실행 가능

 

ECS Anywhere, ECS Anywhere

- 로컬 데이터 센터나 에지 컴퓨팅(Edge Computing) 환경에서도 ECS를 사용할 수 있도록 지원하는 서비스

- 이를 통해 온프레미스(On-Premises) 환경에서도 컨테이너 오케스트레이션을 적용 가능

 

ECS 관련 개념 

ECS 클러스터

- Amazon EC2 인스턴스나 AWS Fargate 태스크를 호스팅하는 가상 컴퓨팅 환경

- CS 클러스터는 하나 이상의 인스턴스 또는 태스크를 실행하는 데 사용

- 작업이 실행되는 EC2들의 집합

 

ECS 서비스

- ECS 서비스는 컨테이너의 논리적 그룹

- 서비스는 지속적으로 실행되는 하나 이상의 작업으로 구성

- 작업은 하나 이상의 컨테이너 인스턴스를 실행

 

작업 (Task)

- 인스턴스에서 실행되는 실제 컨테이너 작업

- 하나 이상의 동일한 작업 정의를 기반으로 실행되는 하나 이상의 컨테이너 인스턴스를 나타내는 개체로 작업은 컨테이너 인스턴스 그룹으로 구성

- 작업은 특정 시점에 한 번 실행할 수도 있고, 주기적으로 실행되거나, 다른 이벤트에 따라 트리거 될 수 있음

- 작업은 ECS 서비스와 함께 사용되는 경우 지속적으로 실행되는 서비스의 일부가 될 수 있음

- 작업은 작업 정의(Task Definition)에서 정의된 컨테이너 이미지와 컨테이너 설정을 사용하여 실행

- 작업은 ECS 클러스터 내에서 실행되며, 작업을 실행할 EC2 인스턴스나 Fargate 태스크를 선택 가능

- 작업은 실행 중인 컨테이너 인스턴스에서 실행됨

- ECS에서 중요한 개념 중 하나이며, 컨테이너 기반 애플리케이션을 관리하고 실행하는 데 매우 유용

 

작업 정의

- 작업에 대한 컨테이너 및 환경 정의

- 작업 정의는 컨테이너 이미지와 실행 구성을 설명하는 객체

- 작업 정의는 ECS 서비스 또는 작업을 생성할 때 사용

- 작업 정의는 컨테이너 이미지, CPU 및 메모리 요구 사항, 컨테이너 실행 시 사용해야 하는 명령 등을 지정

 

클러스터 관리 엔진

- 클러스터 리소스 및 작업 상태 관리

 

스케쥴러

- 클러스터 상태를 고려한 작업 배치

 

에이전트

- EC2 인스턴스 및 매니저와 통신

 

2. Docker 이미지와 Amazon ECS를 이용한 풀스택 앱 배포

Step 0 : 사전 작업: 소스 코드 수정하기

  1. 백엔드 코드 backend/app.js 는 3333번 포트를 노출하는 것으로 변경
    - const port = 80
    + const port = 3333
  2. 프론트엔드 코드 frontend/script.js의 첫번째 줄의 AJAX 요청을 다음과 같이 변경
    - fetch('http://localhost:3333/')
    + fetch(`http://${location.hostname}:3333/`)
  3. (optional) Apple M1을 이용하는 경우, Dockerfile 수정
    - FROM httpd:2.4
    + FROM --platform=linux/amd64 httpd:2.4
    
    - FROM node:16-alpine 
    + FROM --platform=linux/amd64 node:16-alpine

Step 1 : Build a ship a Compose Application

프로젝트 구조 확인

$ tree sprint-docker-app/
...
2 directories, 6 files

 

docker-compose.yml 파일 수정

- push를 염두해 이미지 이름 및 태그를 바르게 지정

version: "3.0"

services:
  frontend:
    build: frontend
    image: <도커허브아이디>/frontend:1.0
    restart: 'always'
    ports:
      - target: 80
        published: 80
        x-aws-protocol: http
    depends_on:
      - backend
    container_name: frontend_container
  backend:
    build: backend
    image: <도커허브아이디>/backend:1.0
    restart: 'always'
    ports:
      - target: 3333
        published: 3333
        x-aws-protocol: http
    container_name: backend_container

-  포트 구성에서 target과 published를 일치하도록 만든 이유

 > 컨테이너 내부에서 사용하는 포트(target)와, ECS(호스트)에서 사용할 포트(published)를 일치시키기 위해

- x-aws-protocol 속성의 의미

 > Compose 파일의 서비스가 포트 80 또는 443만 노출하는 경우 Application Load Balancer가 생성되지만, 그렇지 않으면 ECS 통합이 Network Load Balancer를 프로비저닝

 > x-aws-protocol를 사용하면 고유한 포트를 사용하는 HTTP 서비스는 포트 선언 내에서 사용자 지정 확장이 있는 http 프로토콜을 요청하여 ALB를 강제로 사용 가능

 

docker-compose.yml 파일을 이용해서 로컬에서 도커 기동 및 정상 작동 확인

$ docker compose up -d
[+] Running 3/3
⠿ Network "myproject_default"     Created                     0.5s
⠿ Container myproject_backend_1   Started                     0.7s
⠿ Container myproject_frontend_1  Started                     1.4s

$ docker ps
CONTAINER ID   IMAGE                COMMAND                    CREATED         STATUS         PORTS                NAMES
eec2dd88fd67   myproject_frontend   "/docker-entrypoint...."   4 seconds ago   Up 3 seconds   0.0.0.0:80->80/tcp   myproject_frontend_1
2c64e62b933b   myproject_backend    "python3 /app/main.py"     4 seconds ago   Up 3 seconds                        myproject_backend_1

 

http://localhost 에 잘 연결되었는지 확인

 

기동한 컨테이너 중지

$ docker compose down
[+] Running 3/3
⠿ Container myproject_frontend_1  Removed                                                 0.5s
⠿ Container myproject_backend_1   Removed                                                10.3s
⠿ Network "myproject_default"     Removed                                                 0.4s

 

이미지 빌드

$ docker compose build
[+] Building 1.2s (16/16) FINISHED                                                                                                                                 
=> [myhubuser/starter-front internal] load build definition from Dockerfile            0.0s
=> => transferring dockerfile: 31B                                                     0.0s
=> [myhubuser/starter-back internal] load build definition from Dockerfile 0.0s
...

 

 

이미지를 내 Docker Hub에 push

- ECS에 애플리케이션을 배포하기 위해서는 공개된 레파지토리에 이미지 푸시가 되어야함

- http://hub.docker.com 이미지가 repository에 push되었는지 확인

$ docker login
...
Login Succeeded

$ docker compose push
[+] Running 0/16
⠧ Pushing Pushing frontend: f009a503aca1 Pushing              [===========================================...                                        2.7s
...

 

Step 2 : Create an ECS context to target Amazon ECS

AWS CLI 설치 - (Linux, Ubuntu)

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install

- "docker context create" requires exactly 1 argument 에러가 나면서 context가 생성이 되지 않는 경우 공식 문서 참고

$ curl -L https://raw.githubusercontent.com/docker/compose-cli/main/scripts/install/install_linux.sh | sh

 

AWS 액세스 키 및 시크릿 키 발급

- 아이디/비밀번호 방식의 로그인이 아닌, 프로그래밍 방식의 액세스를 위해서 액세스 키 발급이 필요 ※ 민감한 정보로 노출에 유의할 것, 액세스 키 및 시크릿 키는 비밀번호와 동일하게 취급

 

액세스 키 관리(콘솔)

1. AWS 계정 ID나 계정 별칭, IAM 사용자 이름 및 암호를 사용하여 IAM 콘솔에 로그인AWS 계정 ID를 받으려면 관리자에게 문의

2. 오른쪽 상단의 탐색 모음에서 사용자 이름을 선택한 다음 Security credentials(보안 자격 증명)를 선택

 

 

액세스 키 생성

1. 액세스 키 섹션에서 Create access key(액세스 키 생성)를 선택 (이미 두 개의 액세스 키가 있는 경우, 이 버튼은 비활성화되어 있으며 액세스 키를 삭제해야 새로 생성 가능)

2. Access key best practices & alternatives(액세스 키 모범 사례 및 대안) 페이지에서 액세스 키가 필요하다고 판단되면 Other(기타), Next(다음)를 차례로 선택

3. (선택 사항) 액세스 키에 대한 설명 태그 값을 설정 이렇게 하면 IAM 사용자에게 태그 키-값 페어가 추가

4. 모두 마쳤으면 Create access key(액세스 키 생성)를 선택

5. Retrieve access keys(액세스 키 검색) 페이지에서 Show(표시)를 선택하여 사용자의 비밀 액세스 키 값을 표시하거나 Download .csv file(.csv 파일 다운로드)을 선택 ※ 이것이 비밀 액세스 키를 저장할 수 있는 유일한 기회

6. 비밀 액세스 키를 안전한 위치에 저장한 후 Done(완료)을 선택

 

액세스 키 비활성화

1. Access keys(액세스 키) 섹션에서 비활성화하려는 키를 찾은 다음 Actions(작업), Deactivate(비활성화)를 차례로 선택

2. 확인 메시지가 나타나면 Deactivate(비활성화)를 클릭 비활성화된 액세스 키는 여전히 두 개의 액세스 키 제한에 포함

 

액세스 키 활성화

1. Access keys(액세스 키) 섹션에서 활성화하려는 키를 찾은 다음 Actions(작업), Activate(활성화)를 차례로 선택

 

더이상 필요하지 않은 액세스 키 삭제

1. Access keys(액세스 키) 섹션에서 삭제하려는 키를 찾은 다음 Actions(작업), Delete(삭제)를 차례로 선택

2. 대화 상자의 지침에 따라 먼저 Deactivate(비활성화)를 수행한 다음 삭제를 확인 액세스 키를 영구적으로 삭제하기 전에 액세스 키가 더 이상 사용되고 있지 않은지 확인

 

Amazon ECS 컨텍스트 생성 (공식 문서 참고) 

- 컨테이너의 실행이 내 호스트 PC가 아닌, ECS 플랫폼 상에서 이루어지도록 만듦

 

1. sudo 명령어를 이용해 ECS context 생성, 이 때 발급한 secret and token 사용

- environment variables 같은 경우 ~/.aws/config 등에 환경 변수 설정해 context를 생성하는 것

$ sudo docker context create ecs myecscontext
? Create a Docker context using:  [Use arrows to move, type to filter]
  An existing AWS profile
> AWS secret and token credentials
  AWS environment variables

- 정상적으로 만들어졌는지 확인

$ sudo docker context ls
NAME                TYPE      DESCRIPTION                                   DOCKER ENDPOINT       
default *           moby      Current DOCKER_HOST based configuration       unix:///var/run/docker.sockmyecscontext        ecs       credentials read from environment

 

2. 생성한 ECS Context로 배포 환경 전환 (맥락 이동)

$ sudo docker context use myecscontext
myecscontext


$ sudo docker context ls
NAME                TYPE         DESCRIPTION                               DOCKER ENDPOINT              
default             moby         Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
myecscontext *      ecs          credentials read from environment

 

3. 명령어 수행 시 편의를 위해 환경 변수에 액세스 키 설정

$ AWS_ACCESS_KEY="*****" AWS_SECRET_KEY="******" docker compose ls
NAME                                STATUS


$ export AWS_ACCESS_KEY="*****"
$ export AWS_SECRET_KEY="******"

 

Step 3 : Run the Compose application on Amazon ECS

compose 파일을 실행해 ECS(not local) 상에서 컨테이너 생성 (시간 소요 주의)

$ sudo docker compose up
WARNING services.build: unsupported attribute       
WARNING services.build: unsupported attribute       
[+] Running 18/18
⠿ myproject                      CreateComplete                                     206.0s
⠿ FrontendTCP80TargetGroup       CreateComplete                                       0.0s
⠿ CloudMap                       CreateComplete                                      46.0s
⠿ FrontendTaskExecutionRole      CreateComplete                                      19.0s
⠿ Cluster                        CreateComplete                                       5.0s
⠿ DefaultNetwork                 CreateComplete                                       5.0s
⠿ BackendTaskExecutionRole       CreateComplete                                      19.0s
⠿ LogGroup                       CreateComplete                                       1.0s
⠿ LoadBalancer                   CreateComplete                                     122.0s
⠿ Default80Ingress               CreateComplete                                       1.0s
⠿ DefaultNetworkIngress          CreateComplete                                       0.0s
⠿ BackendTaskDefinition          CreateComplete                                       2.0s
⠿ FrontendTaskDefinition         CreateComplete                                       3.0s
⠿ FrontendServiceDiscoveryEntry  CreateComplete                                       1.0s
⠿ BackendServiceDiscoveryEntry   CreateComplete                                       2.0s
⠿ BackendService                 CreateComplete                                      65.0s
⠿ FrontendTCP80Listener          CreateComplete                                       3.0s
⠿ FrontendService                CreateComplete                                      66.0s

- ECS 컨텍스트 상에서 docker compose up을 한 경우, 실제로 생성되는 AWS 리소스(CloudMap을 비롯하여 총 21개의 리소스가 생성) 

 

compose 파일을 AWS 리소스 집합으로 변환해주는 CloudFormation 파일로 변환

$ sudo docker compose convert
WARNING services.build: unsupported attribute       
WARNING services.build: unsupported attribute       
AWSTemplateFormatVersion: 2010-09-09
Resources:
  BackendService:
    Properties:
      Cluster:
        Fn::GetAtt:
        - Cluster
        - Arn
      DeploymentConfiguration:
        MaximumPercent: 200
        MinimumHealthyPercent: 100...

 

ECS 상에서 컨테이너 실행되었는지 확인

$ sudo docker compose ps
NAME                                              SERVICE             STATUS              PORTS
task/myproject/8c142dea1282499c83050b4d3e689566   backend             Running            
task/myproject/a608f6df616e4345b92a3d596991652d   frontend            Running             mypro-LoadB-1ROWIHLNOG5RZ-1172432386.eu-west-3.elb.amazonaws.com:80->80/http

 

ECS에서 기동되는 컴포즈 컨테이너 로그 확인

$ sudo docker compose logs
backend  |  * Serving Flask app "main" (lazy loading)
backend  |  * Environment: production
backend  |    WARNING: This is a development server. Do not use it in a production deployment.
backend  |    Use a production WSGI server instead.
...
frontend  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
frontend  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
frontend  | /docker-entrypoint.sh: Configuration complete; ready for start up
frontend  | 172.31.22.98 - - [02/Mar/2021:08:35:27 +0000] "GET / HTTP/1.1" 200 212 "-" "ELB-HealthChecker/2.0" "-"
backend   | 172.31.0.11 - - [02/Mar/2021 08:35:27] "GET / HTTP/1.0" 200 -
backend   | 172.31.0.11 - - [02/Mar/2021 08:35:57] "GET / HTTP/1.0" 200 -
frontend  | 172.31.22.98 - - [02/Mar/2021:08:35:57 +0000] "GET / HTTP/1.1" 200 212 "-" "curl/7.75.0" "94.239.119.152"
frontend  | 172.31.22.98 - - [02/Mar/2021:08:35:57 +0000] "GET / HTTP/1.1" 200 212 "-" "ELB-HealthChecker/2.0" "-"

 

AWS Elastic Container Service로 이동해 아래 대시보드 확인


 

EC2의 로드 밸런서 확인

- 자동으로 로드 밸런서가 하나 생성되고, 각 리스너마다 Fargate 서비스가 대상 그룹으로 지정되어 있는 것 확인 가능


 

로드 밸런서 DNS 주소로 접속 시 로컬 환경과 마찬가지로 컨테이너가 작동하는 것을 확인


 

모든 리소스를 삭제하기 위해서는 docker compose down 실행 (시간 소요 주의, clean up을 위해 중지 금지)

$ sudo docker compose down
[+] Running 2/4
⠴ myproject              DeleteInProgress User Initiated                                        8.5s
⠿ DefaultNetworkIngress  DeleteComplete                                                         1.0s
⠿ Default80Ingress       DeleteComplete                                                         1.0s
⠴ FrontendService        DeleteInProgress                                                       7.5s...

 

 

# References

- openai (챗 gpt)

- 도커 compose와 ecs 속성 매핑

 

ECS integration Compose features

 

docs.docker.com

https://docs.docker.com/compose/compose-file/compose-file-v3/

 

Compose file version 3 reference

 

docs.docker.com

https://docs.docker.com/engine/reference/run/#managing-etchosts

 

Docker run reference

 

docs.docker.com

https://stackoverflow.com/questions/46266527/could-not-reliably-determine-the-servers-fully-qualified-domain-name-how-to

 

Could not reliably determine the server's fully qualified domain name ... How to solve it in Docker?

I am just starting in Docker and I was following that tutorial that shows basically these steps: Create a Dockerfile like this: From php:7.0-apache copy src/ /var/www/html EXPOSE 80 Build the con...

stackoverflow.com

https://docs.docker.com/engine/context/working-with-contexts/

 

Docker Context

 

docs.docker.com

https://www.docker.com/blog/docker-compose-from-local-to-amazon-ecs/

 

Docker Compose: From Local to Amazon ECS | Docker

Learn from Docker experts to simplify and advance your app development and management with Docker. Stay up to date on Docker events and new version

www.docker.com

https://docs.docker.com/cloud/ecs-integration/#install-the-docker-compose-cli-on-linux

 

Deploying Docker containers on ECS

 

docs.docker.com

https://aws.amazon.com/ko/blogs/containers/deploy-applications-on-amazon-ecs-using-docker-compose/

 

Deploy applications on Amazon ECS using Docker Compose | Amazon Web Services

There are many reasons why containers have become popular since Docker democratized access to the core Linux primitives that make a “docker run” possible. One reason is that containers are not tied to a specific infrastructure or stack, so developers c

aws.amazon.com

 

'devops bootcamp 4 > 클라우드 서비스 운영' 카테고리의 다른 글

[지속적 통합] 02. 지속적 통합  (0) 2023.04.20
[지속적 통합] 01. CI/CD 리뷰  (0) 2023.04.20
[AWS] 08. 보안  (0) 2023.04.18
[AWS] 08. 서비스 노출  (0) 2023.04.17
[AWS] 07. 수평확장  (0) 2023.04.17
Comments