블로그

GitOps로 수천 개의 Edge Kubernetes 클러스터 관리하기

F5 썸네일
F5
2019년 12월 18일 게시

Volterra에서 SRE 팀의 업무는 글로벌 SaaS 기반 에지 플랫폼을 운영하는 것입니다. 우리는 다양한 상태(예: 온라인, 오프라인, 관리자 중단 등)에서 많은 수의 애플리케이션 클러스터를 관리하는 데 있어 다양한 과제를 해결해야 하며, 이를 위해 GitOps를 사용하여 선언적 풀 기반 모델과 Kubernetes 생태계를 활용하고 도구를 활용합니다.

이 블로그에서는 다음 내용을 설명합니다.

GitOps를 사용하여 대규모 인프라(물리적 또는 클라우드 호스트) 및 K8s 클러스터를 효과적으로 관리하고 모니터링합니다.

  1. CI/CD 관련 문제를 해결하기 위해 구축한 툴링
  2. 객체 오케스트레이션 및 구성 관리
  3. Infra 및 K8s 클러스터 함대 전반의 관찰 가능성

최근 샌디에이고에서 열린 Cloud Native Rejekts에서 제가 한 강연에서도 다루었던, 규모에 따른 교훈(3,000개의 엣지 사이트)을 더 자세히 살펴보겠습니다.

TL;DR (요약)

  1. 우리는 퍼블릭 클라우드, 온프레미스 또는 유목민 위치에서 수천 개(잠재적으로 수백만 개)의 애플리케이션 및 인프라 클러스터를 배포하고 운영하는 데 사용할 수 있는 간단하고 즉시 사용 가능한 솔루션을 찾을 수 없었습니다.
     
  2. 이 솔루션은 호스트(물리적 또는 클라우드), Kubernetes 제어 평면, 애플리케이션 워크로드 및 다양한 서비스의 지속적인 구성에 대한 수명 주기 관리를 제공해야 했습니다. 또한 이 솔루션은 SRE 설계 요구 사항, 즉 선언적 정의, 변경 불가능한 수명 주기, gitops, 클러스터에 대한 직접 액세스 금지 등을 충족해야 했습니다.
     
  3. Kubespray+Ansible(Kubernetes 배포용)이나 Helm/Spinnaker(워크로드 관리용) 등 다양한 오픈소스 프로젝트를 평가한 후, 우리는 이러한 솔루션 중 어느 것도 각 에지 사이트에 상당한 소프트웨어 블로트를 추가하지 않고는 위의 요구 사항을 충족할 수 없다는 결론에 도달했습니다. 결과적으로, 우리는 호스트(물리적 또는 클라우드), Kubernetes 제어 평면 및 애플리케이션 워크로드의 수명 주기 관리를 수행하는 Golang 기반 소프트웨어 데몬을 직접 빌드하기로 결정했습니다.
     
  4. 단일 테넌트 내에서 시스템을 3,000개 클러스터 이상으로 확장하면서 퍼블릭 클라우드 공급자, 소프트웨어 데몬의 확장성, 운영 툴, 관찰 인프라에 대한 모든 가정이 체계적으로 무너졌습니다. 이러한 과제를 극복하기 위해 각각의 소프트웨어 구성 요소를 재구성해야 했습니다.

에지의 정의

  • 고객 에지(CE) — 클라우드(AWS, Azure, GCP 또는 프라이빗 클라우드 등), 온프레미스 위치(공장, 석유/가스 시설 등), 유목형 위치(자동차, 로봇 등)의 고객 위치입니다. CE는 Volterra SRE 팀에서 관리하지만 고객이 선택한 위치에 필요에 따라 배포할 수도 있습니다.
  • 지역 에지(RE) - 이는 주요 대도시 시장의 공동배치 시설에 있는 Volterra 접속 지점(PoP)으로, 당사의 고도로 통합된 전용 백본과 상호 연결되어 있습니다. 이러한 지역 에지 사이트는 고객 에지(CE) 위치를 안전하게 상호 연결하거나 애플리케이션 서비스를 공개 인터넷에 노출하는 데에도 사용됩니다. 부동산 사이트는 Volterra 인프라 운영(Infra SRE) 팀이 전적으로 관리하고 소유합니다.
