마이크로서비스 배포 전략 선택

마이크로서비스로 애플리케이션을 구축하는 방법에 대한 시리즈의 여섯 번째 포스트입니다. 첫 번째 포스트에서는 마이크로서비스 아키텍처 패턴을 소개하고 마이크로서비스 사용의 장점과 단점에 대해 설명했습니다. 다음 포스트에서는 API Gateway 사용, 프로세스 간 통신, 서비스 검색이벤트 주도 데이터 관리와 같은 마이크로서비스 아키텍처의 다양한 측면에 대해 설명했습니다. 이 포스트에서는 마이크로서비스를 배포하기 위한 전략을 살펴봅니다.

목차

1. 동기 (Motivations)
2. 호스트 패턴당 여러 서비스 인스턴스
3. 호스트 패턴별 서비스 인스턴스
3-1. 가상 머신 패턴별 서비스 인스턴스
3-2. 컨테이너 패턴별 서비스 인스턴스
4. 서버리스 배포 (Serverless Deployment)
5. 요약

1. 동기 (Motivations)

모놀리식 애플리케이션을 배포한다는 것은 일반적으로 큰 단일 애플리케이션의 동일한 복사본을 여러 개 실행하는 것을 의미합니다. 일반적으로 N 서버(물리적 또는 가상)를 프로비저닝하고 각각에서 M개의 애플리케이션 인스턴스를 실행합니다. 모놀리식 애플리케이션의 배포가 항상 완전히 간단한 것은 아니지만 마이크로서비스 애플리케이션을 배포하는 것보다 훨씬 간단합니다.

마이크로서비스 애플리케이션은 수십 또는 수백 개의 서비스로 구성됩니다. 서비스는 다양한 언어와 프레임워크로 작성됩니다. 각각은 고유한 배포, 리소스, 확장 및 모니터링 요구 사항이 있는 미니 애플리케이션입니다. 예를 들어, 해당 서비스에 대한 수요에 따라 각 서비스의 특정 수의 인스턴스를 실행해야 합니다. 또한 각 서비스 인스턴스에는 적절한 CPU, 메모리 및 I/O 리소스가 제공되어야 합니다. 더욱 어려운 점은 이러한 복잡성에도 불구하고 서비스 배포가 빠르고 안정적이며 비용 효율적이어야 한다는 것입니다.

몇 가지 다른 마이크로서비스 배포 패턴이 있습니다. 먼저 호스트당 다중 서비스 인스턴스 패턴을 살펴보겠습니다.

2. 호스트 패턴당 여러 서비스 인스턴스

마이크로서비스를 배포하는 한 가지 방법은 호스트당 다중 서비스 인스턴스 패턴을 사용하는 것입니다. 이 패턴을 사용할 때 하나 이상의 물리적 또는 가상 호스트를 프로비저닝하고 각각에서 여러 서비스 인스턴스를 실행합니다. 여러 면에서 이것은 애플리케이션 배포에 대한 전통적인 접근 방식입니다. 각 서비스 인스턴스는 하나 이상의 호스트에서 잘 알려진 포트에서 실행됩니다. 호스트 시스템은 일반적으로 애완 동물처럼 취급됩니다.

다음 다이어그램은 이 패턴의 구조를 보여줍니다.

microservices architecture host

이 패턴에는 몇 가지 변형이 있습니다. 하나의 변형은 각 서비스 인스턴스가 프로세스 또는 프로세스 그룹이 되는 것입니다. 예를 들어 Java 서비스 인스턴스를 Apache Tomcat 서버에 웹 응용 프로그램으로 배포할 수 있습니다. Node.js 서비스 인스턴스는 상위 프로세스와 하나 이상의 하위 프로세스로 구성될 수 있습니다.

이 패턴의 다른 변형은 동일한 프로세스 또는 프로세스 그룹에서 여러 서비스 인스턴스를 실행하는 것입니다. 예를 들어 동일한 Apache Tomcat 서버에 여러 Java 웹 응용 프로그램을 배포하거나 동일한 OSGI 컨테이너에서 여러 OSGI 번들을 실행할 수 있습니다.

