🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

ECS와 EKS로 컨테이너 오케스트레이션 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 29. · 2 Views

ECS와 EKS로 컨테이너 오케스트레이션 완벽 가이드

AWS에서 컨테이너를 운영하는 두 가지 핵심 서비스인 ECS와 EKS를 비교하고, 실무에서 어떻게 활용하는지 단계별로 알아봅니다. 서버리스 컨테이너부터 서비스 메시까지 컨테이너 오케스트레이션의 모든 것을 다룹니다.


목차

  1. ECS_vs_EKS_비교_및_선택_기준
  2. Fargate로_서버리스_컨테이너_실행
  3. ECS_클러스터_및_서비스_구성
  4. EKS_클러스터_생성_및_kubectl_연결
  5. Application_Load_Balancer와_컨테이너_통합
  6. Service_Mesh_App_Mesh_소개

1. ECS vs EKS 비교 및 선택 기준

어느 날 김개발 씨가 팀 회의에서 난감한 상황에 처했습니다. "우리 서비스 컨테이너화하려는데, ECS랑 EKS 중에 뭘 써야 할까요?" 팀장님의 질문에 김개발 씨는 두 서비스의 차이점을 명확히 설명하지 못했습니다.

분명 둘 다 AWS의 컨테이너 서비스인데, 무엇이 다른 걸까요?

**ECS(Elastic Container Service)**는 AWS가 자체 개발한 컨테이너 오케스트레이션 서비스입니다. 반면 **EKS(Elastic Kubernetes Service)**는 오픈소스인 Kubernetes를 AWS에서 관리형으로 제공하는 서비스입니다.

마치 자동차로 비유하면, ECS는 현대자동차가 만든 자동차고 EKS는 세계 표준 설계도로 현대가 조립한 자동차와 같습니다. 프로젝트의 규모, 팀의 기술 스택, 멀티 클라우드 전략에 따라 선택이 달라집니다.

다음 코드를 살펴봅시다.

// ECS Task Definition 예시 (AWS CDK)
import * as ecs from 'aws-cdk-lib/aws-ecs';

// ECS는 Task Definition으로 컨테이너를 정의합니다
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
  memoryLimitMiB: 512,
  cpu: 256,
});

// 컨테이너 추가 - ECS 방식
taskDefinition.addContainer('WebContainer', {
  image: ecs.ContainerImage.fromRegistry('nginx:latest'),
  portMappings: [{ containerPort: 80 }],
  logging: ecs.LogDrivers.awsLogs({ streamPrefix: 'web' }),
});

// EKS는 표준 Kubernetes YAML을 사용합니다
// kubectl apply -f deployment.yaml 형태로 배포

김개발 씨는 입사 2년 차 백엔드 개발자입니다. 최근 팀에서 기존 EC2 기반 서비스를 컨테이너로 전환하는 프로젝트를 맡게 되었습니다.

AWS 콘솔을 열어보니 ECS와 EKS 두 가지 선택지가 있었습니다. 둘 다 컨테이너를 실행하는 서비스인데, 왜 두 개나 있는 걸까요?

선배 개발자 박시니어 씨가 커피를 건네며 설명을 시작했습니다. "쉽게 생각해봐.

ECS는 AWS가 직접 만든 친자식이고, EKS는 입양한 자식 같은 거야. 둘 다 소중하지만 성격이 다르지." ECS는 2014년에 AWS가 자체 개발한 컨테이너 오케스트레이션 서비스입니다.

AWS의 다른 서비스들과 매우 긴밀하게 통합되어 있습니다. IAM, CloudWatch, Application Load Balancer 등과 자연스럽게 연동됩니다.

마치 같은 회사에서 만든 제품들이 서로 잘 맞아떨어지는 것처럼요. 반면 EKS는 2018년에 출시된 서비스로, 오픈소스 Kubernetes를 AWS 환경에서 실행할 수 있게 해줍니다.

Kubernetes는 구글이 만들고 오픈소스로 공개한 컨테이너 오케스트레이션 플랫폼입니다. 전 세계 개발자들이 함께 발전시키고 있는 업계 표준이라고 할 수 있습니다.

그렇다면 어떤 것을 선택해야 할까요? 박시니어 씨가 화이트보드에 표를 그리기 시작했습니다.

ECS를 선택해야 하는 경우는 이렇습니다. 먼저 AWS만 사용할 계획이고 다른 클라우드로 이전할 생각이 없다면 ECS가 좋습니다.

Kubernetes를 배울 시간이 부족하거나, 팀에 Kubernetes 경험자가 없을 때도 ECS가 유리합니다. 무엇보다 빠르게 시작하고 싶다면 ECS의 진입 장벽이 낮습니다.

EKS를 선택해야 하는 경우도 있습니다. 이미 팀에 Kubernetes 경험자가 있거나, 멀티 클라우드 전략을 고려하고 있다면 EKS가 좋습니다.

