Volterra에서 SRE 팀은 글로벌 SaaS 기반 엣지 플랫폼을 운영합니다. 온라인, 오프라인, 관리자에 의한 중지 등 다양한 상태에 있는 수많은 애플리케이션 클러스터를 관리하면서 여러 과제를 해결해야 하며, 이를 위해 Kubernetes 생태계와 도구를 활용하고 GitOps를 사용하는 선언적 풀 기반 모델을 적용합니다.
이 블로그에서는 다음 내용을 설명합니다:
GitOps를 사용하여 대규모 인프라(물리적 호스트 또는 클라우드 호스트)와 K8s 클러스터를 효과적으로 관리하고 모니터링하기
- CI/CD 관련 문제를 해결하기 위해 구축한 도구
- 객체 오케스트레이션 및 구성 관리
- 인프라 및 K8s 클러스터 전체에 대한 관측 가능성
대규모 환경(엣지 사이트 3,000곳)에서 얻은 교훈을 더 자세히 살펴보겠습니다. 이 내용은 최근 샌디에이고에서 열린 Cloud Native Rejekts에서 제가 발표한 세션에서도 다뤘습니다.
요약
- 퍼블릭 클라우드, 온프레미스 또는 이동형 환경 전반에서 수천 개(잠재적으로는 수백만 개)의 애플리케이션 및 인프라 클러스터를 배포하고 운영하는 데 사용할 수 있는 간단한 즉시 사용 가능한 솔루션을 찾을 수 없었습니다.
- 이 솔루션은 호스트(물리적 또는 클라우드), Kubernetes 컨트롤 플레인, 애플리케이션 워크로드의 수명 주기 관리와 다양한 서비스의 지속적인 구성 관리를 제공해야 했습니다. 또한 선언적 정의, 불변 수명 주기, GitOps, 클러스터에 대한 직접 액세스 금지라는 SRE 설계 요구 사항을 충족해야 했습니다.
- 다양한 오픈 소스 프로젝트(예: Kubernetes 배포를 위한 Kubespray+Ansible, 워크로드 관리를 위한 Helm/Spinnaker)를 평가한 결과, 이러한 솔루션 중 어느 것도 각 엣지 사이트에 상당한 소프트웨어 오버헤드를 추가하지 않고서는 앞서 언급한 요구 사항을 충족할 수 없다는 결론에 도달했습니다. 이에 따라 호스트(물리 또는 클라우드), Kubernetes 컨트롤 플레인 및 애플리케이션 워크로드의 수명 주기를 관리하는 자체 Golang 기반 소프트웨어 데몬을 구축하기로 결정했습니다.
- 시스템을 단일 테넌트 내에서 3,000개 이상의 클러스터로 확장하면서 퍼블릭 클라우드 제공업체, 소프트웨어 데몬의 확장성, 운영 도구 및 관측 가능성 인프라에 관한 모든 가정이 체계적으로 무너졌습니다. 이러한 문제를 극복하려면 각각의 영역에서 일부 소프트웨어 구성 요소의 아키텍처를 재설계해야 했습니다.
엣지의 정의
- Customer Edge(CE) — 클라우드(AWS, Azure, GCP 또는 프라이빗 클라우드 등)의 고객 위치, 온프레미스 위치(공장 현장, 석유/가스 시설 등) 또는 이동형 위치(자동차, 로보틱스 등)를 의미합니다. CE는 Volterra SRE 팀에서 관리하지만, 고객이 원하는 위치에 필요에 따라 직접 배포할 수도 있습니다.
- 리전 에지(RE) — 주요 대도시권 시장의 코로케이션 시설에 위치하며, 고도로 메시화된 자체 프라이빗 백본으로 상호 연결된 Volterra의 접속 지점(PoP)입니다. 이러한 리전 에지 사이트는 고객 에지(CE) 위치를 안전하게 상호 연결하거나 애플리케이션 서비스를 공용 인터넷에 공개하는 데에도 사용됩니다. RE 사이트는 Volterra 인프라 운영(Infra SRE) 팀이 전적으로 소유하고 관리합니다.

