상세 컨텐츠

본문 제목

모듈, 모놀리스, 그리고 마이크로 서비스

설명서

by 테일스케일 2021. 3. 9. 05:57

본문

최근 마이크로 서비스는 언제 사용해야 좋은지에 대한 질문을 받습니다. 저는 시스템 설계가 세상을 설명한다(Systems design explains the world)에서 거시적 관점에서의 두 번째 시스템 효과와 혁신자의 딜레마 등에 대하여 이야기해 보았습니다. 과연 시스템 설계가 마이크로 서비스 질문에 대한 해답이 될 수 있을까요?

 

네, 그렇습니다. 하지만, 답변이 마음에 들지 않을 수도 있습니다. 첫째로, 우리는 그간의 역사를 조금 알아 볼 필요가 있습니다.

 

마이크로 서비스란 무엇입니까?

인터넷에서 다양한 정의를 찾을 수 있지만, 제가 내린 정의는 “모놀리스(monolith)에 저항하는 가장 극단적인 반발”입니다.

 

모놀리스는 전체 앱에 필요한 모든 것을 하나의 거대한 프로그램에 연결하고 하나의 큰 블롭(Blob)으로 배포 할 때 발생합니다. 모놀리스는 CGI, Django, Rails 및 PHP와 같은 프레임 워크로 거슬러 올라가는 오랜 역사를 가지고 있습니다.

 

이제 모놀리스나 마이크로 서비스 집합이 유일한 두 가지 옵션이라는 가정을 버려봅시다. "모든 것을 수행하는 하나의 거대한 서비스" 와 "각각 거의 아무것도하지 않는 무한한 작은 서비스" 의 사이에 많은 선택지가 있습니다.

 

유행에 민감하다면, 적어도 한 번은 (의도적이든 기존 프레임 워크가 권장하는 방식을 따른 것이든 간에)모놀리스를 구축하고, 모놀리스에서 몇 가지 문제를 발견한 후, 마이크로 서비스가 해답이라는 말을 듣고, 모든 것을 마이크로 서비스로 재설계 한 경험이 있을것입니다.

 

그러나, 유행을 따르지 마십시오. 그 극단 사이 많은 중간 지점 중 여러분에게 맞는 곳이 분명 있을 것입니다. 더 좋은 접근 방식은 인터페이스의 위치에서 시작됩니다. 

 

상자와 화살

인터페이스는 모듈간의 연결입니다. 모듈은 관련된 코드들의 모음입니다. 시스템 설계에서 우리는 "상자와 화살"엔지니어링에 대해 이야기합니다. 모듈은 상자이고 인터페이스는 화살입니다.

 

더 심도있는 질문은 상자의 크기입니다. 각 상자에 얼마나 들어 갈까요? 하나의 큰 상자를 두개의 작은 상자로 분할하는 시기를 어떻게 결정할까요? 상자를 연결하는 가장 좋은 방법은 무엇일까요? 이에 대한 많은 접근 방식이 있지만, 아무도 최선이 무엇인지 잘 모릅니다. 이는 소프트웨어 아키텍처에서 가장 어려운 문제 중 하나입니다.

 

지난 수십 년 동안 우리는 많은 종류의 "상자"를 통해 발전해 왔습니다. Goto 문이 "유해한 것으로 간주" 된 이유는 계층 구조를 막았기 때문입니다. 그런 다음, 매개 변수와 반환 코드로 구성된 인터페이스로 매우 단순한  상자들을 연결해 기능이나 절차를 추가했습니다. 

 

여러분이 어떤 프로그래밍 종류를 따라가느냐에 따라 재귀 함수, 콤비네이터, 정적 함수 프로토 타입, 정적 또는 런타임으로 링크된 라이브러리, 객체 (OOP), 코 루틴(coroutine), 보호된 가상 메모리, 프로세스, 쓰레드(thread), JIT, 네임 스페이스, 샌드 박스, chroots, jails, 컨테이너, 가상 머신, 수퍼바이저, 하이퍼 바이저, 마이크로 커널 및 유니커널 을 발견하게 됩니다.

 