Kubernetes의 풍부한 에코시스템을 활용하고 싶을 때도 EKS를 선택합니다. 특히 Helm, Istio, ArgoCD 같은 도구들을 사용하려면 EKS가 필수입니다.

비용 측면에서 살펴보면, ECS 자체는 무료입니다. 다만 컨테이너가 실행되는 EC2나 Fargate 비용만 지불합니다.

반면 EKS는 클러스터당 시간당 약 0.10달러의 관리 비용이 추가됩니다. 월로 환산하면 약 72달러 정도입니다.

학습 곡선도 고려해야 합니다. ECS는 AWS 서비스에 익숙하다면 하루면 기본적인 사용법을 익힐 수 있습니다.

하지만 Kubernetes는 Pod, Service, Deployment, ConfigMap 등 수많은 개념을 이해해야 합니다. 제대로 활용하려면 수개월의 학습이 필요할 수 있습니다.

김개발 씨가 고개를 끄덕였습니다. "그러니까 우리 팀은 AWS만 쓰고, Kubernetes 경험자도 없으니까 ECS가 맞겠네요?" 박시니어 씨가 웃으며 대답했습니다.

"정확해. 일단 ECS로 시작하고, 나중에 필요하면 EKS로 마이그레이션하면 돼." 컨테이너 오케스트레이션을 처음 시작하는 팀이라면 ECS로 경험을 쌓고, 점차 요구사항이 복잡해지면 EKS 도입을 검토하는 것이 현명한 전략입니다.

실전 팁

💡 - ECS와 EKS 모두 Fargate를 지원하므로 서버 관리 없이 컨테이너를 실행할 수 있습니다

  • 소규모 프로젝트나 MVP는 ECS로 빠르게 시작하고, 성장하면 EKS 전환을 고려하세요

2. Fargate로 서버리스 컨테이너 실행

김개발 씨가 ECS를 도입하기로 결정했지만, 또 다른 고민이 생겼습니다. "EC2 인스턴스를 직접 관리해야 하나요?

서버 패치하고, 용량 계획하고..." 박시니어 씨가 고개를 저었습니다. "Fargate를 써.

서버 관리 없이 컨테이너만 실행할 수 있어." 서버리스 컨테이너라니, 마법 같은 이야기였습니다.

AWS Fargate는 서버를 프로비저닝하거나 관리하지 않고도 컨테이너를 실행할 수 있는 서버리스 컴퓨팅 엔진입니다. 마치 택시를 타는 것과 같습니다.

목적지만 말하면 운전은 기사님이 알아서 해주듯이, Fargate는 컨테이너 이미지와 필요한 리소스만 지정하면 나머지는 AWS가 알아서 처리합니다. EC2처럼 인스턴스를 선택하고 관리할 필요가 없습니다.

다음 코드를 살펴봅시다.

// Fargate 서비스 생성 (AWS CDK)
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

// VPC와 클러스터 생성
const vpc = new ec2.Vpc(this, 'VPC', { maxAzs: 2 });
const cluster = new ecs.Cluster(this, 'Cluster', { vpc });

// Fargate 서비스 - 서버 관리 불필요!
const fargateService = new ecs.FargateService(this, 'Service', {
  cluster,
  taskDefinition,
  desiredCount: 2,  // 컨테이너 2개 실행
  assignPublicIp: true,
  // vCPU와 메모리만 지정하면 끝
});

// 오토스케일링 설정
const scaling = fargateService.autoScaleTaskCount({ maxCapacity: 10 });
scaling.scaleOnCpuUtilization('CpuScaling', { targetUtilizationPercent: 70 });

컨테이너를 실행하려면 어딘가에서 돌아가야 합니다. 전통적으로는 EC2 인스턴스를 미리 준비해두고, 그 위에서 컨테이너를 실행했습니다.

하지만 이 방식에는 고민거리가 많습니다. 먼저 용량 계획의 어려움이 있습니다.

인스턴스를 너무 많이 준비하면 비용이 낭비되고, 너무 적게 준비하면 트래픽 폭주 시 서비스가 죽습니다. 마치 결혼식 하객 수를 예측하는 것처럼 어렵습니다.

서버 관리 부담도 있습니다. 운영체제 패치, 보안 업데이트, 모니터링 설정 등 컨테이너와 직접 관련 없는 작업에 시간을 써야 합니다.

개발자는 애플리케이션 개발에 집중하고 싶은데 말이죠. Fargate는 이런 고민을 말끔히 해결해줍니다.

AWS가 서버 인프라를 완전히 추상화해서 제공하기 때문입니다. 개발자는 컨테이너 이미지, 필요한 CPU와 메모리만 지정하면 됩니다.

나머지는 AWS가 알아서 합니다. 박시니어 씨가 비유를 들어 설명했습니다.