위의 아키텍처 다이어그램(그림 1)은 RE와 CE 간의 논리적 연결을 보여 주며, 각 CE는 가장 가까운 RE에 이중화된 연결(IPSec 또는 SSL VPN)을 설정합니다.
에지 관리 요구 사항
약 2년 전 플랫폼 설계를 시작했을 때, 제품 팀은 다음과 같은 과제를 해결해 달라고 요청했습니다:
- 시스템 확장성 — 고객들은 수천 개(궁극적으로는 수백만 개)의 고객 엣지 사이트를 지원해 달라고 요구했으며, 이는 클라우드 리전에서 소수의 Kubernetes 클러스터를 운영하는 것과는 매우 다릅니다. 예를 들어, 한 고객은 약 17,000개의 편의점을 보유하고 있고 다른 고객은 20,000개가 넘는 충전소를 운영하고 있습니다. 이러한 규모 때문에 소수의 클러스터를 관리할 때와는 매우 다른 방식으로 도구를 구축해야 했습니다.
- 제로 터치 배포 — 하드웨어, 소프트웨어 또는 Kubernetes에 대한 깊은 이해가 없어도 누구나 새 사이트를 배포할 수 있어야 했기 때문입니다. 엣지 사이트는 전원을 켜면 중앙 시스템에 연결해 온라인 상태가 되는 블랙박스처럼 작동해야 했습니다.
- 플릿 관리 — 수천 개의 사이트와 워크로드를 개별적으로 처리할 필요 없이 간편하게 관리할 수 있습니다. 변경 또는 업그레이드가 요청된 시점에 일부 사이트가 오프라인 상태이거나 사용 불가능할 수 있습니다. 따라서 사이트는 온라인 상태가 되면 업데이트를 가져와야 합니다.
- 내결함성 — 엣지 사이트는 어떤 구성 요소에 장애가 발생하더라도 계속 운영될 수 있어야 합니다. 모든 항목을 원격으로 관리할 수 있어야 하며, 장애 발생 시 공장 초기화나 사이트 재구축과 같은 기능을 제공해야 합니다. 현장에 물리적으로 접근할 수 없다는 전제하에 설계해야 했습니다.
설계 원칙(Kubectl 금지! Ansible 금지! 패키지 금지!)
고도로 분산된 시스템을 운영하기 위한 요구 사항과 과제를 고려하여, 후속 단계에서 발생할 수 있는 문제를 줄이기 위해 SRE 팀이 따라야 할 몇 가지 원칙을 정했습니다:
- 선언적 정의 — 전체 시스템은 선언적으로 기술되어야 합니다. 그래야 간단한 추상화 모델을 만들고 해당 모델을 기준으로 검증할 수 있기 때문입니다.
- 불변 수명 주기 관리 — 과거에는 Ansible, Salt, Puppet과 같은 가변형 LCM 도구를 사용하여 대규모 프라이빗 클라우드 설치 작업을 수행했습니다. 이번에는 기본 OS를 매우 단순하게 유지하고, 패키지 관리나 구성 관리 도구 없이 모든 것을 컨테이너로 제공하고자 했습니다.
- GitOps — Kubernetes 클러스터 관리를 위한 표준 운영 모델을 제공합니다. 또한 별도의 워크플로 관리 시스템을 구축하지 않고도 변경 사항에 대한 승인, 감사 및 워크플로를 즉시 활용할 수 있습니다. 따라서 모든 작업은 git을 통해 이루어져야 한다고 결정했습니다.
- kubectl 사용 금지 — 애플리케이션 클러스터에 직접 액세스하는 것은 누구에게도 허용되지 않으므로, 이는 가장 중요한 원칙 중 하나였습니다. 이에 따라 개별 엣지 클러스터 내에서 kubectl을 실행하거나 중앙 집중식 CD 시스템을 비롯한 중앙 환경에서 실행되는 스크립트를 사용하는 기능을 제거했습니다. 푸시 방식을 사용하는 중앙 집중식 CD 시스템은 수십 개의 클러스터에는 적합하지만, 100% 네트워크 가용성이 보장되지 않는 상황에서 수천 개의 클러스터를 관리하는 데는 적합하지 않습니다.
- 과대평가된 기술(또는 도구) 배제 — 과거 경험을 통해 인기 있는 오픈 소스 도구 중 상당수가 기대에 미치지 못한다는 사실을 알게 되었습니다. 인프라, K8s 및 애플리케이션 워크로드를 배포하기 위해 여러 커뮤니티 프로젝트(Helm, Spinnaker, Terraform 등)를 평가했지만, 결국 가상 인프라 부분에는 Terraform만 사용하고 이 블로그의 다음 글에서 설명할 자체 코드를 개발했습니다.
사이트 수명 주기 관리
엣지 사이트 수명 주기 관리의 일환으로 호스트 OS를 프로비저닝하고, 기본 구성(예: 사용자 관리, 인증 기관, HugePages 등)을 설정하며, K8s를 구동하고, 워크로드를 배포하고, 지속적인 구성 변경을 관리하는 방법을 해결해야 했습니다.
저희가 검토했지만 결국 채택하지 않은 방안 중 하나는 KubeSpray+Ansible(OS 관리 및 K8s 배포용)과 Helm/Spinnaker(워크로드 배포용)를 사용하는 것이었습니다. 이 방안을 채택하지 않은 이유는 2~3개의 오픈 소스 도구를 관리해야 할 뿐만 아니라, 엣지 클러스터 자동 확장, 보안 TPM 모듈 지원, 차등 업그레이드 등의 기능이 추가되면서 계속 늘어나는 요구 사항을 충족하기 위해 상당한 수정 작업까지 해야 했기 때문입니다.
단순성을 유지하고 OS에서(Kubernetes 외부에서) 직접 실행되는 구성 요소의 수를 최소화하는 것이 목표였기 때문에, Volterra Platform Manager(VPM)라는 경량 Golang 데몬을 개발하기로 했습니다. 이는 OS에서 유일하게 systemd로 실행되는 Docker 컨테이너이며, 다목적 도구처럼 다양한 기능을 수행합니다:
호스트 수명 주기
VPM은 설치, 업그레이드, 패치, 구성 등을 포함한 호스트 운영 체제의 수명 주기를 관리합니다. 구성해야 할 항목은 매우 다양합니다(예: hugepages 할당, /etc/hosts 등).
- OS 업그레이드 관리 — 안타깝게도 엣지는 Kubernetes만으로 이루어지는 것이 아니므로 커널과 OS 전반의 버전도 관리해야 합니다. 당사의 엣지는 활성 파티션과 비활성 파티션으로 구성된 CoreOS(또는 고객의 요구 사항에 따라 CentOS)를 기반으로 합니다. 업그레이드가 예약되면 업데이트는 항상 비활성 파티션에 다운로드됩니다. 업데이트의 마지막 단계는 재부팅이며, 이때 활성 파티션과 비활성 파티션이 서로 전환됩니다. 유일하게 주의해야 할 부분은 모든 노드를 동시에 재부팅할 수 없기 때문에 필요한 재부팅 전략(다중 노드 클러스터의 경우)입니다. 당사는 클러스터의 노드를 하나씩 재부팅하도록 자체 etcd 재부팅 잠금 기능을 VPM에 구현했습니다.
- OS 사용자 액세스 관리 — 사용자의 ssh 및 콘솔 원격 액세스를 제한해야 합니다. VPM은 ssh CA 교체와 같은 모든 작업을 수행합니다.
- 자체적으로 L3-L7 데이터 경로를 개발했기 때문에 하드웨어(또는 클라우드 VM) 유형에 따라 호스트 OS에서 2M 또는 1G 대용량 페이지를 구성해야 합니다.
Kubernetes 수명 주기
Kubernetes 매니페스트의 수명 주기를 관리합니다. Helm을 사용하는 대신 K8s client-go 라이브러리를 사용하기로 결정했으며, 이를 VPM에 통합하여 다음과 같은 여러 기능을 활용했습니다:
- 낙관적 배포와 비관적 배포 — 이 기능을 사용하면 정상 상태가 될 때까지 기다려야 하는 애플리케이션을 분류할 수 있습니다. K8s 매니페스트에서 다음 어노테이션을 확인하기만 하면 됩니다. ves.io/deploy: optimistic.낙관적 배포 = 리소스를 생성하고 상태를 기다리지 않습니다. 이는 kubernetes apply 명령과 매우 유사하며, 실제 Pod가 성공적으로 시작되는지는 알 수 없습니다. 비관적 배포 = Kubernetes 리소스의 상태를 기다립니다. 예를 들어 배포의 경우 모든 Pod가 준비될 때까지 기다립니다. 이는 새로운 kubectl wait 명령과 유사합니다.
- 사전 풀링과 같은 업데이트 전 작업 — 특히 네트워크 데이터 플레인이 함께 배포되는 경우에는 K8s 롤링 업데이트에 의존할 수 없는 때가 있습니다. 기존 Pod가 삭제된 후 새 Pod의 이미지를 풀링하기 때문입니다. 하지만 데이터 플레인의 경우 네트워크 연결이 끊어집니다. 따라서 새 컨테이너 이미지를 풀링할 수 없어 Pod가 시작되지 않습니다. 이미지 목록이 포함된 메타데이터 어노테이션 ves.io/prepull을 지정하면 K8s 매니페스트가 적용되기 전에 이미지 풀링 작업이 실행됩니다.
- 재시도 및 롤백 적용 중 오류가 발생하는 경우에 사용합니다. K8s API 서버에 간헐적인 장애가 발생할 때 흔히 볼 수 있는 상황입니다.
지속적인 구성
K8s 매니페스트 관련 구성 외에도 API를 통해 다양한 Volterra 서비스를 구성해야 합니다. IPsec/SSL VPN 구성이 그 예로, VPM은 글로벌 제어 플레인에서 구성을 수신하여 개별 노드에 적용합니다.
공장 초기화
이 기능을 사용하면 장비를 원격으로 초기 상태로 재설정하고 전체 설치 및 등록 절차를 다시 진행할 수 있습니다. 콘솔 또는 물리적 접근이 필요한 사이트를 복구하는 데 매우 중요한 기능입니다.
K8s 수명 주기 관리가 많은 사람에게 큰 논의 주제로 보일 수 있지만, 저희 팀에서는 전체 업무량의 약 40~50%에 불과합니다.
제로 터치 프로비저닝
어떤 위치(클라우드, 온프레미스 또는 이동형 엣지)에 있든 엣지 사이트를 제로 터치 방식으로 프로비저닝하는 기능은 매우 중요합니다. 개별 사이트에 직접 접근할 수 있다고 기대하기 어렵고, 각 사이트를 설치하고 관리하기 위해 수많은 Kubernetes 전문가를 배치하는 것도 바람직하지 않기 때문입니다. 이러한 방식으로는 수천 개 규모로 확장할 수 없습니다.
다음 다이어그램(그림 2)은 새 사이트를 등록하는 과정에 VPM이 어떻게 관여하는지 보여줍니다:

