🚀 쿠버네티스 서비스 타입별 실습 결과 보고서
📋 메타데이터
- 실습일: 2025년 11월 13일
- 환경: minikube v1.37.0, Kubernetes v1.34.0
- 실습자: Claude Code
- 관련 문서: 04_00_kubernetes-service-types-guide
🎯 실습 개요
쿠버네티스의 3가지 핵심 서비스 타입(ExternalName, ClusterIP, Headless)을 실제 환경에서 구현하고 테스트한 결과를 정리
🌐 1. ExternalName 서비스 실습 결과
📝 구현 내용
- 서비스명:
mysql-external,github-api-external - 외부 도메인:
db.example.com,api.github.com - 포트: 3306, 443
🧪 테스트 결과
서비스 생성 확인
$ kubectl get svc mysql-external
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql-external ExternalName <none> db.example.com 3306/TCP 3sDNS 해석 테스트 결과
$ kubectl exec test-pod -- nslookup github-api-external.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
github-api-external.default.svc.cluster.local canonical name = api.github.com
Name: api.github.com
Address: 20.200.245.245✅ 검증 결과
- CNAME 별칭이 올바르게 설정됨
- DNS 해석을 통해 외부 IP 반환 확인
- 서비스 내부에서 외부 도메인에 접근 가능
🏠 2. ClusterIP 서비스 실습 결과
📝 구현 내용
- 백엔드 파드: nginx:alpine × 3개
- 서비스명:
backend-service - 서비스 포트: 8080 → 타겟 포트 80
🧪 테스트 결과
파드 및 서비스 상태
$ kubectl get pods -l app=backend -o wide
NAME READY STATUS RESTARTS AGE IP NODE
backend-app-f8cf8f9bc-9fwkm 1/1 Running 0 15s 10.244.0.6 minikube
backend-app-f8cf8f9bc-km7bw 1/1 Running 0 15s 10.244.0.4 minikube
backend-app-f8cf8f9bc-llxl4 1/1 Running 0 15s 10.244.0.5 minikube
$ kubectl get svc backend-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend-service ClusterIP 10.100.38.243 <none> 8080/TCP 3s엔드포인트 확인
$ kubectl get endpoints backend-service
NAME ENDPOINTS AGE
backend-service 10.244.0.4:80,10.244.0.5:80,10.244.0.6:80 9s로드밸런싱 테스트
$ kubectl exec test-pod -- sh -c "for i in 1 2 3 4 5; do wget -qO- backend-service:8080 | grep '<h1>'; done"
<h1>Welcome to nginx!</h1>
<h1>Welcome to nginx!</h1>
<h1>Welcome to nginx!</h1>
<h1>Welcome to nginx!</h1>
<h1>Welcome to nginx!</h1>✅ 검증 결과
- ClusterIP가 정상 할당됨 (
10.100.38.243) - 3개 파드가 엔드포인트에 등록됨
- 내부 로드밸런싱이 정상 작동
- 포트 포워딩으로 외부 접근 확인
👻 3. Headless 서비스 실습 결과
📝 구현 내용
- StatefulSet: MongoDB × 3개 (mongodb-0, mongodb-1, mongodb-2)
- Headless 서비스:
mongodb-headless(clusterIP: None) - 비교용 ClusterIP:
mongodb-clusterip
🧪 테스트 결과
StatefulSet 및 서비스 상태
$ kubectl get pods -l app=mongodb -o wide
NAME READY STATUS RESTARTS AGE IP NODE
mongodb-0 1/1 Running 0 40s 10.244.0.8 minikube
mongodb-1 1/1 Running 0 21s 10.244.0.9 minikube
mongodb-2 1/1 Running 0 20s 10.244.0.10 minikube
$ kubectl get svc | grep mongodb
mongodb-clusterip ClusterIP 10.97.68.182 <none> 27017/TCP 3s
mongodb-headless ClusterIP None <none> 27017/TCP 97sDNS 해석 비교 테스트
Headless 서비스 (모든 파드 IP 반환)
$ kubectl exec dns-test -- nslookup mongodb-headless.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: mongodb-headless.default.svc.cluster.local
Address: 10.244.0.8
Name: mongodb-headless.default.svc.cluster.local
Address: 10.244.0.10
Name: mongodb-headless.default.svc.cluster.local
Address: 10.244.0.9ClusterIP 서비스 (단일 가상 IP)
$ kubectl exec dns-test -- nslookup mongodb-clusterip.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: mongodb-clusterip.default.svc.cluster.local
Address: 10.97.68.182개별 파드 직접 접근
$ kubectl exec dns-test -- nslookup mongodb-0.mongodb-headless.default.svc.cluster.local
Name: mongodb-0.mongodb-headless.default.svc.cluster.local
Address: 10.244.0.8
$ kubectl exec dns-test -- nslookup mongodb-1.mongodb-headless.default.svc.cluster.local
Name: mongodb-1.mongodb-headless.default.svc.cluster.local
Address: 10.244.0.9
$ kubectl exec dns-test -- nslookup mongodb-2.mongodb-headless.default.svc.cluster.local
Name: mongodb-2.mongodb-headless.default.svc.cluster.local
Address: 10.244.0.10✅ 검증 결과
- ClusterIP가 None으로 설정됨
- DNS 조회 시 모든 파드 IP 반환 확인
-
pod-name.service-name형태로 개별 접근 가능 - StatefulSet과 Headless 서비스 정상 연동
📊 서비스 타입별 비교 분석
| 항목 | ExternalName | ClusterIP | Headless |
|---|---|---|---|
| ClusterIP 할당 | ❌ None | ✅ 가상 IP | ❌ None |
| DNS 해석 결과 | 외부 FQDN | 단일 IP | 모든 파드 IP |
| 로드밸런싱 | ❌ 없음 | ✅ kube-proxy | ❌ 없음 |
| 개별 파드 접근 | ❌ 불가 | ❌ 불가 | ✅ 가능 |
| 주요 용도 | 외부 서비스 추상화 | 내부 마이크로서비스 | StatefulSet, 분산 DB |
🔍 주요 학습 포인트
1. DNS 동작 방식의 차이
- ExternalName: DNS CNAME 레코드로 외부 도메인 매핑
- ClusterIP: A 레코드로 단일 가상 IP 반환 (kube-proxy가 로드밸런싱)
- Headless: 여러 A 레코드로 모든 파드 IP 직접 반환
2. 서비스 디스커버리 패턴
- ExternalName: 환경별 외부 의존성 추상화
- ClusterIP: 표준 마이크로서비스 간 통신
- Headless: 상태가 있는 애플리케이션의 P2P 통신
3. StatefulSet과의 관계
- Headless 서비스: StatefulSet의 serviceName으로 지정
- 안정적인 네트워크 ID:
<pod-name>.<service-name>.<namespace>.svc.cluster.local - 순서보장: StatefulSet 파드의 순차적 생성/삭제
🚨 실습 중 발견한 이슈
1. DNS 검색 도메인 이슈
- 현상: 짧은 이름으로 nslookup 시 NXDOMAIN 오류
- 해결: FQDN 사용 (
service.namespace.svc.cluster.local) - 원인: CoreDNS의 검색 도메인 설정
2. StatefulSet 파드 순차 생성
- 현상: 파드가 한 번에 모두 생성되지 않음
- 정상 동작: StatefulSet은 순차적 파드 생성이 기본 정책
- 확인:
kubectl get pods --watch로 생성 과정 관찰
🛠️ 실습 환경 정보
# 클러스터 정보
Kubernetes: v1.34.0
Platform: minikube v1.37.0
Driver: qemu2
OS: macOS Darwin 24.6.0 (ARM64)
CNI: bridge
DNS: CoreDNS (10.96.0.10)
# 네트워크 정보
Pod Network: 10.244.0.0/16
Service Network: 10.96.0.0/12
Node IP: minikube (single node)📚 관련 문서 및 참고 자료
내부 링크
- 04_00_kubernetes-service-types-guide - 실습 가이드 원본
- Kubernetes (MOC) - 쿠버네티스 개념 지도
- K8s - Service - 서비스 개념 상세
- 워커 노드 (Worker Node) - 노드 아키텍처
외부 참고 자료
🎯 다음 학습 방향
즉시 실습 가능
심화 학습
📝 실습 후기
✅ 성과
- 이론과 실제의 차이 명확히 이해
- DNS 기반 서비스 디스커버리 메커니즘 실증
- 각 서비스 타입의 적절한 사용 사례 파악
- 트러블슈팅 경험 축적
🔄 개선 사항
- 더 복잡한 네트워크 정책과 함께 테스트
- 멀티 노드 환경에서의 동작 확인
- 실제 애플리케이션 워크로드로 성능 테스트
📅 작성일: 2025.11.13
🏷️ 태그: kubernetes service networking 실습 dns statefulset
🔗 연결: K8s_Deep_Dive의 실습 시리즈