"EC2 기반 ECS는 렌터카를 빌려서 직접 운전하는 거야. 차량 상태도 체크하고, 주유도 하고, 주차 공간도 찾아야 하지.

반면 Fargate는 택시를 타는 거야. 목적지만 말하면 끝이야." Fargate의 동작 방식을 살펴보면 이렇습니다.

Task Definition에서 vCPU와 메모리 조합을 선택합니다. 예를 들어 0.25 vCPU에 512MB 메모리, 또는 4 vCPU에 30GB 메모리 같은 식입니다.

AWS는 이 요구사항에 맞는 격리된 컴퓨팅 환경을 즉시 제공합니다. 비용 구조도 다릅니다.

EC2는 인스턴스를 켜둔 시간 전체에 대해 비용을 지불합니다. 컨테이너가 실제로 사용하는 것보다 더 많은 리소스를 할당해야 하는 경우가 많습니다.

반면 Fargate는 컨테이너가 실행된 시간과 실제 사용한 리소스에 대해서만 비용을 지불합니다. 다만 Fargate가 항상 저렴한 것은 아닙니다.

대규모로 안정적인 워크로드를 운영한다면 EC2가 더 경제적일 수 있습니다. 특히 예약 인스턴스나 Savings Plans를 활용하면 EC2 비용을 크게 절감할 수 있습니다.

Fargate의 또 다른 장점은 보안입니다. 각 Task는 자체 커널을 가진 격리된 환경에서 실행됩니다.

다른 고객의 워크로드와 하드웨어를 공유하지만, 완전히 격리되어 있습니다. 이를 하이퍼바이저 수준의 격리라고 합니다.

김개발 씨가 질문했습니다. "그럼 EC2 기반 ECS는 언제 쓰나요?" 박시니어 씨가 대답했습니다.

"GPU가 필요하거나, 특수한 인스턴스 타입이 필요할 때, 또는 대규모 워크로드에서 비용 최적화가 중요할 때 EC2를 써. 하지만 대부분의 웹 서비스는 Fargate로 충분해." Fargate는 특히 변동이 심한 워크로드에 적합합니다.

트래픽이 갑자기 증가해도 필요한 만큼 Task를 추가로 실행하면 됩니다. 서버 용량을 미리 준비해둘 필요가 없습니다.

실전 팁

💡 - Fargate Spot을 사용하면 최대 70%까지 비용을 절감할 수 있지만, 중단 가능성이 있으므로 배치 작업에 적합합니다

  • 개발/테스트 환경은 Fargate로, 프로덕션 대규모 워크로드는 EC2를 고려해보세요

3. ECS 클러스터 및 서비스 구성

김개발 씨가 본격적으로 ECS 구축을 시작했습니다. AWS 콘솔을 열어보니 Cluster, Task Definition, Service라는 용어가 눈에 들어왔습니다.

"클러스터? 서비스?

이게 다 뭐지..." 박시니어 씨가 화이트보드 앞으로 다가갔습니다. "ECS의 핵심 개념 세 가지만 이해하면 돼.

그림으로 그려볼게."

ECS는 세 가지 핵심 개념으로 구성됩니다. Cluster는 컨테이너가 실행되는 논리적인 그룹입니다.

Task Definition은 컨테이너 실행 방법을 정의한 청사진입니다. Service는 Task Definition을 기반으로 지정된 수의 컨테이너를 유지 관리합니다.

마치 회사 조직도처럼, Cluster는 부서, Task Definition은 직무 기술서, Service는 해당 직무를 수행하는 팀이라고 생각하면 됩니다.

다음 코드를 살펴봅시다.

// ECS 클러스터, Task Definition, Service 구성
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecr from 'aws-cdk-lib/aws-ecr';

// 1. 클러스터 생성 - 컨테이너들의 논리적 그룹
const cluster = new ecs.Cluster(this, 'MyCluster', {
  vpc,
  clusterName: 'production-cluster',
  containerInsights: true,  // 모니터링 활성화
});

// 2. Task Definition - 컨테이너 실행 청사진
const taskDef = new ecs.FargateTaskDefinition(this, 'TaskDef', {
  memoryLimitMiB: 1024,
  cpu: 512,
});

taskDef.addContainer('api', {
  image: ecs.ContainerImage.fromEcrRepository(apiRepo, 'latest'),
  portMappings: [{ containerPort: 3000 }],
  environment: { NODE_ENV: 'production' },
  healthCheck: {
    command: ['CMD-SHELL', 'curl -f http://localhost:3000/health || exit 1'],
  },
});

// 3. Service - Task를 원하는 개수만큼 유지
const service = new ecs.FargateService(this, 'ApiService', {
  cluster,
  taskDefinition: taskDef,
  desiredCount: 3,  // 항상 3개의 컨테이너 유지
});

박시니어 씨가 화이트보드에 큰 원을 그렸습니다. "이게 Cluster야.

