← 모든 글

Service를 통한 Pod 네트워킹 - 안정적인 접근 경로 만들기

여러 Pod로 구성된 애플리케이션에 안정적으로 접근하기 위한 Service의 개념과 활용법을 학습했습니다

CKA 준비 · 3 / 8편

이 글의 목차

학습 예시 안내: 본문의 상황과 출력은 개념 설명을 위한 예시로 정리했습니다. 당시 실행 여부는 확인되지 않았으며, 현재 환경에서의 클러스터 실습도 별도 검증이 필요합니다.

🎯 학습 목표

이 글을 통해 다음을 학습할 수 있습니다:

  • Pod 네트워킹의 한계점과 Service의 필요성
  • Service의 종류와 각각의 용도
  • ClusterIP, NodePort, LoadBalancer 실습
  • 서비스 디스커버리와 DNS 이해
  • CKA 준비 과정에서 연습할 Service 관련 문제들

📝 앞선 개념과 이번 예제

지난 글에서는 Deployment로 여러 Pod를 관리하는 방법을 다뤘습니다. 이번에는 클라이언트가 여러 Pod에 접근해야 하는 상황을 가정해 봅니다.

예제에서 가정한 환경

# 지난번에 만든 Deployment 확인
kubectl get deployment nginx-deployment
kubectl get pods -l app=nginx -o wide

출력 형식 예시:

NAME                                READY   STATUS    RESTARTS   AGE   IP            NODE
nginx-deployment-7d4c8f5d6c-abc12   1/1     Running   0          1d    172.17.0.3    minikube
nginx-deployment-7d4c8f5d6c-def34   1/1     Running   0          1d    172.17.0.4    minikube
nginx-deployment-7d4c8f5d6c-ghi56   1/1     Running   0          1d    172.17.0.5    minikube

가정한 문제 상황

각 Pod가 서로 다른 IP를 가지고 있는데, 클라이언트는 어떤 IP로 접근해야 할까요?

# Pod IP로 직접 접근 시도
curl 172.17.0.3
curl 172.17.0.4
curl 172.17.0.5

문제점들:

  1. 변동되는 IP: Pod가 삭제되고 새 Pod로 대체되면 IP가 바뀔 수 있음 (같은 Pod 안의 컨테이너 재시작과는 구분)
  2. 어떤 Pod에 접근?: 3개 중 어떤 것을 선택해야 할지 모름
  3. 로드 밸런싱 부재: 트래픽을 고르게 분산할 수 없음
  4. 외부 접근 설정 필요: 외부에서 Pod IP로 접근 가능한지는 클러스터 네트워크와 라우팅 구성에 따라 달라짐

Pod마다 다른 IP를 클라이언트가 관리하지 않도록 Service라는 접근점을 사용합니다.

🌐 Service란 무엇인가?

Service의 기본 개념

Service는 Pod들에 대한 안정적인 접근점을 제공하는 추상화 계층입니다.

클라이언트 → Service → Pod들
     ↓         ↓        ↓
   안정된    로드밸런싱   실제 워크로드
   접근점    & 디스커버리

Service의 핵심 기능

  1. 안정적인 IP와 DNS 이름 제공
  2. 로드 밸런싱 - 여러 Pod 간 트래픽 분산
  3. 서비스 디스커버리 - 다른 서비스 찾기
  4. 추상화 - Pod의 생성/삭제와 독립적

🔧 첫 번째 Service 만들기

ClusterIP Service (기본 타입)

기본적인 ClusterIP Service 구성 예제입니다:

# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80        # Service가 노출할 포트
    targetPort: 80  # Pod의 실제 포트
  type: ClusterIP   # 기본값 (생략 가능)
# Service 생성
kubectl apply -f nginx-service.yaml

# Service 확인
kubectl get service
kubectl get svc  # 축약형

출력 형식 예시:

NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginx-service   ClusterIP   10.96.123.45    <none>        80/TCP    30s