호스트당 다중 서비스 인스턴스 패턴에는 장점과 단점이 있습니다. 한 가지 주요 이점은 리소스 사용이 상대적으로 효율적이라는 것입니다. 여러 서비스 인스턴스가 서버와 해당 운영 체제를 공유합니다. 프로세스 또는 프로세스 그룹이 여러 서비스 인스턴스(예: 동일한 Apache Tomcat 서버 및 JVM을 공유하는 여러 웹 응용 프로그램)를 실행하는 경우 훨씬 더 효율적입니다.

이 패턴의 또 다른 이점은 서비스 인스턴스 배포가 비교적 빠르다는 것입니다. 서비스를 호스트에 복사하고 시작하기만 하면 됩니다. 서비스가 Java로 작성된 경우 JAR 또는 WAR 파일을 복사합니다. Node.js 또는 Ruby와 같은 다른 언어의 경우 소스 코드를 복사합니다. 두 경우 모두 네트워크를 통해 복사되는 바이트 수는 비교적 적습니다.

또한 오버헤드가 없기 때문에 일반적으로 서비스 시작이 매우 빠릅니다. 서비스가 자체 프로세스인 경우 시작하기만 하면 됩니다. 그렇지 않고 서비스가 동일한 컨테이너 프로세스 또는 프로세스 그룹에서 실행되는 여러 인스턴스 중 하나인 경우 컨테이너에 동적으로 배포하거나 컨테이너를 다시 시작합니다.

그 매력에도 불구하고 호스트당 다중 서비스 인스턴스 패턴에는 몇 가지 중요한 단점이 있습니다. 한 가지 주요 단점은 각 서비스 인스턴스가 별도의 프로세스가 아닌 한 서비스 인스턴스의 격리가 거의 또는 전혀 없다는 것입니다. 각 서비스 인스턴스의 리소스 사용률을 정확하게 모니터링할 수 있지만 각 인스턴스가 사용하는 리소스를 제한할 수는 없습니다. 오작동하는 서비스 인스턴스가 호스트의 모든 메모리 또는 CPU를 소비할 수 있습니다.

여러 서비스 인스턴스가 동일한 프로세스에서 실행되는 경우 격리가 전혀 없습니다. 예를 들어 모든 인스턴스는 동일한 JVM 힙을 공유할 수 있습니다. 오작동하는 서비스 인스턴스는 동일한 프로세스에서 실행 중인 다른 서비스를 쉽게 중단시킬 수 있습니다. 또한 각 서비스 인스턴스에서 사용하는 리소스를 모니터링할 방법이 없습니다.

이 접근 방식의 또 다른 중요한 문제는 서비스를 배포하는 운영 팀이 서비스를 수행하는 방법에 대한 구체적인 세부 정보를 알아야 한다는 것입니다. 서비스는 다양한 언어와 프레임워크로 작성할 수 있으므로 개발 팀이 운영팀과 공유해야 하는 세부 사항이 많이 있습니다. 이러한 복잡성은 배포 중 오류의 위험을 증가시킵니다.

보시다시피 친숙함에도 불구하고 호스트당 다중 서비스 인스턴스 패턴에는 몇 가지 중요한 단점이 있습니다. 이제 이러한 문제를 피하는 마이크로서비스를 배포하는 다른 방법을 살펴보겠습니다.

3. 호스트 패턴별 서비스 인스턴스

마이크로서비스를 배포하는 또 다른 방법은 호스트당 서비스 인스턴스 패턴입니다. 이 패턴을 사용하면 각 서비스 인스턴스를 자체 호스트에서 분리하여 실행합니다. 이 패턴에는 가상 머신당 서비스 인스턴스와 컨테이너당 서비스 인스턴스라는 두 가지 다른 전문화가 있습니다.

3-1. 가상 머신 패턴별 서비스 인스턴스

가상 머신 패턴당 서비스 인스턴스를 사용하는 경우 각 서비스를 Amazon EC2 AMI와 같은 가상 머신(VM) 이미지로 패키징합니다. 각 서비스 인스턴스는 해당 VM 이미지를 사용하여 시작되는 VM(예: EC2 인스턴스)입니다. 다음 다이어그램은 이 패턴의 구조를 보여줍니다.

microservices architecture vm

이것은 Netflix에서 비디오 스트리밍 서비스를 배포하는 데 사용하는 기본 접근 방식입니다. Netflix는 Aminator를 사용하여 각 서비스를 EC2 AMI로 패키징합니다. 실행 중인 각 서비스 인스턴스는 EC2 인스턴스입니다.