그리고, 이것들은 단지 “상자”에 지나지 않습니다! 상자가 서로 분리되면 “화살표”로 연결해야합니다. ABI, API, syscall, 소켓, RPC, 파일 시스템, 데이터베이스, 메시지 전달 시스템 및 "가상화 된 하드웨어"가 그 역할을 합니다.

 

현대 유닉스 시스템의 완전한 상자와 화살표 다이어그램을 그린다면 그것은 매우 복잡한 것이 될 것입니다. 제가 다이어그램을 그리진 않겠지만 설명하자면, 그것은, 쓰레드안의 함수, 프로세스안의 쓰레드, 컨테이너 안의 프로세스, 사용자 공간 안의 컨테이너가 커널 아래 층층이 쌓여, VM 안에서 오케스트레이션(orchestration) 시스템으로 함께 묶여, 클라우드 공급자의 데이터 센터에 있는 하드웨어 랙(rack)에서 실행되는 것입니다.

 

각 추상 계층(abstraction layer)에 있는 각 상자는 어찌되었든 분리되어 일부 다른 상자들과 같은 혹은 다른 계층에서 연결되며, 일부 상자는 다른 상자의 내부에 있습니다. 이차원으로 그리려면, 도저히 알아 볼 수 없을 정도로 절망적으로 교차하는 수많은 선없이는 내용을 그대로 전달하는 정직한 버전의 그림을 그릴 수 없습니다.

 

이 모든 것이 수십 년에 걸쳐 이루어졌습니다. 어떤 사람들은 이것을 멋지게 "경로 의존성(path dependence)"이라고 부릅니다. 저는 이것을 “엉망(mess)”라고 부릅니다. 그리고, 분명한 것은 이런 혼란들은 대부분 더 이상 가치를 불러오지 않는 다는 것입니다.

 

그럼, 이런 절망적인 결과가 어떻게 초래되었나에 초점을 맞추는 대신, 이런 결과가 일어나는 동안 사람들이 실제로 이루고자 했던 것이 무엇이었는지에 대해 이야기 해 봅시다.

 

모듈화를 향한 탐구

모듈 시스템의 최상위 목표는 항상 동일합니다.

  1. 각 코드의 비트를 다른 비트와 분리합니다.

  2. 명시적으로 의도된 경우에만 잘 정의된 인터페이스를 통해 해당 비트를 다시 연결합니다.

  3. 변경한 비트가 올바른 다른 비트와 계속 호환되도록 합니다.

  4. 다른 모든 비트를 동시에 업그레이드하지 않고도 일부 비트를 업그레이드, 다운 그레이드 및 확장 할 수 있게 합니다.

컴퓨터 산업은 엄청난 시간과 노력을 들여 모듈성 문제의 완벽한 균형을 찾는 동시에 개발을 가능한 쉽고 간단하게 하려고 노력합니다.

 

그러나, 요약하자면, 우리는 성공하지 못하고 있습니다. 지금까지 최악의 부분은 ‘분리(isolation)’입니다. 한 비트의 코드가 다른 코드로부터 실제로 효율적으로 분리 될 수 ​​있다면 다른 부분들은 대부분 수월해 질 것입니다. 그러나, 안타깝게도 우리는 그 방법을 모릅니다.

 

수많은 시도와 노력에도 불구하고, 분리는 매우 어려운 문제입니다. 브라우저 샌드박스 이탈이 여전히 정기적으로 발생하고, 감지되지 않은 권한 상승 공격(privilege escalation attack)은 모든 OS에 존재한다고 간주되며, iOS는 여전히 주기적으로 탈옥되고, (더 좋든 나쁘든 간에)DRM은 항상 작동하지 않으며, 가상 머신과 컨테이너에서는 정기적으로 취약점이 발견되고, k8s의 컨테이너는 기본적으로 안전하지 않게 구성되어있습니다.

 

인터넷을 통해 적절한 시간에 패킷전송하여 원격 서버의 암호화 키를 알아내는 방법도 알려졌습니다. 한편, 최근 메모리에서 가장 눈에 띄는 분리 실패는 붕괴(Meltdown) 및 유령공격(Spectre attack)으로, 컴퓨터의 모든 프로그램, 심지어 웹 브라우저의 자바 스크립트 앱까지도 샌드 박스 또는 가상머신을 통해 동일한 컴퓨터에있는 다른 프로그램의 메모리를 읽을 수 있습니다.

 