Service 동작 확인

# Service IP로 접근 테스트
kubectl run test-pod --image=curlimages/curl -it --rm --command -- sh

# Pod 내부에서 Service 접근
curl nginx-service.default.svc.cluster.local
curl nginx-service  # 같은 네임스페이스에서는 간단히
curl 10.96.123.45   # ClusterIP로도 접근 가능

확인할 동작: 여러 요청이 어떤 Pod에 전달되는지 살펴봅니다. 요청마다 반드시 다른 Pod가 선택된다고 가정하지 않습니다.

위의 기본 nginx 응답은 Pod마다 같을 수 있습니다. 분산 여부를 재현하려면 각 Pod의 접근 로그나 응답에 포함한 Pod 이름을 함께 확인해야 합니다.

📋 Service 종류별 상세 학습

1. ClusterIP (기본 타입)

용도: 클러스터 내부에서만 접근 가능한 서비스

# clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: internal-service
spec:
  selector:
    app: nginx
  ports:
  - port: 8080      # Service 포트
    targetPort: 80  # Container 포트
  type: ClusterIP

특징:

  • 클러스터 내부에서만 접근 가능
  • 마이크로서비스 간 통신에 주로 사용
  • 기본 타입이므로 type 생략 가능

2. NodePort

용도: 클러스터 외부에서 Node의 특정 포트로 접근

# nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
spec:
  selector:
    app: nginx
  ports:
  - port: 80        # Service 포트
    targetPort: 80  # Container 포트
    nodePort: 30080 # Node 포트 (30000-32767 범위)
  type: NodePort
# NodePort Service 생성
kubectl apply -f nodeport-service.yaml

# Service 확인
kubectl get svc nginx-nodeport

출력 형식 예시:

NAME             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-nodeport   NodePort   10.96.234.56    <none>        80:30080/TCP   1m

접근 방법:

# minikube에서 Node IP 확인
minikube ip

# 브라우저나 curl로 접근
curl http://192.168.49.2:30080

3. LoadBalancer

용도: 클라우드 환경에서 외부 로드 밸런서 프로비저닝

# loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer
# LoadBalancer Service 생성
kubectl apply -f loadbalancer-service.yaml

# Service 확인 (로컬 환경에서는 EXTERNAL-IP가 <pending>)
kubectl get svc nginx-loadbalancer

로컬 환경에서 테스트:

# minikube에서 LoadBalancer 시뮬레이션
minikube tunnel  # 별도 터미널에서 실행

# 이제 EXTERNAL-IP가 할당됨
kubectl get svc nginx-loadbalancer

🎯 Service와 Pod 연결 이해하기

레이블 셀렉터 동작 원리

Service가 어떤 Pod를 대상으로 삼는지 확인하는 방법입니다:

# Pod의 레이블 확인
kubectl get pods --show-labels

# Service의 셀렉터 확인
kubectl describe service nginx-service

주의할 점: Service의

selector.app: nginx

와 Pod의

labels.app: nginx

가 일치해야 연결됩니다!

Endpoints 확인

2026-09-29 보완: 아래는 기존 Endpoints 조회 예제입니다. Endpoints API는 Kubernetes 1.33부터 사용 중단 예정(deprecated) 상태이며, 새 확인에는 kubectl get endpointslices -l kubernetes.io/service-name=nginx-service -o yaml을 사용합니다. 공식 안내

# Service가 어떤 Pod들을 타겟으로 하는지 확인
kubectl get endpoints nginx-service

# 상세 정보
kubectl describe endpoints nginx-service

출력 형식 예시:

NAME            ENDPOINTS                                      AGE
nginx-service   172.17.0.3:80,172.17.0.4:80,172.17.0.5:80    5m

위 출력 예시에는 세 Pod의 IP가 표시되어 있습니다. 엔드포인트 목록에 포함됐다는 사실과 실제 요청이 분산됐다는 사실은 구분해서 확인해야 합니다.

