13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] Deployment

  • [Kubernetes] StatefulSet vs Deployment: 상태 저장 애플리케이션 배포 비교

    [Kubernetes] StatefulSet vs Deployment: 상태 저장 애플리케이션 배포 비교

    [Kubernetes] Kubernetes StatefulSet vs Deployment 비교 분석

    Kubernetes StatefulSet vs Deployment를 처음 제대로 구분하게 된 건, 홈랩에서 데이터베이스를 올렸다가 볼륨이 꼬이면서 한참 삽질했을 때였습니다. 처음엔 둘 다 그냥 Pod(파드)를 여러 개 띄우는 Kubernetes 워크로드(workload, 애플리케이션 실행 단위)겠거니 싶었거든요. 근데 실제로 운영해보니까 차이가 꽤 크더라고요. 특히 상태 저장 애플리케이션(stateful application, 데이터와 식별성이 중요한 앱) 쪽은 정말 그랬습니다. 웹 API처럼 가볍게 교체되는 애플리케이션 배포는 Deployment(디플로이먼트)가 정말 편한데, MySQL이나 PostgreSQL 같은 건 접근을 잘못하면 나중에 복구할 때 진짜 식은땀이 나더라고요.

    혹시 이런 경험 있으신가요? 애플리케이션은 잘 떴는데, 재시작 후 데이터 경로가 달라지거나 Pod 이름이 바뀌면서 클러스터 구성이 꼬이는 상황 말입니다. 여기서 중요한 포인트! Kubernetes StatefulSet vs Deployment는 단순히 생성 방식만 다른 게 아니라, 애플리케이션의 정체성(identity), 저장소(storage), 배포 순서(ordering)를 다루는 철학 자체가 다릅니다.

    이번 글에서는 제가 직접 홈랩에서 써보며 정리한 기준으로, Kubernetes StatefulSet vs Deployment 차이를 실무 감각으로 풀어보겠습니다. 단순 정의만 보면 헷갈리기 쉬우니까, 실제 YAML 예제와 트러블슈팅까지 같이 보시죠. 이전 글에서 다룬 Persistent Volume(PV, 영구 볼륨)과 StorageClass(스토리지 클래스) 내용을 같이 보시면 이해가 더 빨라집니다. 다음 글에서는 Helm(헬름, 쿠버네티스 패키지 매니저)으로 상태 저장 애플리케이션 배포 자동화하는 방법도 다룰 예정입니다.

    Kubernetes StatefulSet vs Deployment 구조 비교 아키텍처 이미지

    Deployment와 StatefulSet이 Pod, Service, Volume을 어떻게 다르게 다루는지 한눈에 보는 개요 이미지입니다.

    1. 왜 Kubernetes StatefulSet vs Deployment가 중요한가

    쉽게 말해 Deployment는 언제든 교체 가능한 복제본을 잘 다루고, StatefulSet은 각 인스턴스가 자기 이름과 저장소를 유지해야 하는 경우를 잘 다룹니다.

    예를 들어 보겠습니다.

    • 웹 프론트엔드나 API 서버는 Pod가 하나 죽어도 새 Pod가 뜨면 보통 괜찮습니다.
    • 반면 데이터베이스나 메시지 큐(message queue, 비동기 메시지 처리 시스템)는 각 인스턴스가 가진 데이터와 순서가 중요거든요.
    • 캐시 서버도 단일 노드냐 클러스터 구성이냐에 따라 선택이 달라집니다.

    제가 처음엔 Redis를 무조건 Deployment로 올렸었는데요. 단일 캐시 테스트 용도에선 괜찮았는데, 나중에 persistent volume을 붙이고 노드 재스케줄링이 일어나니까 예상과 다르게 동작하는 부분이 있었어요. 그때 느낀 게, 상태 저장 애플리케이션은 살아 있는 데이터만 보는 게 아니라, 재시작 이후의 동일성까지 봐야 한다는 점이었습니다.

    2. 개념부터 쉽게 정리해보겠습니다

    2-1. Deployment란?

    Deployment는 ReplicaSet(레플리카셋, 동일 Pod 복제 관리)을 통해 여러 Pod를 선언적으로 관리하는 방식입니다. 주 목적은 무중단에 가깝게 애플리케이션 배포를 반복 가능하게 만드는 것입니다.

    • Pod 이름은 매번 바뀔 수 있습니다.
    • 특정 Pod가 죽어도 새 Pod가 대체되면 됩니다.
    • Rolling Update(롤링 업데이트, 순차 교체)가 편하죠.
    • 웹 서버, API 서버, 워커(worker, 백그라운드 작업 프로세스)에 잘 맞습니다.

    2-2. StatefulSet이란?

    StatefulSet은 이름 그대로 상태(state)를 가진 워크로드를 위한 리소스입니다. 각 Pod가 고정된 네트워크 식별자와 안정적인 스토리지 연결을 유지하도록 설계되어 있거든요.

    • Pod 이름이 ordinal(순번) 기반으로 고정됩니다. 예: db-0, db-1
    • 생성/삭제 순서가 제어됩니다.
    • 각 Pod마다 독립적인 PersistentVolumeClaim(PVC, 영구 볼륨 요청)이 붙을 수 있습니다.
    • 데이터베이스, ZooKeeper, Kafka 계열, 복제 구조가 있는 저장소에 자주 씁니다.

    저도 처음엔 이게 뭔가 싶었는데, 실제로 써보니까 StatefulSet은 Pod를 복제한다기보다, 번호가 붙은 개별 인스턴스를 관리한다는 느낌으로 이해하는 게 가장 쉽더라고요.

    3. 핵심 차이점 비교: Kubernetes StatefulSet vs Deployment

    항목 Deployment StatefulSet
    주 용도 Stateless 애플리케이션 배포 Stateful 애플리케이션 배포
    Pod 이름 가변적 고정적 순번 부여
    스토리지 공유 또는 외부 스토리지 중심 Pod별 고정 스토리지 할당 가능
    생성/종료 순서 순서 보장 약함 순차 생성, 순차 종료
    네트워크 식별성 Pod 교체 시 변경 가능 안정적인 DNS 이름 유지
    대표 사용 사례 웹, API, 배치 워커 DB, 분산 저장소, 클러스터형 메시지 시스템

    여기서 독자분들이 가장 헷갈리는 부분이 스토리지입니다. Deployment에도 PVC를 붙일 수는 있습니다. 그래서 겉보기엔 둘 차이가 없어 보일 수 있어요. 근데 StatefulSet은 각 Pod가 자기 볼륨을 안정적으로 유지해야 하는 구조를 전제로 설계되어 있거든요. 이 차이가 운영 중엔 꽤 크게 작용합니다.

    3-1. 언제 Deployment를 선택하나

    • Pod가 교체돼도 서비스만 유지되면 되는 경우
    • 세션 상태를 외부 Redis나 DB에 저장하는 경우
    • 스케일 아웃/인 빈도가 잦은 경우
    • CI/CD로 잦은 애플리케이션 배포가 필요한 경우

    3-2. 언제 StatefulSet을 선택하나

    • 각 인스턴스마다 고유 ID가 필요한 경우
    • 볼륨을 Pod별로 안정적으로 유지해야 하는 경우
    • 클러스터 합류 순서나 부팅 순서가 중요한 경우
    • 상태 저장 애플리케이션 특성상 재시작 후에도 동일한 엔드포인트가 필요한 경우

    실제로 써보니까, 애매하면 먼저 데이터의 소유권이 누구에게 붙는지를 보면 판단이 쉽습니다. 데이터가 서비스 전체에 느슨하게 연결되면 Deployment 쪽, 데이터가 특정 인스턴스에 강하게 묶이면 StatefulSet 쪽이더라고요.

    4. 실전 구현 1: Deployment로 Stateless 앱 배포

    먼저 Nginx(엔진엑스, 웹 서버)를 Deployment로 배포해보겠습니다. 이 예제는 구조를 이해하기 위한 가장 기본적인 형태입니다.

    1. Deployment 매니페스트를 작성합니다.
    2. Service(서비스, 네트워크 접근 추상화)로 노출합니다.
    3. 롤링 업데이트와 스케일링을 확인합니다.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-deployment
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
            - name: nginx
              image: nginx:stable
              ports:
                - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: web-service
    spec:
      selector:
        app: web
      ports:
        - port: 80
          targetPort: 80
      type: ClusterIP
    kubectl apply -f web-deployment.yaml
    kubectl get deploy,pods,svc -o wide

    이 상태에서 Pod 하나가 내려가도 새 Pod가 올라오면 됩니다. 이름이 바뀌어도 크게 문제되지 않죠. 바로 이 특성이 Deployment의 장점입니다.

    업데이트도 간단합니다.

    kubectl set image deployment/web-deployment nginx=nginx:latest
    kubectl rollout status deployment/web-deployment

    제가 직접 해보니 테스트 환경이나 프론트엔드 계층은 거의 이 패턴으로 끝나더라고요. 단순하고, 빠르고, 운영 피로도가 낮습니다. 드디어 됐다! 싶은 순간이 자주 오는 쪽이죠.

    Kubernetes StatefulSet vs Deployment 중 Deployment 롤링 업데이트 설명 이미지

    Deployment가 ReplicaSet과 함께 Pod를 순차 교체하는 흐름을 설명하는 이미지입니다.

    5. 실전 구현 2: StatefulSet으로 상태 저장 애플리케이션 배포

    이번엔 StatefulSet 예제를 보겠습니다. 여기서는 이해를 위해 간단한 Nginx 이미지를 쓰되, 핵심은 고정된 Pod 이름과 volumeClaimTemplates 구조를 보는 데 있습니다. 실제 운영에서는 MySQL, PostgreSQL, Redis 클러스터, RabbitMQ 같은 워크로드에서 더 의미가 커요.

    StatefulSet은 보통 Headless Service(헤드리스 서비스, 개별 Pod 식별을 위한 서비스)와 함께 사용합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: web-headless
    spec:
      clusterIP: None
      selector:
        app: web-stateful
      ports:
        - port: 80
          name: http
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web-stateful
    spec:
      serviceName: web-headless
      replicas: 3
      selector:
        matchLabels:
          app: web-stateful
      template:
        metadata:
          labels:
            app: web-stateful
        spec:
          containers:
            - name: nginx
              image: nginx:stable
              ports:
                - containerPort: 80
                  name: http
              volumeMounts:
                - name: web-data
                  mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
        - metadata:
            name: web-data
          spec:
            accessModes: ["ReadWriteOnce"]
            resources:
              requests:
                storage: 1Gi
    kubectl apply -f web-statefulset.yaml
    kubectl get statefulset,pods,pvc,svc

    적용 후 보면 Pod가 이런 식으로 생성됩니다.

    • web-stateful-0
    • web-stateful-1
    • web-stateful-2

    그리고 PVC도 Pod별로 따로 붙습니다. 이게 진짜 중요합니다. 예를 들어 web-data-web-stateful-0 같은 식으로 각 인스턴스가 자기 스토리지를 계속 들고 가거든요.

    여기서 중요한 포인트! StatefulSet은 삭제 후 다시 생성되어도 같은 이름 규칙과 볼륨 연결을 유지하는 데 초점이 있습니다. 이 특성 덕분에 상태 저장 애플리케이션 운영이 가능해집니다.

    kubectl delete pod web-stateful-1
    kubectl get pods -w

    이렇게 해보면 동일한 ordinal을 가진 Pod가 다시 올라옵니다. 제가 홈랩에서 PostgreSQL 실험할 때도 이 패턴 덕분에 노드 교체 후 구조를 이해하기 쉬웠습니다. 물론 데이터 정합성은 애플리케이션 레벨에서 별도로 봐야 하지만요.

    6. ⚠️ 실제로 많이 겪는 문제와 트러블슈팅

    6-1. Deployment에 데이터베이스를 올리고 나중에 후회하는 경우

    이거 진짜 자주 봅니다. 처음엔 빠르게 띄우려고 Deployment로 시작하거든요. 근데 운영 중에 Pod가 교체되고, 스토리지 붙는 방식이 예상과 다르면 문제를 마주하게 됩니다.

    • Pod 이름이 바뀌어 클러스터 노드 인식이 꼬임
    • 단일 PVC 공유 구조가 애플리케이션 특성과 맞지 않음
    • 복제본 간 데이터 소유권이 불명확해짐

    해결 방향: 데이터가 인스턴스별로 귀속되는 구조라면 StatefulSet으로 전환을 검토해야 합니다.

    6-2. Headless Service를 빼먹는 경우

    저도 처음엔 왜 서비스가 꼭 필요하지? 했었는데, StatefulSet에서 안정적인 네트워크 식별성을 얻으려면 Headless Service가 사실상 핵심이거든요.

    kubectl get svc web-headless
    kubectl describe statefulset web-stateful

    Pod 간 통신이나 클러스터 초기화가 필요한 앱이라면 이 부분을 꼭 확인하세요.

    6-3. PVC가 남는 걸 보고 당황하는 경우

    StatefulSet을 줄였는데 볼륨이 바로 안 지워져서 당황하는 경우가 있습니다. 근데 이건 오히려 안전장치에 가깝습니다. 실수로 데이터가 날아가면 더 큰일이거든요.

    주의: StatefulSet 삭제가 곧 데이터 삭제를 의미하지는 않습니다. 스토리지 정책과 reclaim policy를 같이 확인해야 합니다.

    6-4. 순서 의존성을 무시하고 병렬처럼 다루는 경우

    StatefulSet은 생성과 종료 순서가 의미가 있습니다. 특히 클러스터형 데이터베이스나 합의 기반 시스템은 더 그렇습니다. 그래서 readiness probe, startup probe 같은 헬스체크도 같이 설계해야 하죠. 저도 이걸 대충 봤다가 부팅 순서 꼬여서 한참 로그만 들여다봤습니다 ㅎㅎ

    Kubernetes StatefulSet vs Deployment 중 StatefulSet 스토리지 구조 이미지

    StatefulSet에서 각 Pod가 독립적인 영구 볼륨과 DNS 이름을 갖는 구조를 설명하는 이미지입니다.

    7. 검증 방법: 내가 만든 배포가 의도대로 동작하는지 확인

    설정이 끝났으면 꼭 검증해야 합니다. YAML만 맞다고 끝이 아니더라고요. 실제로 재시작, 스케일링, 이름 유지 여부를 봐야 합니다.

    7-1. Deployment 검증

    kubectl get deployment web-deployment
    kubectl rollout history deployment/web-deployment
    kubectl scale deployment web-deployment --replicas=5
    kubectl get pods -l app=web
    • Pod 수가 바로 조정되는지
    • 업데이트 중 서비스 중단이 없는지
    • 새 Pod 이름이 생성되어도 서비스 접근이 유지되는지

    7-2. StatefulSet 검증

    kubectl get statefulset web-stateful
    kubectl get pods -l app=web-stateful
    kubectl get pvc
    kubectl scale statefulset web-stateful --replicas=2
    kubectl get pods,pvc
    • Pod가 역순으로 종료되는지
    • 줄였다가 다시 늘렸을 때 ordinal이 유지되는지
    • PVC가 각 Pod에 맞게 보존되는지

    🎉 여기서 원하는 대로 동작하면 거의 감이 옵니다. Deployment는 교체 가능한 인스턴스 관리에 최적화되어 있고, StatefulSet은 상태와 순서를 존중하는 구조라는 점이 실제 결과에서 드러납니다.

    Kubernetes StatefulSet vs Deployment 검증 결과 대시보드 이미지

    배포 후 Pod, PVC, 롤아웃 상태를 검증하는 운영 화면 느낌의 이미지입니다.

    8. 자주 묻는 질문과 정리

    8-1. Kubernetes StatefulSet vs Deployment: PVC를 붙이면 차이가 없나요?

    비슷해 보일 수는 있지만 다릅니다. 핵심은 Pod별 고정 정체성과 순서 보장입니다. PVC 하나 붙였다고 StatefulSet의 운영 특성이 생기지는 않습니다.

    8-2. 모든 데이터베이스는 무조건 StatefulSet인가요?

    대체로 그렇지만, 실제 운영 구조에 따라 외부 매니지드 데이터베이스를 쓰면 Kubernetes 안에 직접 올리지 않을 수도 있습니다. 즉, 워크로드 선택은 애플리케이션 구조 전체를 봐야 합니다.

    8-3. 캐시는 어떤 걸 써야 하나요?

    단순 캐시, 세션 캐시처럼 날아가도 되는 구조는 Deployment가 편합니다. 반면 복제, 영속성, 노드 식별이 중요해지면 StatefulSet 쪽을 봐야 합니다.

    8-4. 결국 어떤 기준으로 결정하면 되나요?

    1. Pod가 바뀌어도 되는가?
    2. 각 인스턴스가 자기 데이터를 가져야 하는가?
    3. 이름과 네트워크 식별성이 유지되어야 하는가?
    4. 생성/종료 순서가 중요한가?

    이 네 가지에 하나라도 강하게 해당되면 StatefulSet을 우선 검토해보세요.

    정리해보겠습니다.

    • Deployment: 빠르고 유연한 애플리케이션 배포, stateless 워크로드에 적합
    • StatefulSet: 상태 저장 애플리케이션, 고정 이름, 고정 스토리지, 순서 제어에 적합

    저도 처음엔 Kubernetes StatefulSet vs Deployment를 너무 단순하게 봤었는데, 실제로 운영해보니까 선택이 잘못되면 나중에 구조를 다시 뜯어고쳐야 하더라고요. 특히 홈랩처럼 이것저것 실험하는 환경에서는 처음부터 정답을 맞히기 어렵습니다. 그래서 더더욱 워크로드의 상태 특성을 먼저 보는 습관이 중요합니다.

    💡 팁 하나 남기자면, 처음 설계할 때는 “이 Pod가 내일 사라져도 괜찮은가?”를 스스로에게 물어보세요. 괜찮으면 Deployment일 가능성이 높고, 안 괜찮으면 StatefulSet을 봐야 합니다.

    마지막으로, 다음 글에서는 StatefulSet 기반 데이터베이스를 백업/복구 관점에서 어떻게 설계하면 좋은지 다뤄보겠습니다. 그 글까지 같이 보시면 Kubernetes 워크로드 선택 감이 훨씬 또렷해지실 겁니다.

    어떤 워크로드에 Deployment를 쓰고, 어떤 경우 StatefulSet을 써야 하는지 요약한 비교 이미지입니다.

  • [k8s] kubectl 고급 활용법: Pod, Service, Deployment 관리 팁

    [k8s] kubectl 고급 활용법: Pod, Service, Deployment 관리 팁

    안녕하세요, 13년차 서버실 지킴이입니다. 오늘도 서버실의 삐걱거리는 소리와 함께 하루를 시작하네요. 😊

    인프라 엔지니어로 일하다 보면, 매일같이 손에서 놓지 못하는 도구들이 몇 가지 있습니다. 그중에서도 Kubernetes(쿠버네티스) 클러스터를 운영한다면 kubectl(큐브컨트롤)은 정말 없어서는 안 될 존재거든요. <code>kubectl은 쿠버네티스 클러스터와 상호작용하는 CLI(명령줄 인터페이스) 도구로, 파드(Pod), 서비스(Service), 디플로이먼트(Deployment) 등 모든 리소스(resource)를 관리할 수 있게 해줍니다.

    근데 이거, 진짜 제대로 쓰고 있나? 하는 의문, 혹시 여러분도 해보신 적 있으신가요? 저도 처음엔 kubectl get pod, kubectl apply -f 같은 기본적인 명령어만으로 충분하다고 생각했거든요. 하지만 클러스터가 커지고 문제 상황이 복잡해질수록, 더 깊고 강력한 kubectl 활용법이 필요하다는 걸 깨달았습니다. 덕분에 삽질 좀 했습니다만, 그만큼 얻은 꿀팁들도 많았죠. ㅎㅎ

    오늘은 13년차 인프라 엔지니어인 제가 직접 현업과 홈랩에서 써보면서 얻은 kubectl 고급 활용법들을 여러분께 알려드리려고 합니다. 특히 Pod, Service, Deployment를 효과적으로 관리하는 팁과 함께, 제가 겪었던 삽질 경험과 트러블슈팅 노하우도 솔직하게 공유해 드릴게요. 이 글을 통해 여러분의 쿠버네티스 운영 생산성이 한층 더 높아지기를 바랍니다!

    쿠버네티스 Pod, Service, Deployment는 서로 유기적으로 연결되어 동작합니다. (이미지: 쿠버네티스 핵심 컴포넌트 아키텍처)

    핵심 개념 다시 보기: Pod, Service, Deployment

    본격적인 팁을 알려드리기 전에, 오늘 다룰 세 가지 핵심 리소스에 대해 간단히 짚고 넘어갈게요. 이미 잘 알고 계시겠지만, 다시 한번 머릿속에 정리하는 시간이라고 생각하시면 좋습니다.

    • Pod (파드): 쿠버네티스에서 가장 작고 기본적인 배포 단위입니다. 하나 이상의 컨테이너(Container)를 포함할 수 있으며, 같은 파드 내의 컨테이너들은 네트워크와 스토리지를 공유해요. 쉽게 말해, ‘작업을 수행하는 최소한의 묶음’이라고 보시면 됩니다.
    • Service (서비스): 여러 파드에 대한 안정적인 네트워크 접근을 제공하는 추상화 계층이죠. 파드는 언제든 생성되고 삭제될 수 있는데, 서비스는 이런 파드의 동적인 변화와 관계없이 일정한 IP 주소와 DNS 이름을 통해 파드 그룹에 접근할 수 있도록 해줍니다. 마치 변동하는 직원들에게 고정된 부서 전화번호를 할당해주는 것과 같죠.
    • Deployment (디플로이먼트): 파드와 ReplicaSet(레플리카셋)을 선언적으로 관리하는 상위 리소스입니다. 애플리케이션의 버전을 관리하고, 원하는 수의 파드를 항상 유지하며, 롤링 업데이트(Rolling Update)나 롤백(Rollback) 같은 배포 전략을 손쉽게 구현할 수 있어요. ‘애플리케이션의 배포와 생명주기를 책임지는 관리자’라고 생각하시면 편합니다.

    kubectl 고급 활용법: Pod 관리 팁

    파드는 쿠버네티스에서 가장 많이 다루는 리소스 중 하나일 겁니다. 저도 매일 파드 상태를 확인하고, 로그를 보고, 문제가 생기면 파드 안으로 들어가 보곤 하거든요. 몇 가지 유용한 명령어들을 소개합니다.

    1. 로그 실시간 확인 (Log Streaming)

    애플리케이션 개발이나 트러블슈팅 시 가장 기본이 되는 작업이죠. kubectl logs 명령어로 특정 파드의 로그를 확인할 수 있습니다. 특히 -f (follow) 옵션은 로그를 실시간으로 스트리밍해주기 때문에, 마치 tail -f처럼 동작해서 에러를 잡을 때 정말 유용해요.

    # 특정 파드의 로그 실시간 스트리밍
    kubectl logs -f my-app-pod-abcdefg
    
    # 특정 컨테이너의 로그만 보기 (파드에 여러 컨테이너가 있을 경우)
    kubectl logs -f my-app-pod-abcdefg -c my-container-name
    
    # 마지막 100줄만 보고 싶을 때
    kubectl logs --tail=100 my-app-pod-abcdefg
    
    # 특정 시간 이후 로그만 보고 싶을 때
    kubectl logs --since=1h my-app-pod-abcdefg # 1시간 이내 로그
    kubectl logs --since=2023-01-01T00:00:00Z my-app-pod-abcdefg # 특정 시각 이후 로그

    제가 개발 중 에러를 잡을 때 정말 유용하게 썼던 기능입니다. 특히 컨테이너가 갑자기 재시작(restart)될 때, -f 옵션으로 로그를 계속 보고 있으면 어떤 이유로 죽었는지 금방 파악할 수 있더라고요. 💡

    2. 컨테이너 내부 접속 (Exec into Container)

    파드 안에서 직접 명령어를 실행하거나 파일 시스템을 확인해야 할 때가 있습니다. 마치 SSH로 서버에 접속하는 것처럼, kubectl exec 명령어로 컨테이너 내부에 접속할 수 있어요.

    # 특정 파드의 컨테이너 내부로 접속 (bash 셸 사용)
    kubectl exec -it my-app-pod-abcdefg -- bash
    
    # 특정 컨테이너 내부로 접속 (파드에 여러 컨테이너가 있을 경우)
    kubectl exec -it my-app-pod-abcdefg -c my-container-name -- sh # sh 셸 사용 예시

    터미널이 없으면 답답하잖아요? 문제가 생겼을 때 바로 파드 내부로 들어가서 설정 파일을 확인하거나, 특정 명령어를 실행해서 상황을 진단해볼 수 있어서 정말 편하더라고요. ⚠️ 중요한 건 -- 뒤에 실행할 명령어를 붙여야 한다는 점입니다.

    3. 자원 사용량 확인 (Resource Usage)

    파드가 갑자기 죽거나 성능이 저하되는 원인 중 하나는 CPU나 메모리 같은 리소스 부족인 경우가 많습니다. kubectl top pod 명령어를 사용하면 파드별 리소스 사용량을 한눈에 볼 수 있어요. 다만, 이 기능을 사용하려면 클러스터에 Metrics Server(메트릭스 서버)가 설치되어 있어야 합니다.

    # 모든 파드의 CPU 및 메모리 사용량 확인
    kubectl top pod
    
    # 특정 네임스페이스의 파드만 확인
    kubectl top pod -n my-namespace
    
    # 파드를 CPU 사용량 기준으로 정렬
    kubectl top pod --sort-by=cpu

    파드가 갑자기 죽는다? 대부분 CPU나 메모리를 너무 많이 쓰는 경우가 많더라고요. kubectl top pod로 확인해서 리소스 제한(resource limit)을 조정해주곤 합니다. 💡

    4. Pod 이벤트 확인 (Event Check)

    파드가 생성되지 않거나, Pending(대기) 상태에 머무르거나, 예상치 못하게 재시작될 때 그 원인을 알려주는 것이 바로 Event(이벤트)입니다. kubectl describe pod 명령의 하단에 이벤트 정보가 자세히 나옵니다.

    # 특정 파드의 상세 정보 및 이벤트 확인
    kubectl describe pod my-app-pod-abcdefg

    왜 내 파드가 Pending에 머물러 있을까? 답은 Event에 있습니다. 예를 들어, 필요한 볼륨(Volume)이 마운트(mount)되지 않았거나, 노드의 리소스가 부족하거나, 컨테이너 이미지를 풀(pull)하지 못하는 등 다양한 원인이 이벤트로 기록돼요. 저도 처음에 이거 때문에 밤샜습니다. 결국 이벤트 로그에 답이 있더라고요!

    kubectl 고급 활용법: Service 관리 팁

    서비스는 외부 트래픽을 파드로 연결해주는 중요한 역할을 합니다. 서비스 관련 문제가 생기면 애플리케이션 전체가 먹통이 될 수 있죠. 서비스 관리 팁들을 알아볼게요.

    1. 서비스 상세 정보 (Service Details)

    서비스의 IP 주소, 포트 매핑, 연결된 파드 정보 등 상세 정보를 확인할 때 kubectl describe service 명령이 유용해요.

    # 특정 서비스의 상세 정보 확인
    kubectl describe service my-app-service

    외부에서 접근이 안 될 때, 제일 먼저 살펴보는 곳입니다. Cluster IP(클러스터 IP), External IP(외부 IP), Port(포트) 매핑 정보가 정확한지 확인하곤 합니다. 특히 Type이 NodePort나 LoadBalancer일 경우, 외부 접근이 가능해야 하는데 안 된다면 여기서 단서를 찾을 수 있죠.

    2. 서비스 포트 포워딩 (Port Forwarding)

    클러스터 내부의 서비스에 로컬 머신에서 직접 접속해야 할 때가 있습니다. 예를 들어, 개발 중인 로컬 환경에서 클러스터 내부의 데이터베이스 서비스에 연결해야 할 때 유용해요. kubectl port-forward 명령으로 로컬 포트를 서비스 포트에 연결할 수 있습니다.

    # 특정 서비스의 80포트를 로컬 8080포트로 포워딩
    kubectl port-forward service/my-app-service 8080:80
    
    # 특정 파드의 80포트를 로컬 8080포트로 포워딩 (서비스 대신 파드에 직접 연결)
    kubectl port-forward my-app-pod-abcdefg 8080:80

    홈랩에서 외부 IP 없이 내부 서비스 테스트할 때 이거 진짜 꿀팁입니다! 로컬에서 개발한 프론트엔드(frontend)가 백엔드(backend) 서비스에 잘 연결되는지 확인할 때 아주 유용하게 썼어요. 🎉

    3. 엔드포인트 확인 (Endpoint Verification)

    서비스는 파드들의 IP 주소를 모아놓은 Endpoint(엔드포인트)를 기반으로 트래픽을 라우팅합니다. 서비스는 있는데 왜 연결이 안 되지? 싶을 때는 엔드포인트가 제대로 생성되었는지 확인해야 해요. 파드가 정상적으로 Running(실행) 상태여야 엔드포인트에 등록됩니다.

    # 특정 서비스에 연결된 엔드포인트 확인
    kubectl get endpoints my-app-service
    
    # 모든 엔드포인트 확인
    kubectl get ep

    서비스는 잘 있는데 왜 연결이 안 되지? 알고 보니 엔드포인트가 비어있을 때가 있더라고요. 파드가 죽었거나, readinessProbe(레디니스 프로브)가 실패해서 엔드포인트에서 제외된 경우였습니다. ⚠️

    kubectl 고급 활용법: Deployment 관리 팁

    디플로이먼트는 애플리케이션 배포의 핵심입니다. 새로운 버전을 배포하고, 문제가 생기면 이전 버전으로 되돌리고, 트래픽 변화에 따라 파드 개수를 조절하는 등 많은 작업을 디플로이먼트를 통해 하게 됩니다.

    다양한 kubectl 명령어를 활용해 Pod, Service, Deployment의 상태를 실시간으로 모니터링하는 모습입니다. (이미지: kubectl 모니터링)

    1. 롤링 업데이트 & 롤백 (Rolling Update & Rollback)

    새로운 버전의 애플리케이션을 배포할 때, kubectl apply 명령을 사용하면 디플로이먼트가 롤링 업데이트(Rolling Update)를 수행합니다. 이 과정에서 업데이트 상태를 확인하고, 문제가 생겼을 때 이전 버전으로 롤백(Rollback)하는 것이 중요해요.

    # 디플로이먼트 롤아웃(rollout) 상태 확인
    kubectl rollout status deployment/my-app-deployment
    
    # 디플로이먼트 롤아웃 히스토리(history) 확인
    kubectl rollout history deployment/my-app-deployment
    
    # 이전 버전으로 롤백 (이전 리비전으로 되돌리기)
    kubectl rollout undo deployment/my-app-deployment
    
    # 특정 리비전으로 롤백
    kubectl rollout undo deployment/my-app-deployment --to-revision=2

    실수로 잘못된 이미지를 배포했을 때, kubectl rollout undo 이거 한 방이면 되돌릴 수 있어서 얼마나 든든한지 모릅니다. 롤아웃 상태를 보면서 파드가 하나씩 교체되는 걸 지켜보는 것도 꽤 재미있고요. 😅

    2. 스케일링 (Scaling)

    애플리케이션에 트래픽이 몰리거나 반대로 줄어들 때, 파드의 개수를 동적으로 조절해야 합니다. kubectl scale 명령어를 사용하면 디플로이먼트의 파드 개수를 쉽게 늘리거나 줄일 수 있어요.

    # 디플로이먼트의 파드 개수를 5개로 스케일링
    kubectl scale deployment/my-app-deployment --replicas=5
    
    # 오토스케일러(Horizontal Pod Autoscaler, HPA) 설정
    kubectl autoscale deployment my-app-deployment --cpu-percent=50 --min=2 --max=10

    갑자기 트래픽이 몰릴 때, 빠르게 파드를 늘려줄 수 있죠. 물론 HPA를 설정하면 자동으로 스케일링되겠지만, 수동으로 빠르게 대응해야 할 때 이 명령어가 아주 유용해요.

    3. 환경 변수/시크릿 확인 (Env/Secret Check)

    애플리케이션이 제대로 동작하지 않을 때, 환경 변수(Environment Variable)나 시크릿(Secret) 설정이 잘못되었을 가능성도 있습니다. 디플로이먼트의 상세 정보를 통해 이를 확인할 수 있어요.

    # 특정 디플로이먼트의 상세 정보 확인
    kubectl describe deployment my-app-deployment

    describe 명령의 출력에서 Environment 섹션과 Volumes 섹션을 확인하면, 어떤 환경 변수가 설정되었고 어떤 시크릿이나 컨피그맵(ConfigMap)이 마운트(mount)되었는지 알 수 있습니다. 간혹 환경 변수 오타 때문에 앱이 안 뜨는 경우도 있더라고요. 디스크라이브로 확인하면 됩니다.

    ⚠️ 삽질 경험 & 트러블슈팅 팁

    제가 13년 동안 인프라 엔지니어로 일하면서 수없이 겪었던 삽질 경험들 중, kubectl과 관련하여 특히 기억에 남는 몇 가지를 공유합니다. 여러분은 저처럼 밤새지 마세요! 😅

    Problem 1: 파드가 계속 Pending 상태인 경우

    새로운 디플로이먼트를 배포했는데, 파드가 Running 상태가 되지 않고 계속 Pending(대기) 상태에 머무는 경우가 있습니다. 저도 처음엔 이게 뭔가 싶어서 계속 파드를 삭제하고 다시 만들고 했었죠.

    • 원인:
      • 노드의 리소스(CPU, 메모리) 부족
      • 이미지 풀(Image Pull) 실패 (예: 잘못된 이미지 이름, 프라이빗 레지스트리 인증 실패)
      • 볼륨(PersistentVolume, PersistentVolumeClaim) 바인딩 실패
      • 노드 셀렉터(Node Selector)나 테인트/톨러레이션(Taints/Tolerations) 설정 문제로 스케줄링할 노드를 찾지 못함
    • 해결:
      # 파드 상세 정보 확인 (가장 중요!)
      kubectl describe pod <pod-name>
      # 이벤트 섹션에서 FailedScheduling, Failed to pull image 등의 에러 메시지를 찾습니다.
      
      # 노드 리소스 확인
      kubectl top nodes
      
      # 이미지 레지스트리 인증 정보 확인 (Secret)
      kubectl get secret <image-pull-secret-name> -o yaml

      결국 답은 kubectl describe pod의 Events 섹션에 있습니다. 어떤 이유로 파드가 스케줄링되지 못했는지, 이미지를 가져오지 못했는지 자세히 알려주거든요. 저도 이거 때문에 밤샜습니다. 결국 이벤트 로그에 답이 있더라고요! 💡

    Problem 2: 서비스가 외부에서 접근 안 되는 경우

    분명히 서비스를 만들었고 파드도 잘 돌고 있는데, 외부에서 접속이 안 되는 경우가 있습니다. 특히 클라우드 환경에서 많이 겪었던 문제인데요.

    • 원인:
      • 서비스 타입(Service Type) 오설정 (ClusterIP는 외부 접근 불가)
      • 로드밸런서(LoadBalancer)나 인그레스(Ingress) 컨트롤러 문제
      • 클라우드 프로바이더(Cloud Provider)의 방화벽(Firewall) 설정
      • 서비스의 selector와 파드의 labels가 일치하지 않아 엔드포인트가 비어있음
    • 해결:
      # 서비스 타입 및 외부 IP 확인
      kubectl get svc <service-name> -o wide
      
      # 엔드포인트 확인 (파드가 서비스에 제대로 연결되었는지)
      kubectl get ep <service-name>
      
      # 서비스 상세 정보 확인
      kubectl describe svc <service-name>

      로드밸런서 타입으로 만들었는데 왜 안 돼? 알고 보니 클라우드 provider 설정 문제였던 적도 있었어요. 예를 들어, GCP나 AWS에서 로드밸런서가 프로비저닝(provisioning)되지 않았거나, 보안 그룹(Security Group) 설정이 잘못되어 있었죠. 😅 항상 엔드포인트와 서비스 타입을 먼저 확인하는 습관을 들이세요!

    Problem 3: Deployment 롤아웃이 멈춘 경우

    새로운 버전으로 디플로이먼트를 업데이트했는데, 롤아웃이 중간에 멈춰버리고 진행되지 않는 경험, 다들 있으시죠?

    • 원인:
      • 새로 생성된 파드가 CrashLoopBackOff 상태로 계속 죽음
      • 파드의 readinessProbe(레디니스 프로브)가 실패하여 새 파드가 Ready 상태가 되지 못함
      • 리소스 부족으로 새 파드가 생성되지 못함
    • 해결:
      # 롤아웃 상태 확인
      kubectl rollout status deployment/<deployment-name>
      
      # 새로운 파드의 이름 확인 (롤아웃 중 생성된 파드)
      kubectl get pod -l app=<app-label> --sort-by=.metadata.creationTimestamp
      
      # 문제의 파드 로그 및 이벤트 확인
      kubectl logs <new-pod-name>
      kubectl describe pod <new-pod-name>

      새로운 이미지가 문제가 있어서 기존 파드도 못 죽고 롤아웃이 멈춰버린 경험, 다들 있으시죠? 저도 몇 번 겪었습니다. 이럴 때는 새로 생성되는 파드의 로그와 이벤트를 확인해서 왜 Ready 상태가 되지 못하는지 파악하는 것이 중요해요. 그리고 문제가 파악되면 kubectl rollout undo로 빠르게 이전 버전으로 롤백하는 것이 현명한 방법입니다!

    쿠버네티스 환경에서 흔히 겪을 수 있는 트러블슈팅 상황을 한눈에 볼 수 있습니다. (이미지: 쿠버네티스 트러블슈팅)

    검증 및 결과 확인

    위에서 배운 명령어들을 활용하여 변경 사항이 잘 적용되었는지, 클러스터의 상태는 정상적인지 확인하는 것이 중요합니다. 주로 사용하는 명령어는 다음과 같아요.

    # 모든 네임스페이스의 모든 리소스 확인 (초보자에게 추천!)
    kubectl get all --all-namespaces
    
    # 특정 네임스페이스의 주요 리소스 확인 (파드, 서비스, 디플로이먼트, 레플리카셋)
    kubectl get deploy,svc,pod,rs -n my-namespace
    
    # 특정 리소스의 자세한 정보 확인 (IP 주소, 노드 정보 등)
    kubectl get deploy,svc,pod -o wide -n my-namespace

    이 명령어들로 제가 고친 설정이 잘 반영되었는지, 파드들이 정상적으로 돌고 있는지, 외부 IP는 제대로 할당되었는지 확인하곤 합니다. 특히 -o wide 옵션은 더 많은 정보를 보여줘서 매우 편리해요. ✅

    오늘 다룬 kubectl 고급 활용 팁들을 한 장으로 요약한 인포그래픽입니다. (이미지: kubectl 팁 요약)

    마무리하며: `kubectl` 마스터가 되는 그날까지!

    오늘은 13년차 인프라 엔지니어의 경험을 담아 kubectl 고급 활용법에 대해 알아봤습니다. Pod, Service, Deployment를 관리할 때 유용하게 사용할 수 있는 명령어들과 함께, 제가 직접 겪었던 삽질 경험과 트러블슈팅 노하우까지 솔직하게 공유해 드렸네요.

    사실 kubectl은 알면 알수록 강력한 도구거든요. 기본적인 명령어만 쓰기엔 아까운 기능들이 너무 많아요. 클러스터의 모든 것을 kubectl 하나로 제어할 수 있다고 해도 과언이 아닙니다. 저도 처음엔 헷갈렸지만, 꾸준히 사용하고 궁금한 점은 직접 찾아보면서 익혔습니다. 여러분도 저처럼 삽질하면서 얻은 팁들을 활용해서 kubectl 마스터가 되시길 바랍니다! 🎉

    다음에는 kubectl 플러그인이나 K9s 같은 터미널 UI 도구들에 대해서도 다뤄보면 좋겠네요. 쿠버네티스 운영에 또 다른 재미를 더해줄 도구들이거든요. 긴 글 읽어주셔서 감사합니다. 다음에도 더 유익한 정보로 찾아오겠습니다! 😉