모든 새로운 분리 기술은 낙관에서 절망에 이르기까지 다음과 같은주기를 거칩니다.

 

  • 마침내 이번에는 새로운 아이디어를 통해 제대로 해낼 수 있을 것이라 기대합니다.

  • 초기 실험은 효과가있는 것 같습니다.

  • (사용자들은 우리가 마지막으로 시도한 것보다 더 느리고 지루하다고 불평합니다.)

  • 초기에 치명적인 결함을 발견하고 수정합니다.

  • 광범위하게 배포합니다.

  • 점점 더 미묘한 결함이 연속적으로 발견되고 수정됩니다.

  • 결국, 패치 방법을 모르는 결함을 발견합니다.

  • 이 방법으로는 효율적인 격리가 가능하다는 희망을 잃습니다.

  • 그러나, 이제 너무 많은 사람들이 의존하고 있기 때문에 우리는 이것을 결코 폐기 할 수 없습니다.

  • 위의 사례가 반복됩니다.

예를 들어, 지금 시점에서 보안 관계자들은 예전에는 사용 가능한 최고의 기술이었던 다음의 것들이 완전히 안전하다고 믿지 않습니다.

 

  • 유닉스 시스템의 프로세스 분리 및 메모리 보호

  • 원격 코드 실행 (보안 담당자의 경우 "RCE")이 허용시, OS 프로세스 간의 권한 분리

  • Syscall을 필터링한 프로세스를 분리

  • CPU 하이퍼쓰레드(hyperthread)를 공유하는 상호 신뢰가 이루어지지 않은 프로세스

  • CPU 코어에 위치한 가상 머신 간의 메모리 분리

현재 제가 알고 있는 최고의 최첨단 분리 툴은 Chrome 샌드 박스 또는 gVisor 입니다. 대형 브라우저 공급 업체와 클라우드 제공 업체는 모두 이와 같은 툴을 사용합니다. 툴은 여전히 불완전하지만, 공급 업체는 가능한 빠르게 모든 새로운 공격을 추적하며, 새로운 결함의 비율도 상당히 느립니다.

 

분리 기술은 그 어느 때보다 발전했습니다. 모든 분리를 VM (가상 머신)선상에 두면 클라우드 공급자가 업데이트를 대신 수행할 수 있어, 업데이트 방법을 모르거나, 업데이트 시기를 놓치는 것을 방지 할 수 있습니다. 

 

클라우드 제공 업체의 VM 분리 능력을 신뢰한다면, 알려진 모든 문제가 완화되기를 희망할 수 있지만, 동시에, 더 많은 문제가 발견 될 것이라고 예상되는 이유도 많이 있습니다.

 

그것은... 모든 상황을 고려해봤을때, 사실 꽤 긍정적입니다. 적어도 이제 제대로 작동하는 무언가가 존재 한다는 뜻이기 때문입니다.

 

좋습니다! VM으로 모든것을 합시다!

글쎄, 잠깐만요. 모든 작은 모듈에 대해 분리된 VM을 가동하는 것은 힘든 일입니다. 모듈은 얼마나 클까요?

 

오래 전 Java가 처음 출시되었을 때, 모두의 바램은 모든 객체의 모든 기능의 모든 라인이 동일한 애플리케이션 바이너리의 객체 간 권한을 적용 할 수 있게 되어, CPU 기반 메모리 보호가 필요하지 않게 되는 것이 었습니다. 그러나, 더이상 아무도 그것이 가능하다고 믿지 않습니다. 또한, "클라우드 기능"과 같은 마케팅은 제쳐두고서라도, 아무도 여러분이 이것을 시도해야한다고 생각하지 않습니다.

 