관리01
그림 1 : 시스템 개요

위의 아키텍처 다이어그램(그림 1)은 RE와 CE 간의 논리적 연결을 보여줍니다. 각 CE는 가장 가까운 RE에 중복(IPSec 또는 SSL VPN) 연결을 설정합니다.

Edge 관리 요구 사항

약 2년 전 플랫폼을 설계하기 시작했을 때, 제품 팀에서는 다음과 같은 과제를 해결해 달라고 요청했습니다.

  1. 시스템 확장성 - 고객은 수천 개(결국 수백만 개)의 고객 에지 사이트를 지원하길 원했으며, 이는 클라우드 지역에서 소수의 Kubernetes 클러스터를 운영하는 것과는 매우 다릅니다. 예를 들어, 우리 고객 중 한 곳은 약 17,000개의 편의점을 운영하고 있고, 다른 한 곳은 20,000개가 넘는 충전소를 운영하고 있습니다. 이러한 규모로 인해 우리는 몇 개의 클러스터를 처리하는 것과는 매우 다른 방식으로 툴링을 구축해야 했습니다.
  2. 제로터치 배포 - 하드웨어, 소프트웨어 또는 Kubernetes에 대한 이해가 없어도 누구나 새로운 사이트를 배포할 수 있어야 합니다. 엣지 사이트는 켜지고, 홈에 전화를 걸고, 온라인에 접속하는 블랙박스처럼 작동해야 했습니다.
  3. 차량 관리 - 개별적으로 처리할 필요 없이 수천 개의 사이트와 작업 부하를 간편하게 관리할 수 있습니다. 요청된 변경 또는 업그레이드가 수행되는 시점에는 모든 사이트가 오프라인이 되거나 사용할 수 없게 될 수 있습니다. 결과적으로 사이트는 온라인에 접속할 때마다 업데이트를 가져와야 합니다.
  4. 장애 허용성 - 에지 사이트는 모든 구성 요소에 장애가 발생한 후에도 작동해야 합니다. 모든 것을 원격으로 관리해야 하며 장애 발생 시 공장 초기화나 사이트 재구축과 같은 기능을 제공해야 합니다. 우리는 그 장소에는 물리적으로 접근할 수 없다고 가정해야 했습니다.

디자인 원칙 (Kubectl 없음!) 앤서블이 없어! (패키지 없음!)

고도로 분산된 시스템을 운영하는 데 필요한 요구 사항과 과제를 고려하여 다운스트림 문제를 줄이기 위해 SRE 팀이 따라야 할 몇 가지 원칙을 정하기로 했습니다.

  1. 선언적 정의 - 전체 시스템을 선언적으로 기술해야 합니다. 이를 통해 쉬운 추상화 모델을 만들고 모델에 대한 검증을 수행할 수 있습니다.
     
  2. 변경 불가능한 수명 주기 관리 - 과거에는 Ansible, Salt 또는 Puppet과 같은 변경 가능한 LCM 도구를 사용하여 대규모 프라이빗 클라우드 설치를 진행했습니다. 이번에는 기본 OS를 매우 단순하게 유지하고 패키지 관리나 구성 관리 도구가 필요 없이 모든 것을 컨테이너로 제공하고자 했습니다.
     
  3. GitOps 는 Kubernetes 클러스터를 관리하기 위한 표준 운영 모델을 제공합니다. 또한 이를 통해 별도의 워크플로 관리 시스템을 구축하지 않고도 변경 사항에 대한 승인, 감사 및 워크플로를 바로 얻을 수 있습니다. 그래서 우리는 모든 것을 git으로 처리하기로 결정했습니다.
     
  4. kubectl 사용 금지 - 이는 아무도 애플리케이션 클러스터에 직접 액세스할 수 없기 때문에 가장 중요한 원칙 중 하나였습니다. 결과적으로, 개별 에지 클러스터 내부에서 kubectl을 실행하거나 중앙 CD 시스템을 포함한 중앙에서 실행되는 스크립트를 사용하는 기능을 제거했습니다. 푸시 방식을 사용하는 중앙 집중식 CD 시스템은 수십 개의 클러스터에는 적합하지만, 100% 네트워크 가용성이 보장되지 않는 수천 개 클러스터에는 적합하지 않습니다.
     
  5. 과대광고가 아닌 기술(또는 도구) - 우리의 과거 경험에 따르면 많은 인기 있는 오픈소스 도구가 과대광고에 부응하지 못하는 것으로 나타났습니다. 저희는 인프라, K8s 및 애플리케이션 워크로드(Helm, Spinnaker 및 Terraform 등)를 제공하기 위해 여러 커뮤니티 프로젝트를 평가했지만, 결국 가상 인프라 부분에는 Terraform만 사용하고 이 블로그의 다음 부분에서 설명할 사용자 지정 코드를 개발했습니다.

