본문 바로가기

Compute

[실습] ECS로 Container(EC2, Fargate) 생성하기(With ECR, EFS, SSM, CloudWacth, CodePipeline)

반응형

안녕하세요 서후아빠입니다. ^_^

이번 세션은 AWS Container Platform의 대표 ECS에 대해서 연동 가능한 여러 서비스와 함께 실습을 해보겠습니다.

Container에서 Parameter Store 사용하는 부분, Container간 연결, CodePipeline 등은 이 세션에서 다루지 않고 별도 세션에서 포스팅 하도록 하겠습니다. 언제가 될지 가늠이 되지 않으니 무작정 기다리지는 마세요. ㅜㅜ


구성도

ECS 구성 및 흐름도

구조가 복잡해 보여서 송구스럽습니다. ECS와 관련된 기본 개념들을 하나의 구성도로 표현하려고 하다보니 이런 불상사가 발생하게 되었네요. EC2타입과 Fargate타입을 비교하려니 이렇게 되었습니다. 그리고 필연적으로 엮어야 하는 EFS, ECR(S3)와 CloudWatch 등으로 인해서 더 복잡하게 되었습니다. CI/CD는 별도로 그려야 하나? 고민 중입니다. 

사전 작업

인프라 생성(설명 SKIP) : vpc, subnet, igw, nat gateway, routing table, iam 등

1단계 : 보안 그룹 구성

VPC > Security groups > Create a security group  

Security group name VPC Inbound rules Outbound rules
lb-sg vpc Type, Protocol(HTTP, HTTPS), Source(0.0.0.0/0) ANY 허용
ecs-task-sg vpc Type, Protocol(All TCP), Source(lb-sg) ANY 허용
efs-sg vpc Type, Protocol(NFS), Source(ecs-tasks-sg) ANY 허용
1번은 인터넷에서 LB(public subnet)로 요청에 대한 허용 정책입니다.
2번은 LB(public subnet)에서 ECS(private subnet)로 요청에 대한 허용 정책입니다. 인터넷에서 접근이 허용된 것은 LB의 HTTP/S 외 없기 때문에 ECS에도 인터넷에서 접근이 허용된 것은 HTTP/S만 존재합니다. 더불어 LB에서 ECS로 Health check 패킷도 허용이 되었다고 봐야합니다. 
3번은 ECS(private subnet)에서 EFS로 접근에 대한 허용 정책입니다. EFS는 우리가 생성한 subnet에 위치하는 것이 아니라 AWS 내부 어딘가에 있는 subnet에 위치하고 있으며 때문에 Security group에서 허용이 되어야 한다는 의미입니다.

2단계(옵션) : EFS 파일시스템 생성

EFS > File systems > Create file system > Customize

General Network access File system policy
Name : ecs-efs

VPC : vpc
Mount targets : ap-northeast-2 (pri-sn-a)
ap-northeast-2 (pri-sn-b)
Security groups : efs-sg

All uncheck
(Prevent root access by default,
Enforce read-only access by default,
Prevent anonymous access,
Enforce in-transit encryption for all clients)

EFS > File systems > ecs-efs의 파일 시스템 ID 확인 (ex: fs-0f2d44a955c6a269d)

3단계(옵션) : 파라미터 (데이터베이스 자격 증명/이름/서버 세부 정보 등) 저장소 구성

AWS Systems Manager > Parameter Store > Create Parameter 

Name Tier Type, Data type Value
DB_HOST Standard String, txt DB DNS 주소 or IP
DB_NAME Standard String, txt DB명
DB_USERNAME Standard String, txt DB 계정 (ex : MySQL은 admin)
DB_PASSWORD Standard String, txt DB 생성 시 입력한 패스워드
파라미터 스토어의 WAS가 DB를 접속할 때 필요한 정보 등을 하드코딩하지 않도록 하기 위함입니다. 컨테이너가 구동을 시작할 때 파라미터 스토어에서 변수를 읽어서 구동을 하도록 합니다. 

4단계(옵션) : ECR 생성, 작업 PC에서 도커 이미지 Build 및 Upload

Elastic Container Registory > Repositoryes > Create repository

General settings Image scan settings Encryption settings
Visibility settings(표시 여부 설정) : Private
Repository name : wordpress
Disabled Disabled

Elastic Container Registory > Repositoryes > wordpress 선택 > View push commands

사전에 docker 설치를 하고, aws cli 로그인 상태에서 진행하시기 바랍니다.
aws cli 로그인은 https://sh-t.tistory.com/62를 참조하시기 바랍니다.
View push commands에서 제공하는 명령어를 아래 예시처럼 수행하면 됩니다. 
# ECR Repository 위치
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 239243157363.dkr.ecr.ap-northeast-2.amazonaws.com

