Skip to Content
Bloghub/edge 2-클러스터 구조
  • #멀티클러스터
  • #GitOps
  • #SSO
  • #메트릭

hub / edge 두개의 홈랩 클러스터

홈랩 클러스터가 두 환경에 걸쳐 두개로 배포되어있습니다. 하나는 지금 사는 집, 하나는 본가에 배포되어있습니다.

첫 공부를 시작할떄부터 본가에서 홈랩을 구성하기 시작한지 벌써 4년이 넘어가네요. 3년이 넘도록 public IP 변경 한번없이 도메인을 그대로 쓸 수 있게 해줬던 통신사에게도 꽤 고마운 마음을 가지고있긴 헀습니다.

이제는 새로운 환경에서도 홈랩을 구성 할 수 있게되어, 클러스터가 두벌이 되었습니다. Stateless 한 노드들은 여러군데에 둘 수 있지만, 스토리지 장비를 각각 두기엔 또 부담이라, 한군에만 둘 수 있겠더라고요.

사실 이 동일한 패턴을 EKS 클러스터간 매니지먼트할떄와 동일한 패턴으로 쓰고있었는데요 기존에 이 두환경을 Stage / Prod 라고 임의로 이름붙여서 배포하다보니, 실제 두개 상황과는 괴리감이 점점 커지는것같아, 이름을 변경해야겠다는 생각이들어 이름부터 새로 지어줬습니다.

그래서 이름을 역할대로 다시 지었습니다. hubedge.

hub (현재집, 舊 stage)edge (본가, 舊 prod)
도메인hub 전용 도메인edge 전용 도메인
노드다수의 서버 + Synology NAS단일 노드
역할중앙 — 스토리지·관측·SSO·CI등의 종착지스포크 — 서비스만 돌리고 상태저장은 전부 hub로
스토리지NAS 기반의 storageClass (NFS)없음
관측vmcluster(vmstorage) + Grafana + vmalertvmagent 하나
인증Keycloak (hub SSO)자체 IdP 없음 — hub Keycloak에 OIDC 위임

보유중인 도메인이 2개였어서 환경 이름이 도메인과 1:1이 된 것도 장점이라면 장점이겠네요.

1. 전체 지도

hub — 현재집 · 중앙 (스토리지·관측·SSO)edge — 본가 · 스포크 (스토리지 없음)pull · auto-syncpull · auto-syncsyncsyncscraperemote write · 공인망 · vmauth 인증PVC(NFS)조회OIDCOIDC 위임 (공인망)GitHubmontstrap · mont-helm · montstrap-manifest서비스 앱 40여 개ArgoCD (hub)VictoriaMetricsvmclustervmstorage ×4 · RF2 ·90dSynology NASNFS — 상태는 전부 여기로Grafana · vmalert조회·알림도 hub에서만Keycloak두 ArgoCD의 공용 IdPArgoCD (edge)서비스 앱블로그 · 청첩장 · HA …전부 무상태vmagentcluster=edge 라벨 · PVC없음
통합 전체 지도 — 세 흐름을 한 장에 담았습니다. ① 배포: GitHub의 montstrap 3-repo를 두 클러스터 ArgoCD가 각자 pull, ② 관측: edge vmagent가 공인망 위 vmauth 인증을 거쳐 hub vmcluster로 remote write(둘만의 유일한 데이터 접점), ③ 인증: edge ArgoCD가 hub Keycloak에 OIDC 위임. 디스크가 달린 것(store)은 전부 hub에 있고 edge는 무상태입니다 — 메트릭 행(가운데)과 인증 행(아래)을 분리해 서로 무관한 흐름임을 배치로 표현했습니다.

두 집 사이를 오가는 데이터 트래픽은 딱 하나 — edge vmagent의 remote write입니다. 집 밖을 나가는 경로라 인증이 붙습니다.

2. edge를 stateless로 만든 이유

원래 edge에도 hub와 똑같은 VictoriaMetrics 풀스택이 있었습니다. 다만, 스토리지 장비를 들고 이사를갔으니… 상태저장할 곳이 없어지기도 했습니다.

꼭 그게 중요한건 아닌데요, 현재 운영중인 서비스 클러스터의 상태저장소도 “아예” 두지않고 Managed Service 영역으로 이관한 이후하고 클러스터 위에 상태저장이 필요한 컴포넌트들은 그 앞의 관리 클러스터로 이관하는쪽이 좋아보이는 패턴이였습니다.

  • 물론 EKS의 생명주기를 Blue / Green 으로 자주 갈아엎기에 용이한 패턴이라는 뜻 입니다.

  • 부트스트랩이 재현 가능해집니다. edge가 통째로 날아가도 ArgoCD 하나만으로 apps-root 하나만 배포하면 전부 Green 이 됩니다.

  • 원격지에 백업·용량·디스크 교체 같은 운영 부담을 두지 않습니다.

그래서 edge의 VM 스택은 vmagent 하나로 줄였고(저장·조회·알림 전부 hub로 위임), keycloak·uptime-kuma 같은 stateful한 앱은 제거했습니다. 지금 edge에서 도는 건 블로그·청첩장 같은 무상태 서비스 몇 개와 vmagent뿐입니다.

원칙은 딱 하나, edge에는 PVC를 요구하는 앱을 배포하지 말자

3. 메트릭 파이프라인 — 공인망을 건너는 유일한 트래픽

