AWS: 단일 EC2 인스턴스의 여러 컨테이너 간 통신
동기 부여:
때로는 서비스가 단일 애플리케이션이 아니므로 도커화 및 배포가 쉽습니다. 하지만 서비스에 여러 개의 도커 컨테이너가 있고 그 중 하나가 다른 컨테이너의 데이터를 소비한다면 어떻게 될까요? 이를 위해서는 컨테이너 간에 일종의 통신 채널을 만들어야 합니다. 애플리케이션당 EC2 인스턴스를 생성할 때 전략으로 쉽게 달성할 수 있지만 이렇게 하면 비용이 증가하고 분명히 그러한 전략은 비용 효율적이지 않습니다. 그런 다음 EC2 인스턴스를 최대한 활용하고 단일 EC2 인스턴스에서 도커화된 두 애플리케이션을 모두 실행하려고 합니다.
이것은 애플리케이션이 있고 단일 EC2 인스턴스에서 이들 간에 통신할 수 있는 기능이 있는 2개의 도커 컨테이너로 구성된 AWS ECS 작업 정의를 생성하는 방법에 대한 단계별 안내서입니다.
EC2 인스턴스에서 도커 컨테이너를 관리하기 위해 ECS service을 사용할 예정입니다.
ECS 클러스터 및 ECS 서비스 생성
거의 수정하지 않고 공식 AWS-ECSexample의 기본 스택부터 시작하겠습니다.
declare const vpc: ec2.Vpc;
// Create an ECS cluster
const cluster = new ecs.Cluster(this, 'Cluster', {
vpc,
});
// Add capacity to it
cluster.addCapacity('DefaultAutoScalingGroupCapacity', {
instanceType: new ec2.InstanceType("t2.micro"),
desiredCapacity: 1,
});
// Place for adding task definition,
// docker container options,
// and all other options from this article below
// Instantiate an Amazon ECS Service
const ecsService = new ecs.Ec2Service(this, 'Service', {
cluster,
taskDefinition,
});
작업 정의 추가
여기서 가장 중요한 것은 Bridge Network Mode로 작업 정의를 생성하는 것입니다. 이 모드는 동일한 Docker의 내부 네트워크 또는 Bridge에 연결된 도커 컨테이너 간의 통신을 가능하게 합니다.
const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef', {
networkMode: Network.BRIDGE,
});
ProducerApp 컨테이너 추가
이제 생산자 컨테이너를 추가해 보겠습니다. 생산자 응용 프로그램은 소비자가 데이터를 얻을 수 있는 끝점이
/data
인 포트 8080의 간단한 HTTP 서버입니다.const producerContainer = taskDefinition.addContainer('ProducerContainer', {
image: ecs.ContainerImage.fromRegistry('producer-image'),
memoryLimitMiB: 256,
});
producerContainer.addPortMappings({
containerPort: 80,
hostPort: 8080,
protocol: ecs.Protocol.TCP,
});
소비자 컨테이너 추가
또한 소비자 컨테이너를 추가해 보겠습니다. 소비자 응용 프로그램은 매분 생산자 응용 프로그램에서 데이터를 검색하는 HTTP 클라이언트처럼 작동할 수 있는 기능이 있는 포트 8081의 HTTP 서버입니다.
그러나 소비자 응용 프로그램이 생산자 응용 프로그램에 도달하는 방법을 어떻게 알 수 있습니까? 소비자 앱은 어떤 엔드포인트를 핑해야 합니까? 우리는 잠시 후에 이것을 명확히 할 것입니다.
const consumerContainer = taskDefinition.addContainer('ConsumerContainer', {
image: ecs.ContainerImage.fromRegistry('consumer-image'),
memoryLimitMiB: 256,
});
consumerContainer.addPortMappings({
containerPort: 81,
hostPort: 8081,
protocol: ecs.Protocol.TCP,
});
컨테이너 간 통신 추가
그리고 이제 마지막 요령: ProducerContainer와 ConsumerContainer 간의 통신 방법을 만들어야 합니다. addLink 메서드를 사용합니다. 이 방법의 좋은 점은 포트 매핑 등에 대해 걱정할 필요가 없다는 것입니다. 내부적으로 이 방법은 별칭을/etc/hosts에 추가하여 컨테이너가 별칭을 사용하여 서로 통신할 수 있도록 하고 두 컨테이너가 동일한 브리지 네트워크에 있으므로 컨테이너에 연결할 수 있습니다.
consumerContainer.addLink(producerContainer)
그것이 CDK의 관점에서 본 것입니다. 그러나 우리는 여전히 소비자 응용 프로그램이 데이터를 검색해야 하는 생산자의 끝점을 놓치고 있습니다.
Producer 엔드포인트를 찾기 위해 더 깊이 파고들기
CDK를 성공적으로 배포한 후 Producer 엔드포인트가 어떻게 생겼는지 알아봅시다.
SSH 또는 세션 관리자를 통해 EC2 인스턴스에 연결합니다.
~$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6a008b35bb2 producerContainer "/usr/src/app/produc…" 10 min ago Up 10 min producerContainer
a85bbfa3fae3 consumerContainer "/usr/src/app/consum…" 10 min ago Up 10 min consumerContainer
우선 우리는 두 개의 도커 컨테이너가 실행되고 있음을 분명히 알 수 있습니다. consumerContainer에 대해 자세히 살펴보겠습니다.
~$ sudo docker exec -it a85bbfa3fae3 /bin/sh
~$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
172.17.0.2 producerContainer d6a008b35bb2
172.17.0.3 a85bbfa3fae3
보시다시피 이제 우리는 producerContainer의 별칭을 알고 있습니다.
172.17.0.2 producerContainer d6a008b35bb2.
그것에서 데이터를 얻자!
~$ curl producerContainer:8080/data
~$ {data: "Very important data"}
그것은 매력처럼 작동했습니다! 이제 소비자 응용 프로그램의 HTTP 클라이언트에 대한 대상 끝점으로
producerContainer:8080/data
를 추가하고 생산자 응용 프로그램에서 데이터를 검색하기만 하면 됩니다!추가 아이디어로, 데이터를 더 자주 검색하거나 컨테이너 간의 양방향 통신이 필요한 경우 컨테이너 간에 WebSocket 연결을 설정하고 보다 편리하고 빠른 방식으로 데이터를 생성/소비하는 것을 고려할 수 있습니다!
결론:
이 트릭은 docker 및 AWS에 대해 더 많이 이해하는 데 도움이 될 뿐만 아니라 더 많은 EC2 인스턴스를 활용하고 비용을 절약하는 데 도움이 됩니다! 당신이 그것을 즐겼기를 바랍니다!
Reference
이 문제에 관하여(AWS: 단일 EC2 인스턴스의 여러 컨테이너 간 통신), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/nafarya/aws-communication-between-multiple-containers-on-single-ec2-instance-3clj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)