티스토리 뷰
Oracle Cloud + Tailscale + Kubernetes 완벽 가이드(6)
pak2251 2025. 10. 26. 19:275단계: 실전 경험과 아키텍처 결정 배경
시리즈: Oracle Cloud + Tailscale + Kubernetes 완벽 가이드
← 이전: 4단계: 네트워킹 심화 이해 | 처음으로: README
며칠간의 삽질에서 얻은 교훈 - "다음에는 이렇게 하지 말자"
📋 이 문서의 목적
이 가이드의 최종 아키텍처는 처음부터 완벽하게 설계된 것이 아닙니다.
여러 번의 시도와 실패를 거쳐 현재의 구성에 도달했습니다.
왜 이 문서가 필요한가?
- 실패한 방법을 기록하여 같은 함정에 빠지지 않도록
- 아키텍처 결정의 배경과 근거 공유
- "왜 이렇게 했나?"에 대한 솔직한 답변
전체 여정 타임라인
graph TD
Start[목표: Tailscale + Kubernetes 클러스터] --> Attempt1{시도 1: Tailscale in K8s}
Attempt1 -->|DaemonSet 배포| Problem1[❌ 문제 발생]
Problem1 --> Issue1a[네트워크 네임스페이스 충돌]
Problem1 --> Issue1b[Pod 재시작 시 터널 끊김]
Problem1 --> Issue1c[hostNetwork 보안 문제]
Issue1a --> Decision1[🔄 systemd 서비스로 변경]
Issue1b --> Decision1
Issue1c --> Decision1
Decision1 --> Attempt2{시도 2: Cilium Native Routing}
Attempt2 -->|성능 최적화 시도| Problem2[❌ 문제 발생]
Problem2 --> Issue2a[Tailscale이 Pod 라우팅 안함]
Problem2 --> Issue2b[수동 라우팅 관리 악몽]
Problem2 --> Issue2c[자동화 실패]
Issue2a --> Decision2[🔄 VXLAN으로 회귀]
Issue2b --> Decision2
Issue2c --> Decision2
Decision2 --> Final[✅ 최종 아키텍처]
Final --> Layer1[Tailscale: systemd 서비스]
Final --> Layer2[Cilium: VXLAN 모드]
Final --> Layer3[eBPF: kube-proxy 대체]
Layer1 --> Result[안정적 운영 중]
Layer2 --> Result
Layer3 --> Result
style Start stroke:#00bfff,stroke-width:3px
style Problem1 stroke:#ff6b6b,stroke-width:3px
style Problem2 stroke:#ff6b6b,stroke-width:3px
style Decision1 stroke:#ffa500,stroke-width:3px
style Decision2 stroke:#ffa500,stroke-width:3px
style Final stroke:#4ecdc4,stroke-width:3px
style Result stroke:#95e1d3,stroke-width:3px
🚫 실패담 1: Tailscale을 Kubernetes 내부에서 실행
시도한 방법
Tailscale을 Kubernetes 방식으로 관리하려고 시도했습니다:
# 시도했던 방법 (실패)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: tailscale
namespace: kube-system
spec:
template:
spec:
hostNetwork: true # ← 이미 여기서 문제의 냄새
containers:
- name: tailscale
image: tailscale/tailscale:latest
securityContext:
privileged: true # ← 보안 문제왜 시도했나?
- Kubernetes 방식으로 통합 관리
kubectl명령어로 모든 것 제어- GitOps 워크플로우에 포함
겪은 문제
1. CNI와 네트워크 네임스페이스 충돌
# Pod 네트워크 네임스페이스
ip netns exec cni-xxx ip route
# 10.244.0.0/16 via cilium_host
# 호스트 네트워크 네임스페이스
ip route
# 100.64.0.0/10 via tailscale0
# → 두 세계가 서로를 인식하지 못함!증상:
- Tailscale Pod 시작은 되지만 라우팅 작동 안 함
tailscale status는 정상, 실제 통신은 실패- 패킷 드롭 발생
2. Pod 재시작 시 터널 끊김
# Scenario
1. Tailscale Pod 정상 실행 → 터널 연결 OK
2. Pod 재시작 (업데이트, 노드 이동 등)
3. Tailscale 재연결 시도
4. 기존 세션 끊김, 새 IP 할당 가능
5. 클러스터 전체 통신 장애 발생!문제:
- Pod는 ephemeral (일시적)
- Tailscale 터널은 persistent (지속적) 필요
- 근본적인 불일치
3. hostNetwork 사용의 보안 문제
hostNetwork: true # Pod가 호스트 네트워크 직접 사용문제점:
- Pod가 호스트의 모든 네트워크 접근 가능
- Kubernetes 네트워크 격리 무력화
- 보안 감사 실패
기술적 배경: 왜 작동하지 않는가?
네트워크 네임스페이스의 한계
graph TB
subgraph Host["🖥️ Host Network Namespace"]
TS[Tailscale tailscale0]
TSR[라우팅 테이블<br/>100.64.0.0/10]
HostRoute[호스트 라우팅 테이블]
TS --> TSR
TSR --> HostRoute
end
subgraph PodNS["📦 Pod Network Namespace"]
Veth[veth 인터페이스]
PodRoute[독립 라우팅 테이블<br/>10.244.x.0/24]
Veth --> PodRoute
end
Host -.->|❌ 접근 불가| PodNS
PodNS -.->|❌ 접근 불가| Host
style Host stroke:#00bfff,stroke-width:3px
style PodNS stroke:#ff6b6b,stroke-width:3px
style TS stroke:#4ecdc4,stroke-width:2px
style Veth stroke:#ee5a6f,stroke-width:2px
핵심 문제:
- Tailscale은 호스트 라우팅 테이블 수정
- Pod는 독립 네트워크 네임스페이스
- 두 레이어가 서로 통신 불가
결론: 노드 레벨 systemd 서비스
최종 선택:
# 각 노드에서 직접 설치
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --login-server=...장점:
- ✅ 안정적인 터널 (재부팅 시에도 유지)
- ✅ CNI와 충돌 없음
- ✅ 단순하고 명확한 관리
- ✅ Tailscale 공식 권장 방법
단점:
- ❌ 노드별 수동 설정 필요
- ❌ Kubernetes 방식 관리 불가
- ❌ GitOps에 포함 어려움
트레이드오프:
운영 안정성 > 관리 편의성
🚫 실패담 2: Cilium Native Routing 시도
시도한 방법
VXLAN 오버헤드를 제거하여 성능을 높이려고 시도:
# Native Routing 모드로 Cilium 설치
helm install cilium cilium/cilium \
--set routingMode=native \ # ← VXLAN 대신 Native
--set autoDirectNodeRoutes=true \ # ← 자동 라우팅 기대
--set ipv4NativeRoutingCIDR=10.244.0.0/16왜 시도했나?
- VXLAN 캡슐화 오버헤드 제거 (5-10% 성능 향상)
- "더 빠른 네트워크"에 대한 욕심
- 기술 블로그에서 "Native Routing이 최고"라는 글 읽음
겪은 문제
1. Tailscale이 Pod 라우팅을 자동 설정하지 않음
# 기대했던 것:
tailscale up --advertise-routes=10.244.0.0/16
# → 모든 노드에 자동으로 라우팅 설정될 줄 알았음
# 현실:
ip route show
# 100.64.0.2 via tailscale0 ← 노드 IP만 있음
# 10.244.1.0/24는 없음!깨달음:
- Tailscale은 노드 간 터널만 제공
- Pod 네트워크는 별도로 라우팅 설정 필요
advertise-routes는 광고만, 자동 설정 아님
2. 수동 라우팅 테이블 관리의 악몽
각 노드에서 수동 설정 필요:
# Master 노드 (100.64.0.1)
sudo ip route add 10.244.1.0/24 via 100.64.0.2 # Worker 1
sudo ip route add 10.244.2.0/24 via 100.64.0.3 # Worker 2
# Worker 1 (100.64.0.2)
sudo ip route add 10.244.0.0/24 via 100.64.0.1 # Master
sudo ip route add 10.244.2.0/24 via 100.64.0.3 # Worker 2
# Worker 2 (100.64.0.3)
sudo ip route add 10.244.0.0/24 via 100.64.0.1 # Master
sudo ip route add 10.244.1.0/24 via 100.64.0.2 # Worker 1graph TB
subgraph Master["🖥️ Master (100.64.0.1)"]
M1[Pod CIDR: 10.244.0.0/24]
M2[라우팅 테이블]
M3["route add 10.244.1.0/24 via .2"]
M4["route add 10.244.2.0/24 via .3"]
end
subgraph Worker1["🖥️ Worker 1 (100.64.0.2)"]
W1[Pod CIDR: 10.244.1.0/24]
W2[라우팅 테이블]
W3["route add 10.244.0.0/24 via .1"]
W4["route add 10.244.2.0/24 via .3"]
end
subgraph Worker2["🖥️ Worker 2 (100.64.0.3)"]
WW1[Pod CIDR: 10.244.2.0/24]
WW2[라우팅 테이블]
WW3["route add 10.244.0.0/24 via .1"]
WW4["route add 10.244.1.0/24 via .2"]
end
Master <-->|Tailscale 터널| Worker1
Worker1 <-->|Tailscale 터널| Worker2
Master <-->|Tailscale 터널| Worker2
Note1["😱 노드 추가 시<br/>모든 노드에서<br/>라우팅 업데이트 필요!"]
style Note1 stroke:#ff6b6b,stroke-width:3px
style Master stroke:#00bfff,stroke-width:2px
style Worker1 stroke:#4ecdc4,stroke-width:2px
style Worker2 stroke:#ffa500,stroke-width:2px
문제점:
- 노드 추가 시마다 모든 노드에서 업데이트
- IP 변경 시 모든 라우팅 테이블 수정
- 재부팅 시 라우팅 유실 → 스크립트 작성 필요
- 운영 복잡도 기하급수적 증가
3. 자동화의 어려움
시도한 자동화 방법들:
# 1. systemd 서비스로 라우팅 추가 (실패)
# - 노드 추가/제거 시 동기화 문제
# 2. Kubernetes Operator 작성 (너무 복잡)
# - 라우팅 테이블 관리 Operator 필요
# - 오버엔지니어링
# 3. Ansible 플레이북 (관리 포인트 증가)
# - Kubernetes 외부 도구 의존성
# - GitOps와 불일치결론: 모두 만족스럽지 않음
기술적 배경: Native Routing의 요구사항
Native Routing이 작동하는 환경
graph TB
subgraph Ideal["✅ Native Routing 이상적 환경"]
direction LR
N1[Node 1] <--> Switch[L2 스위치 또는<br/>클라우드 라우팅]
N2[Node 2] <--> Switch
N3[Node 3] <--> Switch
Switch --> Auto[자동 라우팅<br/>BGP / VPC Peering /<br/>물리 스위치]
end
subgraph Reality["❌ 우리 환경 (Tailscale)"]
direction TB
subgraph Acc1["Oracle Account 1"]
Node1[Node 1<br/>10.244.0.0/24]
end
subgraph Acc2["Oracle Account 2"]
Node2[Node 2<br/>10.244.1.0/24]
end
subgraph Acc3["Oracle Account 3"]
Node3[Node 3<br/>10.244.2.0/24]
end
Node1 <-.->|WireGuard 터널| Node2
Node2 <-.->|WireGuard 터널| Node3
Node1 <-.->|WireGuard 터널| Node3
Manual[수동 라우팅만 가능<br/>자동화 없음!]
end
style Ideal stroke:#4ecdc4,stroke-width:3px
style Reality stroke:#ff6b6b,stroke-width:3px
style Auto stroke:#95e1d3,stroke-width:2px
style Manual stroke:#ee5a6f,stroke-width:2px
style Acc1 stroke:#00bfff,stroke-width:1px
style Acc2 stroke:#00bfff,stroke-width:1px
style Acc3 stroke:#00bfff,stroke-width:1px
근본적인 불일치:
- Native Routing: Layer 2/3 라우팅 필요
- Tailscale: Layer 4 터널 (라우팅 제공 안 함)
결론: VXLAN 터널링으로 회귀
최종 선택:
helm install cilium cilium/cilium \
--set routingMode=tunnel \
--set tunnelProtocol=vxlan장점:
- ✅ 라우팅 자동 관리 (Cilium이 전담)
- ✅ 노드 추가/제거 시 설정 불필요
- ✅ 운영 복잡도 낮음
- ✅ 안정적이고 예측 가능
단점:
- ❌ VXLAN 캡슐화 오버헤드 (~5-10%)
- ❌ MTU 감소 (1500 → 1200)
성능 테스트 결과:
# iperf3 테스트 (Pod to Pod)
Native Routing: ~9.2 Gbps
VXLAN: ~8.7 Gbps
차이: ~5%
# 실제 워크로드 영향: 거의 무시 가능
# CPU/메모리가 먼저 병목트레이드오프:
미세한 성능 차이 < 압도적인 운영 편의성
✅ 최종 아키텍처 결정
선택한 구성
graph TB
subgraph Layer1["🌐 Layer 1: 노드 간 연결 (Tailscale)"]
TS[Tailscale systemd 서비스]
TSF[WireGuard 터널<br/>100.64.0.0/10]
TSM[관리: systemd]
TS --> TSF
TSF --> TSM
end
subgraph Layer2["📦 Layer 2: Pod 네트워킹 (Cilium CNI)"]
Cilium[Cilium VXLAN 모드]
PodNet[Pod 네트워크<br/>10.244.0.0/16]
AutoRoute[자동 라우팅 관리]
CiliumM[관리: Helm Chart]
Cilium --> PodNet
PodNet --> AutoRoute
AutoRoute --> CiliumM
end
subgraph Layer3["⚡ Layer 3: 서비스 로드밸런싱 (eBPF)"]
eBPF[Cilium eBPF]
KubeProxy[kube-proxy 대체]
SvcLB[Service Load Balancing]
eBPF --> KubeProxy
KubeProxy --> SvcLB
end
Layer1 ==>|노드 터널 제공| Layer2
Layer2 ==>|Pod 네트워크 제공| Layer3
Responsibility["책임 분리<br/>---<br/>Tailscale: 노드만 연결<br/>Cilium: 나머지 전부"]
style Layer1 stroke:#00bfff,stroke-width:3px
style Layer2 stroke:#4ecdc4,stroke-width:3px
style Layer3 stroke:#ffa500,stroke-width:3px
style Responsibility stroke:#ee5a6f,stroke-width:2px
각 계층의 책임
| 계층 | 역할 | 관리 방식 | CIDR 대역 |
|---|---|---|---|
| Tailscale | 노드 간 터널 | systemd 서비스 | 100.64.0.0/10 |
| Cilium | Pod 네트워킹 | Helm Chart | 10.244.0.0/16 |
| eBPF | Service LB | Cilium 내장 | - |
명확한 책임 분리:
- Tailscale: "노드만 연결" (Layer 1)
- Cilium: "나머지 전부" (Layer 2 + 3)
의사결정 플로우차트
graph TD
Start[Kubernetes 클러스터 구축 필요] --> Q1{노드들이<br/>동일 네트워크?}
Q1 -->|예<br/>VPC/L2 동일| VPC[Native Routing 가능]
Q1 -->|아니오<br/>서로 다른 네트워크| Overlay[Overlay 네트워크 필요]
VPC --> Q2{BGP 또는<br/>클라우드 라우팅<br/>사용 가능?}
Q2 -->|예| NativeOK[✅ Cilium Native Routing<br/>최고 성능]
Q2 -->|아니오| ManualRoute{수동 라우팅<br/>관리 가능?}
ManualRoute -->|가능<br/>노드 수 고정| NativeManual[⚠️ Native Routing<br/>+ 수동 설정<br/>5-10% 성능 향상]
ManualRoute -->|불가능<br/>노드 수 가변| UseVXLAN[→ VXLAN 사용]
Overlay --> Q3{Tailscale/WireGuard<br/>터널 사용?}
Q3 -->|예| TailscaleQ{Tailscale을<br/>어디서 실행?}
Q3 -->|아니오| OtherOverlay[다른 Overlay 검토<br/>Flannel, Calico 등]
TailscaleQ -->|K8s 내부<br/>DaemonSet| TSFail[❌ 네임스페이스 충돌<br/>권장 안 함]
TailscaleQ -->|노드 레벨<br/>systemd| TSOK[✅ Tailscale systemd]
TSOK --> UseVXLAN
TSFail -.->|실패 후| TSOK
UseVXLAN --> Final[✅ 최종 구성<br/>Tailscale systemd<br/>+ Cilium VXLAN<br/>+ eBPF]
NativeOK --> CNI[CNI 선택:<br/>Cilium, Calico, Flannel]
UseVXLAN --> CNI2[CNI 선택:<br/>Cilium 권장]
style Start stroke:#00bfff,stroke-width:3px
style Final stroke:#4ecdc4,stroke-width:4px
style NativeOK stroke:#95e1d3,stroke-width:3px
style TSFail stroke:#ff6b6b,stroke-width:3px
style TSOK stroke:#4ecdc4,stroke-width:3px
트레이드오프 분석
성능 vs 운영성
| 구성 | 성능 | 운영 난이도 | 안정성 | 선택 |
|---|---|---|---|---|
| Native + K8s Tailscale | ⭐⭐⭐⭐⭐ | ⭐ | ⭐ | ❌ |
| Native + systemd Tailscale | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐ | ❌ |
| VXLAN + systemd Tailscale | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ✅ |
우선순위:
- 안정성 (가장 중요)
- 운영 편의성 (두 번째)
- 성능 (세 번째)
실무 관점
"완벽한 설정"은 없습니다:
- 모든 것을 만족하는 구성은 존재하지 않음
- 상황과 우선순위에 따라 선택
- 우리의 선택: 안정성과 단순함
💡 배운 교훈
1. 단순함이 최고
복잡한 최적화 << 단순하고 안정적인 구성예시:
- ❌ Native Routing + 자동화 스크립트 + Operator
- ✅ VXLAN + 기본 설정
이유:
- 복잡한 시스템은 디버깅 어려움
- 운영 중 문제 발생 시 원인 파악 지연
- 팀원 온보딩 시간 증가
2. 운영 안정성 > 미세한 성능
5% 성능 향상 vs 50% 운영 부담 감소
- 대부분의 경우 성능은 충분함
- CPU/메모리/디스크가 먼저 병목
- 네트워크 5% 차이는 체감 불가
실제 경험:
# 성능 병목 분석 결과
1. 데이터베이스 쿼리 최적화: 50% 개선
2. 애플리케이션 코드 리팩토링: 30% 개선
3. 네트워크 최적화 (Native vs VXLAN): 5% 개선
→ 우선순위가 명확함3. 공식 문서 권장사항에는 이유가 있다
Tailscale 공식 문서:
"Run Tailscale as a system service on each node"
Cilium 공식 문서:
"VXLAN is recommended for overlay networks"
왜 처음부터 안 따랐나?
- "내 상황은 다를 거야"
- "더 나은 방법이 있을 거야"
- "최신 기술을 써야 해"
깨달음:
- 공식 문서는 수많은 사례 기반
- 대부분의 엣지 케이스 고려됨
- 특별한 이유 없으면 권장사항 따르기
4. 완벽한 설정은 없다
모든 아키텍처는 트레이드오프:
- 성능 ↔ 안정성
- 복잡도 ↔ 유연성
- 자동화 ↔ 제어권
우선순위 명확히:
- 무엇이 가장 중요한가?
- 무엇을 포기할 수 있는가?
- 팀이 관리할 수 있는가?
5. 삽질은 배움의 과정
실패한 시도들이 가치 있는 이유:
- 기술의 한계 이해
- 트레이드오프 체감
- 더 나은 결정의 근거
이 문서의 목적:
- 같은 실수 반복 방지
- 결정의 배경 공유
- 다음 구축자를 위한 가이드
🔮 향후 개선 가능성
1. Tailscale in Kubernetes 재검토
언제 다시 시도할 가치가 있나?
- Tailscale Kubernetes Operator 안정화
- CNI와의 통합 개선
- 공식 지원 시작
현재 상태:
- Tailscale Operator: 베타
- 프로덕션 사용: 권장 안 됨
2. Native Routing 재검토
언제 시도할 가치가 있나?
- BGP 라우팅 가능한 환경
- 클라우드 VPC Peering 사용
- 초고성능 필요 (HPC, ML)
우리 환경에서는:
- 서로 다른 Oracle 계정 = VPC Peering 불가
- Native Routing 불가능
3. 모니터링 강화
추가할 만한 것:
- Cilium Hubble (네트워크 가시성)
- Prometheus + Grafana
- 성능 메트릭 수집
📚 추가 자료
참고한 문서들
비슷한 경험담
✍️ 추가 실패담 (향후 작성 예정)
이 문서는 계속 업데이트됩니다. 앞으로 추가할 내용:
- iptables vs eBPF 선택 과정
- MTU 설정 시행착오
- 블록볼륨 마운트 실수
- Headscale vs Tailscale 공식 서버
- Oracle Cloud 방화벽 설정 함정
- SELinux Permissive 모드의 이유
- 기타...
기여 환영:
비슷한 경험이 있다면 공유해주세요!
*"실패는 성공의 어머니" - 하지만 남의 실패로부터 배우면 더 빠릅니다.*
'실제 경험과 인사이트를 AI와 함께 정리한 글' 카테고리의 다른 글
| Cilium devices 파라미터 완벽 가이드: Tailscale 환경에서의 핵심 (0) | 2025.10.26 |
|---|---|
| Kubernetes Pod Security Standards: nginx-unprivileged로 보안 강화하기 (0) | 2025.10.26 |
| Oracle Cloud + Tailscale + Kubernetes 완벽 가이드(5) (0) | 2025.10.26 |
| Oracle Cloud + Tailscale + Kubernetes 완벽 가이드(4) (0) | 2025.10.26 |
| Oracle Cloud + Tailscale + Kubernetes 완벽 가이드(3) (0) | 2025.10.26 |
- Total
- Today
- Yesterday
- Developer Tools
- Tailwind CSS
- troubleshooting
- Rag
- SHACL
- frontend
- react
- 개발 도구
- workflow
- knowledge graph
- claude code
- AI
- backend
- PYTHON
- AI Development
- authorization
- Tax Analysis
- LLM
- api gateway
- LangChain
- authentication
- Ontology
- Go
- architecture
- Claude
- ai 개발 도구
- Kubernetes
- security
- Next.js
- AI agent
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