edge (본가)hub (현재집)scrape 20s공인망 TLS + basic authbasic auth401 차단/insert/*/select/*내부 svc스크랩 타겟kubelet · apiserver ·node-exporter · KSMvmagentexternalLabelscluster=edge · 디스크버퍼 1GiB외부 조회viewer 계정 · basic auth미인증 요청istio ingressgateway쓰기·읽기 공개 엔드포인트(443)vmauth :8427VMUser edge → /insert/* · viewer → /select/*vminsertvmstorage ×4RF2 · synology PVC900GivmselectGrafana · vmalert내부 svc 직결 — vmauth안 탐
메트릭 파이프라인 — 쓰기와 읽기가 전부 vmauth(:8427)라는 한 관문을 지납니다. edge vmagent는 VMUser `edge` 계정으로 /insert/* 만, 외부 조회는 `viewer` 계정으로 /select/* 만 통과할 수 있고, 계정 없는 요청은 401로 끊깁니다. hub 내부 소비자(Grafana·hub vmagent·vmalert)는 클러스터 내부 svc로 직결이라 vmauth를 타지 않습니다. 인증 자격증명은 git에 없고 양쪽 클러스터의 native secret으로만 존재합니다.

edge vmagent는 자기 클러스터의 메트릭들을 cluster=edge 라벨과 함께 hub의 메트릭 수집 엔드포인트로 remote write 를 수행합니다. hub 자신의 vmagent애서 들어오는 메트릭들은 cluster=hub를 답니다. VM Select 혹은 Grafana에서 라벨 별로 두 클러스터의 메트릭을 각각 조회합니다.

이 경로는 인증 없이 공인망을 타게 둘 수는 없어 쓰기·읽기 앞에 vmauth를 뒀습니다.

  • VMAuth 에서 VMUser 계정별 라우팅을 정의합니다. edge 계정은 /insert/*만 vminsert로, viewer 계정은 /select/*만 vmselect로 통과시킵니다. 경로 밖 요청과 미인증 요청은 401.
  • istio VirtualService의 목적지를 vminsert/vmselect가 아닌 vmauth로 전환
  • hub 내부 소비자는 이 관문과 무관합니다. Grafana·vmalert·hub vmagent는 클러스터 내부 svc로 직결이라 vmauth 장애가 나도 hub 관측은 살아 있습니다.

4. GitOps·CI — 사람 손은 앱 repo까지만

GitHubimage pushnewTag 커밋hub/ pulledge/ pull앱 repo개발자 git pushGitHub ActionsDocker Hubmontstrap 3-repoapp-of-apps 정본hub 클러스터apps-root 자동 동기화edge 클러스터apps-root 자동 동기화
GitOps·CI 파이프라인 — 사람 손은 앱 repo push까지만 닿습니다. GitHub Actions가 이미지를 빌드해 Docker Hub에 올리고 montstrap 계열 repo에 태그 커밋을 밀면, 두 클러스터의 apps-root가 각자 자기 디렉토리만 당겨가 수렴합니다.

배포는 세개의 repo로 나누어 관리중입니다.

repo역할
montstrapapp-of-apps 정의. {hub,edge}/apps/*.yaml에 ArgoCD Application 정의, platform/manifests/에 istio·cert-manager 같은 플랫폼 컴포넌트
mont-helm외부 helm chart에 먹일 custom values ($values 멀티소스로 참조)
montstrap-manifestraw manifest 앱 (deployment/service/VS + kustomization)

앱 repo에 push하면 GitHub Actions가 이미지를 빌드해 Docker Hub에 올리고 montstrap 계열 repo의 kustomization newTag(또는 deployment 이미지 태그)에 커밋을 밉니다. 거기서부터는 두 클러스터의 apps-root가 각자 pull해서 수렴합니다. 배포에 사람이 kubectl을 만지는 지점이 없습니다.

apps-root 자신도 {env}/apps/ 디렉토리 안에 들어 있습니다. 자기가 자기를 관리하는 구조라 루트 Application 스펙을 고치는 것도 git push 하나로 끝납니다. 예전엔 이 파일만 수동 apply 전용이었는데, 그 탓에 edge가 두 달치 수정을 못 받고 방치된 적이 있었습니다.

환경 분리는 디렉토리 하나입니다. 같은 repo의 hub/edge/가 각 클러스터의 전체 상태고 두 클러스터는 서로의 존재를 모릅니다 — 접점은 오직 §3의 remote write와 §5의 OIDC뿐입니다.

리네임 후기: 디렉토리 이름을 바꾸는 것 자체는 git mv 두 번이지만 여파는 세 repo의 경로 참조 전부와 앱 repo 12개의 CI 워크플로우까지 닿았습니다. CI가 stage/... 경로를 하드코딩하고 있었기 때문입니다. 이런 리네임은 “git 치환 → 클러스터 apps-root 재적용 → CI 경로 수정”을 한 호흡에 끝내야 합니다. 그러지 않으면 옛 경로를 바라보는 CI가 존재하지 않는 디렉토리에 커밋을 미는 중간 상태가 생깁니다.

5. IdP는 한곳으로

stateless 원칙은 인증에도 적용됩니다. Keycloak은 DB가 필요한 stateful 앱이라 edge에 둘 수 없고 둘 필요도 없어, edge의 ArgoCD를 포함한 인증/인가는 hub의 Keycloak을 OIDC provider로 등록이 되어있습니다.

이렇게 Stateful 한 클러스터와, Stateless 한 클러스터를 각각 구축해 운영을 시작한 홈랩 프로젝트 근황을 남겨봅니다.

읽어주셔서 감사합니다.