사이트 수명 주기 관리

에지 사이트 수명 주기 관리의 일환으로 호스트 OS 프로비저닝, 기본 구성(예: 사용자 관리, 인증 기관, 대용량 페이지 등), K8s 실행, 워크로드 배포, 진행 중인 구성 변경 관리 등의 문제를 해결해야 했습니다.

우리가 고려했지만 결국 거부한 옵션 중 하나는 KubeSpray+Ansible(OS 관리 및 K8s 배포)과 Helm/Spinnaker(워크로드 배포)를 사용하는 것이었습니다. 우리가 이를 거부한 이유는 이를 위해 오픈소스 도구 2~3개를 관리하고, 우리의 요구 사항을 충족하기 위해 상당한 수정을 해야 하기 때문이었습니다. 에지 클러스터 자동 확장, 보안 TPM 모듈 지원, 차등 업그레이드 등 더 많은 기능을 추가하면서 요구 사항이 계속 증가했습니다.

우리의 목표는 단순함을 유지하고 OS에서 직접 실행되는 구성 요소의 수(Kubernetes 외부)를 최소화하는 것이었기 때문에 Volterra Platform Manager(VPM)라는 가벼운 Golang 데몬을 작성하기로 했습니다. 이것은 OS에서 유일한 systemd Docker 컨테이너이며 다음과 같은 많은 기능을 수행하는 스위스 군용 칼 역할을 합니다.

호스트 라이프사이클

VPM은 설치, 업그레이드, 패치, 구성 등 호스트 운영 체제의 수명 주기를 관리하는 역할을 합니다. 구성해야 할 측면이 많이 있습니다(예: hugepages 할당, /etc/hosts 등)

  1. OS 업그레이드 관리 - 안타깝게도 에지는 쿠버네티스에 관한 것만이 아니며, 커널과 OS의 버전을 전반적으로 관리해야 합니다. 당사의 에지는 활성 및 수동 파티션이 있는 CoreOS(또는 고객 요구에 따라 CentOS) 기반입니다. 업그레이드가 예약되면 업데이트는 항상 수동 파티션에 다운로드됩니다. 재부팅은 업데이트의 마지막 단계로, 활성 및 수동 파티션이 바뀝니다. 유일하게 민감한 부분은 재부팅 전략(다중 노드 클러스터의 경우)인데, 모든 노드를 동시에 재부팅할 수 없기 때문입니다. 우리는 클러스터의 노드가 하나씩 재부팅되는 자체적인 etcd 재부팅 잠금(VPM)을 구현했습니다.
  2. OS에 대한 사용자 접근 관리 - 우리의 요구 사항은 사용자와 ssh 및 콘솔에 대한 접근을 원격으로 제한하는 것입니다. VPM은 ssh CA 로테이션 등의 모든 작업을 수행합니다.
  3. 우리는 자체 L3-L7 데이터 경로를 개발했기 때문에 하드웨어 유형(또는 클라우드 VM)에 따라 호스트 OS에서 2M 또는 1G의 거대 페이지를 구성해야 합니다.

쿠버네티스 라이프사이클