🔍 서비스 디스커버리와 DNS

Kubernetes DNS 이해하기

Kubernetes는 자동으로 DNS 레코드를 생성합니다:

# DNS 테스트 Pod 생성
kubectl run dns-test --image=busybox -it --rm -- sh

# Pod 내부에서 DNS 확인
nslookup nginx-service
nslookup nginx-service.default.svc.cluster.local

DNS 패턴:

<service-name>.<namespace>.svc.cluster.local

환경변수를 통한 서비스 디스커버리

# 새 Pod에서 환경변수 확인
kubectl run env-test --image=busybox -it --rm -- env | grep NGINX_SERVICE

# 결과 예시
NGINX_SERVICE_SERVICE_HOST=10.96.123.45
NGINX_SERVICE_SERVICE_PORT=80

💡 고급 Service 설정

다중 포트 Service

# multi-port-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: multi-port-service
spec:
  selector:
    app: web-app
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: https
    port: 443
    targetPort: 8443
  type: ClusterIP

세션 어피니티 설정

# session-affinity-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: sticky-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  sessionAffinity: ClientIP  # 같은 클라이언트는 같은 Pod로

ExternalName Service

# external-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: database.example.com

이 타입은 외부 서비스에 대한 DNS 별칭을 만들어 줍니다.

🚨 문제 해결과 디버깅

Service가 작동하지 않을 때

1. Endpoints 확인

# Endpoints가 비어있는 경우
kubectl get endpoints my-service

# 비어있다면 셀렉터·대상 Pod 존재 여부·Ready 상태를 확인
kubectl describe service my-service
kubectl get pods --show-labels

2. 네트워크 정책 확인

# Pod 간 통신 테스트
kubectl exec -it test-pod -- wget -qO- nginx-service

3. 포트 설정 확인

# Service와 Pod의 포트 매핑 확인
kubectl describe service my-service
kubectl describe pod <pod-name>

자주 하는 실수들

1. 셀렉터 불일치

# ❌ 잘못된 예
Service selector: app=web
Pod labels: app=nginx

# ✅ 올바른 예
Service selector: app=nginx
Pod labels: app=nginx

2. 포트 매핑 실수

# ❌ 잘못된 예
ports:
- port: 80
  targetPort: 8080  # Pod는 실제로 80포트 사용

---
# ✅ 올바른 예
ports:
- port: 80
  targetPort: 80

🎯 실전 예제: 3-tier 애플리케이션

앞의 개념을 연결하기 위한 가상의 애플리케이션 구성 예제입니다.

Frontend Service (LoadBalancer)

# frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  selector:
    tier: frontend
  ports:
  - port: 80
    targetPort: 3000
  type: LoadBalancer

Backend Service (ClusterIP)

# backend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  selector:
    tier: backend
  ports:
  - port: 8080
    targetPort: 8080
  type: ClusterIP

Database Service (ClusterIP)

# database-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: database-service
spec:
  selector:
    tier: database
  ports:
  - port: 5432
    targetPort: 5432
  type: ClusterIP

네트워크 흐름:

외부 클라이언트 → Frontend Service (LoadBalancer)
                     ↓
              Frontend Pods → Backend Service (ClusterIP)
                               ↓
                        Backend Pods → Database Service (ClusterIP)
                                        ↓
                                 Database Pods

📊 CKA 대비 연습 패턴

연습할 문제 유형

1. Service 생성과 노출

# 문제: 기존 Deployment를 ClusterIP로 노출
kubectl expose deployment nginx-deployment --port=80 --target-port=80

# 문제: NodePort로 노출
kubectl expose deployment nginx-deployment --type=NodePort --port=80

2. Service와 Pod 매핑 확인

# 문제: Service가 어떤 Pod를 타겟으로 하는지 확인
kubectl get endpoints <service-name>
kubectl describe service <service-name>

3. 서비스 디스커버리 테스트