현재 알려진 분리 방법 중 어느 것도 완벽하게 작동하진 않지만 개별적으로는 거의 작동합니다. 수고롭더라도, 공격자들의 기술이 발전함에 따라 보호해야 할 것이 많은 중요한 대상(target)들은 더 효과적인 분리 방법이 필요합니다. 현재 우리가 알고있는 최고의 분리 방법은 Tier-1 클라우드 제공 업체가 제공하는 VM 간 샌드박스 입니다. 최악의 경우, 0까지 내려갑니다.

 

사실 관계를 뒤로하고, 대부분의 시스템이 매우 긴밀하게 결합되어있어 숙련된 공격자가 모듈과 모듈사이로 침입 할 수 있다고 가정해 봅시다. 예를 들어, 누군가가 악성 라이브러리를 Go 또는 C ++ 프로그램에 연결할 수 있다면, 그들은 해당 프로그램 전체를 제어 할 수 있습니다.

 

마찬가지로, 프로그램에 데이터베이스에 대한 쓰기 권한이있는 경우, 공격자는 데이터베이스의 어느 위치에나 쓰기 권한을 부여 할 수 있습니다. 네트워크에 연결할 수 있다면, 아마도 네트워크의 어느 곳 에서나 연결할 수 있을 것입니다. 임의의 Unix 명령이나 시스템 호출을 실행할 수 있다면, 아마도 Unix 루트 액세스 권한을 얻을 수 있을 것입니다. 컨테이너 안에 있다면, 아마도 그 컨테이너에서 다른 컨테이너로 쪼개 넣을 수 있을 것입니다. 악성 데이터가 png 디코더를 충돌 시킬 수 있다면, 디코더 프로그램이 허용하는 다른 작업 또한 수행하도록 만들 수 있을 것입니다. 

 

특히 강력한 형태의 공격은 코드를 커밋(commit) 할 수있는 능력을 얻는 것입니다. 왜냐하면, 그 코드는 결국 개발자 컴퓨터에서 실행되고, 일부 개발자 또는 프로덕션 컴퓨터는 사용자가 원하는 작업을 수행 할 수있는 권한이 있을 수 있기 때문입니다.

 

위의 내용은 너무 비관적이게 느껴질 수 있지만, 이러한 가정을 통해 실제 보안을 개선하지 않은채로 시스템을 과도하게 복잡하게 만드는 것을 방지 할 수 있습니다. 큐메일 1.0 10 년 이후 보안에 대한 약간의 생각들 에서 다니엘 J. 번스타인은 (만약 제가 크게 의역하자면) 그가 큐메일에 추가한 방어 방법들, 특히, chroot와 다른 유닉스의 UID를 사용하여 서로 다른 구성 요소를 분리한 것은 별 다른 성과를 거두지 못했다고 밝혔습니다. 

 

어쨌든, 공격자가 거의 모든 분리 기술을 뚫고 침투해 코드를 실행할 수 있는 능력을 가졌다고 가정해 봅시다.  이는 오직 두가지 모듈 경계만이 존재함을 의미합니다. 

  • 신뢰할 수 있는 경우: 두 모듈이 서로 악의적이지 않다고 신뢰하므로 약한 분리를 사용할 수 있는 경계입니다.

  • 신뢰할 수 없는 경우: 모듈이 서로를 신뢰하지 않는 경계이므로 강력한 분리를 사용해야합니다.

저는 여기서 아주 뛰어난 통찰을 말하고자 하는 것이 아닙니다. 인기있는 최신 플랫폼들은 이미 이러한 구분을 기반으로 구축되었습니다.

 

예를 들어, Chrome은 웹 페이지를 신뢰할 수 없기 때문에 강력하게 분리된 샌드박스 VM에서 무작위의 웹 자바 스크립트를 실행합니다.

 

대부분의 OS는 기본 앱을 공유 파일 시스템, 네트워크 네임 스페이스 등을 사용하여 (샌드 박스 없이) 단순한 프로세스로 실행합니다. 이는 지난 날 한때 이것들이 상대적으로 신뢰할 수 있다고 생각했기 때문입니다. (이것이 바이러스가 발생한 방식이기도 합니다) 

 