Kubernetes 매니페스트에 대한 수명 주기를 제공하는 관리입니다. Helm을 사용하는 대신, 우리는 VPM에 통합한 K8s client-go 라이브러리를 사용하기로 결정했고, 이 라이브러리의 여러 기능을 사용했습니다.

  1. 낙관적 배포 대 비관적 배포 - 이 기능을 사용하면 애플리케이션이 정상 상태가 될 때까지 기다려야 하는 경우를 분류할 수 있습니다. 단순히 K8s 매니페스트 ves.io/deploy: optimistic 에 대한 주석을 감시합니다.

    낙관적 = 리소스를 만들고 상태를 기다리지 않습니다. 이는 실제 Pod가 성공적으로 시작되는지 알 수 없는 Kubernetes apply 명령과 매우 유사합니다.

    비관적 = Kubernetes 리소스 상태를 기다립니다. 예를 들어, 배포는 모든 Pod가 준비될 때까지 기다립니다. 이는 새로운 kubectl wait 명령과 유사합니다.

  2. 사전 풀과 같은 사전 업데이트 작업 - 특히 네트워크 데이터 플레인이 배송될 때 K8의 롤링 업데이트에 의존할 수 없는 경우가 있습니다. 그 이유는 오래된 포드가 파괴된 후 새로운 포드가 뽑히기 때문입니다. 그러나 데이터 플레인의 경우 네트워크 연결이 끊어집니다. 따라서 새로운 컨테이너 이미지를 가져올 수 없고 Pod가 시작되지 않습니다. 이미지 목록이 포함된 메타데이터 주석 ves.io/prepull은 K8s 매니페스트가 적용되기 전에 작업을 끌어오는 것을 트리거합니다.
  3. 적용에 실패한 경우 재시도 및 롤백 . 이는 K8s API 서버가 간헐적으로 중단될 때 매우 흔한 상황입니다.

진행 중인 구성

K8s 매니페스트와 관련된 구성 외에도 API를 통해 다양한 Volterra 서비스를 구성해야 합니다. 한 가지 예가 IPsec/SSL VPN 구성입니다. VPM은 글로벌 제어 평면에서 구성을 수신하여 개별 노드에 프로그래밍합니다.

공장 초기화

이 기능을 사용하면 원격으로 상자를 원래 상태로 재설정하고 전체 설치 및 등록 과정을 다시 수행할 수 있습니다. 콘솔/물리적 접근이 필요한 사이트를 복구하는 데 매우 중요한 기능입니다.

K8의 수명 주기 관리가 많은 사람들에게 중요한 논의 주제인 것처럼 보일 수 있지만, 저희 팀에서는 전체 작업량의 40~50%에 불과할 것입니다.

제로터치 프로비저닝

클라우드, 온프레미스 또는 노마딕 엣지 등 모든 위치에서 엣지 사이트를 제로터치로 프로비저닝하는 것은 중요한 기능입니다. 개별 사이트에 접근할 수 있을 것으로 기대할 수 없고, 개별 사이트를 설치하고 관리하기 위해 많은 Kubernetes 전문가를 배치하고 싶지 않기 때문입니다. 수천 명까지 확장할 수 없습니다.

다음 다이어그램(그림 2)은 VPM이 새로운 사이트를 등록하는 과정에 어떻게 관여하는지 보여줍니다.

