NGINX 모던 앱 참조 아키텍처 버전 1.0.0 발표

NGINX | 2022년 4월 28일

NGINX 최신 애플리케이션 참조 아키텍처(MARA)를 2021년 8월 Sprint 2.0에서 공개하면서 설계 목표를 명확히 밝혔습니다. Kubernetes에서 실행되며 보안, 확장성, 안정성, 모니터링 및 내부 상태 점검을 지원하도록 설계된 최신 애플리케이션 아키텍처의 예시를 만들고자 했습니다. 이 프로젝트는 시간이 많이 드는 통합 작업 없이 기능 구성 요소를 결합할 수 있는 ‘플러그 앤 플레이’ 방식으로 다양한 인프라에 배포할 수 있어야 했습니다.

Sprint 이후 몇 달 동안 저희는 로드맵에 따라 계속해서 프로젝트를 추진해 왔습니다. 다른 모든 프로젝트와 마찬가지로 성공과 실패를 모두 경험했으며, 성공 사례는 MARA에 반영하는 한편 그 과정에서 얻은 교훈도 꾸준히 정리해 왔습니다. 이러한 문제를 문서화하고 그 교훈을 설계에 반영함으로써 다른 사람들이 같은 문제를 겪지 않도록 돕고자 합니다.

최근 MARA 버전 1.0.0이라는 중요한 이정표에 도달했습니다. 이 버전에서는 프로젝트 디렉터리를 재구성하고 환경을 생성하고 제거하는 절차를 변경했습니다. 중복 코드를 없애고 향후 기능을 쉽게 추가할 수 있는 디렉터리 구조를 마련했으며 관리 스크립트를 표준화했습니다. 이번 버전은 MARA의 역사에서 중요한 시점을 나타내는 만큼, 잠시 멈춰 지금까지의 진행 상황을 커뮤니티에 공유하고, 특히 중요하다고 생각하는 교훈을 짚어 보며, 앞으로의 로드맵에 관한 정보를 제공하고자 합니다.

NGINX 최신 앱 참조 아키텍처 버전 1.0.0의 토폴로지 다이어그램

텔레메트리 – 메트릭, 로깅 및 추적

MARA의 핵심 기여자들은 대규모 소프트웨어 운영 경험을 갖추고 있으며, 운영·엔지니어링·관리 관점에서 서비스를 제공하는 데 무엇이 필요한지 잘 알고 있습니다. 또한 애플리케이션이 오작동하는데 정확한 원인을 쉽게 파악할 방법이 없을 때 느끼는 막막함도 잘 압니다. DevOps 업계에서 회자되는 한 문구는 이 문제를 간결하게 요약합니다. “마이크로서비스를 디버깅하는 것은 연쇄 살인 사건의 수수께끼를 푸는 것과 같다.”

이를 염두에 두고, 단기 로드맵에서 관측 가능성 도입을 최우선 과제로 삼았습니다. 여기서 관측 가능성은 로그 관리, 메트릭 및 추적 데이터를 포함합니다. 하지만 단순히 데이터를 수집하는 것만으로는 충분하지 않습니다. 데이터를 심층적으로 분석하여 환경에서 어떤 일이 일어나고 있는지에 대해 의미 있는 판단을 내릴 수 있어야 합니다.

추적 옵션을 검토한 결과, OpenTelemetry (OTEL)를 선택하게 되었습니다. OTEL은 로그, 메트릭, 추적을 비롯한 모든 범위의 텔레메트리 데이터를 지원하기 때문입니다. 저희는 OTEL 에이전트가 모든 추적 데이터를 수집, 처리 및 중복 제거한 후 집계 및 내보내기를 위해 OTEL 수집기로 전달하고, 워크플로의 마지막 단계에 시각화 시스템을 배치하여 데이터를 활용할 수 있도록 하는 구현 방식을 구상했습니다. 이 접근 방식은 사용자에게 데이터를 표시하고 분석할 수 있는 가장 폭넓은 선택지를 제공하는 동시에, OTEL 표준을 활용하여 앞선 단계(수집, 집계 등)를 간소화합니다.

