[AWS] ECS 를 통한 service 배포

김지환·2023년 2월 9일
0

TL:DR;

ECS를 통한 서비스 배포 경험을 잊어먹지 않기 위한 포스팅!

ECS Architecture

Elastic Container Service

AWS 에서 제공하는 Container 관리 서비스이다. 좀 더 쉽게 container 를 run, stop 하고 monitoring 할 수 있다. 필요에 따라서 AWS 에서 제공하는 Loadbalacner, EC2 Autoscaler, ECR ( Elastic Container Registry ) 와 함께 사용되어 진다.

Region 으로 구별되어 지는 Cluster가 가장 큰 단위이고 그 안에 Service, Task 들이 존재하게 된다. 어느 VPC, Subnet으로 Task를 배치할 것인지를 설정할 수 있다.

ECS 용어 정리

Task

Task 란 Docker container 의 작업 단위이다. Task를 만들기 위해서는 Task definition 이 라는 blueprint가 필요한데 이를 통해서 ECS가 task를 만들게 된다. task definition 에는 configuration, resource requirement 들이 들어가 있다.

Service

Service 란 Task 정의를 바탕으로 가동되는 container 들의 집합을 고수준으로 관리하는 상위 집합체라 보면 된다. 서비스는 running task 의 수와 healthy check를 담당할 수 있다. 즉 running task에 장애가 발생하여 failed 될 때 service 가 알아서 새로운 task로 교체해주게 된다.

핵심적인 기능으로 auto scaling 이 가능하다는 점이다. 필요에 따라서 task를 늘리거나 줄일 수 있고 Service에는 load balancing 기능이 있어 service로 오는 traffic을 자동으로 분산 시킬 수 있다.

Capacity provider

Capacity provider 는 ECS Cluster 에서 동작하고 있는 Task의 정의에 따른 리소스 관리를 해주는 방식이다.

우선순위 설정, scale up/down 등을 설정할 수 있고 여러 service, task 들을 동시에 관리할 수 있다.

AWS 에는 Fargate, EC2 사용에 따라서 각각 Capacity Provider가 제공되는데 사용자에 맞게 설정해주면 된다. 모든 Task 들은 각자의 capacity provider를 설정해야하고 만약 설정이 안돼있다면 default capacity provider가 적용된다. 만약 Instance_type을 지정해준다면 capacity provider 는 자동으로 설정된다. ( 해당하는 provider로)

aws cli 를 통해서 capacity provider를 등록할 수 있다.

aws ecs put-cluster-capacity-providers \
--cluster xxxxxxx \
--capacity-providers FARGATE FARGATE_SPOT \
--default-capacity-provider-strategy \
capacityProvider=FARGATE,weight=1,base=1 \
capacityProvider=FARGATE_SPOT,weight=4
{
    "cluster": {
        "clusterArn": "arn:aws:ecs:us-west-1:xxxx:cluster/xxxxxxx",
        "clusterName": "xxxxxx",
        "status": "ACTIVE",
        "registeredContainerInstancesCount": 0,
        "runningTasksCount": 0,
        "pendingTasksCount": 0,
        "activeServicesCount": 0,
        "statistics": [],
        "tags": [],
        "settings": [
            {
                "name": "containerInsights",
                "value": "disabled"
            }
        ],
        "capacityProviders": [
            "FARGATE",
            "FARGATE_SPOT"
        ],
        "defaultCapacityProviderStrategy": [
            {
                "capacityProvider": "FARGATE",
                "weight": 1,
                "base": 1
            },
            {
                "capacityProvider": "FARGATE_SPOT",
                "weight": 4,
                "base": 0
            }
        ],
        "attachments": [],
        "attachmentsStatus": "UPDATE_IN_PROGRESS"
    }
}

Service 배포까지

Task Definition등록

Task를 만들 때 ecs-cli 를 사용하면 굉장히 편하다. macOS기준 brew를 이용해서 받을 수 있다. aws cli도 service를 deploy 할 때 더 디테일한 설정이 가능하기 때문에 받아두는게 좋다.

brew install awscli
brew install amazon-ecs-cli

ecs-cli는 docker-compose 를 지원하기 때문에 docker-compose yaml파일을 만들어서 container를 적용하면 되고 추가적인 parameter들은 따로 yaml 파일로 만들어서 실행할 때 옵션으로 추가해주면 된다.