관리02
그림 2 - 제로터치 프로비저닝 흐름
  1. 전원이 켜지면 CE에서 실행되는 VPM(녹색 상자로 표시)이 글로벌 제어 평면(GC)에 등록 토큰을 제시하여 새로운 등록을 생성합니다. 클라우드 VM의 cloud-init의 일부로 제공되는 등록 토큰은 부팅 프로세스 중에 사람이 입력한 키이거나, 에지 하드웨어의 경우 TPM에 프로그래밍된 키일 수 있습니다.
  2. GC는 토큰과 함께 요청을 받고, 이를 통해 테넌트(토큰에 인코딩됨)로 새로운 등록을 생성할 수 있습니다. 고객 운영자는 지도에서 새로운 엣지 사이트를 즉시 확인하고 이름 및 기타 구성 매개변수를 입력하여 승인할 수 있습니다.
  3. GC 내의 VP-Controller는 etcd, K8s, VPM에 대한 구성(예: K8s 마스터, 미니언 등을 결정) 및 인증서를 생성합니다.
  4. VPM은 Docker 이미지 다운로드, 대규모 페이지 구성, K8s 클러스터 설치, Volterra 제어 평면 서비스 시작 등 사이트 부트스트래핑을 시작합니다.
  5. 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 버전으로 릴리스되어야 합니다.
     
  • 소프트웨어 업그레이드 - 여기에는 K8s 워크로드로 실행되는 VPM, etcd, Kubernetes 및 Volterra 제어 서비스가 포함됩니다. 제가 이미 언급했듯이, 우리의 목표는 K8s 내부의 모든 것을 systemd 컨테이너로 실행하는 것입니다. 다행히도 3개 서비스를 제외한 모든 것을 K8s 워크로드로 변환할 수 있었습니다. VPM, etcd 및 kubelet.

에지 사이트에 업데이트를 전달하는 데 사용할 수 있는 알려진 방법은 두 가지가 있습니다. 

  1. 푸시 기반 - 푸시 방법은 일반적으로 Spinnaker, Jenkins 또는 Ansible 기반 CM과 같은 중앙 집중식 CD(지속적인 배포) 도구를 통해 수행됩니다. 이 경우, 중앙 도구는 대상 사이트 또는 클러스터에 액세스할 수 있어야 하며, 해당 작업을 수행할 수 있어야 합니다.
  2. 풀 기반 - 풀 기반 방식은 중앙 집중화된 전달 메커니즘 없이 독립적으로 업그레이드 정보를 가져옵니다. 확장성이 더 뛰어나고 모든 사이트의 자격 증명을 한곳에 저장할 필요성도 없어졌습니다.

업그레이드에 대한 우리의 목표는 표준 휴대전화 업그레이드와 마찬가지로 단순성과 안정성을 극대화하는 것이었습니다. 또한 업그레이드 전략은 다른 고려 사항도 충족해야 합니다. 업그레이드 컨텍스트는 사이트 운영자에게만 해당될 수도 있고, 연결 문제로 인해 장치가 오프라인이거나 잠시 사용할 수 없는 상태일 수도 있습니다. 이러한 요구사항은 풀 방식을 사용하면 더 쉽게 충족할 수 있었기 때문에 우리는 우리의 요구사항을 충족시키기 위해 풀 방식을 채택하기로 결정했습니다.

깃옵스

또한 SRE 팀에 Kubernetes 클러스터, 워크플로 및 감사 변경 사항을 관리하기 위한 표준 운영 모델을 제공하기 쉽기 때문에 GitOps를 선택했습니다.

수천 개 사이트의 확장 문제를 해결하기 위해 우리는 그림 3에 표시된 SRE 아키텍처를 고안했습니다.

관리03
그림 3 - GitOps 흐름

먼저, Git을 상태나 매니페스트를 저장하는 데만 사용하는 것이 아니라는 점을 강조하고 싶습니다. 그 이유는 우리 플랫폼이 K8s 매니페스트뿐만 아니라 진행 중인 API 구성, K8s 버전 등도 처리해야 하기 때문입니다. 우리의 경우, K8s 매니페스트는 전체 선언적 구성의 약 60%를 차지합니다. 이러한 이유로 우리는 이를 기반으로 우리만의 DSL 추상화를 개발해야 했고, 이는 git에 저장되었습니다. 또한 git은 API나 매개변수 병합 기능을 제공하지 않기 때문에 SRE를 위해 추가 Golang 데몬을 개발해야 했습니다. 구성 API, 실행자 및 VP 컨트롤러.

