이 문서에서는 Kubernetes 클러스터 운영 시 유용한 패턴과 방법론을 정리합니다.

Rollout (재시작) 전략

수동 재시작

다음 명령어로 Deployment를 안전하게 재시작할 수 있습니다.

kubectl rollout restart deployment <deployment-name>

kubectl delete pod보다 안전하며, Rolling Update 방식으로 무중단 재시작이 가능합니다.

주기적 재시작

메모리 누수나 디스크 용량 증가 등 Application에 문제가 있을 때 임시 조치로 주기적 재시작이 필요한 경우가 있습니다.

Warning

주기적 재시작은 임시 조치입니다. 추후에 근본 원인(메모리 누수, 로그 또는 임시 파일 축적 등)을 파악하여 영구적인 해결책을 적용해야 합니다.

방법 1: crontab 사용

crontab -e
*/10 * * * * kubectl rollout restart deployment <deployment-name>

방법 2: Kubernetes CronJob 사용

apiVersion: batch/v1
kind: CronJob
metadata:
  name: rollout-restart
spec:
  schedule: "*/10 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: rollout-restart-sa # 적절한 RBAC 권한 필요
          containers:
            - name: rollout-restart
              image: alpine/kubectl:latest
              command:
                - kubectl
                - rollout
                - restart
                - deployment
                - <deployment-name>
          restartPolicy: OnFailure

GitOps 환경에서 Rollout 트리거

GitOps(ArgoCD, Flux 등)에서 이미지 태그 변경 없이 Rollout을 트리거하는 방법입니다.

Annotation 기반 트리거

Deployment의 annotation에 timestamp 등 고유한 값을 넣고, GitOps에서 이 값을 변경하면 Rollout이 발생합니다.

spec:
  template:
    metadata:
      annotations:
        rollout-trigger: "2025-12-12T10:00:00"

Manifest List Digest

manifest list digest를 사용하면 아키텍처(arm64, amd64 등)에 맞는 이미지가 자동으로 선택됩니다. Digest를 변경하여 Rollout을 트리거할 수 있습니다.

App of Apps에서 컴포넌트 순서 보장 (sync wave)

여러 Helm 차트가 의존성 순서를 가질 때(예: Istio base(CRD) → istiodgateway), 한 Application에 몰아넣으면 순서가 보장되지 않습니다. argocd.argoproj.io/sync-wave는 리소스 단위 annotation이지만 Argo CD Application 자체도 리소스이므로, App of Apps에서 차트마다 Application으로 분리하고 자식 Application에 sync-wave를 부여하면 차트(컴포넌트) 단위 순서를 잡을 수 있습니다.

# 자식 Application 각각에 부여
kind: Application
metadata:
  name: istio-base # CRD 먼저
  annotations:
    argocd.argoproj.io/sync-wave: "1"
---
kind: Application
metadata:
  name: istiod # 컨트롤 플레인
  annotations:
    argocd.argoproj.io/sync-wave: "2"
---
kind: Application
metadata:
  name: istio-gateway
  annotations:
    argocd.argoproj.io/sync-wave: "3"
  • 낮은 wave가 Synced + Healthy가 된 뒤에야 다음 wave로 진행합니다. Argo CD는 Application에 built-in health check가 있어 자식 앱 완료를 기다립니다.
  • 같은 Application 내부의 리소스 순서(ConfigMap/Secret → Migration Job → 앱)도 동일하게 리소스 sync-wave + PreSync Hook으로 제어합니다.1

Swap (노드)

  • kubelet 기본값 failSwapOn: true — 노드에 swap이 켜져 있으면 kubelet이 기동에 실패합니다. 그래서 전통적으로 노드 swap 비활성화가 기본입니다.
  • v1.34부터 LimitedSwap이 GA되어, failSwapOn: false + cgroup v2 환경에서 swap을 의도적으로 활용할 수 있습니다. Pod별 memory.swap.max를 비례 할당하며, Guaranteed QoS(requests=limits) Pod는 swap=0으로 격리됩니다. (위험했던 UnlimitedSwap은 v1.30에서 제거)
  • 정리: 기본은 비활성화 전제, 필요 시 LimitedSwap으로 선택적 활성화.2

PodDisruptionBudget과 오토스케일링

PDB가 너무 빡빡하면 cluster autoscaler가 노드를 scale-down 하지 못합니다. Pod을 다른 노드로 옮기려면 evict해야 하는데 PDB가 이를 막기 때문입니다.

  • 막히는 전형: maxUnavailable: 0, minAvailable이 replica 수와 같음, 또는 단일 replica + minAvailable: 1ALLOWED DISRUPTIONS: 0
  • 완화: replica를 2개 이상으로 HA 구성 / minAvailable 대신 maxUnavailable 사용 / 불필요하면 PDB 완화·제거
  • 주의: PDB가 disruptionsAllowed > 0을 보여도 topology spread constraint와 겹치면 scale-down이 막히는 케이스가 있습니다.3

볼륨 / 스토리지 팁

emptyDir을 RAM(tmpfs) 기반으로 사용하기

emptyDir 볼륨은 기본적으로 노드의 디스크를 사용하지만, medium: Memory를 설정하면 RAM 기반 tmpfs로 동작합니다. 디스크 I/O가 병목인 임시 파일·캐시 용도에 유용합니다.

volumes:
  - name: cache
    emptyDir:
      medium: Memory
      sizeLimit: 512Mi

주의할 점:

  • tmpfs 사용량은 Pod의 memory limit에 포함됩니다. 여유 없이 쓰면 Pod가 OOMKilled 될 수 있으므로 sizeLimit과 컨테이너 resources.limits.memory를 함께 조정합니다.
  • 데이터는 휘발성입니다. Pod 재시작·노드 재부팅 시 사라지므로 영속성이 필요한 데이터에는 쓰지 않습니다.
  • 노드 전체 메모리를 소비하므로, 여러 Pod가 동시에 크게 쓰면 노드 압력(eviction)으로 이어질 수 있습니다.

공식 문서: emptyDir | Kubernetes Volumes

Footnotes

  1. How to Set Up GitOps for Istio with Argo CD | OneUptime

  2. Swap memory management | Kubernetes

  3. kubernetes/autoscaler#9111 — PDB+TopologySpread가 scale-down 차단