🚀 쿠버네티스 서비스 타입별 실습 결과 보고서

📋 메타데이터

🎯 실습 개요

쿠버네티스의 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   3s

DNS 해석 테스트 결과

$ 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   97s

DNS 해석 비교 테스트

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.9

ClusterIP 서비스 (단일 가상 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 서비스 정상 연동

📊 서비스 타입별 비교 분석

항목ExternalNameClusterIPHeadless
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)

📚 관련 문서 및 참고 자료

내부 링크

외부 참고 자료

🎯 다음 학습 방향

즉시 실습 가능

심화 학습


📝 실습 후기

✅ 성과

  1. 이론과 실제의 차이 명확히 이해
  2. DNS 기반 서비스 디스커버리 메커니즘 실증
  3. 각 서비스 타입의 적절한 사용 사례 파악
  4. 트러블슈팅 경험 축적

🔄 개선 사항

  1. 더 복잡한 네트워크 정책과 함께 테스트
  2. 멀티 노드 환경에서의 동작 확인
  3. 실제 애플리케이션 워크로드로 성능 테스트

📅 작성일: 2025.11.13
🏷️ 태그: kubernetes service networking 실습 dns statefulset
🔗 연결: K8s_Deep_Dive의 실습 시리즈