고유한 VM을 구축하는 데 사용할 수 있는 다양한 도구가 있습니다. CI(지속적 통합) 서버(예: Jenkins)를 구성하여 Aminator를 호출하여 서비스를 EC2 AMI로 패키징할 수 있습니다. Packer.io는 자동화된 VM 이미지 생성을 위한 또 다른 옵션입니다. Aminator와 달리 EC2, DigitalOcean, VirtualBox, VMware 등 다양한 가상화 기술을 지원합니다.

Boxfuse 회사는 VM 이미지를 구축하는 강력한 방법을 가지고 있으며, 이는 아래에서 설명하는 VM의 단점을 극복합니다. Boxfuse는 Java 애플리케이션을 최소 VM 이미지로 패키징합니다. 이러한 이미지는 빠르게 빌드하고 빠르게 부팅할 수 있으며 제한된 공격 표면을 노출하므로 더 안전합니다.

CloudNative라는 회사에는 EC2 AMI 생성을 위한 SaaS 제품인 Bakery가 있습니다. 마이크로서비스에 대한 테스트를 통과한 후 베이커리를 호출하도록 CI 서버를 구성할 수 있습니다. 그런 다음 Bakery는 서비스를 AMI로 패키징합니다. Bakery와 같은 SaaS 제품을 사용하면 AMI 생성 인프라를 설정하는 데 귀중한 시간을 낭비할 필요가 없습니다.

가상 머신 패턴당 서비스 인스턴스에는 많은 이점이 있습니다. VM의 주요 이점은 각 서비스 인스턴스가 완전히 격리되어 실행된다는 것입니다. CPU와 메모리가 고정되어 있고 다른 서비스에서 리소스를 훔칠 수 없습니다.

마이크로서비스를 VM으로 배포할 때의 또 다른 이점은 성숙한 클라우드 인프라를 활용할 수 있다는 것입니다. AWS와 같은 클라우드는 로드 밸런싱 및 자동 확장과 같은 유용한 기능을 제공합니다.

서비스를 VM으로 배포할 때의 또 다른 큰 이점은 서비스의 구현 기술을 캡슐화한다는 것입니다. 서비스가 VM으로 패키징되면 블랙박스가 됩니다. VM의 관리 API는 서비스 배포를 위한 API가 됩니다. 배포가 훨씬 간단하고 안정적입니다.

그러나 가상 머신 패턴당 서비스 인스턴스에는 몇 가지 단점이 있습니다. 한 가지 단점은 덜 효율적인 자원 활용입니다. 각 서비스 인스턴스에는 운영체제를 포함한 전체 VM의 오버헤드가 있습니다. 또한 일반적인 공용 IaaS에서 VM은 고정된 크기로 제공되며 VM이 충분히 활용되지 않을 수 있습니다.

공용 IaaS인 Moveover는 일반적으로 VM이 사용 중인지 유휴 상태인지에 관계없이 VM에 대해 요금을 부과합니다. AWS와 같은 IaaS는 Autoscaling을 제공하지만 수요 변화에 빠르게 대응하기 어렵다. 결과적으로 VM을 오버프로비저닝해야 하는 경우가 많아 배포 비용이 증가합니다.

이 접근 방식의 또 다른 단점은 새 버전의 서비스 배포가 일반적으로 느리다는 것입니다. VM 이미지는 일반적으로 크기 때문에 빌드 속도가 느립니다. 또한 VM은 일반적으로 크기 때문에 인스턴스화 속도가 느립니다. 또한 운영체제는 일반적으로 시작하는 데 시간이 걸립니다. 그러나 Boxfuse에서 구축한 것과 같은 경량 VM이 존재하기 때문에 이것은 보편적으로 사실이 아닙니다.

가상 머신별 서비스 인스턴스 패턴의 또 다른 단점은 일반적으로 귀하(또는 조직의 다른 사람)가 많은 미분류 작업에 대한 책임이 있다는 것입니다. VM 구축 및 관리의 오버헤드를 처리하는 Boxfuse와 같은 도구를 사용하지 않는 한 이는 사용자의 책임입니다. 이 필요하지만 시간이 많이 걸리는 활동은 핵심 비즈니스에서 주의를 산만하게 합니다.