컨테이너들이 실행되는 논리적인 경계라고 생각해. 보통 환경별로 클러스터를 분리해.

production-cluster, staging-cluster 이런 식으로." Cluster는 마치 아파트 단지와 같습니다. 단지 안에 여러 동이 있고, 각 동에 여러 세대가 있듯이, 클러스터 안에 여러 서비스가 있고, 각 서비스에 여러 컨테이너(Task)가 있습니다.

클러스터 자체는 빈 껍데기일 뿐, 실제 일을 하는 것은 그 안의 서비스들입니다. 다음으로 박시니어 씨가 설명한 것은 Task Definition입니다.

"Task Definition은 컨테이너 실행 방법을 정의한 JSON 문서야. 어떤 이미지를 쓸지, 얼마나 메모리를 할당할지, 어떤 포트를 열지, 환경변수는 무엇인지 등을 정의해." Task Definition은 요리 레시피와 같습니다.

레시피에 재료, 분량, 조리 방법이 적혀 있듯이, Task Definition에는 컨테이너 이미지, 리소스 할당, 실행 방법이 적혀 있습니다. 같은 레시피로 여러 번 요리할 수 있듯이, 하나의 Task Definition으로 여러 개의 Task를 실행할 수 있습니다.

Task Definition에서 중요한 설정들을 살펴보겠습니다. 컨테이너 이미지는 Docker Hub나 ECR에서 가져올 이미지를 지정합니다.

CPU와 메모리는 컨테이너에 할당할 리소스입니다. 포트 매핑은 컨테이너 내부 포트를 외부에 노출합니다.

환경변수는 컨테이너에 전달할 설정값입니다. Health Check 설정도 중요합니다.

컨테이너가 정상적으로 동작하는지 주기적으로 확인합니다. 위 코드에서는 /health 엔드포인트로 HTTP 요청을 보내 응답을 확인합니다.

응답이 없으면 ECS가 해당 컨테이너를 비정상으로 판단하고 새로운 컨테이너로 교체합니다. 마지막으로 Service입니다.

박시니어 씨가 설명했습니다. "Service는 Task Definition을 기반으로 실제 컨테이너를 실행하고 관리하는 역할을 해.

desiredCount를 3으로 설정하면, ECS가 항상 3개의 컨테이너를 유지해줘." Service의 핵심 기능은 **자가 치유(Self-healing)**입니다. 컨테이너가 죽으면 자동으로 새 컨테이너를 시작합니다.

Health Check가 실패하면 해당 컨테이너를 종료하고 새로 띄웁니다. 마치 24시간 감시하는 보안 요원처럼, Service는 항상 원하는 상태를 유지하려고 노력합니다.

배포 전략도 Service에서 설정합니다. 기본값은 Rolling Update로, 새 버전을 점진적으로 배포합니다.

Blue/Green 배포를 원한다면 CodeDeploy와 연동하면 됩니다. 배포 중에도 서비스 중단 없이 새 버전을 적용할 수 있습니다.

김개발 씨가 정리했습니다. "그러니까 Cluster는 컨테이너들의 집, Task Definition은 컨테이너 실행 설명서, Service는 설명서대로 컨테이너를 관리하는 관리인이네요." 박시니어 씨가 엄지를 치켜세웠습니다.

실무에서는 보통 마이크로서비스 아키텍처를 사용하므로, 하나의 클러스터에 여러 개의 Service가 존재합니다. 사용자 서비스, 주문 서비스, 결제 서비스 등 각각이 독립적인 Service로 운영됩니다.

실전 팁

💡 - Task Definition은 버전 관리되므로, 문제 발생 시 이전 버전으로 빠르게 롤백할 수 있습니다

  • Container Insights를 활성화하면 CPU, 메모리, 네트워크 지표를 CloudWatch에서 상세히 모니터링할 수 있습니다

4. EKS 클러스터 생성 및 kubectl 연결

몇 달 후, 회사가 성장하면서 새로운 요구사항이 생겼습니다. "우리 팀도 이제 Kubernetes를 도입해볼 때가 됐어요." 팀장님의 결정에 따라 김개발 씨는 EKS 클러스터를 구축하게 되었습니다.

Kubernetes를 AWS에서 어떻게 시작하면 될까요? 설레면서도 두려운 마음으로 문서를 펼쳤습니다.

**EKS(Elastic Kubernetes Service)**는 AWS에서 Kubernetes 컨트롤 플레인을 관리형으로 제공하는 서비스입니다. 컨트롤 플레인의 고가용성, 보안 패치, 버전 업그레이드를 AWS가 담당하므로 운영 부담이 줄어듭니다.

클러스터를 생성한 후 kubectl이라는 CLI 도구로 Kubernetes와 통신합니다. 마치 리모컨으로 TV를 조작하듯이, kubectl로 클러스터에 명령을 내립니다.

