TestForge Blog
← 전체 포스트

Kubernetes 개발·운영 실전 4편 — 네트워크 설계 실전 (Service / Ingress / NetworkPolicy)

Kubernetes Service 타입별 차이, Ingress 구성, NetworkPolicy로 Pod 간 통신을 제어하는 실전 가이드. 클러스터 내부/외부 트래픽 흐름을 설계하는 방법.

TestForge Team ·

Kubernetes 네트워크의 기본 원칙

Kubernetes 네트워크는 두 가지 기본 규칙을 따릅니다.

  1. 모든 Pod는 서로 통신 가능 — 기본적으로 클러스터 내 모든 Pod가 직접 통신
  2. Pod IP는 재시작 시 바뀜 — Service가 고정 엔드포인트를 제공

이 구조를 이해하면 Service, Ingress, NetworkPolicy가 왜 필요한지 명확해집니다.


1. Service 타입 선택

ClusterIP — 클러스터 내부 통신 (기본)

apiVersion: v1
kind: Service
metadata:
  name: api-service
  namespace: production
spec:
  type: ClusterIP  # 기본값
  selector:
    app: api-server
  ports:
    - port: 80         # 서비스 포트
      targetPort: 8080 # Pod 포트
      protocol: TCP

클러스터 내부에서만 접근 가능합니다. 외부 노출이 필요 없는 모든 서비스에 사용합니다.

NodePort — 노드 포트로 외부 노출 (개발/테스트 한정)

spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080  # 30000-32767 범위

모든 노드의 30080 포트로 접근 가능합니다. 프로덕션에서는 Ingress를 사용하고, NodePort는 로컬 테스트 또는 로드 밸런서 없는 온프레미스 환경에만 사용합니다.

LoadBalancer — 클라우드 로드 밸런서 연결

spec:
  type: LoadBalancer
  ports:
    - port: 443
      targetPort: 8443

클라우드 프로바이더(AWS ELB, GCP LB 등)가 자동으로 로드 밸런서를 생성합니다. 서비스마다 별도 로드 밸런서가 생성되어 비용이 높아질 수 있으므로, 여러 서비스를 노출할 때는 Ingress를 사용합니다.

Service 타입 선택 기준

외부 노출 불필요     → ClusterIP
HTTP/HTTPS 다중 서비스 → Ingress + ClusterIP
TCP/UDP 단일 서비스   → LoadBalancer
로컬 개발/테스트     → NodePort

2. Ingress — HTTP 트래픽 라우팅

Ingress는 하나의 로드 밸런서로 여러 서비스를 라우팅하는 L7 게이트웨이입니다.

기본 Ingress 설정 (nginx)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls-secret  # cert-manager가 자동 발급
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /api/v1
            pathType: Prefix
            backend:
              service:
                name: api-v1-service
                port:
                  number: 80
          - path: /api/v2
            pathType: Prefix
            backend:
              service:
                name: api-v2-service
                port:
                  number: 80

cert-manager로 TLS 자동화

# ClusterIssuer 설정 (Let's Encrypt)
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx
# Ingress에 자동 인증서 발급 annotation 추가
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - api.example.com
      secretName: api-tls  # cert-manager가 자동 생성

Ingress 고급 설정 — Rate Limiting, 타임아웃

metadata:
  annotations:
    # Rate Limiting
    nginx.ingress.kubernetes.io/limit-rps: "100"
    nginx.ingress.kubernetes.io/limit-connections: "20"
    # 타임아웃
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
    # 요청 크기 제한
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"

3. NetworkPolicy — Pod 간 통신 제어

기본적으로 Kubernetes는 모든 Pod 간 통신을 허용합니다. NetworkPolicy를 적용하면 명시적으로 허용한 트래픽만 통과시킵니다.

기본 정책 — 모든 인바운드 차단

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}  # 네임스페이스 내 모든 Pod
  policyTypes:
    - Ingress       # 인바운드만 차단 (아웃바운드는 허용 유지)

API 서버 — 특정 소스만 허용

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-server-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
    - Ingress
    - Egress
  ingress:
    # Ingress 컨트롤러에서만 인바운드 허용
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ingress-nginx
      ports:
        - protocol: TCP
          port: 8080
  egress:
    # DB 접근 허용
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
    # Redis 접근 허용
    - to:
        - podSelector:
            matchLabels:
              app: redis
      ports:
        - protocol: TCP
          port: 6379
    # DNS 허용 (없으면 도메인 조회 불가)
    - to:
        - namespaceSelector: {}
      ports:
        - protocol: UDP
          port: 53

네임스페이스 간 통신 제어

# payment-service → auth-service 통신 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-payment
  namespace: auth-service
spec:
  podSelector:
    matchLabels:
      app: auth-api
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: payment-service
          podSelector:
            matchLabels:
              app: payment-api
      ports:
        - port: 8080

4. DNS와 서비스 디스커버리

Kubernetes는 CoreDNS로 서비스 디스커버리를 제공합니다.

<service-name>.<namespace>.svc.cluster.local
# 같은 네임스페이스: 서비스 이름만으로 접근 가능
curl http://api-service/health

# 다른 네임스페이스: FQDN 사용
curl http://api-service.production.svc.cluster.local/health

# StatefulSet Pod 직접 접근
curl http://redis-0.redis-headless.production.svc.cluster.local:6379

ndots 설정 — DNS 성능 최적화

spec:
  dnsConfig:
    options:
      - name: ndots
        value: "2"  # 기본 5에서 낮춰 불필요한 DNS 조회 감소

5. 트래픽 흐름 전체 그림

외부 요청

[Cloud Load Balancer]

[Ingress Controller (nginx)]
    ↓ (TLS 종료, 라우팅)
[ClusterIP Service]

[Pod] → [NetworkPolicy 체크] → [DB Service] → [DB Pod]

실전 체크리스트

# Service 엔드포인트 확인 (Pod가 연결됐는지)
kubectl get endpoints api-service -n production

# Ingress 상태 확인
kubectl describe ingress api-ingress -n production

# NetworkPolicy 목록
kubectl get networkpolicy -n production

# DNS 조회 테스트
kubectl run -it --rm dns-test --image=busybox --restart=Never -- \
  nslookup api-service.production.svc.cluster.local

# 서비스 간 통신 테스트
kubectl run -it --rm curl-test --image=curlimages/curl --restart=Never -- \
  curl http://api-service.production.svc.cluster.local/health

정리

컴포넌트역할사용 기준
ClusterIP내부 통신 고정 엔드포인트모든 내부 서비스 기본
LoadBalancer클라우드 LB 연결TCP/UDP 단일 서비스 외부 노출
IngressHTTP 라우팅 + TLS다중 HTTP 서비스 외부 노출
NetworkPolicy트래픽 화이트리스트서비스 간 통신 명시적 제어

다음 편에서는 Helm 실전 관리를 다룹니다. Chart 구조 설계, values 파일로 환경 분리, 배포 전략을 정리합니다.