- 전원이 켜지면 CE에서 실행 중인 VPM(녹색 상자로 표시됨)이 새 등록을 생성하기 위해 글로벌 제어 플레인(GC)에 등록 토큰을 제시합니다. 등록 토큰은 클라우드 VM의 cloud-init에 포함되어 제공되며, 부팅 과정에서 사용자가 입력하는 키이거나 엣지 하드웨어의 TPM에 프로그래밍된 키일 수 있습니다.
- GC는 토큰이 포함된 요청을 수신하고, 이를 통해 테넌트(토큰에 인코딩됨) 아래에 새 등록을 생성할 수 있습니다. 고객 운영자는 지도에서 새 엣지 사이트를 즉시 확인하고, 이름 및 기타 구성 매개변수를 입력하여 승인할 수 있습니다.
- GC 내의 VP-Controller는 구성(예: K8s 마스터와 미니언 등을 결정)을 생성하고 etcd, K8s 및 VPM용 인증서를 발급합니다.
- VPM은 Docker 이미지 다운로드, HugePages 구성, K8s 클러스터 설치 및 Volterra 컨트롤 플레인 서비스 시작을 포함한 사이트 부트스트래핑을 시작합니다.
- VPM은 데이터 트래픽과 사이트 간 및 공용 네트워크와의 상호 연결에 사용될 중복 터널(IPSec/SSL VPN)을 가장 가까운 두 개의 리전 엣지 사이트에 구성합니다.
보시다시피 전체 프로세스가 완전히 자동화되어 있으므로 사용자는 세부 구성에 대해 알거나 수동으로 어떤 단계도 수행할 필요가 없습니다. 전체 장치가 온라인 상태로 전환되어 고객 앱과 요청을 처리할 준비가 되기까지 약 5분이 소요됩니다.
인프라 소프트웨어 업그레이드
업그레이드는 우리가 해결해야 했던 가장 복잡한 과제 중 하나입니다. 엣지 사이트에서 무엇이 업그레이드되는지 정의해 보겠습니다:
- 운영 체제 업그레이드 — 커널과 모든 시스템 패키지가 여기에 포함됩니다. 표준 Linux OS 배포판을 운영해 본 사람이라면 마이너 버전 간 업그레이드(예: Ubuntu 16.04.x에서 16.04.y로 업그레이드)가 얼마나 번거로운지, 메이저 버전 간 업그레이드(예: Ubuntu 16.04에서 18.04로 업그레이드)는 얼마나 더 어려운지 잘 알고 있을 것입니다. 사이트가 수천 개에 달하는 경우 업그레이드는 항상 예측 가능한 결과를 내야 하며 사이트마다 다르게 작동해서는 안 됩니다. 따라서 저희는 2개의 파티션과 경로별 읽기 전용 파일 시스템을 사용해 A/B 업그레이드를 수행할 수 있는 CoreOS와 CentOS Atomic을 선택했습니다. 이를 통해 부팅 순서의 파티션을 전환하여 즉시 이전 상태로 되돌릴 수 있으며, OS 패키지를 별도로 관리하지 않고도 OS의 일관성을 유지할 수 있습니다. 하지만 이제는 새 패키지를 설치하는 것만으로 openssh 서버와 같은 시스템의 개별 구성 요소를 업그레이드할 수 없습니다. 개별 구성 요소의 변경 사항은 새로운 불변 OS 버전으로 릴리스해야 합니다.
- 소프트웨어 업그레이드 — 여기에는 VPM, etcd, Kubernetes 및 K8s 워크로드로 실행되는 Volterra 제어 서비스가 포함됩니다. 앞서 언급했듯이, 저희의 목표는 K8s 내부의 모든 요소를 systemd 컨테이너로 실행하는 것입니다. 다행히 VPM, etcd, kubelet의 세 가지 서비스를 제외한 모든 요소를 K8s 워크로드로 전환할 수 있었습니다.
에지 사이트에 업데이트를 배포하는 데 사용할 수 있는 것으로 알려진 방법은 두 가지입니다:
- 푸시 기반 — 푸시 방식은 일반적으로 Spinnaker, Jenkins 또는 Ansible 기반 CM과 같은 중앙 집중식 CD(지속적 배포) 도구를 통해 수행됩니다. 이 경우 중앙 도구가 대상 사이트 또는 클러스터에 접근할 수 있어야 하며, 작업을 수행할 수 있는 상태여야 합니다.
- 풀 기반 — 풀 기반 방식은 중앙 집중식 배포 메커니즘 없이 독립적으로 업그레이드 정보를 가져옵니다. 확장성이 더 뛰어나며 모든 사이트의 자격 증명을 한곳에 저장할 필요도 없습니다.
업그레이드의 목표는 일반적인 휴대폰 업그레이드와 마찬가지로 단순성과 안정성을 극대화하는 것이었습니다. 또한 업그레이드 전략은 몇 가지 다른 사항도 고려해야 했습니다. 예를 들어 업그레이드 작업을 현장 운영자만 수행할 수 있거나, 연결 문제로 인해 장치가 일정 시간 동안 오프라인 상태이거나 사용할 수 없을 수도 있습니다. 이러한 요구 사항은 풀 방식으로 더 쉽게 충족할 수 있으므로, 당사의 요구에 맞게 이 방식을 채택하기로 결정했습니다.
GitOps
또한 SRE 팀이 Kubernetes 클러스터와 워크플로를 관리하고 변경 사항을 감사할 수 있는 표준 운영 모델을 더 쉽게 제공할 수 있어 GitOps를 선택했습니다.
수천 개 사이트의 확장성 문제를 해결하기 위해 그림 3과 같은 SRE 아키텍처를 고안했습니다:

먼저, 저희는 단순히 상태나 매니페스트를 저장하기 위해 Git을 사용하는 것이 아니라는 점을 강조하고 싶습니다. 저희 플랫폼은 K8s 매니페스트뿐만 아니라 지속적으로 변경되는 API 구성과 K8s 버전 등도 처리해야 하기 때문입니다. 저희의 경우 K8s 매니페스트는 전체 선언적 구성의 약 60%를 차지합니다. 따라서 그 위에 자체 DSL 추상화 계층을 구축해 git에 저장해야 했습니다. 또한 git은 API나 매개변수 병합 기능을 제공하지 않기 때문에 SRE를 위한 추가 Golang 데몬인 Config API, Executor, VP Controller를 개발해야 했습니다.
SaaS 플랫폼을 사용해 고객 엣지에 새 소프트웨어 버전을 릴리스하는 워크플로를 살펴보겠습니다:
- 운영자가 새 버전을 릴리스하기로 결정하고 Git 모델에 대한 병합 요청(MR)을 생성합니다.
- 이 MR이 승인되고 병합되면 CI가 git 모델 구성을 SRE Config-API 데몬에 로드하는 작업을 트리거합니다. 이 데몬은 매개변수 병합, 내부 DNS 구성 등을 위한 여러 API를 제공합니다.
- Executor 데몬은 Config-API를 감시하며, git 변경 사항이 로드되는 즉시 주석에 버전이 포함된 최종 K8s 매니페스트 렌더링을 시작합니다. 그런 다음 이 매니페스트는 다음 경로의 아티팩트 스토리지(S3와 유사)에 업로드됩니다. ce01-site//.yml
- 새 버전의 렌더링이 완료되어 아티팩트 스토리지에 업로드되면 Executor는 고객 API에 사용 가능한 버전이 있음을 나타내는 새로운 상태를 생성합니다. 이는 휴대폰에서 새 버전을 사용할 수 있다고 표시되는 것과 매우 유사합니다.
- 고객(또는 운영자)은 자신의 사이트를 최신 버전으로 업데이트하도록 예약할 수 있으며, 이 정보는 VP-Controller로 전달됩니다. VP-Controller는 프로비저닝, 서비스 해제 또는 다른 위치로의 마이그레이션을 비롯한 사이트 관리를 담당하는 데몬입니다. 이는 제로 터치 프로비저닝에서 이미 일부 설명되었으며, mTLS API를 통해 엣지 사이트를 업데이트하는 역할을 합니다.
- 다이어그램의 마지막 단계는 엣지 사이트에서 진행됩니다. IPSec/SSL VPN 연결이 설정되면 VP-Controller가 엣지의 VPM에 새 버전의 업데이트를 다운로드하도록 알립니다. 단, 연결이 끊기거나 간헐적인 문제가 발생하는 경우 VPM은 5분마다 업데이트가 있는지 확인합니다.
- 새 K8s 매니페스트와 구성을 가져와 K8s에 배포합니다. 이전 섹션에서 설명한 비관적 배포 기능을 사용하여 VPM은 모든 Pod가 준비될 때까지 기다립니다.
- 마지막 단계로 VPM은 업그레이드 상태를 VP Controller로 다시 전송하며, 이 상태는 고객 API에 전달됩니다.
여기에서 전체 워크플로의 데모를 확인할 수 있습니다:

3,000개 엣지 사이트 테스트에서 얻은 교훈
앞 절에서는 엣지 사이트를 배포하고 수명 주기를 관리하는 데 당사의 도구가 어떻게 사용되는지 설명했습니다. 설계를 검증하기 위해 고객 엣지 사이트 3,000개로 구성된 대규모 환경을 구축하기로 했습니다(그림 4 참조).

규모를 시뮬레이션하기 위해 Terraform을 사용하여 AWS, Azure, Google 및 자체 온프레미스 베어메탈 클라우드 전반에 3,000개의 VM을 프로비저닝했습니다. 이 모든 VM은 독립적인 CE(고객 엣지 사이트)로서 당사의 리전 엣지 사이트(일명 PoP)에 이중화 터널을 구축했습니다.
아래 스크린샷은 SRE 대시보드에서 가져온 것으로, 원의 크기로 표시된 각 위치의 엣지 사이트 수를 보여줍니다. 스크린샷을 촬영할 당시 정상 상태인 엣지 사이트는 약 2,711개, 비정상 상태인 엣지 사이트는 356개였습니다.

주요 결과: 운영
확장 과정에서 구성 및 운영 측면의 몇 가지 문제를 발견했으며, 이를 해결하기 위해 소프트웨어 데몬을 수정해야 했습니다. 또한 클라우드 제공업체와 관련해 여러 문제가 발생하여 다수의 지원 티켓을 접수했습니다. 예를 들어 API 응답 지연, 단일 리전에서 500대가 넘는 VM을 확보할 수 없는 문제 등이 있었습니다.
- VP-Controller 최적화 — 초기에는 등록을 순차적으로 처리했으며, etcd, kubernetes 및 VPM용 인증서를 여러 개 발급해야 했기 때문에 각 등록에 약 2분이 걸렸습니다. 엔트로피가 더 높은 키를 미리 생성하고 작업자 수를 늘려 병렬 처리함으로써 이 시간을 단축했습니다. 그 결과 100개 사이트의 등록을 20초 이내에 처리할 수 있었습니다. VP-Controller에서 약 1개의 vCPU와 2GB의 RAM만 사용해 3,000개의 엣지 사이트를 모두 지원할 수 있었습니다.
- Docker 이미지 전송 최적화 — 규모를 확장하기 시작하면서 엣지 사이트로 전송되는 데이터의 양이 방대하다는 사실을 깨달았습니다. 각 엣지에서 약 600MB를 다운로드했으며(3000개 엣지 기준), 총 전송 데이터양은 1.8TB에 달했습니다. 또한 테스트 중에 엣지 사이트를 여러 차례 재구축했기 때문에 실제 데이터양은 이보다 훨씬 더 많았습니다. 이에 따라 다운로드를 줄이기 위해 Docker 이미지 크기를 최적화하고, Docker 이미지가 미리 풀링된 클라우드 이미지와 ISO 이미지를 빌드해야 했습니다. 현재도 퍼블릭 클라우드 컨테이너 레지스트리 서비스를 사용하고 있지만, RE(PoP)를 통해 컨테이너 레지스트리를 분산하고 증분(바이너리 차이) 업그레이드를 수행하는 설계를 적극적으로 개발하고 있습니다.
- 글로벌 제어 데이터베이스 작업 최적화 — 모든 Volterra 제어 서비스는 ETCD를 데이터베이스로 사용하는 Golang 서비스 프레임워크를 기반으로 합니다. 각 사이트는 구성 객체로 표현됩니다. 각 사이트 구성 객체에는 software-upgrade, hardware-info, ipsec-status와 같은 몇 가지 StatusObject가 있습니다. 이러한 StatusObject는 다양한 플랫폼 구성 요소에서 생성되며 모두 글로벌 구성 API에서 참조됩니다. 사이트 수가 3,000개에 도달했을 때 객체 스키마를 일부 최적화해야 했습니다. 예를 들어 글로벌 구성 API에서 허용하는 StatusObject 유형 수를 제한하거나, 구성 객체 DB의 과부하 위험을 줄이기 위해 전용 ETCD 인스턴스로 옮겼습니다. 이를 통해 구성 데이터베이스의 가용성과 응답 시간을 개선할 수 있으며, 장애 발생 시 상태 DB를 재구축할 수도 있습니다. 또 다른 최적화 사례로는 모든 테넌트에 걸쳐 불필요하게 사이트 객체 목록을 조회하는 작업을 중단하거나, 데이터베이스 부하를 줄이기 위해 보조 인덱스를 도입한 것이 있습니다.
주요 결과: 관측 가능성
시스템을 확장함에 따라 분산 시스템 전반의 관측 가능성을 확보하는 데 훨씬 더 많은 과제가 발생했습니다.
처음에는 메트릭을 위해 Prometheus 페더레이션을 사용했습니다. 글로벌 제어 영역의 중앙 Prometheus가 리전 엣지(RE)의 Prometheus 인스턴스들을 페더레이션하는 구조였으며, 각 리전 엣지의 Prometheus는 자체 서비스 메트릭을 스크레이핑하고 연결된 CE의 메트릭을 페더레이션했습니다. 최상위 Prometheus는 알림을 평가하고 추가 분석을 위한 메트릭 소스 역할을 했습니다. 하지만 이 접근 방식은 약 1,000개의 CE에서 빠르게 한계에 도달했고, 늘어나는 CE 수의 영향을 최소화하고자 했습니다. 히스토그램과 기타 카디널리티가 높은 메트릭에 대해 사전 계산된 시리즈를 생성하기 시작했습니다. 이 방법으로 하루나 이틀 정도는 버틸 수 있었지만, 이후에는 메트릭에 화이트리스트를 적용해야 했습니다. 결국 CE 사이트당 시계열 메트릭 수를 약 60,000개에서 2,000개로 줄일 수 있었습니다.
결국 CE 사이트를 3,000개 이상으로 계속 확장하고 프로덕션 환경에서 여러 날 동안 운영한 결과, 이 방식으로는 확장할 수 없다는 점이 분명해졌고 모니터링 인프라를 재고해야 했습니다. 이에 최상위 Prometheus(글로벌 제어 영역)를 제거하고 각 RE의 Prometheus를 두 개의 독립된 인스턴스로 분리하기로 했습니다. 하나는 로컬 서비스 메트릭 수집을 담당하고, 다른 하나는 CE 메트릭 페더레이션을 담당합니다. 두 인스턴스 모두 알림을 생성하고 메트릭을 Cortex의 중앙 스토리지로 전송합니다. Cortex는 분석 및 시각화를 위한 데이터 소스로 사용되며, 핵심 모니터링 알림 흐름에는 포함되지 않습니다. Thanos와 M3db를 비롯한 여러 중앙 집중식 메트릭 솔루션을 테스트한 결과, Cortex가 요구 사항에 가장 적합하다는 결론을 내렸습니다.