전문가들은 더 이상 프로세스 격리가 약한 것으로 판명된 다중 사용자 유닉스 시스템을 신뢰하지 않습니다. 루트(root)와 비루트(non-root)격리가 약한 것으로 판명 되었기 때문에 Cloud VM은 기본적으로 비밀번호없는 sudo로 설정되어 있습니다.

 

(모든 파일을 삭제하는 등의 경우, 사람의 실수로 인한 에러를 줄이기 위해 여전히 sudo를 입력하도록합니다.)

 

여러 공급 업체의 공유 라이브러리와 DLL은 모든 코드를 신뢰할 수 있는 것으로 간주하기 하기 때문에 다른 공급 업체의 앱에 연결됩니다. (이는 오픈 소스 라이브러리 공급 업체를 통한 공급망 공격의 길을 열어줍니다. 저는 이런 일이 더 자주 발생하지 않는다는 것이 여전히 ​​놀랍습니다. 어쩔때는, 이런일이 생기고 있지만, 거의 감지되지 않고 있을 뿐이라는 생각도 듭니다.)

 

스마트폰 OS는 앱 스토어 규정상 앱 샌드 박스를 충분히 신뢰할 수 있어야 하기 때문에 탈옥되지만, 분리는 여전히 너무 약한 것으로 밝혀졌습니다.

 

컨테이너는 모두 암시적으로 신뢰할 수있는 것으로 간주되기 때문에, Kubernetes 및 Docker 는 단일 머신 또는 VM으로부터 잘 분리되지 않은 여러 컨테이너를 실행합니다. 다중 테넌트 Kubernetes는 신뢰할 수 없는 앱이 상호 신뢰하지 않는 사용자를 대신하여 작동할 수 있고, 컨테이너 분리가 약한 것으로 판명 되었기 때문에 실행하지 않는 것이 좋습니다.

 

덧붙여, 모든 서비스에 gVisor가 적용된 VM과 같은 강력한 분리를 사용하더라도 코드 자체가 강력하게 분리된 도구 체인을 사용하여 빌드되지 않으면 도움이 되지 않습니다. 만약, 일정 사용자들이 일정 앱에 연결된 라이브러리를 업데이트 할 수 있다면, 해당 앱은 실행 방법에 관계없이 실제로 서로 분리되지 않습니다.

 

모듈 경계 VS 서비스 경계

너무 많은 분리 계층이 보안에 취약한데 우리는 왜 계속 개선을 위해 노력하는 것일까요?

 

역사적으로 볼때, 대체로, 이러한 계층의 대부분을 버리면 보안에 큰 영향을 주지 않을 뿐더러, 단순성이 향상됩니다. 저는 이런 현상이 시간이 지남에 따라 일어날 것으로 예측하고 있으며, 이미 이러한 추세가 보여지고 있습니다. 다중 사용자 유닉스 시스템은 이제 거의 찾아보기 힘듭니다. "서버리스"서버는 가장 강력한 격리 유형만 남기고, 다른 모든 유형 버리는 동시에 사용자가 클라우드 제공업체 안에서만 위치할 수 있도록 합니다. 

 

그러나 역사는 제쳐둡시다. 저는 다음의 간단한 한 문장을 소개하기 위해 이 모든 분리 개념에 대해 설명했습니다. 보안상의 이유로 모듈 경계를 정의하는 일은 거의 없습니다.

 

대신, 모듈 경계는 일반적으로 Conway의 법칙을 따릅니다. 사람들은 팀에서 개발 작업을 세분화하려는 방법에 따라 모듈을 나누고, 모듈은 결국 팀과 팀원이 의사 소통하는 방법을 기반으로 통신됩니다. (Conway의 법칙은 매력적이고 현실적이지만, 지금은 건너 뛰겠습니다.)

 

모듈 경계가 하지 않는 것은 배포 단위의 크기를 정의하는 것입니다.

 