구현은 두 단계로 진행했습니다:

  1. 환경에 Kubernetes용 OpenTelemetry Operator를 배포하여 OTEL 수집기를 관리합니다
  2. Instrument the Bank of Sirius 애플리케이션을 계측하여 트레이스와 메트릭을 내보냅니다

MARA의 원래 버전에서는 로깅에 Elasticsearch와 Filebeat를 사용했습니다. 이를 Grafana Loki로 교체하는 방안도 고려했지만, 당분간은 기존 선택을 유지하기로 했습니다. 메트릭 측면에서는 Prometheus와 Grafana를 기반으로 한 기존 배포를 수정해야 한다고 판단했습니다. 이에 따라 처음에 사용했던 맞춤형 Prometheus 구성을 커뮤니티에서 유지 관리하는 kube-prometheus-stack Helm 차트로 교체했습니다. 이 차트는 Grafana, 노드 익스포터, 그리고 Kubernetes 환경 관리에 적합하도록 사전 구성된 여러 대시보드와 스크레이프 대상을 포함하는 완전한 Prometheus 환경을 구축합니다. 여기에 F5 NGINX Ingress Controller와 Bank of Sirius 애플리케이션을 위한 대시보드도 추가했습니다.

이는 OTEL을 구현하는 데 필요한 방대한 작업을 간략히 요약한 것에 불과합니다. 다른 분들이 똑같이 가파른 학습 곡선을 오르는 수고를 덜 수 있도록 전체 과정을 블로그의 「최신 앱 참조 아키텍처에 OpenTelemetry 통합하기 – 진행 상황 보고서」에 정리했습니다.

배포 옵션 – Kubeconfig

MARA의 초기 버전에서는 배포 환경으로 Amazon Elastic Kubernetes Service (EKS)를 선택했습니다. 이후 많은 사용자가 비용상의 이유로 실습실이나 워크스테이션처럼 리소스 요구량이 적은 ‘로컬’ 환경에서 MARA를 실행하고 싶다는 의견을 전해 왔습니다. 이식성은 원래 프로젝트의 핵심 목표였으며 지금도 마찬가지이므로, 이는 우리가 그 목표를 달성할 수 있음을 입증할 기회였습니다. 작업을 더 쉽게 진행하기 위해, 몇 가지 최소 요구 사항을 충족하는 모든 Kubernetes 클러스터에서 실행할 수 있는 배포 절차를 설계하기로 했습니다.

첫 단계로, Kubernetes 클러스터와 통신하기 위해 kubeconfig 파일을 읽는 새로운 Pulumi 프로젝트를 MARA에 추가했습니다. 이 프로젝트는 Pulumi Kubernetes 프로젝트와 인프라 프로젝트(AWS 및 Digital Ocean용 프로젝트 등) 사이에 위치합니다. 실질적으로 kubeconfig 프로젝트를 만들면 새로운 인프라 프로젝트를 더 쉽게 통합할 수 있습니다. 인프라 프로젝트가 kubeconfig 파일, 클러스터 이름 및 클러스터 컨텍스트를 kubeconfig 프로젝트에 전달할 수 있다면 나머지 MARA 배포 절차는 원활하게 진행됩니다.

테스트에는 CPU 및 메모리 요구 사항이 낮고 설치가 간편한 여러 Kubernetes 배포판을 사용했으며, 여기에는 K3s, Canonical MicroK8s, minikube가 포함됩니다. 모든 배포판은 CPU 2개와 16GB RAM을 갖추고 Ubuntu 21.10을 실행하는 가상 머신(VM)에 배포했습니다. 또한 모든 배포판에서 영구 볼륨과 Kubernetes LoadBalancer를 지원하도록 구성했습니다.

이 과정에서 가장 어려웠던 부분은 프로젝트에 포함된 맞춤형 NGINX Ingress Controller에서 사용하는 프라이빗 레지스트리를 다루는 일이었습니다. (MARA를 배포할 때는 이 맞춤형 NGINX Ingress Controller뿐만 아니라 NGINX Open Source 또는 NGINX Plus 기반의 표준 NGINX Ingress Controller도 사용할 수 있습니다.) 레지스트리 로직을 Amazon Elastic Container Registry (ECR)에서 분리하여 플랫폼에 구애받지 않는 방식으로 전환해야 한다는 사실을 확인했으며, 이 작업은 현재 진행 중입니다. 또한 이그레스 주소의 호스트 이름을 가져오는 로직이 AWS Elastic Load Balancing (ELB)에 지나치게 특화되어 있어 다른 사용 사례에도 적용할 수 있도록 다시 작성해야 한다는 점도 알게 되었습니다.