이제 더 가벼우면서도 여전히 VM의 많은 이점이 있는 마이크로서비스를 배포하는 다른 방법을 살펴보겠습니다.

3-2. 컨테이너 패턴별 서비스 인스턴스

컨테이너별 서비스 인스턴스 패턴을 사용하는 경우 각 서비스 인스턴스는 자체 컨테이너에서 실행됩니다. 컨테이너는 운영체제 수준의 가상화 메커니즘입니다. 컨테이너는 샌드박스에서 실행되는 하나 이상의 프로세스로 구성됩니다. 프로세스의 관점에서 볼 때 자체 포트 네임스페이스와 루트 파일 시스템이 있습니다. 컨테이너의 메모리 및 CPU 리소스를 제한할 수 있습니다. 일부 컨테이너 구현에는 I/O 속도 제한도 있습니다. 컨테이너 기술의 예로는 Docker 및 Solaris 영역이 있습니다.

다음 다이어그램은 이 패턴의 구조를 보여줍니다.

microservices architecture container

이 패턴을 사용하려면 서비스를 컨테이너 이미지로 패키징합니다. 컨테이너 이미지는 서비스를 실행하는 데 필요한 애플리케이션과 라이브러리로 구성된 파일 시스템 이미지입니다. 일부 컨테이너 이미지는 완전한 Linux 루트 파일 시스템으로 구성됩니다. 다른 것들은 더 가볍습니다. 예를 들어 Java 서비스를 배포하려면 Java 런타임(아마도 Apache Tomcat 서버 및 컴파일된 Java 응용 프로그램)이 포함된 컨테이너 이미지를 빌드합니다.

서비스를 컨테이너 이미지로 패키징한 후에는 하나 이상의 컨테이너를 시작합니다. 일반적으로 각 물리적 또는 가상 호스트에서 여러 컨테이너를 실행합니다. Kubernetes 또는 Marathon과 같은 클러스터 관리자를 사용하여 컨테이너를 관리할 수 있습니다. 클러스터 관리자는 호스트를 리소스 풀로 취급합니다. 컨테이너에 필요한 리소스와 각 호스트에서 사용 가능한 리소스를 기반으로 각 컨테이너를 배치할 위치를 결정합니다.

컨테이너당 서비스 인스턴스 패턴에는 장점과 단점이 있습니다. 컨테이너의 이점은 VM의 이점과 유사합니다. 서비스 인스턴스를 서로 격리합니다. 각 컨테이너에서 사용하는 리소스를 쉽게 모니터링할 수 있습니다. 또한 VM과 마찬가지로 컨테이너는 서비스를 구현하는 데 사용되는 기술을 캡슐화합니다. 컨테이너 관리 API는 서비스 관리를 위한 API 역할도 합니다.

그러나 VM과 달리 컨테이너는 경량 기술입니다. 컨테이너 이미지는 일반적으로 빌드 속도가 매우 빠릅니다. 예를 들어 노트북에서 Spring Boot 애플리케이션을 Docker 컨테이너로 패키징하는 데 5초밖에 걸리지 않습니다. 긴 OS 부팅 메커니즘이 없기 때문에 컨테이너도 매우 빠르게 시작됩니다. 컨테이너가 시작되면 실행되는 것은 서비스입니다.

컨테이너를 사용하는 데에는 몇 가지 단점이 있습니다. 컨테이너 인프라는 빠르게 성숙하고 있지만 VM을 위한 인프라만큼 성숙하지 않습니다. 또한 컨테이너는 호스트 OS의 커널을 서로 공유하므로 컨테이너는 VM만큼 안전하지 않습니다.

컨테이너의 또 다른 단점은 컨테이너 이미지를 관리해야 하는 무차별적인 무거운 짐을 본인이 책임져야 한다는 것입니다. 또한 Google Container Engine 또는 Amazon EC2 Container Service(ECS)와 같은 호스팅된 컨테이너 솔루션을 사용하지 않는 경우 컨테이너 인프라 및 실행되는 VM 인프라를 관리해야 합니다.

또한 컨테이너는 VM당 가격이 책정되는 인프라에 배포되는 경우가 많습니다. 결과적으로 앞서 설명한 것처럼 부하 급증을 처리하기 위해 VM을 과도하게 프로비저닝하는 추가 비용이 발생할 수 있습니다.