SaaS 플랫폼을 사용하여 고객 엣지에서 새로운 소프트웨어 버전을 릴리스하는 워크플로를 살펴보겠습니다. 

  1. 운영자는 새 버전을 릴리스하기로 결정하고 git 모델에 대한 병합 요청(MR)을 엽니다.
     
  2. 이 MR이 승인되고 병합되면 CI는 SRE Config-API 데몬에 git 모델 구성을 로드하는 작업을 트리거합니다. 이 데몬에는 매개변수 병합, 내부 DNS 구성 등을 위한 여러 API가 있습니다.
     
  3. Config-API는 Executor 데몬에 의해 감시되며, git 변경 사항이 로드된 직후에 주석에 버전이 포함된 최종 K8s 매니페스트를 렌더링하기 시작합니다. 이러한 매니페스트는 Artifact 저장소(S3와 유사)에 ce01-site// .yml 경로로 업로드됩니다.
     
  4. 새 버전이 렌더링되어 아티팩트 저장소에 업로드되면 Executor는 고객 API에 사용 가능한 버전이 있는 새 상태를 생성합니다. 이는 휴대전화에서 사용 가능한 새 버전과 매우 유사합니다.
     
  5. 고객(또는 운영자)은 자신의 사이트를 최신 버전으로 업데이트하도록 예약할 수 있으며, 이 정보는 VP-Controller에게 전달됩니다. VP-Controller는 프로비저닝, 해체 또는 다른 위치로의 마이그레이션을 포함하여 사이트 관리를 담당하는 데몬입니다. 이는 이미 제로터치 프로비저닝에서 부분적으로 설명되었으며 mTLS API를 통해 에지 사이트를 업데이트하는 역할을 합니다.
     
  6. 다이어그램의 마지막 단계는 에지 사이트에서 발생합니다. IPSec/SSL VPN 연결이 설정되면 VP-Controller는 에지의 VPM에 새 버전으로 업데이트를 다운로드하도록 알립니다. 그러나 연결이 끊어지거나 간헐적인 문제가 발생하는 경우 VPM은 5분마다 업데이트를 폴링합니다.
     
  7. 새로운 K8s 매니페스트와 구성을 가져와서 K8s에 배포합니다. 이전 섹션에서 설명한 비관적 배포 기능을 사용하여 VPM은 모든 Pod가 준비될 때까지 기다립니다.
     
  8. 마지막 단계로, VPM은 업그레이드 상태를 VP Controller로 다시 전송하고 이는 고객 API에 상태로 푸시됩니다.

전체 워크플로우의 데모는 여기에서 볼 수 있습니다:

3000개 Edge 사이트 테스트에서 얻은 교훈

이전 섹션에서는 엣지 사이트의 수명 주기를 배포하고 관리하는 데 툴을 사용하는 방법을 설명했습니다. 설계의 유효성을 검증하기 위해 우리는 3,000개의 고객 에지 사이트가 있는 대규모 환경을 구축하기로 결정했습니다(그림 4 참조).

관리04
그림 4 - 3000개의 고객 엣지 사이트

우리는 Terraform을 사용하여 AWS, Azure, Google과 자체 온프레미스 베어 메탈 클라우드에서 3,000개의 VM을 프로비저닝하여 규모를 시뮬레이션했습니다. 모든 VM은 지역 에지 사이트(일명 PoP)에 중복 터널을 구축한 독립적인 CE(고객 에지 사이트)였습니다.

아래 스크린샷은 SRE 대시보드에서 가져온 것이며, 원의 크기로 표현된 위치에 있는 에지 번호를 보여줍니다. 스크린샷을 찍을 당시 약 2,711개의 건강한 에지 사이트와 356개의 건강에 해로운 에지 사이트가 있었습니다.

관리05
그림 5–3000 고객 에지 사이트 배포

주요 결과: 운영