MARA 관리 스크립트와 Pulumi 프로젝트는 현재 위에서 설명한 문제를 해결하기 위해 몇 가지 특수 로직을 사용합니다. 현재로서는 Kubernetes 구성 기반 배포에서 공식 NGINX 레지스트리의 NGINX Ingress Controller(NGINX Open Source 또는 NGINX Plus 기반)를 사용해야 합니다.

클라우드 기반 배포에 필요한 리소스를 제공하지 못하는 로컬 배포 환경을 지원하기 위해 MARA 구성 파일에 여러 튜닝 매개변수를 추가했습니다. 대부분의 매개변수는 Elastic Stack의 다양한 구성 요소에 요청되는 복제본 수와 관련이 있습니다. 테스트가 진행됨에 따라 배포 환경의 리소스 제약 조건에 맞춰 MARA를 세부적으로 조정할 수 있는 매개변수가 추가될 예정입니다.

이러한 변경 사항을 적용하면 K3s, MicroK8s 및 Minikube에 성공적으로 배포할 수 있으며, Azure Kubernetes Service (AKS), Digital Ocean, Google Kubernetes Engine, Linode 및 Rancher의 Harvester에서도 해당 로직을 성공적으로 테스트했습니다. 자세한 내용은 블로그의 MARA 공급자 상태 페이지 및 MARA: 이제 가까운 워크스테이션에서 실행됩니다를 참조하세요.

파트너와의 협업

파트너들은 MARA와 함께하는 저희의 작업에 매우 긍정적인 반응을 보이며 적극적으로 지원해 주었습니다. 많은 파트너가 프로젝트에 대해 더 자세히 알아보고, 자사 제품에 어떻게 활용할 수 있는지 문의하거나, 새로운 기능을 추가하기 위해 먼저 연락해 왔습니다.

저희가 Pulumi를 MARA의 핵심 요소로 선택한 이유는 사용하기 쉽고 Python을 지원하기 때문입니다. 특히 Python은 널리 사용되는 언어이므로 많은 사람이 MARA 코드를 쉽게 이해할 수 있습니다. 또한 Pulumi의 활발한 커뮤니티와 프로젝트 참여 방식은 저희가 MARA를 통해 이루고자 하는 커뮤니티 참여의 모범이 되었습니다.

2021년 말, 저희는 Sumo Logic와 협력하여 NGINX Ingress Controller를 사용하는 Sumo Logic의 클라우드 모니터링 솔루션에 MARA를 통합했습니다. 이는 MARA가 플러그형이라는 저희의 주장을 검증할 기회였습니다. 과제는 MARA의 Grafana, Prometheus, Elastic을 Sumo Logic 솔루션으로 대체하는 것이었습니다. 다른 배포에서 사용하는 것과 동일한 로직으로 솔루션을 성공적으로 구축하고, Sumo Logic SaaS에 연결할 뿐만 아니라 저희 환경에서 메트릭을 가져오도록 구성할 수 있어 만족스러웠습니다.

OpenTelemetry 관련 작업의 일환으로 저희는 Lightstep과 협력했으며, OTEL 수집기를 손쉽게 재구성하여 추적 데이터와 메트릭을 Lightstep의 SaaS 서비스로 내보낼 수 있도록 했습니다. 저희는 OTEL이 옵저버빌리티의 미래라고 굳게 믿고 있기에, 이 분야를 더욱 심도 있게 살펴보고자 합니다.

지금까지 얻은 교훈