흥미롭게도 컨테이너와 VM의 구분이 흐려질 가능성이 있습니다. 앞서 언급했듯이 Boxfuse VM은 구축 및 시작이 빠릅니다. Clear Containers 프로젝트는 경량 VM을 만드는 것을 목표로 합니다.

또한 컨테이너 또는 VM에 서비스를 배포하는 것 중에서 선택해야 하는 문제를 회피하는 접근 방식인 서버리스 배포라는 새롭고 점점 더 대중적인 개념이 있습니다. 다음으로 살펴보겠습니다.

4. 서버리스 배포 (Serverless Deployment)

AWS Lambda는 서버리스 배포 기술의 한 예입니다. Java, Node.js 및 Python 서비스를 지원합니다. 마이크로서비스를 배포하려면 ZIP 파일로 패키징하고 AWS Lambda에 업로드합니다. 또한 요청(일명 이벤트)을 처리하기 위해 호출되는 함수의 이름을 지정하는 메타데이터를 제공합니다. AWS Lambda는 요청을 처리하기에 충분한 마이크로서비스 인스턴스를 자동으로 실행합니다. 소요된 시간과 사용한 메모리를 기준으로 각 요청에 대해 간단히 청구됩니다. 물론 devil는 세부 사항에 있으며 AWS Lambda에는 한계가 있음을 곧 알게 될 것입니다. 그러나 개발자나 조직의 어느 누구도 서버, 가상 머신 또는 컨테이너의 모든 측면에 대해 걱정할 필요가 없다는 개념은 매우 매력적입니다.

Lambda 함수는 상태 비저장 서비스입니다. 일반적으로 AWS 서비스를 호출하여 요청을 처리합니다. 예를 들어 이미지가 S3 버킷에 업로드될 때 호출되는 Lambda 함수는 DynamoDB 이미지 테이블에 항목을 삽입하고 Kinesis 스트림에 메시지를 게시하여 이미지 처리를 트리거할 수 있습니다. Lambda 함수는 타사 웹 서비스를 호출할 수도 있습니다.

Lambda 함수를 호출하는 네 가지 방법이 있습니다.

  1. 웹 서비스 요청을 사용하여 직접
  2. S3, DynamoDB, Kinesis 또는 Simple Email Service와 같은 AWS 서비스에서 생성된 이벤트에 대한 응답으로 자동
  3. 애플리케이션 클라이언트의 HTTP 요청을 처리하기 위해 AWS API Gateway를 통해 자동으로
  4. 주기적으로 cron과 같은 일정에 따라

보시다시피 AWS Lambda는 마이크로서비스를 배포하는 편리한 방법입니다. 요청 기반 가격 책정은 서비스가 실제로 수행하는 작업에 대해서만 비용을 지불하는 것을 의미합니다. 또한 IT 인프라에 대한 책임이 없기 때문에 애플리케이션 개발에 집중할 수 있습니다.

그러나 몇 가지 중요한 제한 사항이 있습니다. 타사 메시지 브로커의 메시지를 사용하는 서비스와 같은 장기 실행 서비스를 배포하는 데 사용하기 위한 것이 아닙니다. 요청은 300초 이내에 완료되어야 합니다. 이론적으로 AWS Lambda는 각 요청에 대해 별도의 인스턴스를 실행할 수 있으므로 서비스는 상태 비저장이어야 합니다. 지원되는 언어 중 하나로 작성해야 합니다. 서비스도 빨리 시작해야 합니다. 그렇지 않으면 시간이 초과되어 종료될 수 있습니다.

5. 요약

마이크로서비스 애플리케이션을 배포하는 것은 어려운 일입니다. 다양한 언어와 프레임워크로 작성된 수십 또는 수백 개의 서비스가 있습니다. 각각은 고유한 배포, 리소스, 확장 및 모니터링 요구 사항이 있는 미니 애플리케이션입니다. 가상 머신당 서비스 인스턴스 및 컨테이너당 서비스 인스턴스를 비롯한 여러 마이크로 서비스 배포 패턴이 있습니다. 마이크로서비스를 배포하기 위한 또 다른 흥미로운 옵션은 서버리스 접근 방식인 AWS Lambda입니다. 이 시리즈의 다음이자 마지막 부분에서는 모놀리식 애플리케이션을 마이크로서비스 아키텍처로 마이그레이션하는 방법을 살펴보겠습니다.