다음 코드를 살펴봅시다.

// EKS 클러스터 생성 (AWS CDK)
import * as eks from 'aws-cdk-lib/aws-eks';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

// EKS 클러스터 생성 - 컨트롤 플레인은 AWS가 관리
const cluster = new eks.Cluster(this, 'MyEksCluster', {
  vpc,
  version: eks.KubernetesVersion.V1_28,
  clusterName: 'production-eks',
  defaultCapacity: 0,  // 노드 그룹 별도 설정
});

// Fargate 프로파일 추가 - 서버리스 노드
cluster.addFargateProfile('FargateProfile', {
  selectors: [{ namespace: 'default' }],
});

// 또는 관리형 노드 그룹 추가
cluster.addNodegroupCapacity('NodeGroup', {
  instanceTypes: [ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM)],
  minSize: 2,
  maxSize: 10,
  desiredSize: 3,
});

// kubectl 설정 명령어 (터미널에서 실행)
// aws eks update-kubeconfig --name production-eks --region ap-northeast-2

Kubernetes를 직접 설치하고 운영해본 사람이라면 그 복잡함을 알 것입니다. 컨트롤 플레인 구성요소인 API Server, etcd, Scheduler, Controller Manager를 고가용성으로 구성하는 것만 해도 상당한 노력이 필요합니다.

EKS는 이 모든 것을 AWS가 대신 관리해줍니다. 박시니어 씨가 EKS의 구조를 설명했습니다.

"EKS는 크게 두 부분으로 나뉘어. 컨트롤 플레인데이터 플레인이야.

컨트롤 플레인은 클러스터의 두뇌로, AWS가 관리해. 데이터 플레인은 실제 워크로드가 실행되는 곳으로, 우리가 관리해." 컨트롤 플레인은 여러 가용 영역에 걸쳐 고가용성으로 배포됩니다.

etcd 데이터도 자동으로 백업됩니다. Kubernetes 버전 업그레이드도 콘솔에서 클릭 몇 번으로 가능합니다.

이 부분에 대해 시간당 0.10달러의 비용이 발생합니다. 데이터 플레인은 워커 노드라고도 불리며, 실제 Pod가 실행되는 곳입니다.

EC2 인스턴스를 사용하는 관리형 노드 그룹, 서버리스인 Fargate, 직접 EC2를 관리하는 자체 관리형 노드 세 가지 옵션이 있습니다. 관리형 노드 그룹을 사용하면 EC2 인스턴스의 프로비저닝과 수명 주기 관리를 AWS가 도와줍니다.

AMI 업데이트, 노드 드레인, 롤링 업데이트 등을 자동화할 수 있습니다. 대부분의 경우 관리형 노드 그룹을 권장합니다.

EKS에서도 Fargate를 사용할 수 있습니다. ECS의 Fargate와 동일한 개념으로, Pod 단위로 서버리스 컴퓨팅을 제공합니다.

Fargate Profile을 설정하면 특정 네임스페이스의 Pod가 자동으로 Fargate에서 실행됩니다. 클러스터를 생성했으면 kubectl을 연결해야 합니다.

kubectl은 Kubernetes 클러스터와 통신하는 CLI 도구입니다. AWS CLI의 aws eks update-kubeconfig 명령을 실행하면 자동으로 kubeconfig 파일이 설정됩니다.

김개발 씨가 터미널을 열고 명령어를 입력했습니다. "aws eks update-kubeconfig --name production-eks --region ap-northeast-2" 실행 후 kubectl get nodes를 입력하니, 클러스터의 노드 목록이 출력되었습니다.

연결 성공입니다. IAM과 Kubernetes RBAC의 통합도 EKS의 장점입니다.

IAM 사용자나 역할을 Kubernetes의 사용자나 그룹에 매핑할 수 있습니다. 이를 통해 AWS의 인증 체계와 Kubernetes의 권한 관리를 연동할 수 있습니다.

네트워킹도 중요한 고려사항입니다. EKS는 Amazon VPC CNI 플러그인을 사용하여 Pod에 VPC IP 주소를 직접 할당합니다.

이를 통해 Pod가 VPC 내의 다른 리소스와 직접 통신할 수 있습니다. 박시니어 씨가 마지막으로 조언했습니다.

"EKS를 처음 쓴다면 eksctl 도구를 추천해. 클러스터 생성부터 노드 그룹 관리까지 한 줄 명령어로 할 수 있어.

나중에 익숙해지면 CDK나 Terraform으로 전환하면 돼."

실전 팁

💡 - eksctl을 사용하면 eksctl create cluster --name my-cluster 한 줄로 클러스터를 생성할 수 있습니다

  • kubectl 자동 완성을 설정해두면 명령어 입력이 훨씬 편해집니다

5. Application Load Balancer와 컨테이너 통합