지금까지 얻은 가장 큰 교훈은 모듈식 접근 방식이 현명하다는 것입니다. Sumo Logic과의 작업을 통해 MARA 구성 요소를 성공적으로 조합해 사용할 수 있음을 확인했습니다. 앞으로 OTEL을 환경에 더욱 완전하게 통합하면 이를 추가로 검증할 수 있을 것으로 기대합니다. 앞서 스택의 리소스 사용량을 줄일 수 있다는 이유로 로그 관리 환경을 Elasticsearch에서 Grafana Loki로 교체하는 방안을 고려 중이라고 언급했습니다. 그렇다고 해서 모든 것을 마이크로서비스로 만드는 극단적인 방식을 택하기보다는 ‘실용적인 모듈화’를 지향합니다. 예를 들어 여러 애플리케이션의 로그를 처리할 수 있는 전문 서비스를 두는 것은 합리적이지만, 로그 수집, 저장, 시각화를 각각 별도의 마이크로서비스로 분리해야 하는지는 명확하지 않습니다.

또한 관련 매개변수를 단순히 생략하는 대신 기본값을 구성에 명시적으로 포함해 설정하는 것이 유용하다는 점도 알게 되었습니다. 이는 관리자에게 두 가지 측면에서 편리합니다. 기본값을 기억할 필요가 없고, 구성의 올바른 위치에 정확한 구문으로 이미 표시된 매개변수를 수정하기만 하면 기본값을 쉽게 변경할 수 있습니다.

우리가 뼈저리게 깨달은 또 다른 교훈은 일부 솔루션이 최고의 선택이라서가 아니라 설치가 가장 쉽거나 가장 좋은 튜토리얼을 제공하기 때문에 인기를 얻는다는 점입니다. 그렇기 때문에 설계 과정에서 자신의 가정에 의문을 제기하고 동료들과 상의하는 것이 매우 중요합니다. 열린 소통의 문화는 문제를 조기에 발견하고 해결하는 데 큰 도움이 됩니다.

하지만 여러 차례에 걸쳐, 작동은 하지만 향후 선택의 폭을 제한하거나 다른 문제를 일으키는 로직을 구현하기도 했습니다. 예를 들어 Pulumi를 통해 애플리케이션을 배포하기 시작했을 때는 ConfigMaps에 YAML 매니페스트를 사용하고, Pulumi transformations을 통해 변수를 업데이트했습니다. 이 방식은 작동했지만 유지 관리가 어렵다는 점을 비롯해 여러 이유로 이상적이지 않았습니다. 다음 반복 작업에서는 kube2pulumi를 사용해 매니페스트를 Pulumi 코드로 변환한 다음, 이 코드로 ConfigMaps를 생성함으로써 코드의 가독성과 유지 관리성을 개선했습니다.

또 다른 교훈은 병합 과정에서 배포 YAML에 잘못된 설정이 삽입되면서 얻게 되었습니다. 코드가 구문상 올바르고 의도한 대로 작동하는지 확인하기 위해 YAML의 상당 부분을 다시 작성하고 꼼꼼히 검토해야 했는데, 이는 답답하고 시간이 많이 드는 과정이었습니다. 향후 이러한 문제를 방지하기 위해 이제 GitHub 푸시 과정에서 일반 YAML과 Kubernetes 전용 린팅 및 유효성 검사를 모두 자동화했습니다.

마지막으로, 처음부터 저희의 목표는 메인라인 브랜치가 항상 실행 가능한 상태를 유지하도록 하는 것이었습니다. 새 프로젝트를 체크아웃했는데 유지관리자가 메인라인에 만들어 놓은 문제를 직접 해결해야 한다면 답답할 수밖에 없습니다. 안타깝게도 저희도 몇 차례 이 목표를 지키지 못했으며, Bank of Sirius 하위 모듈과 관련된 다음 사례들이 그 예입니다:

  • 실수로 URL 스킴을 ssh://에서 https://로 변경하는 것을 깜빡했습니다. 저희는 모두 ssh를 사용해 GitHub에 연결하기 때문에 문제가 되지 않았습니다. 하지만 GitHub용 SSH 키가 없는 사용자가 서브모듈을 초기화하려고 하면 오류 메시지가 쏟아졌습니다.
  • 관리 스크립트의 한 릴리스에는 공통 패키지에 대한 의존성이 있었는데, 저희 컴퓨터에 설치되어 있다는 이유로 모든 사용자의 컴퓨터에도 설치되어 있을 것이라고 잘못 생각했습니다.
  • 시작 로직을 다시 작성하는 과정에서 서브모듈 소스를 확인하는 절차를 넣는 것을 깜빡했습니다. 이 서브모듈에는 Bank of Sirius를 배포하는 데 필요한 매니페스트가 포함되어 있는데, 안타깝게도 이러한 매니페스트를 사용할 수 없을 때 발생한 오류와 경고가 너무 모호해서 근본 원인을 발견하기까지 며칠 동안 이상 동작을 디버깅하느라 고생해야 했습니다.