# 문제: Pod에서 다른 서비스에 접근 가능한지 확인
kubectl exec -it <pod-name> -- nslookup <service-name>
kubectl exec -it <pod-name> -- curl <service-name>

4. 문제 해결

  • Service가 Pod와 연결되지 않는 이유 찾기
  • 외부에서 서비스에 접근할 수 없는 문제 해결

시간 단축 명령어

# 빠른 Service 생성
kubectl expose deployment <name> --port=80 --target-port=80
kubectl expose deployment <name> --type=NodePort --port=80

# Service 정보 빠른 확인
kubectl get svc -o wide
kubectl describe svc <name>

# 서비스 테스트
kubectl run test --image=curlimages/curl -it --rm --command -- curl <service-name>

📚 Service 타입별 정리

Service 타입 비교표

타입 접근 범위 사용 사례 EXTERNAL-IP
ClusterIP 클러스터 내부 마이크로서비스 간 통신 None
NodePort 클러스터 외부 개발/테스트 환경 None
LoadBalancer 클러스터 외부 운영 환경 (클라우드) 할당됨
ExternalName DNS 별칭 외부 서비스 연동 설정한 FQDN

포트 설정 이해

ports:
- port: 80          # Service에서 노출하는 포트
  targetPort: 8080  # Pod의 실제 포트
  nodePort: 30080   # Node에서 노출하는 포트 (NodePort만)

필수 명령어 정리

# Service 관리
kubectl expose deployment <name> --port=<port>
kubectl get services  # 또는 kubectl get svc
kubectl describe service <name>
kubectl delete service <name>

# 연결 확인
kubectl get endpoints <name>
kubectl describe endpoints <name>

# 네트워크 테스트
kubectl exec -it <pod> -- curl <service>
kubectl exec -it <pod> -- nslookup <service>

🚀 다음 학습 계획

Service 다음에는 애플리케이션의 설정을 관리하는 ConfigMap과 Secret을 살펴볼 계획입니다.

다음 주제들

  • ConfigMap과 Secret으로 설정 관리 - 환경별 설정 분리
  • Pod 리소스 제한과 요청 설정 - 리소스 최적화
  • Liveness와 Readiness Probe 구성 - 헬스체크
  • Ingress를 통한 외부 트래픽 관리 - 고급 라우팅
  • 네임스페이스를 통한 리소스 격리

개인 학습 목표

  • 복잡한 네트워크 구조에서의 서비스 디스커버리 이해
  • 다양한 Service 타입의 적절한 활용
  • 네트워크 문제 발생 시 빠른 진단 능력 향상

Service는 Pod 교체와 클라이언트의 접근 경로를 분리하는 역할을 합니다. 실습할 때는 대상 Pod 선택, 엔드포인트 등록, 실제 요청 전달을 나누어 확인하는 것이 핵심입니다.

다음 글에서는 컨테이너의 설정 데이터를 분리하는 ConfigMap과 Secret을 다룹니다.


🔗 참고 자료:


yellow.log · 2025.08.02에 작성 · 2026.09.29에 수정

CKA 준비 전체 8편

  1. 1.Pod 생성과 관리 - 쿠버네티스의 기본 단위 이해하기
  2. 2.ReplicaSet과 Deployment로 Pod 관리하기 - 확장성과 가용성 확보
  3. 3.Service를 통한 Pod 네트워킹 - 안정적인 접근 경로 만들기읽는 중
  4. 4.ConfigMap과 Secret으로 설정 관리하기 - 환경별 설정 분리
  5. 5.Pod 리소스 제한과 요청 설정 - 안정적인 클러스터 운영을 위한 리소스 관리
  6. 6.Liveness와 Readiness Probe 구성 - 헬스체크와 자동 복구
  7. 7.네임스페이스를 통한 리소스 격리와 다중 테넌시 - 팀별, 환경별 격리
  8. 8.Ingress를 통한 외부 트래픽 관리와 라우팅 - 클러스터의 똑똑한 관문 구축