확장 과정의 일환으로 우리는 소프트웨어 데몬을 수정해야 하는 구성 및 운영 측면에서 몇 가지 문제를 발견했습니다. 또한 클라우드 공급업체와 관련하여 여러 문제에 부딪혀 여러 지원 티켓이 개설되기도 했습니다. 예를 들어 API 응답 지연, 단일 지역에서 500개가 넘는 VM을 확보할 수 없음 등이 있습니다. 

  1. VP-Controller 최적화 - 처음에는 등록을 순차적으로 처리했고, etcd, kubernetes 및 VPM에 대한 다양한 인증서를 만들어야 했기 때문에 각각 약 2분이 걸렸습니다. 이번에는 더 높은 엔트로피를 사용하여 미리 생성된 키와 더 많은 수의 작업자를 통한 병렬화를 통해 시간을 최적화했습니다. 이를 통해 20초 이내에 100개 사이트의 등록을 처리할 수 있었습니다. VP-Controller에서 단 하나의 vCPU와 2GB의 RAM만 사용하여 3000개의 모든 엣지 사이트에 서비스를 제공할 수 있었습니다.
     
  2. Docker 이미지 전송 최적화 - 확장을 시작했을 때, 우리는 엣지 사이트에 전송되는 데이터 양이 엄청나다는 것을 깨달았습니다. 각 에지는 약 600MB(3000배)를 다운로드했으며, 총 1.8TB의 데이터가 전송되었습니다. 또한, 우리는 테스트하는 동안 엣지 사이트를 여러 번 재구축했기 때문에 실제로는 그 숫자가 훨씬 더 많았을 것입니다. 결과적으로, 다운로드를 줄이기 위해 Docker 이미지의 크기를 최적화하고 미리 가져온 Docker 이미지로 클라우드 및 ISO 이미지를 빌드해야 했습니다. 아직 퍼블릭 클라우드 컨테이너 레지스트리 서비스를 사용하고 있지만 RE(PoP)를 통해 컨테이너 레지스트리를 배포하고 증분적(바이너리 차이) 업그레이드를 수행하는 설계를 적극적으로 진행하고 있습니다.
     
  3. 글로벌 제어 데이터베이스 운영 최적화 - 모든 Volterra 제어 서비스는 ETCD를 데이터베이스로 사용하는 Golang 서비스 프레임워크를 기반으로 합니다. 모든 사이트는 구성 객체로 표현됩니다. 각 사이트 구성 개체에는 software-upgrade, hardware-info, ipsec-status와 같은 몇 가지 StatusObject가 있습니다. 이러한 StatusObjects는 다양한 플랫폼 구성 요소에서 생성되며 모두 글로벌 구성 API에서 참조됩니다. 3000개 사이트에 도달했을 때 개체 스키마에서 특정 최적화를 수행해야 했습니다. 예를 들어, 글로벌 구성 API에서 허용하는 StatusObjects 유형의 수를 제한하거나, 구성 개체 DB에 과부하가 걸리는 위험을 줄이기 위해 이를 전용 ETCD 인스턴스로 옮기기로 결정했습니다. 이를 통해 구성 데이터베이스의 가용성과 응답 시간을 향상시킬 수 있으며, 장애 발생 시 상태 DB를 재구축할 수도 있습니다. 최적화의 또 다른 예로는 모든 테넌트에서 불필요한 사이트 개체 목록 작업을 중단하거나 보조 인덱스를 도입하여 데이터베이스의 부하를 줄이는 것이 있습니다.

주요 결과: 관찰 가능성

분산 시스템 전반의 관찰성은 시스템을 확장함에 따라 훨씬 더 큰 과제에 직면하게 되었습니다.

처음에는 메트릭의 경우 Prometheus 연합으로 시작했습니다. 즉, 글로벌 제어에 있는 중앙 Prometheus가 지역 에지(RE)에 있는 Promethei를 연합하여 서비스 메트릭을 스크래핑하고 연결된 CE에서 메트릭을 연합합니다. 최상위 수준의 Prometheus는 경고를 평가하고 추가 분석을 위한 메트릭 소스 역할을 했습니다. 우리는 이 접근 방식의 한계에 빠르게 도달했습니다(약 1000명의 CE). 그리고 증가하는 CE 수의 영향을 최소화하려고 노력했습니다. 우리는 히스토그램과 기타 고차수 지표에 대해 미리 계산된 시리즈를 생성하기 시작했습니다. 이를 통해 하루나 이틀을 절약할 수 있었지만 그 후에는 메트릭을 위한 허용 목록을 사용해야 했습니다. 결국, 우리는 CE 사이트별로 시계열 지표의 수를 약 60,000개에서 2,000개로 줄일 수 있었습니다.