# 예제 Dockerfile 내용 확인
cat Dockerfile
FROM nginx
EXPOSE 80
RUN apt-get update -y && \
  apt-get upgrade -y && \
  apt-get install -y curl && \
  cd /tmp && \
  apt-get install awscli -y && \
  rm -rf /tmp/* && \
  rm -rf /var/lib/apt/lists/*
COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY ./index.html /usr/share/nginx/html/index.html

cat defult.conf
server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    location /dogs {
        alias   /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to ECS</title>
</head>
<h1>This is what happiness looks like</h1>

# 도커 이미지 빌드
docker build -t wordpress .

# 도커 이미지 tag (Repository name과 동일하게 tag)
docker tag wordpress:latest 339243157363.dkr.ecr.ap-northeast-2.amazonaws.com/wordpress:latest

# 도커 이미지 push (Repository로 업로드)
docker push 339243157363.dkr.ecr.ap-northeast-2.amazonaws.com/wordpress:latest
인터넷이 가능한 환경이고, 소스 그대로 사용이 가능한 구조라면 이처럼 별도의 ECR을 구성할 필요가 없습니다. 하지만 폐쇄망으로 구성되고, 별도 관리가 필요한 구성이라면 이처럼 별도의 ECR을 구성하여야 합니다. 

5단계 : ECS 클러스터 생성 및 작업 정의

ECS 권한 부여

  - IAM > Role > AWSServiceRoleForECS 수정 : 복잡 

  - 기존 정책(AWSServiceRoleForECS) 삭제하고, AWS CLI로 생성 : 쉬움

    ※ 참조 URL : 기존 정책 삭제하고 AWS CLI로 생성하는 방법이 가장 간편

        $ aws iam create-service-linked-role --aws-service-name ecs.amazonaws.com
ECS Task 실행에 필요한 정책 생성 : IAM > Role > Create role > Trusted entity type(AWS service), Use case의 Use cases for other AWS services(Elastic Container Service Task) > 검색(AmazonECSTaskExecutionRolePolicy) 후, 하단 Set permissions boundary(Create role without a permissions boundary) > Role name(ecsTaskExecutionRole)  > 아래 내용 확인 > Create role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

ECS > Cluster > Create a cluster

구분 Select cluster template Configure cluster
Fargate 경우 Networking only Cluster name : ecs-fargate-cluster
CloudWatch Container Insights : Enable
EC2 경우 EC2 Linux + Networking Cluster name : ecs-ec2-cluster
구분 Configure cluster
EC2 경우만 Provisioning Model : On-Demand Instance
EC2 instance type : t2.micro
Number of instances : 2
EC2 AMI ID : Amazon Linux 2 AMI 
Root EBS Volume Size : 30GB
Key pair : None-unable to SSH (or 지정)
VPC : vpc
Subnet : pri-sn-a, pri-sn-b
Auto assign public IP : Use subnet setting
Security group : efs-sg
Container instance IAM role : Create new role(ecsInstanceRole 자동 생성됨)
CloudWatch Container Insights : Enable

EC2의 경우 필요한 IAM 추가 : IAM > Role > ecsInstanceRole > Add permission > CloudWatchLogsFullAccess 
ECS > Task Definitions > Create new Task Definition

구분 Configure task and container definitions
Fargate 경우 Task definition name : ecs-fargate-task-def
Task role : ecsTaskExecutionRole
Operating system family : Linux (or Windows)
Task execution role :  ecsTaskExecutionRole
Task memory : 1GB
Task CPU : 0.5vCPU
EC2 경우 Task definition name : ecs-ec2-task-def 
Task role : ecsTaskExecutionRole
Network mode : default (or bridge, host, etc)
Task execution role :  ecsTaskExecutionRole
Task memory : Option
Task CPU : Option
Fargate경우 필수적으로 입력되는 작업 메모리/작업 CPU는 Application 설계자와 협의하여 설정하는 것이 바람직합니다. 

Task에 설정 가능한 CPU/MEM 범위 : CPU(0.5~4vCPU), MEM(512~30GB)
구분 Add container
Standard Container name : web-container
Image : wordpress:latest
Memory Limits(MiB) : 400 
  ※ hard limit, soft limit 선택 가능

Host Port(only EC2), Container port, Protocol : 0, 80, TCP
  ※ Port 여러개 등록 가능
Advanced container configuration >
environment > Environment variables
※ 3단계 파라미터 스토어 내용 등록
WORDPRESS_DB_HOST / Value / DB_HOST
WORDPRESS_DB_NAME / Value / DB_NAME
WORDPRESS_DB_PASSWORD / Value / DB_PASSWORD
WORDPRESS_DB_USER / Value / DB_USERNAME
Advanced container configuration
> storage and logging
Mount points : wp-content 
Volumes from(컨테이너 마운트 경로) : /var/www/html/wp-content
Log configuration : Auto-configure CloudWatch Logs
  ※ CloudWatch 로그로 전송할 때 Key/Value 추가 가능
능력이 된다면 작업 정의/컨테이너 추가/볼륨 추가를 JSON으로 만들어서 "Configure via JSON" 클릭해서 구성 가능합니다.

컨테이너 추가 시 이미지 경로(Add container > Standard > Image)를 ECR Repository로 할 경우 경로 확인 방법

  - Elastic Container Registory > Repositoryes > 해당 이미지 URI 확인
    (ex : 339243157363.dkr.ecr.ap-northeast-2.amazonaws.com/wordpress)

6단계 : ELB 생성

EC2 > load balancing > load balancer > Create a load balancer > Application load balancer

basic configuration network mapping security group listeners and routing > Create target group Target configuration
load balancer name : ecs-fargate-lb
System : Internet facing
VPC : vpc 
Subnet : pub-sn-a, pub-sn-b
lb-sg Choose the target type : IP
target group name : ecs-fagate-tg
Protocol:Port : HTTP:80
VPC : vpc

-
load balancer name : ecs-ec2-lb
System : Internet facing
VPC : vpc 
Subnet : pub-sn-a, pub-sn-b
lb-sg Choose the target type : Instance
target group name : ecs-ec2-tg
Protocol:Port : HTTP:80
VPC : vpc

-
5단계 생성한 컨테이너를 노출시킬 ELB이므로 target group은 컨테이너에 구동되는 프로세스(ex : wordpress)의 Protocol과 Port를 설정하여야 합니다. 

7단계 : ECS 서비스 생성하면서 ELB 연결

ECS > Cluster > ecs-fargate-cluster or ecs-ec2-cluster 선택 >  Services (tab) > Create 

구분 Configure service Configure network
ecs-fargate-cluster Launch type : Fargate
Operating system family : Linux
Task Definition : ecs-fargate-task-def
Revision : latest
Platform version : 1.4.0
Cluster : ecs-fargate-cluster
Service name : ecs-fargate-svc
Number of tasks(컨테이너 개수) : 2
VPC : vpc
Subnet : pri-sn-a, pri-sn-b
Security group : 80 허용 설정
Auto assign public IP : DISABLED
Load balancer type : ALB
Load balancer name : ecs-fargate-lb
Container name:port(Add to load balancer) : web-container:80:80
Production listener port : 80:HTTP
Target group name : ecs-fargate-tg
Health check path(옵션) : 컨테이너별 체크 시 설정
서비스 검색 통합 활성화 : 체크 해제
ecs-ec2-cluster Launch type : EC2
Task Definition : ecs-ec2-task-def
Revision : latest
Cluster : ecs-ec2-cluster
Service name : ecs-ec2-svc
Number of tasks(컨테이너 개수) : 2
Service type : REPLICA
Deployment type : Rolling update (or blue/green)
Placement Templates : AZ Balanced Spread
Load balancer type : ALB (or None or NLB or CLB)
Service IAM role : AWSServiceRoleForECS

Load balancer name  : ecs-ec2-lb
Container name:port(Add to load balancer) : web-container:0:80
Production listener port : 80:HTTP
Target group name : ecs-ec2-tg
Health check path(옵션) : 컨테이너별 체크 시 설정
서비스 검색 통합 활성화 : 체크 해제
Fargate 경우는 컨테이너 설정에서 host port를 설정하지 않고 container port만 설정하였기 때문에 web-container:80:80로 표현되고, EC2 경우는 컨테이너 설정에서 host port를 0으로 설정하기 때문에  web-container:0:80로 표현이 되는 것입니다.

EC2의 경우 컨테이너 배치 템플릿 옵션은 AZ Balanced Spread, AZ Balanced BinPack, BinPack, One Task Per Host, Custom이 있으며 일반적으로 AZ Balanced Spread로 구현합니다.

AutoScaing 옵션을 설정할 경우 fargate/EC2 모두 아래처럼 동일하게 진행하여 테스트합니다.

Set Auto Scaling (옵션)
Min / Desired / Max : 2 / 2 / 200
Scaling policy type : Target tracking
IAM role for Service Auto Scaling : AWSServiceRoleForApplicationAutoScaling_ECSService
Policy name : Requests-policy
ECS service metric(지표) : ALBReqestCountPerTarget
Target value(임계치) : 300
Scale-out cooldown peried(휴지 기간) : 300초

ECS > Cluster > ecs-fargate-cluster or ecs-ec2-cluster > Tasks (tab) : 컨테이너 상태 “RUNNING” 확인

8단계 : CI/CD는 별도 포스팅

테스트 : 웹 접속

EC2 > load balancing > load balancer > ecs-fargate-lb or ecs-ec2-lb > 설명 탭 > DNS name 확인
웹 브라우저에서 DNS 이름으로 접속 시도

접속하면 첫 화면이 이렇게 출력됩니다.

ECS > Cluster > ecs-fargate-cluster or ecs-ec2-cluster > Services (tab) > 서비스 선택 > Event (tab) : 로그 확인

ETC

실행 중 컨테이너 강제 중지 : ecs-fargate-cluster or ecs-ec2-cluster > Tasks (tab) > 컨테이너 선택 > 중지
서비스에 대한 이벤트 확인 : ecs-fargate-cluster or ecs-ec2-cluster > Services (tab) > 서비스 선택 > Event (tab)   
AutoScaling 및 서비스 수정 : ecs-fargate-cluster or ecs-ec2-cluster > Services (tab) > 서비스 선택 > Update > 컨테이너 수, 배치 템플릿 등 수정 > Update service

반응형