다음 스크린샷(그림 7)은 엔드포인트가 3,000개일 때 prometheus-cef를 스크레이핑하면서 발생한 메모리 사용량을 보여줍니다. 주목할 점은 RAM 사용량이 29.7GB라는 것인데, 시스템 규모를 고려하면 실제로 그리 많은 양은 아닙니다. 스크레이핑 작업을 여러 개로 분할하거나 원격 쓰기 기능을 Cortex에서 엣지 자체로 직접 옮기면 추가로 최적화할 수 있습니다.

다음 스크린샷(그림 8)은 이 규모에서 Cortex ingestor(최대 19GB RAM)와 distributor에 얼마나 많은 메모리 및 CPU 리소스가 필요했는지 보여줍니다. Cortex의 가장 큰 장점은 수평 확장이 가능하다는 점입니다. 따라서 수직으로 확장해야 하는 Prometheus와 달리 복제본을 더 추가할 수 있습니다.

CE 및 RE의 로깅 인프라에는 노드별로 Fluentbit 서비스를 사용합니다. 이 서비스는 서비스 및 시스템 로그 이벤트를 수집하여 연결된 RE의 Fluentd로 전달합니다. Fluentd는 데이터를 RE에 있는 ElasticSearch로 전달합니다. ElasticSearch의 데이터는 Elastalert에서 평가되며, Alertmanager 알림을 생성하도록 규칙이 설정됩니다. 또한 Elastalert와 Alertmananger 간의 자체 통합 기능을 사용하여 Prometheus가 생성하는 것과 동일한 레이블을 가진 알림을 생성합니다.
모니터링 여정의 주요 사항:
- 새로운 Prometheus 페더레이션 필터를 사용하여 사용하지 않는 메트릭과 레이블 제거- 초기에는 CE당 약 50,000개의 시계열이 있었고 시계열당 평균 15개의 레이블이 있었습니다. 이를 CE당 평균 2,000개로 최적화했습니다. 메트릭 이름에는 간단한 허용 목록을, 레이블 이름에는 차단 목록을 사용했습니다.
- 글로벌 Prometheus 페더레이션에서 Cortex 클러스터로 전환- 중앙 집중식 Prometheus가 모든 RE와 CE의 Prometheus에서 메트릭을 수집했습니다. - CE가 1,000개에 이르자 메트릭 양을 관리하기가 어려워졌습니다. - 현재는 각 RE에 Prometheus를 두고(연결된 CE의 Prometheus와 페더레이션) RW를 통해 Cortex로 전송합니다.
- Elasticsearch 클러스터 및 로그- 분산형 로깅 아키텍처 - 각 노드에서 수집기 역할을 하는 Fluentbit가 로그를 RE의 Fluentd(집계기)로 전달 - 모든 RE에 ElasticSearch를 배포하고 원격 클러스터 검색을 사용하여 단일 Kibana 인스턴스에서 로그를 조회
요약
이 블로그를 통해 전 세계에 배포된 수천 개의 엣지 사이트와 클러스터를 관리하기 위해 고려해야 할 사항을 이해하는 데 도움이 되기를 바랍니다. 초기 설계 요구사항의 대부분을 충족하고 검증했지만, 앞으로도 개선해야 할 부분이 많이 남아 있습니다…
작성자 소개
관련 블로그 게시물
성평등을 향한 여정: 사이버 보안 분야에서 성공적인 커리어를 개척하는 방법에 관한 Jenn Gile과의 Q&A
F5의 ‘성평등을 향한 여정’ 시리즈 네 번째 Q&A에서는 Rachael Shah와 NGINX 제품 마케팅 책임자 Jenn Gile이 사이버 보안 직종에 대한 오해를 바로잡고, 사이버 보안 분야의 성별 격차를 해소하기 위한 조언과 그 이점에 대해 이야기합니다.
TLS 검사에서 피터 파커 원칙 다루기
“큰 힘에는 큰 책임이 따른다.” 볼테르와 처칠도 이와 비슷한 말을 남겼지만, 이 문구는 스파이더맨 코믹스에서 벤 삼촌의 말로 가장 널리 알려져 있습니다. 물론 이 문구가 문화적으로 널리 통용되는 이유 중 하나는 TLS 검사를 비롯해 수많은 상황과 주제에 적용할 수 있기 때문입니다.
Venafi와 F5를 통한 머신 아이덴티티 보호
‘머신 아이덴티티’란 간단히 말해 자동화된 프로세스가 자신의 신원을 식별할 수 있도록 하고, 다른 자동화 시스템과 프로세스가 관련 리소스에 적절한 수준의 접근 권한을 부여하도록 하는 방법을 의미합니다. 이 개념 자체는 새로운 것이 아닙니다. 비교적 새로운 점은 이를 구현해야 하는 규모입니다.
마이너와 미니언: 데이터 유출만이 비용을 초래하는 것은 아닙니다
물론 데이터 유출은 더 큰 비용을 초래할 수 있고(적어도 지금은), 실패 사실을 세상에 드러낼 수밖에 없게 합니다(통지 의무가 있으니까요). 하지만 보안을 단순히 데이터 노출 문제로만 봐서는 안 됩니다. 요즘은 데이터가...
내 클라우드에서 나가!
F5의 Jay Kelley가 전하는 최신 소식에는 Microsoft Office 365용 신규 ID 및 액세스 솔루션을 배포할 때 고려해야 할 사항이 정리되어 있습니다.
Shift(웹 앱) 보안 레터
웹 앱 보안을 개발 초기 단계로 앞당기세요. F5 블로그에서 DevOps 파이프라인 초기에 보안을 통합하여 취약점을 예방하고 시간을 절약하는 방법을 알아보세요.