김개발 씨의 ECS 서비스가 잘 동작하고 있습니다. 하지만 문제가 있습니다.

컨테이너가 여러 개인데, 사용자 트래픽을 어떻게 분산해야 할까요? 그리고 새 버전을 배포할 때 기존 트래픽은 어떻게 처리해야 할까요?

박시니어 씨가 해답을 알려주었습니다. "ALB를 연결해.

로드 밸런싱부터 헬스 체크까지 다 해줘."

**Application Load Balancer(ALB)**는 HTTP/HTTPS 트래픽을 여러 컨테이너에 분산하는 7계층 로드 밸런서입니다. ECS와 EKS 모두 ALB와 긴밀하게 통합됩니다.

ALB는 단순한 트래픽 분산뿐만 아니라 경로 기반 라우팅, 호스트 기반 라우팅, 헬스 체크, SSL 종료 등 다양한 기능을 제공합니다. 마치 호텔 프런트 데스크가 손님을 적절한 방으로 안내하듯이, ALB는 요청을 적절한 컨테이너로 라우팅합니다.

다음 코드를 살펴봅시다.

// ALB와 ECS 서비스 통합 (AWS CDK)
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as ecs from 'aws-cdk-lib/aws-ecs';

// Application Load Balancer 생성
const alb = new elbv2.ApplicationLoadBalancer(this, 'ALB', {
  vpc,
  internetFacing: true,
});

// HTTPS 리스너 추가
const listener = alb.addListener('HttpsListener', {
  port: 443,
  certificates: [certificate],
});

// ECS 서비스를 타겟 그룹에 등록
listener.addTargets('EcsTarget', {
  port: 3000,
  targets: [fargateService],
  healthCheck: {
    path: '/health',
    interval: Duration.seconds(30),
    healthyThresholdCount: 2,
    unhealthyThresholdCount: 3,
  },
});

// 경로 기반 라우팅 - /api/*는 API 서비스로
listener.addTargets('ApiTarget', {
  port: 3000,
  targets: [apiService],
  conditions: [elbv2.ListenerCondition.pathPatterns(['/api/*'])],
  priority: 1,
});

웹 서비스를 운영할 때 로드 밸런서는 필수입니다. 단일 서버로는 감당할 수 없는 트래픽을 여러 서버에 분산해야 하기 때문입니다.

컨테이너 환경에서는 이 역할을 ALB가 담당합니다. 박시니어 씨가 ALB의 동작 방식을 설명했습니다.

"사용자가 우리 서비스에 접속하면, 먼저 ALB가 요청을 받아. ALB는 등록된 컨테이너들 중 정상인 컨테이너에게 요청을 전달해.

라운드 로빈이나 최소 연결 방식으로 고르게 분산하지." 타겟 그룹은 ALB가 트래픽을 전달할 대상의 집합입니다. ECS 서비스를 타겟 그룹에 등록하면, ECS가 자동으로 새로운 Task를 타겟 그룹에 추가하고, 종료되는 Task는 제거합니다.

이를 동적 포트 매핑이라고 합니다. 전통적인 EC2 환경에서는 서버마다 고정된 포트를 사용했습니다.

하지만 컨테이너는 동적으로 생성되고 삭제됩니다. 호스트에서 여러 컨테이너가 실행될 때 각각 다른 포트를 사용해야 합니다.

ALB는 이런 동적 환경을 완벽하게 지원합니다. 헬스 체크는 ALB의 핵심 기능입니다.

주기적으로 각 컨테이너에 HTTP 요청을 보내 정상 여부를 확인합니다. 응답이 없거나 오류 코드가 반환되면 해당 컨테이너를 비정상으로 표시하고 트래픽을 보내지 않습니다.

이를 통해 장애가 발생한 컨테이너로 요청이 가는 것을 방지합니다. 경로 기반 라우팅도 강력한 기능입니다.

