Kubernetes/Kubernetes Advanced

📌 [StatefulSet 심화편 #2] StatefulSet의 Pod 네트워크와 DNS 관리

ygtoken 2025. 3. 13. 10:56
728x90

 

1️⃣ 개요

 

StatefulSet은 각 Pod가 고유한 네트워크 ID를 유지해야 하는 애플리케이션을 위한 쿠버네티스 리소스입니다.

특히 데이터베이스, 메시지 브로커, 캐시 시스템과 같이 노드 간 통신이 필요한 경우 고유한 DNS 주소와 네트워크 정책이 필수적입니다.

 

이번 글에서는 StatefulSet의 네트워크 관리 방식과, Headless Service를 활용한 Pod 간 통신 방법을 설명하겠습니다. 🚀

 


2️⃣ StatefulSet의 네트워크 관리 원리

 

✅ 1. StatefulSet Pod의 고유 네트워크 ID

 

일반적인 Deployment의 Pod는 삭제 후 재시작되면 임의의 이름이 부여됩니다.

반면, StatefulSet은 각 Pod가 고유한 네트워크 이름을 유지합니다.

 

📌 StatefulSet Pod 네이밍 규칙

<StatefulSet 이름>-<순번>.<Service 이름>

예를 들어, StatefulSet 이름이 redis이고, Service 이름이 redis-headless인 경우:

redis-0.redis-headless

redis-1.redis-headless

redis-2.redis-headless

 

이처럼 각 Pod는 고유한 DNS 이름을 가지므로, 클러스터 내에서 서로 안정적으로 통신할 수 있습니다.

 


✅ 2. Headless Service를 활용한 DNS 설정

 

StatefulSet Pod의 DNS 주소를 유지하려면 Headless Service를 사용해야 합니다.

이는 일반적인 Service와 달리 클러스터 내부에서 개별 Pod를 직접 참조할 수 있도록 지원합니다.

 

📌 Headless Service 설정 예제

apiVersion: v1
kind: Service
metadata:
  name: redis-headless
spec:
  clusterIP: None  # Headless Service로 설정
  selector:
    app: redis
  ports:
    - port: 6379

이 설정을 적용하면 각 Pod는 redis-0.redis-headless, redis-1.redis-headless 같은 DNS 이름을 가지게 됩니다.

 


3️⃣ StatefulSet을 활용한 Pod 간 통신 구성

 

✅ 1. StatefulSet과 Headless Service를 활용한 Redis 클러스터 구축

 

아래 설정을 적용하면 Pod 간 네트워크 통신이 가능한 Redis 클러스터를 구축할 수 있습니다.

 

📌 StatefulSet 설정 예제

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: redis-headless  # Headless Service 연결
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:latest
          args:
            - "--cluster-enabled yes"
            - "--cluster-config-file nodes.conf"
          volumeMounts:
            - name: redis-data
              mountPath: /data
  volumeClaimTemplates:
    - metadata:
        name: redis-data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Gi

 

📌 각 Pod 간 통신 확인

kubectl exec -it redis-0 -- ping redis-1.redis-headless
kubectl exec -it redis-1 -- ping redis-2.redis-headless

각 Pod가 redis-0.redis-headless, redis-1.redis-headless 같은 고유한 DNS 이름을 가지므로 안정적인 통신이 가능합니다.

 


4️⃣ StatefulSet 네트워크 관리 시 고려해야 할 점

 

✅ 1. StatefulSet Pod 삭제 시 네트워크 ID 유지

 

StatefulSet의 Pod를 삭제해도 이전과 동일한 네트워크 ID를 유지해야 합니다.

이를 위해 --cascade=orphan 옵션을 사용하여 ReplicaSet을 삭제하지 않고 유지할 수 있습니다.

 

📌 Pod 삭제 시 네트워크 ID 유지

kubectl delete pod redis-1 --cascade=orphan

이렇게 하면 redis-1이 다시 생성될 때 동일한 네트워크 이름을 유지할 수 있습니다.

 


✅ 2. StatefulSet Pod의 재배포 시 네트워크 복원 순서

 

StatefulSet Pod가 재시작될 경우, 기본적으로 순차적으로 복원됩니다.

즉, redis-0이 정상적으로 기동된 후에야 redis-1이 시작됩니다.

 

📌 Pod 복원 순서 확인

kubectl rollout status statefulset redis

이 방식은 데이터 정합성을 보장해야 하는 애플리케이션(예: DB, 메시지 브로커)에 유용합니다.

 


✅ 3. NetworkPolicy를 활용한 StatefulSet 네트워크 보안 설정

 

StatefulSet Pod 간 네트워크 통신을 보장하면서 외부 접근을 제한하려면 NetworkPolicy를 활용해야 합니다.

 

📌 Redis StatefulSet 내부 통신을 허용하고, 외부 접근 차단

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: redis-network-policy
spec:
  podSelector:
    matchLabels:
      app: redis
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: redis
      ports:
        - protocol: TCP
          port: 6379
  policyTypes:
    - Ingress

 

📌 NetworkPolicy 적용

kubectl apply -f network-policy.yaml

이제 Redis Pod 간 통신은 가능하지만, 외부에서 직접 접근할 수 없습니다.

 


🔥 5️⃣ 결론

 

StatefulSet은 각 Pod가 고유한 네트워크 ID를 유지해야 하는 애플리케이션에 적합

Deployment와 달리 StatefulSet Pod는 DNS 주소를 유지하며, 순차적으로 복구됨

Pod 간 통신을 위해 반드시 Headless Service를 활용해야 함

Pod 삭제 시에도 네트워크 ID를 유지할 수 있도록 관리해야 함

NetworkPolicy를 설정하여 StatefulSet Pod 간 보안 설정을 강화할 수 있음

728x90