배경
리눅스 컨테이너의 탄생 및 Big Tech 기업의 발전으로 전 세계는 클라우드 열풍이 불고 있습니다. 이제 우리의 IT 환경에서 클라우드를 배제할 수는 없습니다.
하지만, 정작 우리가 클라우드를 적용하고자 할 때에는 많은 어려움을 겪고 있는 것도 현실입니다. 많은 엔터프라이즈 시스템들은 비용관리, 보안, 전문가 부족, 거버넌스, 컴프라이언스 등을 해결하기 위하여 많은 노력을 기울이고 있습니다.
<출처 : Flexera 2024 State of the Cloud Report>
이 글은 클라우드의 기본 원리를 이해하고 엔터프라이즈 클라우드는 무엇이 다른지, 그리고 고려해야 하는 권고사항을 다루고자 합니다.
Contents 배경 컨테이너에 대한 이해 클라우드 네이티브에 대한 이해 엔터프라이즈의 클라우드 네이티브는 무엇이 다른가? 엔터프라이즈 클라우드 네이티브 개발 시 권고사항 | ||
컨테이너에 대한 이해
소프트웨어 애플리케이션에서 발생하는 주요 위험은 애플리케이션이 중단될 수 있는 런타임 업데이트 시점입니다. 예를 들어 OS 업데이트에는 라이브러리를 포함하여 호환되지 않는 업데이트로 실행중인 애플리케이션에 영향을 미칠 수 있는 많은 업데이트가 포함될 수 있습니다.
일반적으로 동일한 호스트 내에는 애플리케이션과 함께 동작하는 다른 소프트웨어(데이터베이스, 프록시 등)들이 있습니다. 그들은 모두 동일한 운영체계와 라이브러리를 공유하고 있습니다. 따라서 업데이트로 인해 애플리케이션에 직접 충돌이 발생하지 않는다 하더라도 다른 서비스와의 충돌이 발생할 수 있습니다.
이러한 업데이트는 위험하지만, 업데이트 개선을 통해 제공된 버그 수정 또는 보안 및 안정성 문제 등에 대한 필요 때문에 수행할 수밖에 없는 경우가 많습니다. 업데이트로 인하여 문제가 발생하는지 여부를 확인하기 위해 애플리케이션 및 그 환경에 대한 테스트를 수행해야 합니다. 특히 대규모 애플리케이션의 경우 이는 매우 큰 작업입니다.
하지만 해결방법이 있으므로 슬퍼할 필요가 없습니다. 단일 운영 체제 내부에서 독립적 파티션이라고 할 수 있는 컨테이너를 사용할 수 있습니다. 가상 머신과 동일한 보안, 스토리지 및 네트워크 격리와 같은 많은 이점을 제공하면서도 훨씬 적은 하드웨어 리소스를 필요로 합니다. 컨테이너는 가상머신과 달리 시스템 운영 체계를 직접 사용하기 때문에 실행 및 종료가 더 빠릅니다.
컨테이너화를 통해 리소스 활용도를 격리하고 추적할 수 있습니다. 이 격리는 우리의 호스트 운영체계 업데이트와 관련된 많은 위험으로부터 애플리케이션을 보호합니다.
<전통적, 가상머신, 컨테이너, 쿠버네티스 배포 아키텍처>
컨테이너는 개발자와 시스템 관리자 모두에게 아래와 같은 많은 이점을 제공합니다.
일관된 환경(Consistent Environment)
컨테이너를 통해 개발자는 다른 애플리케이션과 격리 된 예측 가능한 환경을 만들 수 있습니다. 컨테이너에는 프로그래밍 언어 런타임 및 기타 소프트웨어 라이브러리의 특정 버전 등 애플리케이션에 필요한 종속 소프트웨어도 포함될 수 있습니다.
개발자의 관점에서 보면, 이 모든 것은 애플리케이션이 최종적으로 배포되는 곳이 어디든 일관성이 보장됩니다. 이러한 모든 것이 생산성으로 이어지며, 개발자와 IT 운영팀이 환경의 차이를 디버깅하고 진단하는 데 걸리는 시간, 더 나아가 사용자에게 새로운 기능을 전달하는 시간 비용을 줄이게 됩니다.
개발자가 개발 및 테스트 환경이 확실히 그대로 프로덕션에 적용된다는 가정을 할 수 있기 때문에 버그가 적다는 것을 의미합니다.
어디서든지 실행(Run Anywhere)
컨테이너는 리눅스, 윈도우즈 및 맥 운영 체제 가상 머신 또는 베어 메탈, 개발자의 머신 또는 온 프레미스 데이터 센터, 퍼블릭 클라이드 등 거의 모든 곳에서 가상으로 실행할 수 있으므로 개발 및 배포가 크게 쉬워집니다. 소프트웨어를 실행하기 원하는 어디든지 컨테이너를 사용할 수 있습니다.
격리(Isolation)
컨테이너는 OS 수준에서 CPU, 메모리, 스토리지 및 네트워크 리소스를 가상화하여 개발자들에게 다른 애플리케이션로부터 논리적으로 격리된 OS의 샌드박스로 제공됩니다.
이외에도 컨테이너는 다중 시스템 환경의 복잡성이 없는 상용 또는 개발 환경으로 배포할 수있는 서비스를 만들고 실행할 수 있도록 가볍고 안정적인 환경을 제공하기 때문에 애자일 비즈니스에 적합한 마이크로서비스 개발 접근 방식을 강화합니다.
컨테이너를 사용하여 애플리케이션을 배포하는 것을 컨테이너화(Containerization)라고 합니다. 컨테이너화는 다음과 같은 이유로 점점 인기를 얻고 있습니다.
유연성(Flexible) : 매우 복잡한 애플리케이션도 컨테이너화할 수 있습니다.
경량화(Lightweight) : 컨테이너가 호스트 커널을 활용하고 공유합니다.
상호 교환가능성(Interchangeable) : 업데이트 및 업그레이드를 즉시 배포 할 수 있습니다.
이식성(Portable) : 로컬에서 빌드하고 클라우드에 배포하고 어디서나 실행할 수 있습니다.
확장성(Scalable) : 컨테이너 복제본을 늘리고 자동으로 배포 할 수 있습니다.
스택화(Stackable) : 서비스를 즉석으로 수직 스택화할 수 있습니다.
마이크로서비스 아키텍처의 이해
이전 챕터에서 컨테이너가 마이크로서비스 아키텍처를 구현하는데 효과적이라고 말했는데, 그럼 마이크로서비스 아키텍처는 무엇일까요?
대부분의 기업용 애플리케이션은 하나의 통합된 서비스 형태로 개발되어 왔습니다. 모놀리식(Monolithic) 아키텍처라고 불리는 이러한 단순한 애플리케이션의 구조는 개발과 관리가 용이하다는 장점이 있습니다.
하지만, 애플리케이션의 종류가 다양해지고 여러가지 기능을 제공하는 대규모 시스템이 생겨나면서 규모가 커질 경우 복잡도가 증가해 코드의 분석과 통합이 어려워지고 작은 수정사항에도 전체를 빌드 배포해야 하는 비효율이 발생하는 등의 개선과 확장이 어렵다는 단점이 발생하게 되었습니다.
이러한 단점을 극복하고자 확장성에 초점을 맞추어 탄생한 아키텍처 설계 방법이 MSA(Microservices Architecture)입니다.
마이크로서비스는 경량화되고 독립적인 여러 개의 서비스를 조합하여 애플리케이션을 구현하는 방식으로, 서비스마다 자체 데이터베이스를 가지고 동작할 수 있기 때문에 개발부터 빌드 배포까지 효율적으로 수행할 수 있으며 독립적인 서비스의 형태로 존재하기 때문에 이식성 측면에서 높은 효과를 보이게 됩니다.
각각의 서비스들은 비즈니스별로 독립적인 서비스로 볼 수 있으며 서로 호환성이 높도록 구현되기 때문에 각각의 서비스 구현 과정에서 공통된 데이터 포맷이나 표준 기반의 API를 동일하게 사용한다면 타 클라우드 서비스와도 높은 상호운용성 수준을 확보할 수 있게 됩니다.
그러나 마이크로서비스 아키텍처는 기존 모놀로식 구조와 비교해서 결코 단순하지 않습니다. 하나의 서비스를 작게 나눔으로 인하여 서비스 간 복잡도가 증가될 수 있으며 서비스 라우팅, Circuit breaker, 각 서비스들의 스케쥴링 등 고려해야 할 것들이 기존보다 더 많아질 수도 있습니다.
그럼에도 불구하고 서비스들을 나누고 권한을 위임하면서, 고가용성, 유연한 스케일링, 빠르고 쉬운 배포 등의 큰 장점들이 있기 때문에 협업 부서가 많거나 규모가 큰 시스템이라면 충분히 고려해 볼 만한 가치가 있습니다.
우리는 마이크로서비스 아키텍처를 접근할 때 모든 서비스를 마이크로서비스로 분해하기 보다는 시스템 진화 측면에서 점진적으로 분해하는 것을 고려하는 것이 좋습니다.
클라우드 네이티브에 대한 이해
클라우드 컴퓨팅 환경이란, 클라우드 공간에 가상화된 공유자원을 사용자의 요구에 따라 할당하고 해제할 수 있는 동적인 컴퓨팅 환경을 말하며, 클라우드에서 제공하는 서비스의 유형에 따라서, 퍼블릭 클라우드, 프라이빗 클라우드, 하이브리드 클라우드 등의 환경으로 나뉩니다.
산업계 표준 단체인 Cloud Native Computing Foundation은 다음과 같이 클라우드 네이티브를 정의하였습니다.
“클라우드 네이티브 기술을 통해 조직은 퍼블릭, 프라이빗 및 하이브리드 클라우드와 같은 최신 동적 환경에서 스케일링 가능한 애플리케이션을 빌드하고 실행할 수 있습니다. 이 방법의 예로 컨테이너, 서비스 메시, 마이크로서비스, 변경할 수 없는 인프라 및 선언적 API를 들 수 있습니다.
이러한 기술을 통해 복원력 있고 관리 가능하며 관찰 가능한 느슨하게 결합된 시스템을 사용할 수 있습니다. 강력한 자동화와 결합되므로 엔지니어는 최소한의 수고로 자주 발생하며 예측 가능한 방식으로 높은 영향을 미치는 변경을 수행할 수 있습니다.”
클라우드 네이티브는 비즈니스 역량에 따라 서비스가 분할되기 때문에 비즈니스 요구사항에 빠르게 반응할 수 있다는 측면에서 Big Tech 기업에 의하여 채택되었으며, 최근에는 엔터프라이즈 환경에도 확산되고 있는 추세입니다.
마이크로소프트의 가이드에 따르면 클라우드 네이티브 아키텍처는 아래 그림과 같이 클라우드 인프라 뿐 만 아니라 5개의 핵심 요소를 충족하여야 합니다.
<출처 : 마이크로소프트>
클라우드(Cloud)
클라우드 네이티브 시스템은 클라우드 서비스 모델을 최대한 활용합니다. 또한 클라우드 환경에 배포될 시스템을 전제로 애플리케이션이 개발되어야 합니다.
최신 디자인(Modern Design)
12 Factor App이나 15 Factor App을 준수하여 애플리케이션을 개발해야 합니다.
마이크로서비스(Microservices)
클라우드 네이티브 시스템은 마이크로서비스를 수용합니다. 그러나, 이것이 클라우드에 배치되는 모든 서비스가 마이크로서비스여야 한다는 것을 의미하지는 않습니다. 마이크로서비스 아키텍처는 분산환경에서 발생할 수 있는 모든 경험을 패턴화 및 프레임워크화하였으며, 이를 이용하여 애플리케이션을 개발하여야 합니다.
컨테이너(Container)
모든 ‘클라우드 네이티브’ 대화에서 ‘컨테이너’가 언급되는 것을 자주 듣게 될 것입니다. 클라우드 네이티브 패턴 책에서 저자인 Cornelia Davis는 “컨테이너가 클라우드 네이티브 소프트웨어의 뛰어난 활성화 요인”이라고 말합니다.” Cloud Native Computing Foundation은 클라우드 네이티브 여정을 시작하는 기업을 위한 지침인 클라우드 네이티브 트레일 맵의 첫 번째 단계로 마이크로 서비스 컨테이너화를 배치합니다.
지원서비스(Backing Service)
클라우드 네이티브 시스템은 데이터 저장소, 메시지 브로커, 모니터링 및 ID 서비스와 같은 다양한 보조 리소스에 의존합니다. 이러한 서비스를 지원 서비스라고 합니다.
자동화(Automation)
클라우드 네이티브 시스템은 마이크로 서비스, 컨테이너 및 최신 시스템 디자인을 수용하여 속도와 민첩성을 달성합니다. 시스템이 실행되는 클라우드 환경을 어떻게 프로비저닝할 것인지, 앱 기능 및 업데이트를 신속하게 배포하려면 어떻게 해야 하는지에 대한 IaC(Infrastructure as Code)와 배포 자동화를 요구하게 됩니다.
엔터프라이즈의 클라우드 네이티브는 무엇이 다른가?
클라우드 네이티브의 모든 인프라가 제공된다고 하더라도 엔터프라이즈 환경은 또다른 숙제를 남겨 놓고 있습니다. 이는 대부분의 엔터프라이즈가 클라우드로 전환하면서 겪는 고통이지만 아직까지는 뚜렷한 솔루션이 없는 것이 현실입니다.
개인정보 보호법과 보안
개인정보 보호법은 시스템이 기민하게(Agile) 동작하는데 매우 큰 걸림돌입니다. 개인정보는 암호화된 프로토콜에 의하여 별도의 서비스로 격리되어야 하고, 이로 인하여 시스템의 결합도는 증가합니다.
IT Outsourcing
많은 엔터프라이즈 시스템은 IT Outsourcing에 의하여 관리되고 있습니다. 이는 클라우드 시스템으로 전환하는 프로젝트도 계약에 의하여 진행되며 이는 결국 점진적인 접근 방법을 취하기 어렵고 초기 전환 시 시행착오에 대한 위험을 수반하게 됩니다. Big Tech 기업들은 아웃소싱에서 인하우스 개발로 변화하였지만 엔터프라이즈는 TCO 측면에서 아웃소싱을 변경하기 어렵습니다.
2 Phase Commit Transaction
대부분의 엔터프라이즈 시스템은 하나의 모놀리스가 아닌 거대한 몇 개의 모놀리스가 분산되어 운영되고 있습니다. 또한 기업의 비즈니스를 지원하기 위한 인사, 회계, SCM 등의 시스템이 데이터베이스로 정보가 저장되며 상호 연계되어 있습니다. 이들은 오래된 전통 처리 방식인 2 Phase Commit으로 트랜잭션을 처리합니다. 모놀리스 내부 통신 혹은 TCP가 지원되는 IIOP(Internet Inter Operable Protocol)가 아닌 HTTP에 의하여 동작하는 마이크로서비스 아키텍처에서는 이를 지원할 수 없으며, 마이크로서비스 사상에도 위배됩니다.
수 많은 Legacy Sytem과의 의존성
우리가 엔터프라이즈라고 할 때에는 직원의 수에만 의존하지 않습니다. 통상적으로 New Tech 기업과는 달리 전통적인 비즈니스에 의하여 동작하는 시스템이 있는 경우를 지칭합니다. 이들은 짧게는 10년, 길게는 30년 이상된 시스템과 연동하고 있으며 이 오래된 시스템에는 시스템 로직을 수정하지 않고 현행 상태로 유지만 하는 경우도 허다합니다.
거버넌스
엔터프라이즈는 핵심 비즈니스 시스템에 있어 거버넌스가 매우 중요합니다. 자율적인 행위보다는 내부 통제에 의하여 모든 업무가 승인하게 동작하기를 희망합니다. 이는 자동화에 제약을 주게 되며 대부분의 오픈소스 솔루션들은 거버넌스 기능을 제공하지 않습니다. 클라우드 거버넌스가 정립되지 않으면 이로인해 비즈니스는 보안 침해, 예산 초과, 컴플라이언스 위배, 서비스 품질 저하, 시스템 중단 등의 위험을 갖게 됩니다.
컴플라이언스
엔터프라이즈 비즈니스는 국제/국내법에 의거한 규정을 준수해야 합니다. 또한 계약, 표준, 감사 등에 있어 엔터프라이즈의 모든 행위를 이를 증빙할 수 있어야 합니다. 기업은 컴플라이언스 점검을 위해 보안, 유효성, 기밀성, 처리 무결성, 개인정보에 대한 처리 지침이 올바르게 수행되고 있는지 정기적인 감사를 수행합니다. 클라우드 제공업체는 이에 대한 상세한 자료를 제공하지 않을 수도 있습니다.
엔터프라이즈 클라우드 네이티브 개발 시 권고사항
앞서 이야기한 내용을 바탕의로 우리는 아래와 같은 결론을 가질 수 있습니다. 이러한 모든 설계를 할 때에는 엔터프라이즈 클라우드에 대한 특성을 이해해야 합니다. 시중에 나오는 클라우드 네이티브 서적이나 블로그들은 엔터프라이즈에 대한 고려가 부족한 것이 사실입니다.
보안 및 기존 시스템 연동 Layer 분리
민감정보를 보관하고 있는 도메인은 분리되어 별도의 공간에서 관리될 수 있어야 합니다. 만약 민감정보가 마이크로서비스 전체에 걸쳐 존재하게 된다면 모든 마이크로서비스들은 개인정보를 관리하는 시스템이 되고 말 것입니다.
이러한 민감정보는 가상화, 암호화되어야 하며 이것이 비즈니스에 포함되지 않도록 설계하여야 합니다. 가급적 별도의 서비스로 분리하십시오.
또한 기존 시스템과의 연동도 마찬가지입니다. 기존 시스템은 마이크로서비스의 통신 프로토콜인 REST/JSON을 기반으로 HTTP 프로토콜이 아닌 SOAP, IIOP, TCP, Message Queue, File 등이 될 것입니다.
클린 아키텍처에서 로버트 마틴이 말했듯이 이러한 외부 인터페이스 Layer는 분리되어야 하며 경우에 따라서는 Wrapping된 별도의 서비스로 설계하는 것이 좋습니다. 이방인 들을 별도의 공간으로 격리시키는 방법은 Anti-Corruption Layer 패턴에 잘 제시되어 있습니다.
API-Gateway의 도입
API-Gateway는 거버넌스, 컴플라이언스, 장애 대응 측면에서 매우 중요한 역할을 하고 있습니다. 모든 외부로부터의 통신이 API-Gateway에 의하여 제어된다면 인증 및 권한, 감사 등 비즈니스를 복잡하게 만드는 여러 문제를 여러분의 마이크로서비스에서 분리시킬 수 있습니다.
물론 시스템 초기부터 API-Gateway를 적용하여 시스템 비용을 증가시킬 필요는 없습니다. 시간이 흐르거나 비즈니스 규모가 커서 여러분의 시스템이 성숙단계에 이르고자 한다면 API-Gateway를 도입하십시오.
코드와 구성정보(Configuration)의 분리
코드와 구성정보의 분리는 클라우드 네이티브 아키텍처에 있어서는 필수요소이자 첫 단계입니다. 또한 많은 상용 시스템 업데이트의 사고가 개발 혹은 테스트 환경의 구성정보가 적용되는 실수로 인하여 발생되기도 합니다. 만약 Spring Cloud를 사용하고 있다면 지금 바로 Config Server나 CONSUL을 검토하십시오.
만약 Kubernetes를 사용하고 있다면 ConfigMap과 Secret을 적극적으로 사용하십시오. 모든 환경변수와 민감정보는 ConfigMap과 Secret으로 관리되어야 합니다.
DevOps 요구사항 정의
DevOps요구사항도 이제는 비기능 요구사항이 되어야 합니다. DevOps에 대한 이해관계자(Stakeholder)는 프로젝트 팀, ITO 개발/운영팀이 될 것입니다. 이들의 요구사항이 조기에 식별되지 않는다면 여러분들은 끝없이 수정되는 DevOps의 늪에서 벗어날 수 없게 됩니다.
2-Phase Commit의 재설계
엔터프라이즈 시스템의 가장 큰 숙제는 2-Phase Commit 문제입니다. 마이크로서비스 세계에서 2-Phase Commit은 존재하지도 않습니다. 분산 환경에서 데이터 일관성(Consistency)을 유지시키는 방법은 순차처리, 2-Phase Commit, 비동기 통신, SAGA 패턴 등 크게 4가지 방법으로 분류됩니다. 가급적 비동기 통신으로 전환하기 바랍니다. 순차처리는 시스템 성능 저하시키고, 모든 예외처리를 위한 복잡도를 증가시키며, 2-Phase Commit을 위해서는 관련 모든 트랜잭션이 하나의 마이크로서비스에 있거나 REST/JSON 프로토콜을 포기해야 합니다. SAGA 패턴이 2-Phase Commit에 가장 유사한 이벤트 방식의 트랜잭션 처리이지만 애플리케이션 난이도와 장애 관리 측면에서 최후의 선택이 되길 권고드립니다.
마치며
어쩌면 클라우드는 엔터프라이즈와는 맞지 않는다고 생각하시는 분도 있을지 모릅니다. 하지만 클라우드는 이미 거스를 수 없는 방향이 되었으며 우리는 이를 수행해야 하는 혁신가들입니다.
항상 처음은 어렵습니다. 그러나 그 어려움을 극복하였을 때 얻는 성취감은 좋은 개발자로 성장시키는 양식이 됩니다.