Amazon ECS 사용하기

Hyeokminn·2025년 9월 29일

aws-ecs

목록 보기
2/2
post-thumbnail

예시를 통해 알아보자

만약에...
원본 영상을 받아 여러 개의 컨테이너를 동시에 실행시켜 여러가지 해상도와 포맷으로 변환(인코딩)하는 작업을 병렬로 처리하도록 구현해주세요.
=> 맡은 업무: OTT 플랫폼의 콘텐츠 인코딩

설계 및 준비

ECS 작업을 통해 위와 같은 업무를 처리해보자.

만약 1080p, 720p, 360p 로 인코딩을 해야한다면, 작업 정의는 몇 개가 필요한가? -> 1개

변수로 화질을 입력 받아, 작업을 시키면 된다.. 후에, 4K 인코딩 등 여러 기능이 추가되어도, 새로 작업 정의를 만들 필요 없음.

ECS 작업을 실행시키는 방법 
	1. 수동 실행(Run Task) ex. 1회성 작업, 수동 실행
    2. ECS 서비스로 실행(Service) ex. 웹사이트 24/7
    3. 스케쥴 실행(주기, 반복) ex. 매일 데이터 백업 (Amazon EventBridge ->)
    4. 이벤트 기반(Trigger) ex. S3 put -> encoding (Amazon EventBridge -> ...)

간단히 하고자 수동 실행 Run Task를 통해 한다고 가정해보았다.


1. 우선 이미지를 만들어 ECR에 업로드

dockerfile 작성

FROM alpine:latest

RUN apk update && apk add ffmpeg

WORKDIR /app

COPY run_encoding.sh .
RUN chmod +x run_encoding.sh
CMD ["./run_encoding.sh"]

run_encoding.sh 파일 작성

# 예: INPUT_FILE="s3://originals/movie.mp4", RESOLUTION="1080p"

aws s3 cp ${INPUT_FILE} ./input_file.mp4

ffmpeg -i ./input_file.mp4 -s ${RESOLUTION} ./output_${RESOLUTION}.mp4

aws s3 cp ./output_${RESOLUTION}.mp4 s3://streams/output_${RESOLUTION}.mp4

2. IAM 권한 설정

현재 이미지에서 사용하는 권한을 허용해 주어야한다.
컨테이너가 S3 버킷 파일 접근할 수 있도록 S3:get, put 권한 허용한 Role 부여

3. 작업 정의

requiresCompatibilities: 이 작업 정의는 오직 명시된 타입에서만 실행되어야만 한다는 문구로, compatibilities와는 다르다. "FARGATE"가 AWS가 모든 서버 관리해주기에 편리함.
memory: 인코딩 작업이기에, 넉넉하게 설정
executionRoleArn: 컨테이너가 시작되기 전에 ECS 서비스가 사용하는 권한. ex. 컨테이너 이미지 다운, 로그 설정 등
taskRoleArn: 컨테이너가 실행된 후 그 안의 애플리케이션이 사용하는 권한. ex. 아까 만든 S3:get, put Role
environment: 컨테이너 값 전달 방법 중 변수를 넣을 때 환경변수를 택하는 방법

{
  "family": "video-encoder",
  "networkMode": "awsvpc",
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "cpu": "2048",
  "memory": "4096",
  "executionRoleArn": "arn:aws:iam::ACCOUNT_ID:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::ACCOUNT_ID:role/MyEcsTaskS3AccessRole",
  "containerDefinitions": [
    {
      "name": "ffmpeg-encoder",
      "image": "ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/my-ffmpeg-encoder:latest",
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/ott-video-encoder",
          "awslogs-region": "ap-northeast-2",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "environment": [
        {
          "name": "INPUT_FILE",
          "value": "placeholder_input"
        },
        {
          "name": "RESOLUTION",
          "value": "placeholder_resolution"
        }
      ]
    }
  ]
}

2. RunTask: 작업 정의를 통한 작업을 실제 실행 시키는 부분

작업을 실행하기 위해선 여러 값이 필요하다.
  1. 컨테이너 이름 ( 이전에 작업정의한 컨테이너 이름 )
  2. 클러스터 이름 ( 작업들이 소속될 논리적인 그룹, ECS의 작업 공간으로, 작업 정의에 따른 작업을 실행할 공간 )
  3. 네트워크 설정
      - 서브넷( 작업이 실행될 가상 네트워크 공간 )
      - 보안그룹 ( 작업에 적용될 가상 방화벽, 인바운드와 아웃바운드 규칙 )
  + 환경변수
  ...

위와 같은 작업은 AWS SDK를 통해 쉽게 호출 가능하다.

  • AWS SDK(Java, Python, Javascript, Go 등) 무엇을 사용하든, 아래와 같은 내용을 적어 RunTask 하면 됨.

    무엇을? -> '작업'을 (작업정의한)
    어디서? -> '클러스터'에서 (만든 클러스터 중)
    어떻게? -> '실행유형'으로 (Launch Type) FARGATE? EC2?
    + 네트워크 구성: subnets, security groups
    + 오버라이드: container, environmet

RunTask의 응답은 단순히 작업을 시작만 시키고 결과를 확인하지 않고 요청의 성공 실패만 응답한다.
Response 내의 failures와 tasks를 보고 요청의 성공, 실패를 알 수 있다.

이후 정상적으로 처리되었는지의 판별은 폴링(Polling) 방식: 계속 물어보는 방식, 이벤트 기반(Event-Driven) 방식: 완료 알림을 받는 방식으로 구현이 가능하다.

3. 작업 결과 확인

실행된 작업은 RUNNING 상태를 거쳐 최종적으로 STOPPED 상태가 된다.
왜 중지되었는가와 컨테이너의 종료 코드가 확인 가능하다.

성공: 종료 코드 = 0 컨테이너가 모든 임무를 완수하고 스스로 종료
실패: 종료 코드 != 0. 메모리 부족, 애플리케이션 오류 등으로 비정상 종료

이전 폴링 방식과 이벤트 기반 방식 중 선호되는 것은 후자인 이벤트 기반 방식이다.
폴링 방식은 끝날 때까지 계속 물어봐야하기에 비효율적이다.

이벤트 기반 방식은 "ECS 작업의 마지막 상태가 STOPPED으로 변경되면 특정 Lambda 함수를 호출하라"는 규칙을 설정하여, 종료코드에 맞게 작업의 성공 실패를 반환하도록 처리할 수 있다.

0개의 댓글