물리 네트워크 위에 사설 클라우드 만들기
2차 프로젝트 | 2026.03.05 – 2026.03.24
물리 네트워크 인프라 기반 컨테이너 오케스트레이션 통합 및 사설 클라우드 전환
프로젝트 개요
![[FOR_PROJECT2-1776263821774.webp]]

| 항목 | 내용 |
|---|---|
| 기간 | 2026년 3월 5일 ~ 3월 24일 (약 3주) |
| 팀원 | 신승훈(PM), 김희수(PL), 정요한, 김진아 |
| 물리 장비 | HP DL360e Gen8 × 4대, Cisco 2911 라우터, Catalyst 2960 스위치 |
| 핵심 키워드 | Kubernetes HA, Calico BGP, VMware vSphere, GitOps, iSCSI, VLAN |
퍼블릭 클라우드 비용 절감과 데이터 보안 강화를 원하는 연구소 시나리오를 가정하여, 자체 사설 클라우드 인프라를 처음부터 끝까지 직접 설계·구축했습니다.
단순히 VM을 띄우는 수준이 아니라 물리 네트워크(Cisco 장비)부터 컨테이너 오케스트레이션(Kubernetes), CI/CD 자동화(GitOps)까지 실제 엔터프라이즈 환경에서 통용되는 풀스택 인프라를 구현하는 것이 목표였습니다.
구현 목표
- VLAN 기반 트래픽 격리 — 관리망 / 서비스망 / 스토리지망을 물리적으로 분리
- Kubernetes HA 클러스터 — 마스터 이중화로 컨트롤 플레인 단일 장애점 제거
- Calico BGP ↔ Cisco 라우터 피어링 — K8s Pod IP를 물리 네트워크에 직접 광고
- TrueNAS iSCSI 공유 스토리지 — 노드 장애 시에도 데이터 보존
- GitLab CI + ArgoCD GitOps — 코드 Push → 자동 빌드 → 자동 배포 파이프라인
전체 아키텍처
인프라는 크게 네 계층으로 구성됩니다.
[ L1 물리 ] HP DL360e Gen8 × 4대 + Cisco 2911 + Catalyst 2960
↓
[ L2 가상화 ] VMware ESXi 7.0.3 × 3대 + vCenter + vDS(분산 스위치)
↓
[ L3 오케스트레이션 ] Kubernetes v1.29 — Master HA × 2 + Worker × 2
↓
[ L4 서비스/운영 ] GitLab, ArgoCD, Grafana, Prometheus, TrueNAS, Bastion Host
네트워크 설계 — VLAN으로 트래픽 격리
VLAN(Virtual LAN) 이란 하나의 물리 스위치를 여러 개의 논리적 네트워크로 나누는 기술입니다. 서로 다른 VLAN에 속한 장치는 라우터를 거치지 않는 한 직접 통신할 수 없어 보안 격리 효과를 얻을 수 있습니다.
| VLAN | 용도 | 대역 | 특이사항 |
|---|---|---|---|
| VLAN 10 | 관리망 (MGMT) | 172.16.10.0/24 | ESXi 관리, vCenter, Bastion Host |
| VLAN 20 | 서비스망 (Service) | 172.16.20.0/24 | K8s 노드, GitLab, ArgoCD, Grafana |
| VLAN 30 | 스토리지망 (Storage) | 172.16.30.0/24 | TrueNAS iSCSI 전용 — ACL로 외부 라우팅 완전 차단 |
Router-on-a-Stick
Cisco 2911의 단일 물리 인터페이스(GE0/1)를 서브인터페이스(GE0/1.10 / .20 / .30)로 논리 분할하여 각 VLAN에 게이트웨이를 제공했습니다. 하나의 물리 포트로 세 개 망을 처리하면서도, VLAN 간 불필요한 브로드캐스트를 차단하고 필요한 트래픽만 라우팅합니다.
VLAN 30(스토리지)에는 ACL로 외부 라우팅을 완전히 차단했습니다. iSCSI 트래픽이 외부로 유출될 경우 보안 위협이 크기 때문에, 스토리지 대역은 내부 전용으로 격리했습니다.
가상화 인프라 — VMware vSphere
VMware vSphere(ESXi) 는 물리 서버 위에 여러 가상 머신(VM)을 올릴 수 있게 해주는 하이퍼바이저입니다. ESXi 4대를 vCenter로 통합 관리하고, vDS(가상 분산 스위치)로 네트워크를 중앙에서 일괄 제어했습니다.
물리 서버 역할 분담
| 서버 | ESXi IP | 탑재 VM |
|---|---|---|
| 서버1 | 172.16.10.11 | vCenter, GitLab, Bastion, CCTV, ArgoCD, Grafana (인프라 관리 집중) |
| 서버2 | 172.16.10.12 | Master-00 (K8s Control Plane), Worker-01 |
| 서버3 | 172.16.10.13 | Master-01 (K8s Control Plane HA), Worker-02 |
| 서버4 | 172.16.10.14 | TrueNAS 전용 (컴퓨트와 스토리지 완전 분리) |
vDS (분산 스위치)
vDS(vSphere Distributed Switch) 는 여러 ESXi 호스트에 걸친 가상 스위치를 vCenter 한 곳에서 통합 관리하는 기능입니다. VLAN 10/20/30 포트그룹을 한 번만 정의하면 4대의 서버에 일괄 적용됩니다.
10Lab-MGMT-Net— VLAN 10 포트그룹20Lab-SERVICE-Net— VLAN 20 포트그룹30Lab-STORAGE-Net— VLAN 30 포트그룹
TrueNAS iSCSI 공유 스토리지
iSCSI(Internet Small Computer Systems Interface) 는 네트워크를 통해 블록 스토리지를 연결하는 프로토콜입니다. 쉽게 말해 “네트워크로 연결된 외장 하드"처럼 동작하여 여러 서버가 하나의 디스크 공간을 공유합니다.
TrueNAS를 서버4에 단독 배치하고 VLAN 30을 통해 iSCSI Target을 제공했습니다. K8s 워커 노드들이 iSCSI_Storage(200GB Mirror)를 공유 데이터스토어로 마운트하므로, 워커 노드 장애가 발생해도 스토리지 데이터는 NAS에 안전히 보존됩니다.
Kubernetes 클러스터
Kubernetes(K8s) 는 컨테이너화된 애플리케이션의 배포·확장·복구를 자동화해주는 오케스트레이션 플랫폼입니다. “어느 서버에서 컨테이너를 몇 개 실행할지"를 알아서 관리하고, 장애 발생 시 자동으로 재시작합니다.
Master HA — 컨트롤 플레인 이중화
Kubernetes의 마스터 노드(Control Plane)는 클러스터 전체를 제어하는 두뇌 역할을 합니다. 이 두뇌가 하나뿐이라면 장애 시 클러스터 전체가 마비됩니다.
두 마스터(master-00, master-01) 앞에 Keepalived로 가상 IP(VIP)를 배치하여, API 요청이 항상 살아있는 마스터로 라우팅되도록 구성했습니다. 한 마스터가 다운되어도 나머지가 즉시 요청을 이어받아 무중단 운영을 보장합니다.
- 구성 버전: Kubernetes v1.29 (kubeadm), Container Runtime: containerd
Calico CNI — BGP 모드 (핵심 기술)
CNI(Container Network Interface) 는 Pod(컨테이너 묶음)끼리 통신할 수 있도록 네트워크를 연결해주는 플러그인입니다. Calico는 K8s에서 가장 많이 쓰이는 CNI 중 하나입니다.
이 프로젝트에서는 일반적인 오버레이 방식(VXLAN 등) 대신 BGP 모드를 선택했습니다.
왜 BGP 모드인가?
오버레이 방식은 패킷을 한 번 더 감싸 터널로 전송하기 때문에 오버헤드가 발생합니다. BGP 모드는 K8s Pod의 IP를 물리 라우터에 직접 광고하여 오버헤드 없이 최단 경로로 통신합니다. 또한 기존 물리 네트워크 장비와 표준 BGP 프로토콜로 통합할 수 있어 엔터프라이즈 환경에 더 적합합니다.
구성 내용:
- Calico AS64512 ↔ Cisco 2911 AS64513 간 eBGP 피어링 수립
- Calico가 K8s VIP Pool(
172.16.20.192/26)을 Cisco 라우터에 광고 → 외부에서 Pod IP로 직접 접근 가능 - K8s 노드 추가·삭제 시 BGP 경로 자동 갱신 — 수동 설정 불필요
- Calico NetworkPolicy White-list 적용 → Pod 레벨의 세밀한 접근 제어
MetalLB — 온프레미스 LoadBalancer
퍼블릭 클라우드에서는 LoadBalancer 타입 서비스를 생성하면 자동으로 외부 IP가 할당됩니다. 온프레미스 환경에는 이 기능이 없습니다. MetalLB는 이를 해결하는 소프트웨어 로드밸런서입니다.
- L2 모드로
172.16.20.200–172.16.20.255IP 풀 할당 - 각 서비스에 고정 External IP 부여 (web, mail, jupyter, CoreDNS)
Ingress & CoreDNS 외부 노출
Nginx Ingress Controller를 통해 도메인 기반 라우팅을 구현했습니다. www.edgea.lab 으로 접근하면 Ingress가 경로 재작성(Rewrite) 규칙을 적용하여 내부 web-svc로 트래픽을 전달합니다.
CoreDNS를 MetalLB로 외부에 노출(172.16.20.200)하여, 클러스터 외부 호스트도 edgea.lab 같은 커스텀 도메인을 DNS 서버로 등록해 사용할 수 있게 했습니다.
CI/CD 자동화 파이프라인 — GitOps
CI/CD(Continuous Integration / Continuous Delivery) 는 코드 변경 사항이 자동으로 빌드·테스트·배포되도록 하는 개발 방식입니다. 이 프로젝트에서는 GitOps 패턴을 채택하여 Git 저장소의 상태가 곧 인프라의 상태와 동일하게 유지되도록 구성했습니다.
파이프라인 흐름
1. 개발자가 GitLab 저장소에 코드를 Push
↓
2. GitLab CI Runner 자동 트리거 — Dockerfile 빌드 시작
↓
3. 빌드된 이미지를 GitLab Container Registry에 저장 (Harbor 없이 운영)
↓
4. GitLab 저장소의 K8s YAML 파일 업데이트
↓
5. ArgoCD가 변경 감지 → Kubernetes 클러스터에 자동 배포 (Sync)
ArgoCD — GitOps 컨트롤러
ArgoCD는 Git 저장소를 진실의 원천(Source of Truth)으로 삼아, 저장소의 상태와 클러스터의 실제 상태를 지속적으로 동기화하는 도구입니다.
- 3개 애플리케이션 관리:
kedu-apps(실제 서비스),kedu-infrastructure(인프라 설정),kedu-monitoring(모니터링) - Auto Sync 활성화 — Git 커밋 즉시 클러스터에 반영
- History & Rollback 기능으로 배포 이력 관리 및 빠른 롤백 가능
GitLab — 코드 + 이미지 레지스트리 통합
GitLab은 코드 저장소(Git) + CI 파이프라인 + 컨테이너 이미지 저장소(Registry)를 단일 플랫폼으로 통합 제공합니다. 별도의 Harbor 레지스트리 없이 GitLab 내장 Registry만으로 전체 빌드·배포 사이클을 완성했습니다.
모니터링 — Prometheus + Grafana + Alertmanager
Prometheus는 K8s 클러스터의 CPU, 메모리, 네트워크 등 메트릭을 수집·저장하는 시계열 데이터베이스입니다. Grafana는 이 데이터를 시각화하는 대시보드 도구입니다.
- Node Exporter: DaemonSet으로 모든 노드에 자동 배포 → 하드웨어 지표 수집
- Service Discovery: 새로 추가되는 Pod/Node를 자동 감지하여 모니터링 대상에 포함
- Alertmanager: 임계치 초과 시 네이버 SMTP로 즉각 이메일 알림 발송
- 동일 장애의 반복 알람은 1시간 간격으로 묶어 알람 피로도 관리
send_resolved: true로 장애 해소 시 복구 완료 통보
배포한 K8s 서비스 목록
| 서비스 | External IP | 내용 |
|---|---|---|
| web-svc (Nginx) | 172.16.20.201 | Edge A Research Lab 웹사이트, Ingress 도메인 접근 |
| mail-svc (Postfix/Dovecot) | 172.16.20.202 | 사내 메일 서버, SMTP/POP3 |
| jupyter-svc | 172.16.20.203 | 데이터 분석 환경, 전용 PV 연결 |
| db-svc (MariaDB) | ClusterIP 내부 | K8s 내부 DB, PVC로 데이터 영속성 확보 |
| prometheus-svc | NodePort :30003 | 메트릭 수집 엔진 |
| grafana-svc | NodePort :3000 | 대시보드 시각화 |
| argocd | NodePort | GitOps 컨트롤러 |
| alertmanager-svc | NodePort :30005 | 알람 라우팅 및 웹 UI |
보안 설계
Bastion Host — 단일 진입점
Bastion Host(배스천 호스트) 는 외부에서 내부 인프라에 접근할 수 있는 유일한 경유 서버입니다. 모든 SSH 접속은 반드시 Bastion을 통해서만 가능하도록 설계했습니다.
외부 → Bastion 허용
외부 → 내부 서버 직접 차단
Bastion → 내부 서버 허용
ACL 기반 접근 제어
- VLAN 30(스토리지) 외부 라우팅 차단 ACL — iSCSI 트래픽 내부 격리
- Cisco 2911 White-list ACL — VLAN 10/20만 외부 NAT 허용
- Calico NetworkPolicy White-list — Pod 간 통신을 명시적 허용 목록으로만 제한
NAT 구성
- Dynamic PAT(Overload): K8s 워커 노드가 외부 인터넷(DNS, 이미지 풀) 접근 시 사용
- Static PAT(포트 포워딩): 외부에서 내부 관리 서버 접근 시 허용 포트만 개방
핵심 설계 결정 근거
왜 Calico BGP 모드인가?
Flannel·Weave 같은 오버레이 방식은 VXLAN 터널로 패킷을 감싸기 때문에 오버헤드가 발생합니다. Calico BGP 모드는 Pod IP를 물리 라우터에 직접 광고하여 추가 캡슐화 없이 최단 경로로 통신합니다. 기존 물리 네트워크 장비와 표준 BGP 프로토콜로 통합할 수 있어 엔터프라이즈 환경에 더 적합한 선택이었습니다.
왜 GitLab 내장 Registry인가? (Harbor 미사용)
Harbor는 기업용 컨테이너 레지스트리로 강력한 기능을 제공하지만, 별도 서버와 운영 비용이 필요합니다. GitLab은 코드 저장소 + CI 파이프라인 + Registry를 단일 플랫폼으로 통합하므로, 이 규모에서는 Harbor를 추가하지 않고 전체 빌드·배포 사이클을 완성할 수 있었습니다.
왜 TrueNAS를 서버4에 단독 배치했는가?
iSCSI 스토리지는 I/O 집약적이어서 다른 VM과 자원을 공유하면 성능 저하와 안정성 문제가 발생할 수 있습니다. 서버4를 TrueNAS 전용으로 격리함으로써 스토리지 레이어를 컴퓨트 레이어와 완전히 분리(Decoupling)하는 클라우드 네이티브 아키텍처 원칙을 따랐습니다.
왜 kubeadm + Keepalived로 Master HA를 구성했는가?
Keepalived로 VIP를 구성하고 kubeadm의 --control-plane-endpoint 옵션을 사용하는 방식은, 외부 로드밸런서 없이도 마스터 이중화를 달성할 수 있는 가장 표준적인 온프레미스 방법입니다. 추가 인프라 비용 없이 K8s 공식 권장 방식을 따르면서 SPoF(단일 장애점)를 제거했습니다.
기술 스택 요약
| 분류 | 기술 | 버전 / 세부사항 |
|---|---|---|
| 물리 네트워크 | Cisco 2911 / Catalyst 2960 | VLAN, Router-on-a-Stick, BGP AS64513, ACL, NAT |
| 하이퍼바이저 | VMware ESXi 7.0.3 × 4 | vCenter VCSA, vDS 분산 스위치 |
| OS (VM) | Ubuntu Server 22.04 LTS | K8s 노드 / Rocky Linux 9 (기타 서버) |
| 오케스트레이션 | Kubernetes v1.29 | kubeadm, Master HA (Keepalived VIP) |
| 컨테이너 런타임 | containerd | K8s 1.29 기본 런타임 |
| CNI | Calico BGP 모드 | AS64512, eBGP ↔ Cisco 2911 AS64513 |
| 스토리지 | TrueNAS CORE | iSCSI / NFS / S3, 200GB Mirror |
| LB (온프레미스) | MetalLB L2 | IP Pool 172.16.20.200–255 |
| CI/CD | GitLab + ArgoCD | GitOps, 내장 Container Registry |
| 모니터링 | Prometheus + Grafana | Node Exporter DaemonSet, Alertmanager (Naver SMTP) |
| 보안 | Bastion Host + Calico NetworkPolicy | White-list 정책 |
회고 — Project Story
왜 만들었나
1차 프로젝트가 가상 환경(GNS3, VMware Workstation)에서의 네트워크 시뮬레이션이었다면, 2차는 전혀 달랐습니다. HP DL360e Gen8이라는 실제 물리 서버가 눈앞에 있고, Cisco 라우터와 스위치를 직접 케이블로 연결해야 했습니다.
‘퍼블릭 클라우드가 비싸서 자체 클라우드를 직접 만들어야 하는 연구소’라는 시나리오는 현실에서 수없이 존재하는 요구입니다. 그 현실적인 문제를 부트캠프 교실 안에서 실제로 구현해보는 것이 이 프로젝트의 출발점이었습니다.
어떻게 만들었나
첫 번째 벽은 물리 네트워크였습니다. 가상 환경에서는 VLAN 설정 하나가 잘못되어도 금방 되돌릴 수 있지만, 실제 Catalyst 스위치에서 trunk 설정이 틀리면 서버 4대가 동시에 통신 불능이 됩니다. VLAN 10/20/30 trunk 설정과 Router-on-a-Stick 구성을 맞추는 데만 상당한 시간을 썼습니다.
두 번째 벽은 Calico BGP 피어링이었습니다. K8s 내부 네트워크와 물리 Cisco 라우터를 BGP로 연결한다는 개념 자체가 생소했고, AS 번호 설정부터 VIP Pool 광고까지 각 단계에서 예상치 못한 에러 로그와 씨름했습니다. BGP 세션이 Established 상태가 되는 순간은 프로젝트 전체에서 가장 뚜렷하게 기억나는 장면 중 하나입니다.
세 번째 어려움은 팀 내 소통이었습니다. 네 명이 동시에 서로 다른 계층(네트워크 / 가상화 / K8s / CI-CD)을 작업하다 보니, 중첩 가상화 환경에서 서로 다른 기준으로 이야기해 혼선이 생기는 일이 반복되었습니다. 전체 구성도를 기준으로 매일 진행 상황을 공유하는 방식으로 해결해나갔습니다.
뭘 배웠나
이 프로젝트에서 배운 가장 큰 것은 인프라의 각 계층이 어떻게 연결되는가에 대한 거시적 시각입니다. VLAN이 어떻게 끊기는지, K8s Pod가 왜 외부와 통신이 안 되는지, iSCSI 마운트가 실패하는 이유가 무엇인지 — 모두 계층 간 연결 고리에서 발생하는 문제였고, 그 연결 고리를 직접 손으로 이어붙이는 경험이 이론으로는 결코 얻을 수 없는 이해를 만들어줬습니다.
또한 인프라 엔지니어링에서 Trade-off 판단이 얼마나 중요한지를 배웠습니다. Harbor vs GitLab Registry, VXLAN vs BGP, 단일 마스터 vs HA — 모든 선택에는 득과 실이 있었고, 제한된 자원과 시간 안에서 합리적인 결정을 내리는 것이 기술 역량만큼 중요한 엔지니어의 능력이라는 것을 실감했습니다.