k8s 환경에서의 테스트 추가 고려사항
K8s + Cilium ClusterMesh 조합이면, 지금까지 bare-metal에서 검증한 걸 "그대로 믿으면 안 되는" 항목들이 꽤 생김. 단순히 새 테스트를 추가하는 것보다, 컨테이너화/오버레이 네트워크가 기존 검증 결과를 몰래 깨뜨리지 않는지 재검증하는 항목과 K8s+ClusterMesh 고유 신규 항목을 나눠서 보는 게 정확함.
Stage1에서 NCCL All-Reduce로 NVLink 대역폭을 검증했는데, K8s Pod 내부에서 반드시 재검증 필요. 현재 Cilium이 Native Routing을 사용하는 환경이어서 Pod의 eth0는 veth 기반이지만 Cilium eBPF와 Linux native routing을 거쳐 물리 NIC으로 전달됨.
RDMA가 없는 상황에서는 TCP 경로에 추가 오버헤드가 조금이라도 붙으면 그대로 성능 손실로 직결됨.
지금까지의 stage3a6(포화점), stage5b(부하테스트)는 "점진적으로 동시성을 올리는" 패턴이었는데, 실제 이 엔진들의 트래픽은 성격이 다름.
| 엔진 | 실제 패턴 | 추가로 봐야 할 것 |
|---|---|---|
| Spark | 수백 개 executor가 동시에 폭발적으로 추론 요청을 쏨(스텝 함수형 버스트) | 점진적 동시성 램프업이 아니라 즉각적 스파이크(예: 0→256 동시성이 수 초 내) 테스트, LiteLLM/Envoy 레벨 커넥션 풀 고갈 여부 |
| Trino/StarRocks | 쿼리 페더레이션 중 GPU 노드로의 소수의 긴 요청(UDF 스타일) | 쿼리 타임아웃과 vLLM 응답시간 불일치 시 커넥션 누수 여부 |
| JupyterLab | 사람이 쓰는 인터랙티브 — 낮은 동시성, 매우 불규칙, 장시간 유휴 후 갑작스런 요청 | Stage1에서 짚었던 "유휴 후 첫 요청 지연(warm-up latency)"이 K8s 파드 레벨에서도 재현되는지 — 특히 GPU가 아니라 파드 자체가 스케일다운되어 있다가 콜드 스타트하는 경우(오토스케일링 쓴다면) 지연이 수십 초까지 갈 수 있음 |
stage3a6(점진적 램프업)와 별개로, 순간적으로 목표 동시성에 도달하는 패턴 전용 스크립트.STORAGE_NODE_IP 고정 IP로 접근했는데, ClusterMesh에서는 Global Service(같은 이름의 서비스가 여러 클러스터에 존재할 때 자동 로드밸런싱/장애조치)로 접근하게 됨. 이 서비스 디스커버리 자체의 지연과, 실제로 "가까운"(같은 클러스터) MinIO 백엔드를 우선 선택하는지(Cilium의 로컬리티 우선순위 설정) 확인 필요.initialDelaySeconds/startupProbe 설정 검증 필수firewalld 규칙이었는데, K8s에서는 CiliumNetworkPolicy/CiliumClusterwideNetworkPolicy로 전환 — Compute 클러스터의 어떤 워크로드 아이덴티티(namespace/서비스어카운트)만 GPU 서비스에 접근 가능한지를 IP 기반이 아니라 아이덴티티 기반으로 재설계·검증| 우선순위 | 영역 | 테스트 시나리오 | 사전 조건 및 필수 설정 | 핵심 측정 지표 | 합격 기준 (Pass Criteria) |
|---|---|---|---|---|---|
| P0 (Critical) | 네트워크 기반 | Host vs hostNetwork vs Pod veth TCP 성능 및 RTT 비교 | MTU 9000 통일(스위치·노드·Pod veth); Cilium Native Routing 및 eBPF Host Routing 활성화 | iperf3 단일·멀티 Throughput; ping·sockperf RTT; CPU softirq 점유율 | Bare-metal 대비 처리량 손실률 5% 이하; Pod 간 RTT 증가 0.1ms 이하 |
| P0 (Critical) | GPU 통신 | Pod 환경 NCCL All-Reduce 대역폭 및 인터페이스 바인딩 검증 | NCCL_SOCKET_IFNAME 물리 NIC 지정; Pod net.ipv4.tcp_rmem/wmem 튜닝; NVIDIA Operator 및 Topology Manager 구성 | Bus Bandwidth (GB/s); NCCL 커널 로그 인터페이스 확인; NUMA 소켓 간 트래픽 여부 | 단일 노드 8-GPU: Bare-metal 대비 NVLink 98% 이상 유지; 멀티 노드: Bare-metal 대비 TCP 90% 이상 유지 |
| P0 (Critical) | 수명주기/안정성 | 대형 모델(R1 등) Pod 콜드 스타트 및 Startup/Readiness 프로브 오탐 검증 | startupProbe 분리(failureThreshold 넉넉히 설정); Ingress/Service 라우팅 연계 | 모델 가중치 메모리 적재 완료 시간; Probe 실패로 인한 컨테이너 비정상 재시작 횟수 | 초기 모델 로딩 중 비정상 재시작 0회; 실제 서빙 준비 완료 전 트래픽 유입 0건 |
| P1 (High) | 서비스 디스커버리 | ClusterMesh Global Service 경유 MinIO Cold Load 및 로컬리티 라우팅 검증 | Cilium ClusterMesh 피어링 정상 상태; service.kubernetes.io/topology-mode: Auto 적용 | MinIO 읽기·쓰기 Throughput (MB/s); 클러스터 간 Egress/Ingress 트래픽 발생 비율 | 동일 클러스터 내 백엔드로 100% 로컬 라우팅 유지; 고정 IP 직접 접근 대비 전송 속도 저하 3% 이하 |
| P1 (High) | 워크로드 부하 | Spark 대규모 동시 요청(스텝 버스트: 0→256) 급증 시 TCP 커넥션 처리 | somaxconn 및 tcp_max_syn_backlog 상향; Envoy/LiteLLM 연결 풀 설정 완료 | SYN Drop 횟수 (netstat -s); Conntrack 테이블 사용률; TTFT P95/P99 레이턴시 | SYN 드롭 및 커넥션 거부 0건; Conntrack 테이블 포화율 70% 이하 |
| P1 (High) | 회복탄력성 | GPU 워커 노드 유지보수(Drain/Cordon) 시 Graceful Shutdown 및 PDB 동작 | preStop 훅(5~10초 sleep); PodDisruptionBudget(minAvailable) 설정 | 처리 중이던 In-flight 요청 실패율; 엔드포인트 슬라이스 동기화 지연 | 노드 드레인 시 처리 중인 요청의 502/504 에러 0건; PDB 위반 없는 롤링 퇴거 확인 |
| P2 (Medium) | 라우팅 수렴 | ClusterMesh 장애·단절 시뮬레이션 및 BGP 라우트 수렴 시간 측정 | BGP 라우팅 피어링 및 BFD 연동; 장애 주입 툴 또는 인터페이스 down 스크립트 | BGP Route Convergence Time (초); 클러스터 단절 중 로컬 Pod 간 요청 성공률 | BGP 라우트 재수렴 3초 이하 (BFD 적용 시 1초 이하); 원격 클러스터 단절 시 로컬 트래픽 영향 0% |
| P2 (Medium) | 노이즈 네이버 | Spark 대용량 셔플·분산 쿼리와 GPU 통신 간 네트워크 경합 완화 | Cilium Bandwidth Manager 활성화; Linux 커널 FQ(Fair Queueing) 스케줄러 적용 | 백그라운드 셔플 중 vLLM 토큰 생성 속도 저하율; 네트워크 패킷 지연 편차(Jitter) | 대역폭 포화 상태에서도 GPU 외부 통신 Throughput 저하 15% 이내 방어 |
| P2 (Medium) | 보안/관측성 | CiliumNetworkPolicy 적용 및 Hubble 기반 클러스터 간 트래픽 플로우 추적 | Hubble Relay 및 UI/CLI 구동; Workload Identity(Namespace/SA) 기반 정책 배포 | eBPF 맵 엔트리 크기 및 메모리 점유율; 정책 파싱으로 인한 데이터 플레인 레이턴시 | 정책 적용 전후 RTT 차이 오차범위(0.05ms 이하) 유지; 비인가 접근 즉각 DROP 및 감사 로그 적재 |
전체적으로 매우 좋은 구성입니다. 특히 “bare-metal 테스트를 K8s에서 반복한다”와 “K8s/ClusterMesh에서만 생기는 신규 failure mode를 별도로 검증한다”를 분리한 것이 맞습니다.
다만 실무 관점에서는 몇 군데 중요한 수정/보강이 필요합니다. 특히 B의 ClusterMesh 경로, E의 Global Service, C의 GPU topology, 그리고 I의 네트워크 경합은 조금 더 정확하게 정의하는 것이 좋습니다.
제가 보면 현재 문서는 약 85~90% 완성된 상태이고, 아래처럼 다듬으면 실제 K8s validation plan으로 바로 사용할 수 있습니다.
| 영역 | 평가 | 수정 필요성 |
|---|---|---|
| A. NCCL 재검증 | ★★★★★ | 거의 그대로 사용 가능 |
| B. ClusterMesh | ★★★★☆ | Native routing/ClusterMesh 경로 표현 보강 |
| C. GPU topology | ★★★★☆ | Topology Manager에 대한 표현 수정 |
| D. 실제 workload | ★★★★☆ | 일부 workload 특성 재검토 |
| E. AIStor | ★★★★☆ | Global Service와 AIStor 고정 IP를 분리해서 정의 |
| F. Resilience | ★★★★★ | 매우 중요 |
| G. Observability | ★★★★☆ | federation보다 correlation이 더 중요 |
| H. Security | ★★★★★ | 반드시 포함 |
| I. Resource contention | ★★★★★ | 매우 중요한 신규 항목 |
그리고 하나 더 추가하고 싶습니다.
J. Kubernetes scheduling / lifecycle / CPU-memory overhead
현재 문서에는 GPU와 network는 잘 들어가 있지만, K8s가 GPU inference 성능에 추가하는 CPU, memory, IRQ, cgroup, NUMA, eviction 등의 영향이 별도 항목으로 빠져 있습니다.
이 부분은 그대로 가져가도 됩니다.
다만 문장을 하나 수정하는 것을 권합니다.
현재:
NCCL_SOCKET_IFNAME이 올바른 물리 NIC을 가리키는지
이렇게 쓰면 Pod 내부에서 물리 NIC 이름을 지정해야 한다는 의미로 오해할 수 있습니다.
일반 Pod에서는 Pod namespace 안에 물리 NIC이 직접 보이지 않고 보통 eth0가 보입니다.
따라서:
NCCL이 의도한 Pod interface/IP 경로를 선택하는지 확인하고, hostNetwork/일반 Pod에서 실제 물리 NIC으로 연결되는 경로를 검증한다.
가 더 정확합니다.
예를 들어:
Pod
eth0
│
▼
veth
│
▼
Cilium eBPF
│
▼
Linux routing
│
▼
Intel E810
Native routing은 encapsulation을 하지 않고 Linux routing을 이용합니다. :chatgpt-content-reference{index="0"}
그리고 ClusterMesh에서도 cross-cluster Pod-to-Pod traffic은 별도의 proxy/gateway를 반드시 거치는 구조가 아닙니다. Cilium 문서도 노드 간, 클러스터 간 Pod traffic이 직접 forwarding된다고 설명합니다. :chatgpt-content-reference{index="1"}
따라서 A는:
Bare Metal
↓
hostNetwork Pod
↓
Cilium Pod
비교가 매우 좋습니다.
여기서 가장 중요한 것은:
"ClusterMesh라서 TCP 경로에 추가 오버헤드가 붙는다"
라고 일반화하면 안 된다는 것입니다.
현재 구성:
Cilium
routing-mode=native
BGP
ECMP
ClusterMesh
이라면:
Pod A
↓
Cilium
↓
native routing
↓
Node NIC
↓
network
↓
Node NIC
↓
native routing
↓
Cilium
↓
Pod B
형태가 될 수 있습니다.
Native routing은 기본적으로 encapsulation을 하지 않습니다. :chatgpt-content-reference{index="2"}
따라서 B에서는 "ClusterMesh overhead"를 하나의 숫자로 측정하지 말고 경로별로 분리하는 것이 좋습니다.
| Test | Source → Destination | 목적 |
|---|---|---|
| B1 | Host → Host | 물리 네트워크 baseline |
| B2 | Pod → Pod, same node | Cilium local datapath |
| B3 | Pod → Pod, different node, same cluster | Cilium + native routing |
| B4 | Pod → Pod, different cluster | ClusterMesh + native routing |
| B5 | hostNetwork → hostNetwork | Pod/veth 제거 baseline |
| B6 | Pod → Pod + ECMP | ECMP path 확인 |
이렇게 하면:
B1 → B2
에서 Cilium 자체 비용,
B2 → B3
에서 node routing 비용,
B3 → B4
에서 ClusterMesh cross-cluster 비용
을 분리할 수 있습니다.
단순 throughput뿐 아니라:
RTT
p50
p95
p99
jitter
packet loss
retransmission
을 봐야 합니다.
NCCL에서는 평균 bandwidth가 괜찮아도 tail latency / retransmission이 증가하면 collective performance가 크게 영향을 받을 수 있기 때문입니다.
이건 유지하세요.
다만:
수 초 vs 수십 초
처럼 고정된 기대치를 쓰기보다는 실제 환경에서 측정하는 게 좋습니다.
예:
T0 node down
T1 BGP route withdrawn
T2 Cilium route update
T3 ECMP table update
T4 traffic recovery
그리고 다음을 측정합니다.
Recovery Time
Packet Loss Duration
Connection Reset
Existing TCP session survival
New TCP connection recovery
특히 inference에서는:
새로운 요청이 복구되는 시간
뿐 아니라
이미 진행 중인 inference 요청이 살아남는가
가 중요합니다.
현재 문장:
NVIDIA GPU Operator + Node Feature Discovery + (필요시) Topology Manager
방향은 맞습니다.
하지만 Topology Manager가 "8 GPU가 같은 NVSwitch domain인지 보장하는 기능"이라고 이해하면 안 됩니다.
Topology Manager는 NUMA topology alignment 같은 리소스 할당 정합성에 중요한 역할을 하지만, GPU topology 자체를 magically 최적화해주는 것은 아닙니다.
따라서 실제 검증은:
nvidia-smi topo -m
와 Kubernetes에서 할당된 GPU ID를 연결해서 확인하는 방식이 좋습니다.
예:
Pod
├─ GPU0
├─ GPU1
├─ GPU2
...
└─ GPU7
↓
nvidia-smi topo -m
GPU0 ↔ GPU1 : NV#
GPU0 ↔ GPU2 : NV#
...
그리고 TP=8에서는 GPU allocation 결과와 실제 NCCL topology를 같이 확인해야 합니다.
GPU Operator는 Kubernetes에서 GPU device plugin, GFD, DCGM 등 GPU 관련 구성요소를 관리합니다. :chatgpt-content-reference{index="3"}
이것도 맞습니다.
다만 현재 B300 inference benchmark가 목적이라면 저는 문서에:
MIG 사용 여부를 테스트 시작 전에 고정한다.
라고 명시하는 것을 추천합니다.
MIG configuration은 GPU workload 자체를 중지시키는 reconfiguration이 될 수 있으므로 benchmark 중간에 변경하면 안 됩니다. NVIDIA GPU Operator의 MIG Manager도 configuration 변경 시 GPU workload와 관련 operator component를 중지시키는 절차를 수행합니다. :chatgpt-content-reference{index="4"}
여기서는 Spark에 대한 표현을 약간 수정하고 싶습니다.
Spark가 수백 개 executor가 동시에 추론 요청을 쏜다
이것은 특정 Spark inference architecture에서는 맞지만 Spark 일반적인 특성이라고 정의하면 너무 강합니다.
더 정확하게:
Spark-based batch inference에서는 executor/task scheduling에 따라 요청이 짧은 시간에 집중되는 burst pattern이 발생할 수 있다.
정도가 좋습니다.
그리고 D에서 제가 하나 추가하고 싶은 것이 있습니다.
입니다.
단순:
0 → 256 concurrency
만 보는 것보다:
0
↓
256 burst
↓
queue 증가
↓
GPU saturation
↓
request completion
↓
0
전체 lifecycle을 측정해야 합니다.
특히:
을 같이 봐야 합니다.
현재:
ClusterMesh에서는 Global Service로 접근하게 됨.
이건 항상 그런 것은 아닙니다.
Global Service를 사용하도록 구성했을 경우에 그렇습니다.
Cilium ClusterMesh는 Global Service와 MCS-API 두 가지 방식으로 cross-cluster service discovery/load-balancing을 지원합니다. :chatgpt-content-reference{index="5"}
따라서:
AIStor fixed IP
와
AIStor ClusterIP
와
AIStor Global Service
를 서로 다른 테스트 케이스로 보는 것이 좋습니다.
| Test | 접근 방식 |
|---|---|
| E1 | Pod → AIStor local ClusterIP |
| E2 | Pod → AIStor remote ClusterIP/endpoint |
| E3 | Pod → Global Service, local preferred |
| E4 | Pod → Global Service, remote preferred |
| E5 | Global Service + local backend 장애 |
| E6 | Global Service + cluster 장애 |
Cilium은 Global Service에 대해 service.cilium.io/affinity=local을 사용해서 local endpoint를 우선하고 local endpoint가 없거나 unhealthy할 때 remote endpoint를 사용할 수 있습니다. :chatgpt-content-reference{index="6"}
따라서 사용자 환경에서 AIStor 모델 로딩을 생각하면:
Inference Pod
│
▼
AIStor Global Service
│
├── local AIStor ← preferred
│
└── remote AIStor
이 구조가 실제로 의도대로 동작하는지 확인하는 것이 중요합니다.
이 부분은 반드시 유지하겠습니다.
특히 사용자 환경에서는:
DeepSeek-R1
large model
long loading time
이 있기 때문에 startupProbe와 readinessProbe를 별도 검증해야 합니다.
여기서 중요한 것은:
container started
≠
model loaded
≠
ready to serve
입니다.
따라서 최소한:
Pod Scheduled
↓
Container Started
↓
Model Loading
↓
Weights Loaded
↓
CUDA/NCCL initialized
↓
Warm-up completed
↓
Ready
각 timestamp를 수집하는 것이 좋습니다.
현재:
Prometheus/Grafana federation할지 별도 유지할지
이건 운영 설계 문제이고 테스트 항목에서는 조금 후순위입니다.
오히려 validation에서 중요한 것은 cross-layer correlation입니다.
예:
Request latency ↑
│
├─ vLLM queue time ↑
│
├─ GPU utilization ↑
│
├─ Cilium drops ↑ ?
│
├─ TCP retransmission ↑ ?
│
├─ NIC utilization ↑ ?
│
└─ AIStor latency ↑ ?
즉 하나의 테스트 ID에:
vLLM
GPU/DCGM
Cilium
Hubble
Node exporter
NIC
Prometheus
AIStor
의 timestamp-aligned metric을 남기는 것이 더 중요합니다.
Hubble은 이 부분에 매우 적합합니다.
이것도 아주 좋습니다.
특히 사용자 환경은:
Compute Cluster
↓
Gateway
↓
LLM Router
↓
GPU Cluster
구조를 고려하고 있기 때문에 단순 IP allowlist보다:
namespace
service account
Cilium identity
기반 접근 제어를 테스트해야 합니다.
예를 들어:
spark namespace
└── inference SA → allowed
jupyter namespace
└── user SA → allowed
random namespace
└── default SA → denied
그리고 반드시:
same-cluster
cross-cluster
둘 다 테스트해야 합니다.
ClusterMesh에서는 연결된 클러스터가 하나의 trust domain을 형성하므로, 보안 설계에서도 이 점을 별도로 고려해야 합니다. :chatgpt-content-reference{index="7"}
이 부분은 아주 중요합니다.
특히 사용자 환경에서는:
GPU inference
+
AIStor
+
Spark shuffle
+
StarRocks
+
Trino
가 동일한 physical network fabric을 공유할 가능성이 있기 때문입니다.
예를 들어:
Spark shuffle
████████████████████████ 40Gbps
AIStor model load
████████ 10Gbps
NCCL TCP
██ 2Gbps
처럼 경쟁이 발생하면 inference 성능이 떨어질 수 있습니다.
그런데 이때 단순 GPU utilization만 보면:
GPU utilization 70%
처럼 정상적으로 보일 수도 있습니다.
그래서 반드시:
NIC throughput
NIC drops
TCP retransmission
Cilium drops
Cilium bandwidth
AIStor latency
NCCL bandwidth
GPU utilization
을 동시에 봐야 합니다.
이게 현재 문서에서 가장 큰 누락입니다.
Bare metal:
Process
↓
CPU
↓
GPU
K8s:
Pod
↓
cgroup
↓
CPU request/limit
↓
scheduler
↓
NUMA
↓
GPU
가 됩니다.
따라서 다음을 별도로 검증하는 것이 좋습니다.
| Test | 확인 항목 |
|---|---|
| J1 | CPU request/limit 영향 |
| J2 | CPU pinning / exclusive CPU |
| J3 | NUMA locality |
| J4 | GPU ↔ CPU PCIe locality |
| J5 | IRQ/NIC ↔ CPU locality |
| J6 | CPU throttling |
| J7 | Memory pressure |
| J8 | OOM/eviction |
| J9 | Pod restart 후 GPU 재초기화 |
| J10 | 여러 inference Pod 간 CPU contention |
특히 B300에서는 GPU만 잘 붙어 있다고 끝나는 것이 아닙니다.
예를 들어:
GPU0-3
│
PCIe root complex A
│
NUMA 0
│
CPU 0-31
GPU4-7
│
PCIe root complex B
│
NUMA 1
│
CPU 32-63
같은 topology라면 vLLM의 CPU-side preprocessing, networking, tokenization, scheduler, NCCL socket thread 등이 어느 NUMA에 배치되는지가 영향을 줄 수 있습니다.
현재 문서를 조금 재구성하면 훨씬 강력한 validation plan이 됩니다.
K8s GPU Validation
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
A. Regression B. Network C. Runtime
│ │ │
bare-metal vs Cilium GPU Operator
K8s Pod Native/BGP/ECMP scheduling
│ ClusterMesh NUMA
NCCL MTU cgroup
GPU topology packet loss lifecycle
│ BGP convergence probes
│
└──────────────────────┐
▼
D. Application
│
vLLM / AIStor
Spark / Trino
StarRocks
Jupyter
그리고 테스트 번호를 다음처럼 만드는 것을 추천합니다.
| Section | 의미 |
|---|---|
| K1 | Bare-metal → Pod regression |
| K2 | GPU/NVLink/NCCL |
| K3 | Cilium datapath |
| K4 | ClusterMesh/BGP/ECMP |
| K5 | AIStor connectivity |
| K6 | GPU scheduling/NUMA |
| K7 | Workload/burst |
| K8 | Failure/Recovery |
| K9 | Security/NetworkPolicy |
| K10 | Observability |
| K11 | Resource contention |
현재 문서에서 실제 장애를 잡아낼 가능성이 가장 높은 테스트는 다음 다섯 가지입니다.
① Bare metal → hostNetwork Pod → Cilium Pod NCCL 비교
→ GPU/container/Cilium 문제를 분리.
② Pod → same-node → same-cluster remote-node → cross-cluster iperf3
→ Cilium/Native Routing/ClusterMesh 오버헤드를 단계별 분리.
③ Global Service local/remote affinity
→ AIStor 모델 loading에서 의도하지 않은 cross-cluster traffic 방지. Cilium은 local affinity를 명시적으로 지원합니다. :chatgpt-content-reference{index="8"}
④ GPU topology + NUMA + CPU/NIC locality
→ "8 GPU가 할당됐다"와 "8 GPU가 효율적으로 연결됐다"는 다른 문제.
⑤ Network contention + inference 동시 부하
→ 실제 운영환경에서 가장 재현하기 어려운 AIStor/Spark/StarRocks/Trino ↔ inference 간 noisy-neighbor 문제를 잡을 수 있음.
따라서 현재 작성하신 A~I는 그대로 버릴 필요가 전혀 없고, 다음 세 가지를 수정하면 상당히 좋은 K8s validation plan이 됩니다.
same-node → same-cluster → cross-cluster로 경로별 측정그리고 현재 사용자 환경처럼 Cilium Native + BGP + ECMP + ClusterMesh + B300 8GPU + AIStor 조합이라면, 저는 이 K8s 테스트를 단순히 “Stage 4”로 만들기보다 기존 Stage 1~3 결과를 기준선으로 삼는 K-Regression + K-Network + K-Resilience 구조로 만드는 것을 권합니다. Cilium의 Native Routing과 ClusterMesh는 실제로 cross-cluster Pod connectivity를 native datapath로 구성할 수 있기 때문에, 이 구조가 현재 환경과 가장 잘 맞습니다. :chatgpt-content-reference{index="9"}