version: '3'
services:
    app_main:
        image: xxxxx:xxx
        restart: always
        env_file:
            - .env
        logging:
            driver: awslogs
            options:
                awslogs-group: app_main
                awslogs-region: your-region
                awslogs-stream-prefix: prefix
        command: main
    app_dead:
        image: xxxxx:xxx
        restart: always
        env_file:
            - .env
        logging:
            driver: awslogs
            options:
                awslogs-group: app_main
                awslogs-region: your-region
                awslogs-stream-prefix: prefix
        command: dead

만약 awslog ( CloudWatch ) 를 이용하고 싶다면 awslogs driver 를 선택하고 옵션들을 설정해줘야한다.

version: 1
task_definition:
  task_execution_role: ecsTaskExecutionRole
  ecs_network_mode: awsvpc
  task_size:
    mem_limit: 2.0GB
    cpu_limit: 1024
run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - ${YOUR_SUBNET_A}
        - ${YOUR_SUBNET_B}
      security_groups:
        - ${YOUR_SG}
      assign_public_ip: "DISABLED"

ecs param에는 task_definition 정보와 run_params를 넣어줄 수 있단 task_definition의 configuration 정보를 통해서 task를 만들게 되고 run_param은 해당 task 의 환경구성에 필요한 configuration정보들을 담고 있다. aws 를 사용하기 때문에 해당 vpc, subnet 정보를 넣어주면 된다. 따로 private nat gateway 에 대한 routing table 설정이 docker image를 가져올 수 있도록 설정돼 있다면 public ip가 필요하지 않기 때문에 DISABLED 시켰다.

나는 ecs-cli 를 통해서 task definition을 만들고 난후 aws-cli를 통해서 만들어진 task definition 정보를 통해서 service를 등록시켰다. ecs-cli를 통해서 deploy 를 하게 되면 설정할 수 있는 option들에 제한이 있었다. ( 대표적으로 desired_count )

ecs-cli compose --project-name YOUR_PROJECT_NAME --ecs-params ecs-param.yml create --create-log-groups --cluster-config ${ECS_ALERT_CLUSTER_CONFIG}

cluster-config 는 mac 기준 ~/.ecs/config 안에 있는 cluster configuration name을 기반으로 선택되게 된다.

version: v1
default: default-cluster-name
clusters:
  your-cluster-name-alias:
    cluster: your-cluster-name
    region: your-region
    default_launch_type: "FARGATE"

cli 를 통해서 cluster 를 만들면 자동으로 폴더가 만들어지고 설정값을 토대로 config 파일이 만들어지게 된다. ( console를 통해서 만들었다면 따로 파일을 만들어줘도 됨 )

Service 등록

aws-cli를 통해서 service를 등록한다.

aws ecs create-service --cluster arn:aws:ecs:${AWS_REGION}:${AWS_ACCOUNT_ID}:cluster/${AWS_ECS_CLUSTER_NAME} \
    --service-name your-service-name \
    --task-definition YOUR_PROJECT_NAME \
    --desired-count 1 \
    --network-configuration "awsvpcConfiguration={subnets=[${YOUR_SUBNET_A},${YOUR_SUBNET_B}],securityGroups=[${YOUR_SG}]}" \
    --capacity-provider-strategy capacityProvider=FARGATE,weight=1 \
    --tags key=Owner,value="${AWS_TAG_OWNER}" key=Env,value=${AWS_TAG_ENV} key=Project,value=${AWS_TAG_PROJECT} key=Name,value=${AWS_TAG_NAME}
   ;;

다음과 같이 필요한 Option들을 추가하여서 service를 만들어줄 수 있다. service를 만들면 바로 service 에서 task definition에 맞춰서 task를 질행시켜준다.

service 에 대한 update가 필요하면 update-service를 통해서 가능하다.

aws ecs update-service --cluster arn:aws:ecs:${AWS_REGION}:${AWS_ACCOUNT_ID}:cluster/${AWS_ECS_CLUSTER_NAME} \
    --service your-service-name \
    --task-definition YOUR_PROJECT_NAME \
    --desired-count 4 \
    --network-configuration "awsvpcConfiguration={subnets=[${YOUR_SUBNET_A},${YOUR_SUBNET_B}],securityGroups=[${YOUR_SG}]}" \
    --capacity-provider-strategy capacityProvider=FARGATE,weight=1 \

Conclusion

Control plane, Cluster 같은 부분들을 AWS에서 모두 관리해주기 때문에 좀 더 container의 관리에 집중할 수 있는 것 같다. service를 통한 task들의 가용성도 확보할 수 있다는 점이 가볍게 Production 인프라 구축을 하는데 이점이 있을 것 같다.

profile
Developer

0개의 댓글