ARM 서버 Kubernetes Part 4: 외부 접근 환경 구성
오늘은 KVM 가상머신 위에 구성된 K8s 클러스터에 외부 접근 환경을 만드는 작업을 했다.
WiFi 환경이라 브리지 네트워킹이 안 되는 제약이 있었고, OpenVPN + MetalLB + Ingress 조합으로 해결했다.
환경
호스트 서버 (ARM64, Ubuntu 24.04)
├── WiFi (192.168.200.100) — 외부 통신
├── virbr0 (192.168.122.1/24) — KVM NAT 브리지
│ ├── k8s-master (192.168.122.10)
│ ├── k8s-worker1 (192.168.122.11)
│ └── k8s-worker2 (192.168.122.12)
└── OpenVPN 서버 (Docker, UDP 51194)
VPN 대역: 192.168.255.0/24
K8s: v1.29.15, 3노드 구성
문제: WiFi는 브리지가 안 된다
WiFi 어댑터는 AP가 단일 MAC 주소만 허용하기 때문에, VM들이 외부 IP를 직접 가질 수 없다.
이더넷이었다면 virbr0를 브리지로 연결해 VM이 직접 외부 IP를 받을 수 있지만, WiFi에서는 불가능하다.
대안으로 선택한 방법: OpenVPN
이미 호스트에 OpenVPN 서버가 Docker로 구성되어 있었다. VM마다 클라이언트를 발급해서 VPN 망을 통해 고정 IP를 부여하는 방식을 선택했다.
1단계: K8s VM에 VPN 고정 IP 부여
클라이언트 발급
| |
CCD로 고정 IP 설정
OpenVPN의 CCD(Client Config Directory)를 사용하면 클라이언트별로 고정 IP를 지정할 수 있다.
| |
openvpn.conf에 다음 두 줄 추가:
client-config-dir /etc/openvpn/ccd
topology subnet
VM에 openvpn 설치 및 자동 시작
| |
결과적으로 K8s 노드들이 tun0 인터페이스에 VPN IP를 가지게 되었고,
K8s 자체도 이 VPN IP를 INTERNAL-IP로 인식했다.
NAME INTERNAL-IP ...
k8s-master 192.168.255.10
k8s-worker1 192.168.255.11
k8s-worker2 192.168.255.12
2단계: MetalLB 설치 (L4 로드밸런서)
클라우드 환경에서는 type: LoadBalancer 서비스에 자동으로 외부 IP가 붙지만, 베어메탈에서는 그게 없다.
MetalLB가 이 역할을 해준다.
설치
| |
IP 풀 설정
VPN 대역에서 K8s 노드 IP와 겹치지 않는 범위를 할당한다.
| |
L2 모드의 한계: tun 인터페이스에서 ARP가 안 된다
MetalLB L2 모드는 ARP로 IP를 광고하는 방식인데, tun 인터페이스는 L3 전용이라 ARP(L2 브로드캐스트)를 지원하지 않는다.
VPN 클라이언트에서 MetalLB IP로 접근해도 ARP 응답이 없어서 패킷이 버려진다.
해결책: OpenVPN iroute
OpenVPN 서버의 CCD에 iroute를 추가하면, VPN 서버가 해당 IP 대역을 특정 클라이언트(k8s-master)를 통해 라우팅하도록 설정할 수 있다.
ARP 없이 L3 라우팅으로 해결된다.
| |
openvpn.conf에도 서버 측 route 추가:
route 192.168.255.96 255.255.255.224
이렇게 하면 MetalLB 풀 전체가 k8s-master를 통해 라우팅되고, kube-proxy가 나머지를 처리한다.
새 서비스가 추가되어도 IP 풀 범위 안이면 별도 설정이 필요 없다.
3단계: Ingress Controller (L7 로드밸런서)
MetalLB는 IP + 포트 수준의 L4만 담당한다. HTTP 경로나 도메인 기반 분기는 Ingress Controller가 필요하다.
nginx-ingress가 이미 설치되어 있었다. NodePort → LoadBalancer로 변경하면 MetalLB가 외부 IP를 자동 할당한다.
| |
결과: 192.168.255.101 할당
4단계: nginx + apache 서비스 + 경로 기반 라우팅
서비스 배포
| |
Ingress 규칙
| |
배포 검증
1. nginx-demo Deployment 배포
nginx 서비스가 없으면 / 경로가 동작하지 않으므로, nginx-demo를 추가로 배포해야 합니다:
| |
2. 배포 상태 확인
| |
3. 외부 접근 테스트
VPN 클라이언트에서 아래 명령어로 테스트:
| |
4. 실제 테스트 결과
/ 경로 (nginx):
HTTP/1.1 200 OK
Content-Type: text/html
...
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working.
/ apache 경로 (apache):
HTTP/1.1 200 OK
Content-Type: text/html
...
It works!
Apache httpd
✅ 경로 기반 라우팅 성공!
최종 구조
VPN 클라이언트 (핸드폰, PC 등)
↓ OpenVPN 연결 (192.168.255.x)
│
└── 192.168.255.100 (Ingress Controller - LoadBalancer)
│
├── GET / → nginx-demo (1개 Pod)
│
└── GET /apache → apache-demo (2개 Pod)
실제 구성:
- Ingress External IP: 192.168.255.100 (MetalLB 할당)
- 경로 분기:
/→ nginx-demo-svc → nginx-demo Pod (nginx:alpine)/apache→ apache-demo-svc → apache-demo Pods (httpd:alpine × 2)
정리
| 레이어 | 역할 | 담당 |
|---|---|---|
| VPN | 외부 클라이언트 → K8s 접근 터널 | OpenVPN (192.168.255.0/24) |
| L4 | 외부 IP 할당, 포트 라우팅 | MetalLB (192.168.255.100-150) |
| L7 | 경로 기반 HTTP 분기 | Nginx Ingress Controller |
핵심 포인트
- WiFi 환경에서 외부 접근: OpenVPN + VPN 고정 IP
- 베어메탈 K8s에서 LoadBalancer: MetalLB (클라우드의 LB 대체)
- HTTP 경로 분기: Ingress Controller (L7 라우팅)
- 실제 서비스: nginx + apache 배포 완료
WiFi 브리지 제약이 있는 환경에서도 OpenVPN iroute를 활용하면 외부에서 K8s 서비스에 깔끔하게 접근할 수 있다.tap 모드 VPN이나 BGP 라우팅 없이도 L3 라우팅만으로 충분히 해결 가능하다.
작성일: 2026-02-18
검증일: 2026-02-20
최종 상태: ✅ 모든 테스트 성공