운영 체제를 예로 들어 보겠습니다. 

  • ChromeOS에는 수천 명의 개발자가 있지만 사용자는 Linux 커널, 디바이스 드라이버, 윈도우 매니저, 웹 브라우저 등의 테스트가 모두 완료되어 포함된 단일 업데이트를 받습니다. 모듈 간에 위치하는 인터페이스는 이전 버전과의 호환성이 필요하지 않기 때문입니다. (물론 하드웨어 및 웹은 제외됩니다) MacOS, iOS 및 Android도 이와 유사한 모델을 따릅니다.

  • Debian Linux에는 수천 명의 개발자가 있지만 사용자는 개별 패키지를 다운로드하여 설치합니다. 구식의 Debian-oldstable 를 현재의 Debian-unstable와 함께 실행할 수 있으며, 대부분 작동 할 것입니다. 그 특정 조합을 테스트하지 않았겠지만, 매우 강력하게 정의된 인터페이스 덕분에 그것은 아마도 작동 할 것입니다. 

(사람들은 "데스크탑상의 Linux"의 불안정성에 대해 농담하며, 항상 첫번째나 주류, 테스트하기 쉬운 종류가 대신 두 번째, 틈새 시장, 테스트하기 어려운 종류에 대해 이야기합니다. 저는 사람들이 느끼는 품질 차이는 기업의 자본력이 바탕이 되었는지 아니면 오픈 소스인지의 차이라기보다 배포 모델의 차이에서 온다고 생각합니다.)

 

두 시스템에는 팀으로 구성된 여러 개발자가 개발한 수많은 패키지(모듈)가 포함되어 있습니다. 두 시스템 모두 모듈 사이에 인터페이스가 있습니다. 각 시스템을 커널, 드라이버, 윈도우 시스템, 샌드 박스, 웹 브라우저 등으로 구성된 상자와 화살표 다이어그램으로 그려본다면, 이 둘은 매우 비슷해 보일 것입니다.

 

하지만, 만약, 이것이 OS가 아닌 백엔드 클라우드 서비스라면 우리는 이 두 모델을 모놀리스나 마이크로 서비스로 각각 배포 합니다. 하나는 오직 배포된 하나의 "서비스" 일 뿐이고, 다른 하나는 각 각 개별적으로 배포된 여러 서비스를 가지고 있습니다. 동일한 모듈인데 말입니다. 도대체 무슨일이 벌어지고 있는 것일까요?

 

모듈 경계와 서비스 경계는 서로 다른 것입니다.

 

서비스 경계를 ​​어디에 두어야 할까요?

 

모듈화의 본래 목표를 검토해 봅시다.

  1. 분리: 보안 목적을 위해 강력한 분리가 필요한 경우, 분리된 VM을 롤아웃하는 유일한 방법은 별도로 있기 때문에 지금까지는 별도의 서비스가 필요합니다. (참고로, 이것은 아키텍처적인 목표가 아니라 분리 시스템의 한계에 가깝습니다. "코드로서의 인프라" 및 블루/그린 배포는 이런 서비스를 다시 동기화하려고 시도하므로 모놀리스식 배포 모델을 가질 수 있습니다.)

  2. 연결: Conway의 법칙을 따릅니다. 모듈 경계는 팀의 개인 커뮤니케이션 패턴을 따르는 경향이 있습니다. 그러나, 반직관적으로, Conway의 법칙은 서비스 경계를 ​​정의 할 필요가 없습니다.

  3. 호환성 보장: 모놀리스에 대한 압박으로 다가옵니다. 모놀리스가 Go, typescript, rust 혹은 C ++와 같은 안전 언어로 작성된 경우 특히 그렇습니다. (예를들어, Chrome은 하나의 거대한 바이너리입니다.)

  4. 업그레이드, 다운 그레이드 및 확장성: 주로 서비스 경계를 ​​결정하는 요소입니다. 그들에 대해 조금 더 이야기 해 봅시다.