단일 ALB로 여러 마이크로서비스를 서비스할 수 있습니다. 예를 들어 /api/*로 시작하는 요청은 API 서비스로, /admin/*은 관리자 서비스로, 나머지는 프론트엔드 서비스로 라우팅할 수 있습니다.

김개발 씨가 질문했습니다. "배포할 때는 어떻게 되나요?

새 버전 컨테이너가 뜨면 바로 트래픽을 받나요?" 박시니어 씨가 고개를 저었습니다. "아니야.

새 컨테이너가 뜨면 먼저 헬스 체크를 통과해야 해. 드레이닝 기간 동안은 기존 컨테이너가 진행 중인 요청을 처리하고, 새 요청만 새 컨테이너로 가.

그래서 무중단 배포가 가능한 거야." SSL/TLS 종료도 ALB에서 처리합니다. 인증서를 ALB에 등록하면 HTTPS 트래픽을 복호화하여 컨테이너에는 HTTP로 전달합니다.

컨테이너에서 SSL을 처리하지 않아도 되므로 성능이 향상되고 인증서 관리가 간편해집니다. EKS에서는 AWS Load Balancer Controller를 설치하면 Kubernetes Ingress 리소스가 자동으로 ALB를 생성합니다.

Kubernetes 방식으로 로드 밸런서를 선언적으로 관리할 수 있습니다. 스티키 세션이 필요한 경우도 있습니다.

동일한 사용자의 요청을 항상 같은 컨테이너로 보내야 할 때 사용합니다. 다만 컨테이너 환경에서는 가급적 스테이트리스하게 설계하여 스티키 세션 없이도 동작하도록 하는 것이 좋습니다.

실전 팁

💡 - ALB 액세스 로그를 S3에 저장하면 트래픽 분석과 문제 추적에 유용합니다

  • ALB의 Connection Draining 시간을 적절히 설정하여 배포 시 기존 요청이 완료되도록 하세요

6. Service Mesh App Mesh 소개

서비스가 늘어나면서 새로운 고민이 생겼습니다. API 게이트웨이, 사용자 서비스, 주문 서비스, 결제 서비스...

서비스 간 통신이 복잡해지기 시작했습니다. "서비스 A가 서비스 B를 호출하는데, B가 죽으면 어떻게 하죠?

재시도는요? 타임아웃은요?" 김개발 씨의 질문에 박시니어 씨가 답했습니다.

"이제 서비스 메시를 도입할 때가 됐어."

Service Mesh는 마이크로서비스 간 통신을 관리하는 인프라 계층입니다. AWS App Mesh는 AWS에서 제공하는 서비스 메시 솔루션입니다.

각 서비스 옆에 **사이드카 프록시(Envoy)**를 배치하여 트래픽을 제어합니다. 마치 각 서비스에 전담 비서를 붙여주는 것과 같습니다.

비서가 다른 부서와의 소통, 일정 관리, 문제 발생 시 대처를 모두 처리해주듯이, 사이드카 프록시가 서비스 간 통신의 모든 복잡성을 처리합니다.

다음 코드를 살펴봅시다.

// AWS App Mesh 구성 (AWS CDK)
import * as appmesh from 'aws-cdk-lib/aws-appmesh';

// 메시 생성 - 서비스 메시의 컨테이너
const mesh = new appmesh.Mesh(this, 'AppMesh', {
  meshName: 'my-app-mesh',
});

// 가상 노드 - 실제 서비스를 추상화
const userServiceNode = new appmesh.VirtualNode(this, 'UserServiceNode', {
  mesh,
  virtualNodeName: 'user-service',
  serviceDiscovery: appmesh.ServiceDiscovery.cloudMap(userService),
  listeners: [appmesh.VirtualNodeListener.http({ port: 3000 })],
  // 재시도 정책 설정
  backends: [appmesh.Backend.virtualService(orderVirtualService)],
});

// 가상 서비스 - 서비스 이름으로 접근
const userVirtualService = new appmesh.VirtualService(this, 'UserVS', {
  virtualServiceName: 'user.local',
  virtualServiceProvider: appmesh.VirtualServiceProvider.virtualNode(userServiceNode),
});

// 가상 라우터 - 트래픽 분산 규칙
const router = new appmesh.VirtualRouter(this, 'Router', {
  mesh,
  listeners: [appmesh.VirtualRouterListener.http(3000)],
});

// 라우트 - 카나리 배포 (90% v1, 10% v2)
router.addRoute('CanaryRoute', {
  routeSpec: appmesh.RouteSpec.http({
    weightedTargets: [
      { virtualNode: v1Node, weight: 90 },
      { virtualNode: v2Node, weight: 10 },
    ],
  }),
});

마이크로서비스 아키텍처가 성숙해지면 필연적으로 서비스 간 통신 문제를 마주합니다. 서비스 A가 서비스 B를 호출하는데, B가 응답하지 않으면 어떻게 할까요?

무한정 기다릴 수는 없습니다. 재시도를 해야 할까요?

몇 번이나? 이런 복잡한 로직을 모든 서비스에 직접 구현하는 것은 중복이고 실수하기 쉽습니다.

서비스 메시는 이런 문제를 해결합니다. 핵심 아이디어는 네트워크 통신 로직을 애플리케이션에서 분리하여 인프라 계층에서 처리하는 것입니다.

박시니어 씨가 그림을 그리며 설명했습니다. "각 서비스 컨테이너 옆에 사이드카 프록시를 붙여.

Envoy라는 고성능 프록시를 사용해. 서비스의 모든 인바운드, 아웃바운드 트래픽이 이 프록시를 통해 지나가." App Mesh의 핵심 개념을 살펴보겠습니다.

Mesh는 서비스 메시의 경계입니다. 일반적으로 애플리케이션당 하나의 Mesh를 생성합니다.

Virtual Node는 실제 서비스를 추상화한 것입니다. ECS 서비스나 EKS의 Deployment가 Virtual Node에 매핑됩니다.

Virtual Service는 서비스 이름으로 접근할 수 있게 해줍니다. user.local이라는 이름으로 요청하면 App Mesh가 적절한 Virtual Node로 라우팅합니다.

Virtual Router는 트래픽을 어떻게 분산할지 규칙을 정의합니다. 서비스 메시의 대표적인 기능들을 알아보겠습니다.

재시도(Retry) 정책을 설정할 수 있습니다. 요청이 실패하면 자동으로 재시도합니다.

재시도 횟수, 재시도 간격, 어떤 오류에 대해 재시도할지 세밀하게 설정할 수 있습니다. **타임아웃(Timeout)**도 중요합니다.

응답이 너무 오래 걸리면 연결을 끊고 에러를 반환합니다. 무한정 기다리는 것보다 빠르게 실패하고 다음 동작을 취하는 것이 좋습니다.

**서킷 브레이커(Circuit Breaker)**는 장애 전파를 방지합니다. 특정 서비스의 실패율이 임계치를 넘으면 해당 서비스로의 요청을 일시적으로 차단합니다.

마치 전기 과부하 시 차단기가 내려가는 것과 같습니다. 카나리 배포도 App Mesh로 쉽게 구현할 수 있습니다.

위 코드에서 보듯이 트래픽의 90%는 v1으로, 10%는 v2로 보낼 수 있습니다. 새 버전에 문제가 없으면 점진적으로 비율을 높여갑니다.

**관찰 가능성(Observability)**도 향상됩니다. 모든 트래픽이 프록시를 통과하므로 지표를 수집하기 쉽습니다.

X-Ray와 통합하여 분산 추적을 할 수 있고, CloudWatch로 메트릭을 보낼 수 있습니다. 김개발 씨가 질문했습니다.

"근데 프록시를 거치면 느려지지 않나요?" 박시니어 씨가 답했습니다. "Envoy는 C++로 작성된 고성능 프록시야.

지연 시간은 보통 1밀리초 미만이야. 서비스 메시가 주는 이점에 비하면 충분히 감수할 만해." 다만 서비스 메시가 만능은 아닙니다.

소규모 서비스에는 오버헤드가 될 수 있습니다. 서비스가 많지 않고 통신 패턴이 단순하다면 ALB와 기본적인 재시도 로직만으로 충분할 수 있습니다.

서비스 메시는 마이크로서비스가 충분히 성숙했을 때 도입을 고려하세요.

실전 팁

💡 - 서비스 메시 도입 전에 먼저 ALB와 기본적인 헬스 체크로 시작하고, 필요성이 명확해지면 도입하세요

  • Istio도 EKS에서 사용할 수 있는 인기 있는 서비스 메시 옵션입니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#AWS#ECS#EKS#Container#Kubernetes

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스

실전 프로젝트 글로벌 엔터프라이즈급 AWS 아키텍처

글로벌 서비스를 위한 엔터프라이즈급 AWS 아키텍처 설계부터 구축까지 실전 프로젝트로 배우는 완벽 가이드입니다. 멀티 리전 고가용성, 보안, 모니터링, CI/CD까지 실무에서 바로 적용할 수 있는 노하우를 담았습니다.

CodePipeline으로 완전 자동화된 CI/CD 구축

AWS CodeCommit, CodeBuild, CodeDeploy, CodePipeline을 활용하여 코드 커밋부터 배포까지 완전히 자동화된 CI/CD 파이프라인을 구축하는 방법을 초급 개발자를 위해 쉽게 설명합니다. 실무 상황을 스토리로 풀어내며 각 단계를 자세히 다룹니다.

AWS 비용 최적화 및 FinOps 전략 완벽 가이드

AWS 클라우드 비용을 효과적으로 관리하고 최적화하는 방법을 알아봅니다. Reserved Instance, Spot Instance, Savings Plans 등 다양한 비용 절감 전략과 FinOps 사고방식을 초급 개발자도 쉽게 이해할 수 있도록 설명합니다.

대규모 트래픽을 위한 확장 가능한 아키텍처 완벽 가이드

AWS 환경에서 대규모 트래픽을 처리하기 위한 확장 가능한 아키텍처 설계 방법을 다룹니다. 수평/수직 확장부터 Stateless 설계, 세션 관리, 메시지 큐, Lambda, API Gateway까지 실무에서 바로 적용할 수 있는 핵심 개념을 초급 개발자도 이해할 수 있도록 친절하게 설명합니다.

AWS Organizations로 멀티 계정 거버넌스 구축

AWS Organizations를 활용하여 여러 AWS 계정을 효율적으로 관리하고 보안 정책을 일관성 있게 적용하는 방법을 알아봅니다. 초급 개발자도 쉽게 이해할 수 있도록 실무 사례와 함께 설명합니다.