다시 정리하면, 지금 비교 대상은 아래 두 가지입니다.
1안. Kubernetes 클러스터 분리
- hot-k8s-cluster
└─ hot AIStor ObjectStore / NVMe pools
- warm-k8s-cluster
└─ warm AIStor ObjectStore / SATA/SSD pools
2안. Kubernetes 클러스터 공용, ObjectStore 분리
- storage-k8s-cluster
├─ namespace: aistor-hot
│ └─ hot AIStor ObjectStore / NVMe pools
└─ namespace: aistor-warm
└─ warm AIStor ObjectStore / SATA/SSD pools
제 최종 판단은 이렇습니다.
단기 구축성과 운영 단순성은 2안이 좋지만, hot tier와 warm tier가 모두 계속 pool 추가로 커질 예정이라면 목표 아키텍처는 1안, 즉 Kubernetes 클러스터 분리가 더 타당합니다.
다만 “당장 별도 K8s 클러스터를 만들 여력이 없다면” 2안으로 시작할 수 있습니다. 이 경우에도 endpoint, DNS, 인증, GitOps, monitoring, replication/tiering 구성을 처음부터 나중에 warm cluster를 떼어낼 수 있게 설계해야 합니다.
| 항목 | 더 유리한 선택 |
|---|---|
| 초기 구축 속도 | 2안: 공용 K8s + ObjectStore 분리 |
| 운영 단순성 | 2안 |
| Hot/Warm 장애반경 분리 | 1안 |
| Cilium/BGP 장애 영향 분리 | 1안 |
| 재활용 warm 장비의 노이즈 격리 | 1안 |
| 향후 hot/warm 각각 pool 추가 확장성 | 1안 |
| 장기 DR/BCP 성격 | 1안 |
| 기존 운영팀 부담 최소화 | 2안 |
| 나중에 500대 이상으로 커질 가능성 | 1안 |
따라서 제 추천은 다음과 같습니다.
권장 목표안:
1안. Hot K8s cluster와 Warm K8s cluster 분리
현실적 단계안:
먼저 2안으로 Warm ObjectStore를 같은 K8s 안에 만들 수는 있음.
단, DNS/LB/BGP/Keycloak/GitOps/backup/monitoring은 나중에 1안으로 분리 가능한 구조로 설계.
현재 규모를 단순 계산하면 이렇습니다.
Hot NVMe:
128 nodes x 20 disks = 2,560 disks
6.8TiB x 2,560 = 약 17,408TiB raw ≒ 17.0PiB raw
Warm SATA/SSD:
170 nodes x 20 disks = 3,400 disks
3.4TiB x 3,400 = 약 11,560TiB raw ≒ 11.3PiB raw
2안을 선택하면 한 Kubernetes 클러스터 안에 storage node만 약 298대, disk/PV 단위는 약 5,960개 이상이 됩니다. Kubernetes 자체는 대형 클러스터 기준으로 5,000 nodes, 150,000 pods, 300,000 containers 같은 상한을 제시하므로 “숫자상 불가능”한 것은 아닙니다. 하지만 공식 기준은 가능 범위일 뿐이고, 실제 운영에서는 etcd/API server watch 수, Cilium agent/operator, DirectPV, Prometheus, event, controller reconcile 부하가 훨씬 먼저 체감됩니다. (Kubernetes)
특히 앞으로 hot도 pool 추가, warm도 pool 추가가 반복된다면 2안은 점점 아래 구조가 됩니다.
하나의 K8s control plane
하나의 Cilium control plane
하나의 LB IPAM/BGP control plane
하나의 DirectPV/CSI/Operator 계층
하나의 cert-manager/admission webhook 계층
├─ hot objectstore 계속 확장
└─ warm objectstore 계속 확장
반면 1안은 이렇게 됩니다.
hot-k8s-cluster
└─ hot objectstore만 확장
warm-k8s-cluster
└─ warm objectstore만 확장
이 차이가 장기적으로 큽니다. pool 추가 작업 자체는 AIStor ObjectStore 단위로 분리되지만, Kubernetes/Cilium/CSI/Operator의 이벤트와 장애반경은 2안에서 계속 공유됩니다.
hot-k8s-cluster
└─ namespace: aistor-hot
└─ hot ObjectStore
warm-k8s-cluster
└─ namespace: aistor-warm
└─ warm ObjectStore
첫째, hot tier 보호가 가장 확실합니다.
warm 장비는 재활용 장비이고 disk size도 다르며 pool도 복수로 나눠야 합니다. 이런 환경에서는 node flap, disk failure, DirectPV reconcile, Cilium endpoint churn, event 폭증, SMART 경고, heal 부하가 hot보다 더 자주 발생할 가능성이 큽니다. 1안은 이런 노이즈가 hot Kubernetes control plane에 들어오지 않습니다.
둘째, Cilium/BGP 장애반경이 분리됩니다.
Cilium BGP Control Plane에서 Cilium Operator가 내려가면 BGP control plane provisioning, PodCIDR allocation, LB-IPAM allocation, Service VIP route advertisement 변경이 멈출 수 있습니다. 기존 광고된 경로가 모두 즉시 사라진다는 뜻은 아니지만, 변경·복구·신규 광고가 막히는 것은 운영상 큽니다. 1안은 warm 쪽 BGP/Operator 이슈가 hot 쪽 Cilium control plane에 직접 영향을 주지 않게 만듭니다. (Cilium Docs)
셋째, hot/warm 각각의 확장 계획을 독립적으로 가져갈 수 있습니다.
AIStor는 Kubernetes에서 pool을 추가할 때 objectStore.pools 배열을 수정하고 Helm upgrade로 확장합니다. 이 작업은 해당 ObjectStore 단위의 변경이지만, 2안에서는 같은 Kubernetes API server, scheduler, CSI, Cilium 위에서 동시에 누적됩니다. 1안은 hot 증설과 warm 증설의 변경 창, 검증, rollback, 장애 대응을 완전히 분리할 수 있습니다. (MinIO AIStor Documentation)
넷째, upgrade 전략이 훨씬 안전합니다.
hot은 안정성을 우선하고, warm은 상대적으로 먼저 업그레이드하거나 패치 검증 대상으로 삼을 수 있습니다. Cilium, Kubernetes, AIStor Operator, DirectPV, cert-manager, monitoring agent를 각각 다른 일정으로 검증할 수 있습니다.
다섯째, DR/BCP 의미가 더 분명합니다.
ObjectStore가 분리되어도 같은 K8s cluster면 API server, etcd, Cilium, cluster DNS, cert-manager, admission webhook 장애는 공유됩니다. 중요 데이터 보호를 위해 replication을 고려한다면, replica가 같은 Kubernetes 장애 도메인 안에 있는 것보다 별도 K8s 장애 도메인에 있는 것이 훨씬 설득력이 있습니다.
첫째, 초기 구축과 운영 항목이 늘어납니다.
Kubespray inventory, Cilium 설치, BGP peering, DirectPV, AIStor Operator, cert-manager, monitoring, logging, ArgoCD, NetworkPolicy, Secret 관리가 한 벌 더 생깁니다.
둘째, cross-cluster 네트워크 설계가 필요합니다.
Hot → Warm replication, Hot → Warm ILM transition 트래픽이 cluster boundary를 넘어갑니다. Cilium ClusterMesh를 쓸 수도 있고, 단순히 warm S3 endpoint를 BGP/LB로 노출해 hot에서 접근하게 할 수도 있습니다. ClusterMesh를 쓴다면 PodCIDR 충돌 방지, native routing CIDR, cluster ID/name, cross-cluster connectivity 같은 요건을 맞춰야 합니다. (Cilium Docs)
셋째, Keycloak/TLS/KMS/정책 동기화가 더 복잡합니다.
Hot과 warm이 별도 K8s이므로 CA, cert-manager issuer, Keycloak client, OIDC/LDAP 설정, KMS/KES/Vault 접근 정책을 양쪽에서 맞춰야 합니다.
storage-k8s-cluster
├─ namespace: aistor-hot
│ └─ hot ObjectStore
└─ namespace: aistor-warm
└─ warm ObjectStore
첫째, 구축이 빠릅니다.
기존 Kubernetes, Cilium BGP, Keycloak, monitoring, GitOps, image registry, certificate chain을 그대로 활용할 수 있습니다.
둘째, network path가 단순합니다.
Hot과 warm이 같은 K8s 안에 있으므로 Service, DNS, NetworkPolicy, LB IPAM, BGP advertisement를 한 클러스터 안에서 관리할 수 있습니다. Cilium LB IPAM은 LoadBalancer Service에 IP를 할당하고, BGP Control Plane이 그 IP를 외부로 광고하는 구조로 사용할 수 있습니다. (Cilium Docs)
셋째, 운영팀 입장에서는 day-1/day-2 부담이 낮습니다.
ArgoCD app, Helm release, monitoring dashboard, alert rule, log pipeline, backup SOP를 한 클러스터 안에서 정리할 수 있습니다.
넷째, AIStor 관점의 hot/warm 분리는 충분히 됩니다.
Hot ObjectStore와 Warm ObjectStore가 별도라면, 기존 hot NVMe ObjectStore에 SATA/SSD pool을 섞는 문제는 없습니다. ILM tiering도 “hot NVMe deployment → warm SSD deployment” 시나리오에 맞습니다. AIStor 문서는 primary bucket에서 remote AIStor deployment bucket으로 transition하는 절차를 설명하며, hot NVMe에서 warm SSD로 tiering하는 cost-management 전략을 예시로 듭니다. (MinIO AIStor Documentation)
첫째, Kubernetes 장애반경은 공유됩니다.
Hot ObjectStore와 Warm ObjectStore가 namespace로 분리되어도 API server, etcd, scheduler, kubelet config, Cilium, CoreDNS, cert-manager, admission webhook, CSI/DirectPV, monitoring stack은 공유될 수 있습니다.
둘째, warm 장비의 노이즈가 hot 운영면에 영향을 줄 수 있습니다.
재활용 SATA/SSD node 170대가 추가되면 node condition 변화, disk 장애, PVC/PV event, Cilium endpoint 변화, DirectPV reconcile, SMART monitoring, log/metric cardinality가 증가합니다. S3 data path가 즉시 깨진다는 뜻은 아니지만, control plane과 운영 관측면에는 영향을 줍니다.
셋째, Cilium/BGP upgrade와 장애가 hot/warm 공통 이벤트가 됩니다.
Hot과 warm의 Service VIP, BGP advertisement, LB IPAM이 같은 Cilium control plane 아래 있습니다. Cilium Operator HA, BGP policy 분리, LB IP pool 분리, route/nexthop limit 검증을 잘 해도 “같은 장애 도메인”이라는 사실은 바뀌지 않습니다.
넷째, 장기 확장 시 한 클러스터가 너무 커질 수 있습니다.
현재만 해도 storage node 약 298대입니다. 여기에 hot NVMe pool 추가, warm SATA/SSD pool 추가가 반복되면 400대, 500대 이상으로 커질 수 있습니다. Kubernetes 공식 상한과 별개로, storage 전용 대형 클러스터는 CSI/PV/watch/event/metric 때문에 운영 난도가 빠르게 올라갑니다.
AIStor는 pool 단위로 용량을 확장할 수 있지만, 몇 가지 중요한 특성이 있습니다.
첫째, 새 pool을 추가해도 기존 object가 자동 rebalance되지는 않습니다. 새 write는 pool별 free space 비율에 따라 배치됩니다. 즉 hot이든 warm이든 새 pool 추가 후에는 새 pool 쪽으로 신규 write가 더 많이 몰릴 수 있습니다. (MinIO AIStor Documentation)
둘째, AIStor는 pool 내부 hardware/software 구성을 유사하게 맞추는 것을 권장합니다. 특히 pool-level stripe size가 섞이면 pool별 read/write quorum 특성과 object SLA가 달라질 수 있습니다. (MinIO AIStor Documentation)
셋째, erasure set의 개수와 크기는 server pool 초기화 시 결정되고 이후 변경할 수 없습니다. 따라서 warm pool을 여러 개 만들 때도 “일단 붙이고 나중에 바꾸자”가 어렵습니다. (MinIO AIStor Documentation)
이 관점에서 보면 1안과 2안은 아래처럼 갈립니다.
| 확장 항목 | 1안: K8s 분리 | 2안: K8s 공용/ObjectStore 분리 |
|---|---|---|
| Hot pool 추가 | hot K8s만 영향 | 공용 K8s control plane 영향 |
| Warm pool 추가 | warm K8s만 영향 | 공용 K8s control plane 영향 |
| Warm node 장애/노후 이슈 | warm cluster 내부로 제한 | 공용 cluster event/control plane에 유입 |
| Hot/Warm 동시 확장 | 각 cluster에서 독립 작업 가능 | 같은 API/CSI/Cilium에서 동시 변경 위험 |
| Cilium/BGP route 변화 | hot/warm 별도 | 하나의 Cilium/BGP control plane에 누적 |
| Operator/CRD 변경 | cluster별 분리 | CRD/API 계층 공유 |
| 장기 node 수 증가 | cluster별 분산 | 하나의 대형 storage cluster로 비대화 |
| 장애 분석 | 영역이 명확 | hot/warm 원인 분리 어려워질 수 있음 |
확장성이 단순히 “노드를 더 붙일 수 있느냐”라면 둘 다 가능합니다.
하지만 운영 확장성, 장애반경, 변경 안정성까지 포함하면 1안이 더 좋습니다.
여기서 중요한 점은 ILM transition과 replication은 목적이 다르다는 것입니다.
AIStor object tiering은 object data를 secondary tier로 옮기고, metadata는 primary tier에 남깁니다. AIStor 문서는 tiered object의 metadata가 primary에 남고 data가 secondary에 있으며, warm/cold remote tier의 data는 source metadata와 강하게 연결되어 있다고 설명합니다. 즉 tiering은 hot 용량 절감에는 좋지만, 그 자체가 DR/backup은 아닙니다. (MinIO AIStor Documentation)
반대로 bucket replication은 보호 목적에 가깝습니다. AIStor bucket replication은 versioning을 요구하고, source/destination ObjectStore version 일치와 TLS 사용을 권장합니다. 또한 replication은 source write 이후 비동기 또는 동기 방식으로 destination에 object를 복제할 수 있습니다. (MinIO AIStor Documentation)
따라서 구조는 이렇게 나눠야 합니다.
Hot 용량 절감:
- Hot → Warm ILM transition
중요 데이터 보호:
- Hot → Warm bucket replication
휴지통/실수 삭제 복구:
- versioning + noncurrent lifecycle
삭제 불가 보호:
- object lock / retention
이때 1안은 replication target이 Kubernetes 장애 도메인까지 분리되므로 보호 의미가 더 강합니다.
2안은 ObjectStore 장애에는 대비되지만, Kubernetes/Cilium/control plane 장애까지는 같이 맞을 수 있습니다.
2안도 틀린 설계는 아닙니다. 다만 아래 조건을 반드시 지켜야 합니다.
storage-k8s-cluster
├─ hot-nvme-nodes
│ ├─ label: storage-tier=hot
│ ├─ taint: storage-tier=hot:NoSchedule
│ └─ hot ObjectStore만 배치
└─ warm-sata-nodes
├─ label: storage-tier=warm
├─ taint: storage-tier=warm:NoSchedule
└─ warm ObjectStore만 배치
그리고 아래를 분리해야 합니다.
| 항목 | 분리 권장 |
|---|---|
| namespace | aistor-hot, aistor-warm |
| node label/taint | hot/warm 분리 |
| StorageClass 또는 DirectPV drive selector | hot/warm 분리 |
| AIStor ObjectStore Helm release | hot/warm 분리 |
| Service/LB IP | s3-hot, s3-warm 분리 |
| CiliumLoadBalancerIPPool | hot/warm 분리 |
| BGP advertisement policy | hot/warm 분리 |
| Prometheus scrape/alert | hot/warm label 분리 |
| root/access key secret | hot/warm 분리 |
| replication user | 최소 권한으로 분리 |
| GitOps app | hot/warm app 분리 |
AIStor Operator는 WATCHED_NAMESPACE를 지정해 특정 namespace만 관리하도록 제한할 수 있고, 여러 operator instance가 서로 다른 namespace 집합을 관리하도록 구성할 수 있습니다. 2안을 쓴다면 최소한 hot/warm operator 관리 범위를 분리하는 방식을 검토하는 것이 좋습니다. (MinIO AIStor Documentation)
2안으로 시작하더라도 아래처럼 설계해야 합니다.
Hot에서 warm tier endpoint를 이렇게 등록:
https://warm-aistor.aistor-warm.svc.cluster.local
이렇게 하면 나중에 warm을 별도 K8s cluster로 떼어낼 때 ILM/replication endpoint 변경이 매우 부담스러워집니다.
Hot endpoint:
https://s3-hot.company.internal
Warm endpoint:
https://s3-warm.company.internal
처음에는 s3-warm.company.internal이 같은 K8s cluster의 warm Service/LB를 가리키게 합니다. 나중에 warm을 별도 cluster로 이전하면 DNS/BGP/LB만 바꾸는 방식으로 갑니다.
다만 ILM transition된 object는 source metadata와 remote data가 강하게 연결되어 있으므로, warm cluster를 사후 이전할 때는 단순 rsync나 임의 이동으로 처리하면 안 됩니다. AIStor 문서도 transitioned data는 source metadata와 연결되어 있으며, remote data를 임의 수정하면 object data 손실이 발생할 수 있다고 경고합니다. (MinIO AIStor Documentation)
즉, 나중 분리를 고려한다면 처음부터 안정적인 FQDN, bucket, prefix, TLS, credential naming을 장기 고정값으로 잡아야 합니다.
아래 중 3개 이상이면 1안이 맞습니다.
- warm 장비가 재활용 장비라 장애율/노드 flap 가능성이 있다.
- warm node가 170대에서 더 늘어날 가능성이 크다.
- hot tier도 별도 NVMe pool 추가가 계속 필요하다.
- hot S3는 분석 플랫폼의 핵심 서비스라 장애반경을 최소화해야 한다.
- Cilium/BGP upgrade나 장애가 hot/warm에 동시에 영향 주면 안 된다.
- replication을 단순 복사본이 아니라 DR/BCP 근거로 삼고 싶다.
- 운영 조직이 hot/warm 변경 window를 분리하고 싶다.
- 나중에 warm을 다른 랙/망/상면/사이트로 옮길 수 있다.
현재 설명만 보면 여기에 꽤 많이 해당합니다. 그래서 장기 목표는 1안이 낫습니다.
아래 조건이면 2안도 현실적인 1차안입니다.
- 현재 storage K8s control plane이 300~500 storage nodes 규모를 감당하도록 설계되어 있다.
- Cilium BGP/LB IPAM/Operator HA가 충분히 검증되어 있다.
- warm node 장애가 잦지 않을 것으로 예상된다.
- hot/warm node taint/label/DirectPV/StorageClass 분리를 확실히 할 수 있다.
- 당장 별도 K8s cluster 구축보다 빠른 용량 확보가 중요하다.
- replication/ILM 초기 적용 범위가 제한적이다.
- 나중에 warm cluster를 분리할 수 있도록 DNS/FQDN 기반으로 설계한다.
[hot-storage-k8s]
- NVMe nodes 128대 + 향후 NVMe pool 추가
- Cilium BGP / LB IPAM: hot 전용
- AIStor ObjectStore: hot
- endpoint: s3-hot.company.internal
- active analytics / Iceberg metadata / recent data
│
│ 1) bucket replication: 중요 데이터 보호
│ 2) ILM transition: 오래된 데이터 이동
▼
[warm-storage-k8s]
- SATA/SSD 재활용 nodes 170대 + 향후 warm pool 추가
- Cilium BGP / LB IPAM: warm 전용
- AIStor ObjectStore: warm
- endpoint: s3-warm.company.internal
- replica / noncurrent version / archive / tiered data
[storage-k8s: 현재 공용]
├─ aistor-hot namespace
│ └─ hot ObjectStore
│ └─ endpoint: s3-hot.company.internal
└─ aistor-warm namespace
└─ warm ObjectStore
└─ endpoint: s3-warm.company.internal
단, warm을 나중에 별도 k8s로 분리할 수 있게:
- s3-warm.company.internal 사용
- cluster.local endpoint 사용 금지
- hot/warm LB IP pool 분리
- hot/warm BGP policy 분리
- hot/warm GitOps app 분리
- hot/warm operator watched namespace 분리 검토
지금 당장 운영 부담과 구축 속도를 보면 2안이 매력적이지만, hot/warm 모두 앞으로 pool 추가가 필요하고 warm이 재활용 장비 기반이라면 장기적으로는 1안, 즉 Kubernetes 클러스터 분리가 더 안전합니다.
다만 처음부터 1안을 만들 여력이 부족하다면, 2안으로 시작하되 “warm은 언젠가 별도 cluster로 분리될 수 있다”는 전제로 endpoint/DNS/BGP/GitOps/Operator/DirectPV를 설계하는 것이 가장 현실적인 절충안입니다.