마이크로서비스는 클라우드 애플리케이션을 만들기 위한 아키텍처 접근 방식입니다. 각 애플리케이션은 서비스의 한 세트로 구축되며, 각 서비스는 자체 프로세스에서 실행되고 API를 통해 통신합니다. 클라우드 마이크로서비스 아키텍처로 이어진 혁신은 20여 년 전에 시작되었습니다. 서비스 구조의 개념은 컨테이너보다 오래되었으며 최신 웹 애플리케이션 시대 이전부터 시작됩니다. 마이크로서비스 아키텍처는 시간이 지남에 따라 모범 사례로 발전한 애플리케이션 개발 방식입니다.
현재 마이크로서비스 아키텍처의 이점을 이해하려면 마이크로서비스의 출발점이 어디였는지 이해하는 것이 중요합니다.
모놀리식 애플리케이션
처음에는 단일 서버에 상주하는 각 애플리케이션이 다음 세 계층으로 구성되어 있었습니다.
이들 계층은 데이터 센터의 단일 모놀리식 서버에 위치한 단일 통합 스택에 구축되었습니다. 이러한 패턴은 모든 산업 분야와 기술 아키텍처에서 공통으로 적용되었습니다. 일반적으로 애플리케이션은 데이터베이스, 다양한 유형의 비즈니스 로직, 그래픽 렌더링 코드 또는 로깅과 같은 특정 기능을 제공하는 코드 모듈의 모음입니다.
이 모놀리식 아키텍처에서 사용자는 비즈니스 로직 계층 및 데이터베이스 계층과 통신하는 프레젠테이션 계층과 상호 작용했으며 정보는 스택을 통해 다시 최종 사용자에게 전달되었습니다. 이 방법이 애플리케이션을 구성하는 효율적인 방법이기는 하지만 많은 단일 장애 지점이 생성되어 하드웨어 장애나 코드 버그가 있는 경우 장기간의 가동 중단을 초래할 수 있습니다. 안타깝게도 이 구조에는 '자동 복구'가 존재하지 않았습니다. 시스템의 일부가 손상되면 사람이 개입하여 하드웨어 또는 소프트웨어를 수정해야 했습니다.
게다가 이러한 계층 중 하나를 확장한다는 것은 완전히 새로운 서버를 구매해야 함을 의미했습니다. 단일 서버에서 실행되는 모놀리식 애플리케이션을 구매하고 사용자들 중 일부를 새 시스템으로 분할해야 했습니다. 이러한 분할로 인해 사용자 데이터의 사일로가 발생했으며, 야간 일괄 보고서를 통해 조정하는 작업이 필요했습니다. 다행히 웹 페이지 및 모바일 애플리케이션이 대중화되면서 클라이언트의 필요성은 적어지고, 새로운 애플리케이션 개발 방법이 형성되기 시작했습니다.
서비스 중심 아키텍처(SOA)
2000년대 중반에는 단일 서버 외부에 다양한 계층이 독립적인 서비스 사일로로 존재하도록 아키텍처가 변화하기 시작했습니다. 애플리케이션은 통신용 엔터프라이즈 서비스 버스를 사용하여 이러한 서비스를 통합하도록 설계되었습니다. 이 방식에서 관리자는 프록시 기능을 통해 서버를 통합하여 이러한 서비스를 독립적으로 확장할 수 있습니다. 또한, 엔지니어가 애플리케이션 서비스 구조의 한 부분에만 집중할 수 있어 개발 주기가 단축되었습니다. 서비스를 분리하고 독립적인 개발을 허용하려면 서비스가 서로 통신하는 데 사용하는 구문 규칙 집합인 API를 사용해야 했습니다.
또한, SOA는 가상 머신(VM)의 증가에 맞추어 물리적 서버 리소스의 효율성을 높였습니다. 베어 메탈 서버의 이전 모놀리식 애플리케이션과 비교하여 소규모 VM에 서비스를 훨씬 더 빠르게 배포할 수 있었습니다. 이러한 기술의 결합을 통해 서비스 아키텍처 및 관련 인프라 기술 모두에서 더 나은 고가용성(HA) 솔루션이 개발되었습니다.
마이크로서비스
오늘날, 클라우드 마이크로서비스는 세분화된 기능별 서비스 모음으로서 SOA 전략을 더욱 세분화합니다. 마이크로서비스 모음이 대규모 매크로서비스로 결합되어 전체 서비스 또는 대규모 최종 사용자 애플리케이션에서 단일 기능의 코드를 더욱 빠르게 업데이트할 수 있는 훨씬 더 뛰어난 기능을 제공합니다. 마이크로서비스는 데이터 검색, 로깅 기능 또는 웹 서비스 기능과 같은 단일 문제를 해결하는 데 주력합니다. 이러한 접근 방식은 마이크로서비스 아키텍처의 나머지 부분을 리팩토링하거나 재배포할 필요 없이 단일 기능의 코드만 업데이트하면 되므로 유연성이 높아집니다. 장애 지점은 상호 독립적이므로 전반적인 애플리케이션 아키텍처의 안정성이 더욱 향상됩니다.
또한, 이 접근 방식에서는 마이크로서비스가 자동 복구될 수 있습니다. 예를 들어, 한 클러스터의 마이크로서비스에 세 개의 하위 기능이 포함되어 있다고 가정하겠습니다. 이러한 하위 기능 중 하나가 실패하면 해당 마이크로서비스는 복구되고 있는 것입니다. Kubernetes와 같은 오케스트레이션 툴을 사용하면 사람의 개입 없이 자동 복구가 가능하며, 백그라운드에서 자동으로 수행되고 최종 사용자는 투명하게 확인할 수 있습니다.
마이크로서비스 아키텍처는 패키징 및 배포 구조인 Docker 컨테이너와 함께 사용됩니다. VM 이미지가 다년간 배포 메커니즘으로 사용되어 왔지만 컨테이너가 VM보다 훨씬 효율적이므로 모든 Linux 시스템 또는 Docker 컨테이너를 지원하는 모든 OS에 코드(및 필수 코드 라이브러리)를 배포할 수 있습니다. 컨테이너는 마이크로서비스를 위한 완벽한 배포 형식입니다. 또한, 몇 초 이내에 시작할 수 있으므로 장애 또는 마이그레이션 후에 신속하게 재배포할 수 있으며 요구사항에 따라 빠르게 확장할 수 있습니다. 컨테이너는 Linux의 네이티브 기능이므로 모든 데이터 센터, 프라이빗 클라우드 또는 하이브리드 멀티 클라우드에 있는 방대한 마이크로서비스 팜에 일반 하드웨어를 적용할 수 있습니다.
마이크로서비스는 처음부터 거의 클라우드 네이티브 아키텍처와 얽혀 있어 여러 면에서 서로 구분하기 어렵습니다. 마이크로서비스와 컨테이너는 상당히 추상화되기 때문에 모든 호환 OS(일반적으로 Linux)에서 실행할 수 있습니다. 해당 OS는 퍼블릭 클라우드, 온프레미스, 가상 하이퍼바이저, 심지어 베어 메탈 등 어디에나 존재할 수 있습니다. 클라우드에서 더 많은 개발이 수행되면서 클라우드 네이티브 아키텍처와 방식이 온프레미스 데이터 센터로 다시 마이그레이션되었습니다. 많은 조직이 클라우드와 동일한 기본 특성을 공유하도록 로컬 환경을 구축하고 있으며, 이를 통해 모든 위치에서 단일 개발 방식을 구현하거나 어디서나 클라우드 네이티브를 구현하고 있습니다. 이러한 클라우드 네이티브 접근 방식은 마이크로서비스 아키텍처와 컨테이너 기술을 도입했기에 가능해졌고, 또한 이 방식이 필요합니다.
마이크로서비스는 분산되어 서로 다른 서버에서 실행되지만 여전히 애플리케이션을 위해 함께 작동합니다. 이상적인 것은 한 마이크로서비스가 하나의 기능을 제공하고 API 통신으로 서비스 간에 단순 라우팅되는 방식입니다. 이 외에도 몇 가지 이점이 더 있습니다.
컨테이너
컨테이너는 변경 불가능합니다. 즉, 배포한 후에는 변경할 수도 변경해서도 안 됩니다. 새 버전의 코드가 개발되면 컨테이너가 삭제되고 최신 코드가 포함된 새 컨테이너가 그 자리에 배포됩니다. 컨테이너를 몇 초 또는 몇 밀리초 이내에 시작할 수 있으므로 필요할 때 필요한 곳에 추가 서비스 구성 요소를 즉시 배포할 수 있습니다. VM 또는 베어 메탈에 비해 상대적으로 리소스 설치 공간이 적기에 컨테이너는 마이크로서비스를 위한 최고의 배포 메커니즘입니다. VM에는 모든 OS 구성 요소가 포함되어 있지만 컨테이너는 마이크로서비스 코드 자체와 지원 코드 라이브러리로만 구성됩니다. 기타 필요한 기능은 컨테이너에서 실행되는 다른 마이크로서비스와 공통 OS에서 공유됩니다.
오케스트레이션
컨테이너 오케스트레이션 툴은 컨테이너 자체만큼이나 오랫동안 사용되어 왔습니다. 수천 개의 마이크로서비스가 함께 작동하여 서비스와 애플리케이션을 형성하며, 이를 수동으로 관리하는 것은 수많은 관리자가 있어도 거의 불가능합니다. 대부분의 IT 인력 예산은 그대로 유지되고, 자동화의 등장과 DevOps 방식이 도입되면서 우수한 오케스트레이션 툴의 필요성이 더욱 중요해졌습니다.
Kubernetes(K8s)의 첫 번째 버전은 Docker 컨테이너가 등장한 직후인 2015년에 출시되었으며, 컨테이너 환경에서 가장 중요한 오케스트레이션 툴로 빠르게 자리잡았습니다. Kubernetes를 통해 개발자는 컨테이너 기반 애플리케이션 또는 마이크로서비스를 공통 라이브러리에 등록하고 Kubernetes 컨트롤러에 매니페스트 파일을 제공할 수 있습니다. 그런 다음 Kubernetes는 공통 레지스트리의 컨테이너 이미지를 사용하여 매니페스트 파일의 사양에 따라 해당 작업자 노드에 애플리케이션을 배포합니다.
Kubernetes의 핵심 개념인 '원하는 상태'를 통해 자동 복구 및 자동 업그레이드 기능을 솔루션의 필수 요소로 통합할 수 있습니다. 예를 들어, 버전 1.1의 특정 마이크로서비스(컨테이너 포드) 인스턴스 10개가 항상 실행 중이어야 한다고 가정해 보겠습니다. Kubernetes는 배포를 모니터링하여 원하는 상태를 확인합니다. 컨테이너 중 하나에 장애가 발생하고 9개만 실행 중인 경우 Kubernetes는 다른 컨테이너를 배포하고 이를 실행하여 버전 1.1에서 원하는 상태인 10개의 인스턴스를 달성합니다. 버전 1.2를 지정하도록 매니페스트가 변경되면 Kubernetes는 원하는 상태가 충족되지 않은 것으로 간주하고 10개 인스턴스 모두를 버전 1.2로 롤링 업그레이드합니다(버전 1.2가 컨테이너 레지스트리에서 사용 가능한 이미지라고 가정).
Kubernetes가 이렇게 빠르게 성장하여 컨테이너 오케스트레이션 분야를 장악하게 된 이유와 Amazon Web Services, Microsoft Azure, Google Cloud Platform 등 모든 주요 퍼블릭 클라우드 공급자가 자체 버전의 Kubernetes를 보유하고 있는 이유를 쉽게 짐작할 수 있습니다.