이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • Pod, Deployment, Service, Ingress는 요청 경로에서 각각 무엇을 담당하는가?
  • Spring 애플리케이션을 Kubernetes에 배포할 때 어떤 운영 신호를 봐야 하는가?
  • Running Pod가 있어도 사용자가 API를 못 쓰는 이유는 무엇인가?

개요

Kubernetes는 컨테이너를 직접 실행하는 도구가 아니라 원하는 상태를 선언하고 controller가 그 상태를 유지하게 하는 운영 시스템이다.

Spring 백엔드 입장에서 가장 먼저 이해해야 할 리소스는 Pod, Deployment, Service, Ingress다.

Pod는 컨테이너 실행 단위다.

Deployment는 원하는 Pod 수와 배포 전략을 유지한다.

Service는 계속 바뀌는 Pod IP 앞에 안정적인 접근 지점을 만든다.

Ingress는 외부 HTTP 요청을 host와 path 기준으로 Service에 연결한다.

이 네 가지를 분리해 이해해야 “Pod는 있는데 API가 안 된다” 같은 장애를 분석할 수 있다.

요청 흐름

client
  Ingress
    Service
      Pod IP:containerPort
        Spring Boot application

각 단계의 실패 신호는 다르다.

  • Ingress가 틀리면 외부 요청이 Service에 도달하지 않는다.
  • Service selector가 틀리면 정상 Pod가 있어도 endpoint가 비어 있다.
  • Pod가 Running이어도 readiness가 실패하면 Service endpoint에서 제외될 수 있다.
  • containerPort와 Spring server port가 다르면 요청이 연결되지 않는다.
  • Deployment rollout이 멈추면 새 버전 Pod가 충분히 준비되지 않는다.

따라서 장애 중에는 Pod 로그만 보는 것이 아니라 리소스 연결을 따라가야 한다.

Deployment 예시

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  template:
    metadata:
      labels:
        app: order-api
    spec:
      containers:
        - name: api
          image: registry.example.com/order-api:2026.07.01
          ports:
            - containerPort: 8080
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: prod
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080

Deployment에서 중요한 것은 image tag, label, selector, replica 수, update strategy, port, readiness다.

Spring 애플리케이션이 뜨기 전에 트래픽을 받으면 배포 직후 장애가 된다.

Service와 Ingress 예시

apiVersion: v1
kind: Service
metadata:
  name: order-api
spec:
  selector:
    app: order-api
  ports:
    - name: http
      port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: order-api
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /orders
            pathType: Prefix
            backend:
              service:
                name: order-api
                port:
                  number: 80

Service의 selector가 Deployment template label과 맞아야 한다.

Ingress의 host와 path가 기대한 API 경로와 맞아야 한다.

관찰 명령

kubectl get deploy,rs,pod,svc,ingress
kubectl rollout status deploy/order-api
kubectl get endpoints order-api
kubectl describe ingress order-api
kubectl logs deploy/order-api --tail=100

명령 결과는 리소스가 존재하는지만 보지 않는다.

Deployment의 desired/current/available 수, Pod event, Service endpoint, Ingress backend 연결을 함께 본다.

kubectl logs는 애플리케이션 내부 문제를 보여 주고, kubectl describe는 controller가 왜 원하는 상태를 만들지 못했는지 보여 준다.

장애 신호

  • Deployment rollout이 끝나지 않는다.
  • 새 ReplicaSet의 Pod가 계속 CrashLoopBackOff가 된다.
  • Pod는 Running인데 Service endpoint가 비어 있다.
  • Ingress는 존재하지만 host 또는 path rule이 기대와 다르다.
  • 특정 Pod만 5xx가 많다.
  • readiness 실패로 새 Pod가 트래픽을 받지 못한다.
  • image pull 실패로 새 버전이 생성되지 않는다.

이 신호는 Kubernetes 리소스 연결이나 Spring 기동 조건 중 하나가 어긋났다는 뜻이다.

안전한 완화 조치

  • 새 Deployment가 문제라면 rollout undo 전에 현재 ReplicaSet과 image tag를 기록한다.
  • Service endpoint가 비어 있으면 selector와 Pod label을 먼저 비교한다.
  • 특정 Pod만 문제라면 해당 Pod를 트래픽에서 제외하거나 삭제해 재생성을 유도한다.
  • Ingress rule 문제는 영향 host/path만 수정하고 전체 rule을 흔들지 않는다.
  • image pull 문제는 registry 권한과 tag 존재 여부를 확인한다.
  • 배포 중 장애가 커지면 이전 ReplicaSet이 충분히 살아 있는지 확인한 뒤 되돌린다.

완화는 리소스 관계를 좁혀 적용해야 한다.

하지 말아야 할 대응

  • label과 selector를 확인하지 않고 Pod를 계속 재시작하지 않는다.
  • Running 상태만 보고 서비스가 정상이라고 판단하지 않는다.
  • latest tag를 운영 배포에 사용하지 않는다.
  • Ingress 전체 rule을 임시로 삭제해 다른 경로까지 중단하지 않는다.
  • rollout 실패 원인을 남기지 않고 바로 manifest를 덮어쓰지 않는다.

인프라 담당자와 공유할 자료

  • namespace, Deployment, Service, Ingress 이름
  • image tag와 rollout 시작 시각
  • desired/current/available Pod 수
  • Service selector와 endpoint 목록
  • Ingress host/path와 backend Service
  • Pod event와 애플리케이션 로그 샘플
  • 이미 실행한 rollout, scale, delete 조치

공유 자료는 “Kubernetes가 이상하다”가 아니라 “이 리소스 관계에서 어디가 끊겼다”로 정리해야 한다.

운영 체크리스트

  • Deployment label과 Service selector가 일치하는가?
  • containerPort와 Spring server port가 일치하는가?
  • readiness가 설정되어 배포 직후 트래픽을 늦추는가?
  • rollout 실패 시 이전 버전으로 돌아가는 절차가 있는가?
  • Ingress host/path 변경이 API 경로와 같이 검토되는가?
  • Pod 로그와 event를 모두 확인하는가?

확인 질문

확인 질문

  • Service가 필요한 이유는 무엇인가?
    • Pod IP는 계속 바뀌므로 Pod 집합 앞에 안정적인 접근 지점이 필요하기 때문이다.
  • Pod가 Running인데 사용자가 API를 못 쓰는 이유는 무엇인가?
    • readiness, Service selector, endpoint, Ingress rule, port 연결 중 하나가 실패할 수 있기 때문이다.
  • Deployment 장애에서 먼저 비교할 두 값은 무엇인가?
    • 원하는 replica 수와 실제 available Pod 수, 그리고 Service selector와 Pod label이다.

리뷰 체크포인트

  • Pod, Deployment, Service, Ingress의 책임이 분리되어 있는가?
  • 요청 경로를 리소스 관계로 따라갈 수 있는가?
  • Spring port와 readiness가 manifest에 반영되어 있는가?
  • rollout 실패와 되돌림 절차가 있는가?
  • selector/label 불일치 점검이 포함되어 있는가?