향후 계획

향후 몇 달간의 개발을 위해 NGINX Ingress Controller 빌드, 레지스트리 푸시, Ingress 호스트 이름/IP 주소 로직의 리팩터링을 비롯한 대규모 계획을 세워 두었습니다.

MARA를 구축할 때마다 발견한 한 가지 사실은 NGINX Ingress Controller를 대상으로 한 스캔과 공격이 매우 빠르게 시작된다는 점입니다. 이에 따라 MARA에 NGINX Ingress Controller와 NGINX App Protect WAF를 통합하기 시작했습니다. 이 과정에서 App Protect가 생성하는 로그를 가장 효과적으로 관리하는 방법을 결정해야 하는 과제와 기회가 생겼습니다.

향후 몇 달 내에 적용할 또 다른 변경 사항은 모든 모듈이 Pulumi와 Kubernetes 양쪽이 아닌 Kubernetes에서만 보안 비밀을 가져오도록 하는 것입니다. 이렇게 하면 모든 모듈이 공통 보안 비밀 저장소를 사용하게 되며, 관리자는 보안 비밀을 채우는 방식을 제어할 수 있습니다. 현재 사용자가 선택한 저장소에서 보안 비밀을 읽어 해당 Kubernetes 보안 비밀을 생성하는 새 모듈을 개발하고 있습니다.

MARA에는 현재 부하를 생성하는 도구가 포함되어 있으며, 이는 Locust 기반 도구를 업그레이드하고 일부 수정한 버전입니다. 이 도구는 Bank of Sirius의 기반이 된 원본 Bank of Anthos 앱에 포함되어 있습니다. 현재 개발 중인 새로운 테스트 도구 Cicada Swarm은 부하를 생성할 뿐만 아니라 지표가 사용자가 설정한 임계값을 넘는 시점을 추적하고 보고하므로, 클라우드에서 소프트웨어 제품의 성능을 신속하게 테스트할 수 있는 프레임워크 역할을 합니다. 병렬화 기법을 사용하여 필요한 신뢰 수준과 더 높은 정밀도로 테스트 결과를 제공하며, 사용자 지정 가능한 회귀 분석을 통해 CI/CD 파이프라인에서 빌드의 성공 또는 실패 여부를 판단합니다.

마지막으로, 부하 테스트가 미치는 영향을 어떻게 측정할지 이야기하지 않고서는 부하 테스트를 논할 수 없으며, 이는 다시 텔레메트리로 이어집니다. 저희는 OpenTelemetry의 잠재력에 큰 기대를 걸고 있으며, 조만간 더욱 포괄적인 구현을 마련할 수 있기를 바랍니다. 완전한 구현이 이루어지지 않은 상태에서도 테스트를 실행하고 그 영향을 측정한 뒤, 데이터가 보여 주는 바를 토대로 운영상의 의사 결정을 내릴 수 있도록 하는 것이 저희의 목표입니다.

언제나 그렇듯 여러분의 풀 리퀘스트, 이슈, 그리고 의견을 환영합니다. MARA의 목표는 커뮤니티가 함께 다양한 잠재적 솔루션을 논의하고, 시도하고, 테스트하고, 반복적으로 개선하도록 독려함으로써 최신 애플리케이션을 배포하고 관리하는 최선의 방법에 대한 이해를 높이는 것입니다.

관련 게시물

이 게시물은 시리즈의 일부입니다. 앞으로 MARA에 새로운 기능을 추가할 때마다 자세한 내용을 블로그에 게시할 예정입니다:


공유

관련 블로그 게시물

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
NGINX | 2023. 11. 30.

시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric

이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
NGINX | 2023. 03. 23.

F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법

앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
NGINX | 2021. 09. 27.

Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션

개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX | 2021. 07. 06.

진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법

NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX | 2021. 06. 30.

NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리

NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
NGINX | 2015. 03. 25.

Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유

Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.