Amazon ECS 컨테이너 이미지 모범 사례

Amazon ECS 컨테이너 이미지 모범 사례

컨테이너 이미지는 컨테이너를 어떻게 빌드할지 알려주는 일련의 지침이에요. 컨테이너 이미지는 애플리케이션 코드와 애플리케이션 코드가 실행되는 데 필요한 모든 의존성을 담고 있어요. 애플리케이션 의존성에는 애플리케이션 코드가 의존하는 소스 코드 패키지, 인터프리터 언어를 위한 언어 런타임, 동적으로 링크된 코드가 의존하는 바이너리 패키지가 포함돼요. 컨테이너 이미지를 설계하고 빌드할 때 다음 지침을 따라 보세요.

출처: 문서

본문

  • 컨테이너 이미지를 완전하게 만드세요. 모든 애플리케이션 의존성을 컨테이너 이미지 내부의 정적 파일로 저장하세요.

  • 컨테이너 이미지에서 무언가를 변경했다면, 변경 사항이 반영된 새 컨테이너 이미지를 빌드하세요.

  • 컨테이너 안에서 단일 애플리케이션 프로세스를 실행하세요.

  • 컨테이너 수명은 애플리케이션 프로세스가 실행되는 동안 지속돼요. Amazon ECS는 충돌한 프로세스를 교체하고, 교체 프로세스를 어디에 실행할지 결정해요. 완전한 이미지는 전체 배포의 복원력을 높여 줘요.

  • 애플리케이션이 SIGTERM을 처리하도록 만드세요. Amazon ECS가 태스크를 중지할 때, 먼저 태스크에 SIGTERM 신호를 보내 애플리케이션이 종료하고 마무리해야 한다는 것을 알려 줘요. 그런 다음 Amazon ECS는 SIGKILL 메시지를 보내요. 애플리케이션이 SIGTERM을 무시하면, Amazon ECS 서비스는 프로세스를 종료하기 위해 SIGKILL 신호를 보낼 때까지 기다려야 해요.

    • 애플리케이션이 작업을 완료하는 데 얼마나 걸리는지 파악하고, 애플리케이션이 SIGTERM 신호를 처리하도록 해야 해요. 애플리케이션의 신호 처리는 애플리케이션이 새로운 작업을 받지 못하게 하고 진행 중인 작업을 완료하거나, 작업이 너무 오래 걸릴 때 태스크 외부의 저장소에 미완료 작업을 저장해야 해요.
  • 컨테이너화된 애플리케이션이 로그를 stdout과 stderr로 쓰도록 구성하세요. 로그 처리를 애플리케이션 코드에서 분리하면 인프라 수준에서 로그 처리를 조정할 수 있는 유연성이 생겨요. 예를 들어 로깅 시스템을 변경할 때 서비스를 수정하고 새 컨테이너 이미지를 빌드할 필요 없이 설정만 조정하면 돼요.

  • 태그를 사용해 컨테이너 이미지 버전을 관리하세요. 컨테이너 이미지는 컨테이너 레지스트리에 저장돼요. 레지스트리의 각 이미지는 태그로 식별돼요. latest라는 태그가 있는데, 이 태그는 애플리케이션 컨테이너 이미지의 최신 버전을 가리키는 포인터 역할을 해요. git 저장소의 HEAD와 비슷하다고 보면 돼요. latest 태그는 테스트 목적으로만 사용하는 것을 권장해요. 모범 사례로, 각 빌드마다 고유한 태그로 컨테이너 이미지에 태그를 지정하세요. 이미지를 빌드하는 데 사용한 git 커밋의 git SHA로 이미지에 태그를 지정하는 것을 권장해요.

    • 모든 커밋마다 컨테이너 이미지를 빌드할 필요는 없어요. 다만 특정 코드 커밋을 프로덕션 환경에 릴리스할 때마다 새 컨테이너 이미지를 빌드하는 것을 권장해요. 또한 이미지 안에 있는 코드의 git 커밋에 해당하는 태그로 이미지에 태그를 지정하는 것도 권장해요. 이미지에 git 커밋으로 태그를 지정했다면, 이미지가 실행 중인 코드 버전을 더 빨리 찾을 수 있어요.
    • Amazon Elastic Container Registry에서 **불변 이미지 태그(immutable image tags)**를 켜는 것도 권장해요. 이 설정을 사용하면 태그가 가리키는 컨테이너 이미지를 변경할 수 없어요. 대신 Amazon ECR은 새 이미지를 새 태그로 업로드해야 한다고 강제해요. 자세한 내용은 Amazon ECR User Guide의 Image tag mutability를 참고하세요.

AWS Fargate에서 실행되도록 애플리케이션을 설계할 때는, 여러 컨테이너를 같은 태스크 정의에 배포할지, 컨테이너를 여러 태스크 정의에 별도로 배포할지 결정해야 해요. 다음 조건이 필요하다면 같은 태스크 정의에 여러 컨테이너를 배포하는 것을 권장해요.

  • 컨테이너가 공통된 수명 주기를 공유해요 (즉, 함께 시작되고 함께 종료돼요).
  • 컨테이너가 같은 기본 호스트에서 실행되어야 해요 (즉, 한 컨테이너가 localhost 포트에서 다른 컨테이너를 참조해요).
  • 컨테이너가 리소스를 공유해요.
  • 컨테이너가 데이터 볼륨을 공유해요.

이런 조건이 필요하지 않다면, 컨테이너를 여러 태스크 정의에 별도로 배포하는 것을 권장해요. 이렇게 하면 컨테이너를 각각 별도로 스케일링, 프로비저닝, 해제할 수 있어요.