서비스 경계를 ​​선택할 때, 고려해야 할 사항은 다음과 같습니다.

  • 모놀리스를 시작할때, 시간이 오래 걸리나요? 이럴 경우, 업그레이드 시간이 길어 지므로, 느린 부분만 분리하면 다른 작업들을 더 빠르게 업그레이드 할 수 있습니다.

  • 스키마 버전 데이터 저장소 필요하십니까? 그렇다면, 백엔드의 모든 인스턴스가 동일한 스키마 버전에 있도록 하기위해 때때로 Lockstep 업그레이드/다운그레이드를 해야합니다. Lockstep 업그레이드는 위험하고 롤백을 방지하는 경향이 있기때문에,  스키마에 종속되는 부분을 가능한 한 작게 유지하는 것이 좋을 수 있습니다.

  • 통합 테스트가 자주 실패합니까? 그렇다면, 그것은 나쁜 소식입니다. 실패한 테스트들은 코드의 손상, 즉 기능의 손상을 의미합니다. 서비스를 분할하여 별도로 배포하면 테스트를 통과하도록 속일 수 있지만, 대신 프로덕션에서 호환성 및 버전 왜곡 문제가 발생합니다. 그것은 전혀 도움이 되지 않습니다.

  • 일부 부품이 다른 부품들과 다르게 확장됩니까? 예를 들어, 일부 작업은 메모리를 많이 사용하는 반면 다른 작업은 CPU를 많이 사용합니다. 이것은 생각보다 자주 중요하게 나타나지 않습니다. 모든 인스턴스가 적절하게 로드 밸런싱되면 로드가 매우 효율적인 방식으로 자연스럽게 분산되는 경향이 있습니다. 로드 밸런싱이 문제가되는 경우, 이를 측정하고 나중에 특정 세분화된 문제를 수정할 수 있습니다.

  • 비용이 많이 드는 요청을 더 작은 병렬 처리로 실행해야 합니까? 일반적인 마이크로 서비스 아키텍처는 요청을 메시지 대기열에 넘기고 작업자 인스턴스가 요청을 순차적으로 처리하도록하는 것입니다. 그러나 이것은 생각보다 더 자주 문제가 발생 할 뿐더러 "대기열 폭발"문제를 피할 수 있게 개선된 설계가 있습니다. 모놀리스에서 이와 동일한 디자인을 구현할 수 있습니다.

  • 다른 품질이나 신뢰성 목표를 가진 서비스가 있습니까? 이것은 서비스를 분할하는 좋은 이유가 될 수 있습니다. 예를 들어, Tailscale 에는 가동 시간 목표가 매우 엄격한 몇 가지 서비스(조정 서비스로그 캐처 서비스)만 있습니다. 로그에 매우 민감하기 때문에 이 두 가지는 이미 보안 격리를 위해 분할되어 있습니다. 또한, "실시간" 로그/지표 처리 파이프 라인은 더 많은 다운 타임을 허용해 더 많은 실험을 할 수 있으므로 신뢰성이 높은 서비스와 분리되어 다른 배포 절차를 가질 수 있습니다.

사실, 위의 대부분은 일반적으로 서비스 간의 경계를 만들기엔 매우 설득력 없는 이유들이지만, 모듈이나 팀 사이의 경계를 만드는데는 좋은 이유가 될 수 있습니다! 그러나, 모듈을 하나 또는 몇 개의 단일체로 재결합 한 후 롤아웃 하는 것은 가능합니다.

 

기억하십시오. ChromeOS는 모놀리스입니다. iOS는 모놀리스입니다. 여러분의 팀은 아마도 이 두 팀보다 훨씬 작을 것입니다. 따라서, 원하는 것을 얻기 위해 많은 마이크로 서비스를 조작 할 필요가 없습니다. 어려운 방식으로 작업을 해야만하는 어쩔수 없는 절대적 시점이 오기전까지는 작업을 쉽게 설계하십시오. 그것이 우리가 하는 일입니다.

 

업데이트 2020-02-24 : 아, 그리고 Ycombinator

 

글쓴이: 테일스케일 CEO 에이브리 페나런 

번역자: 남궁선 (tailscale.kr@gmail.com)

 

원본 블로그

 

Modules, monoliths, and microservices

What is a microservice? When are microservices a good idea? Lately, I get people asking me when microservices are a good idea. In systems design explains the world, I talked about big-picture issues like second system effect, innovator's dilemmas, and more

tailscale.com

 

'설명서' 카테고리의 다른 글

테일스케일은 어떻게 작동하는가  (0) 2020.12.10
제로 트러스트 메시 VPN  (0) 2020.12.08
와이어가드 기반 기업용 VPN  (0) 2020.12.08

관련글 더보기