결국, 3000개 CE 사이트를 넘어 확장을 계속하고 여러 날 동안 프로덕션에서 운영한 결과, 이 방식은 확장성이 없다는 점이 분명해졌고 모니터링 인프라를 다시 고려해야 했습니다. 우리는 최상위 Prometheus(전역 제어)를 제거하고 각 RE의 Prometheus를 두 개의 별도 인스턴스로 분할하기로 결정했습니다. 한 사람은 로컬 서비스 메트릭을 스크래핑하는 일을 맡고, 두 번째 사람은 CE 메트릭을 통합하는 일을 맡습니다. 둘 다 알림을 생성하고 측정 항목을 Cortex의 중앙 저장소로 푸시합니다. Cortex는 분석 및 시각화 소스로 사용되며 핵심 모니터링 알림 흐름의 일부가 아닙니다. 우리는 Thanos와 M3db 등 여러 가지 중앙 집중형 메트릭 솔루션을 테스트했으며, Cortex가 우리의 요구 사항에 가장 적합하다는 것을 발견했습니다.

관리06
그림 6 - 메트릭 수집 아키텍처

다음 스크린샷(그림 7)은 3000개 엔드포인트에서 prometheus-cef를 스크래핑하는 데 사용되는 메모리 소비량을 보여줍니다. 흥미로운 점은 29.7GB의 RAM이 소모된다는 점인데, 이는 실제로 시스템 규모에 비해 그렇게 많은 것은 아닙니다. 스크래핑을 여러 개로 분할하거나 Cortex에 대한 원격 쓰기를 엣지 자체로 직접 옮기면 더욱 최적화할 수 있습니다.

관리07
그림 7 - RE 사이트의 자원 활용

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

관리08
그림 8 - 글로벌 제어에서의 리소스 활용

CE와 RE의 로깅 인프라의 경우 노드당 Fluentbit 서비스를 사용하여 서비스 및 시스템 로그 이벤트를 수집하고 이를 연결된 RE의 Fluentd로 전달합니다. Fluentd는 RE에 있는 ElasticSearch로 데이터를 전달합니다. ElasticSearch의 데이터는 Elastalert에 의해 평가되고 Alertmanager 알림을 생성하기 위한 규칙이 설정됩니다. 우리는 Prometheus가 생성하는 것과 동일한 라벨이 있는 알림을 생성하기 위해 Elastalert에서 Alertmananger까지 맞춤 통합을 사용하고 있습니다.

모니터링 여정의 핵심 포인트:

  • 새로운 Prometheus 페더레이션 필터를 사용하여 사용되지 않는 메트릭, 레이블 삭제

    - 처음에는 CE당 약 50,000개의 시계열이 있었고 평균 15개의 레이블이 있었습니다.

    - CE당 평균 2000으로 최적화했습니다.

    메트릭 이름에 대한 간단한 while 목록 및 레이블 이름에 대한 black 목록

  • 글로벌 Prometheus 연합에서 Cortex 클러스터로 이동

    - 중앙화된 Prometheus는 모든 RE 및 CE의 Prometheus를 스크랩했습니다.

    - 서기 1000년경에는 측정항목의 양을 관리하는 것이 더 이상 지속 불가능해졌습니다.

    - 현재 우리는 각 RE에 Prometheus를 두고 있으며(연결된 CE의 Promethei에 연합) RW는 Cortex에 있습니다.

  • Elasticsearch 클러스터 및 로그

    - 분산 로깅 아키텍처

    - 각 노드의 수집기인 Fluentbit는 RE의 Fluentd(집계기)로 로그를 전달합니다.

    - ElasticSearch는 단일 Kibana 인스턴스에서 로그를 쿼리하기 위해 원격 클러스터 검색을 사용하여 모든 RE에 배포됩니다.

요약

이 블로그를 통해 전 세계에 배포된 수천 개의 엣지 사이트와 클러스터를 관리하는 데 고려해야 할 사항에 대한 통찰력을 얻을 수 있기를 바랍니다. 초기 설계 요구 사항의 대부분을 충족하고 검증할 수 있었지만, 아직도 많은 개선 사항이 우리 앞에 있습니다...