Skip to content

쿠버네티스 실전 치트시트 ​

  • 쿠버네티스 기반으로 실제 서비스를 구축/운영할 때 바로 찾아보는 용도
  • 기초 개념 설명은 생략, "왜 써야 하는지 + 옵션 리스트" 위주로 정리

1. 클러스터 내부 DNS (Service Discovery) ​

왜 써야 하나 ​

  • 클러스터 내부 통신은 반드시 내부 도메인으로. 트래픽이 클러스터 외부(LB, 공인망)로 나갔다 들어오지 않으므로 레이턴시/비용/보안 모두 이득. MSA 설계 시 필수
  • Pod/Deployment 재생성으로 IP가 바뀌어도 도메인에 자동 매핑됨 → IP 하드코딩 금지

도메인 양식 ​

대상형식예시
Service<svc>.<ns>.svc.cluster.localorder-api.commerce.svc.cluster.local
Pod<pod-ip-dashed>.<ns>.pod.cluster.local10-10-10-10.commerce.pod.cluster.local
Headless Service의 개별 Pod<pod-name>.<svc>.<ns>.svc.cluster.localmysql-0.mysql.db.svc.cluster.local
  • 같은 네임스페이스면 order-api만으로 호출 가능, 다른 네임스페이스면 order-api.commerce까지 (FQDN 전체는 안 써도 됨)
  • 단, 트래픽 많은 서비스는 FQDN(끝에 . 포함: order-api.commerce.svc.cluster.local.)을 쓰면 ndots 기반 불필요한 DNS 질의를 줄일 수 있음

spec.dnsPolicy ​

값동작
ClusterFirst기본값. cluster.local 매칭 안 되는 도메인은 upstream DNS로 질의
Default파드가 뜬 노드의 DNS 설정(/etc/resolv.conf)을 그대로 상속
ClusterFirstWithHostNethostNetwork: true로 실행하는 파드에 반드시 지정
None클러스터 DNS 무시. spec.dnsConfig로 직접 설정 필수

dnsConfig 튜닝 (외부 API 호출 많은 서비스) ​

yaml
spec:
  dnsConfig:
    options:
      - name: ndots
        value: "1"   # 기본 5 → 외부 도메인 질의 시 search 도메인 순회 방지

CoreDNS ​

  • v1.11+ 기본 DNS. kube-system 네임스페이스, 설정은 coredns ConfigMap의 Corefile
  • 플러그인 구조: errors, health, kubernetes, forward, cache, rewrite 등
  • 실무 팁
    • DNS 병목 시: NodeLocal DNSCache 도입 (노드별 DNS 캐시 데몬셋, conntrack 이슈도 완화)
    • 특정 외부 도메인 강제 매핑: Corefile에 rewrite 또는 hosts 플러그인
    • 디버깅: kubectl run -it --rm dns-test --image=busybox:1.36 -- nslookup <svc>

2. Service 타입 ​

타입용도비고
ClusterIP클러스터 내부 통신 (기본값)내부 MSA 호출은 전부 이것으로
NodePort노드 IP:포트(30000-32767)로 노출직접 노출용으론 비권장, LB 뒷단으로만
LoadBalancerCSP LB 자동 프로비저닝서비스당 LB 1개 = 비용↑. Ingress/Gateway 뒤로 모으는 게 정석
ExternalName외부 도메인의 CNAME 별칭외부 DB 등을 내부 도메인처럼 호출
Headless (clusterIP: None)개별 Pod DNS 필요 시StatefulSet(DB, Kafka 등)과 세트
  • sessionAffinity: ClientIP — 세션 고정 필요 시 (기본 None)
  • externalTrafficPolicy: Local — 클라이언트 소스 IP 보존 + 불필요한 노드 홉 제거 (LB/NodePort 타입에서)
  • internalTrafficPolicy: Local — 같은 노드 내 파드로만 라우팅 (데몬셋 로컬 호출 등)

3. Ingress → Gateway API ​

현황 (2026) ​

  • ingress-nginx는 2026년 3월부로 리타이어(유지보수 종료). 신규 구축은 Gateway API가 표준
  • Ingress 리소스 자체는 남아있지만 frozen 상태 — 신규 기능은 전부 Gateway API로만 추가됨
  • 마이그레이션 도구: ingress2gateway
  • 구현체: Envoy Gateway, Istio, Cilium Gateway, Traefik, NGINX Gateway Fabric, 각 CSP LB 컨트롤러

Ingress(레거시) 핵심만 ​

  • L7(HTTP) 라우팅 규칙 모음. TLS 종료, 경로/호스트 기반 라우팅
  • NodePort/ExternalIP는 L4라 세부 라우팅 불가 → L7 필요하면 Ingress/Gateway
  • 주요 필드: ingressClassName, rules[].host, paths[].pathType(Prefix|Exact|ImplementationSpecific), tls[]

Gateway API 구조 (역할 분리가 핵심) ​

리소스담당역할
GatewayClass인프라 관리자어떤 구현체(컨트롤러)를 쓸지
Gateway클러스터 운영자LB 인스턴스, 리스너(포트/프로토콜/TLS) 정의
HTTPRoute / GRPCRoute / TCPRoute / TLSRoute앱 개발자실제 라우팅 규칙
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: order-route
spec:
  parentRefs:
    - name: main-gateway
  hostnames: ["api.example.com"]
  rules:
    - matches:
        - path: { type: PathPrefix, value: /orders }
      backendRefs:
        - name: order-api
          port: 8080
  • HTTPRoute에서 헤더 매칭, 트래픽 가중치(카나리), 헤더 수정, 리다이렉트, 미러링까지 표준 스펙으로 지원 (Ingress는 전부 벤더 어노테이션이었음)
  • TLS 인증서는 cert-manager + Let's Encrypt 조합이 사실상 표준

4. 네트워크 (CNI / NetworkPolicy) ​

CNI 플러그인 선택 ​

CalicoCilium
기반BGP 기반 L3 (iptables/eBPF 모드)eBPF 네이티브
강점성숙도, NetworkPolicy 완성도, 온프렘 BGP 연동성능(kube-proxy 대체), L7 정책, Hubble 관측성, Gateway API 내장
특징네트워크 장비가 지원하면 네이티브 라우팅 구성 가능XDP로 경로 단축 → 동일 노드 컨테이너 간 통신 성능 大 향상 (NIC 단계 skip)
  • 신규 클러스터라면 Cilium 우세 (kube-proxy replacement + Hubble + L7 policy)
  • EKS/GKE/AKS는 기본 CNI 쓰다가 필요 시 교체 검토 (교체 비용 큼)

NetworkPolicy — 운영 시 필수 ​

  • 기본은 전부 허용. 네임스페이스 단위 default-deny부터 시작이 정석
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}          # 네임스페이스 내 모든 파드
  policyTypes: [Ingress, Egress]
  • 이후 필요한 통신만 podSelector/namespaceSelector/ipBlock으로 화이트리스트
  • 주의: DNS(53/UDP) egress는 항상 열어줘야 함 (안 열면 전체 장애처럼 보임)

5. 워크로드 리소스 선택 ​

리소스언제핵심 옵션
Deployment무상태 앱 (대부분)strategy.rollingUpdate.maxSurge/maxUnavailable
StatefulSetDB, Kafka 등 (고정 ID/스토리지 필요)volumeClaimTemplates, podManagementPolicy: Parallel, Headless Service 필수
DaemonSet노드당 1개 (로그수집, 모니터링 에이전트)updateStrategy, toleration으로 마스터 노드 포함 여부
Job일회성 배치backoffLimit, activeDeadlineSeconds, ttlSecondsAfterFinished, completions/parallelism
CronJob주기 배치concurrencyPolicy(Forbid

배포 전략 ​

  • RollingUpdate 기본값: maxSurge: 25%, maxUnavailable: 25%
  • 무중단 보장하려면 maxUnavailable: 0 + readinessProbe 필수
  • 카나리/블루그린이 필요하면 → Argo Rollouts 또는 Gateway API 가중치 라우팅

6. Probe 3종 — 무중단 운영의 기본 ​

Probe실패 시용도
livenessProbe컨테이너 재시작데드락 등 회복 불가 상태 감지. 보수적으로 설정 (외부 의존성 체크 넣지 말 것 — DB 죽었다고 앱 전체 재시작 루프 돔)
readinessProbeService 엔드포인트에서 제외트래픽 받을 준비 확인. 외부 의존성 체크는 여기에
startupProbe재시작 (성공 전까지 다른 probe 정지)기동 느린 앱(JVM 등). liveness의 initialDelay 대용
yaml
startupProbe:
  httpGet: { path: /healthz, port: 8080 }
  failureThreshold: 30      # 30 × 10s = 최대 5분 기동 허용
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /ready, port: 8080 }
  periodSeconds: 5
livenessProbe:
  httpGet: { path: /healthz, port: 8080 }
  periodSeconds: 10
  failureThreshold: 3
  • 공통 옵션: initialDelaySeconds, periodSeconds, timeoutSeconds, successThreshold, failureThreshold
  • 방식: httpGet | tcpSocket | exec | grpc

Graceful Shutdown (배포 시 502 방지 세트) ​

yaml
spec:
  terminationGracePeriodSeconds: 60   # 기본 30
  containers:
    - lifecycle:
        preStop:
          exec: { command: ["sleep", "10"] }  # 엔드포인트 제거 전파 대기
  • SIGTERM 핸들링은 앱에서 구현 (in-flight 요청 drain 후 종료)
  • 순서: 엔드포인트 제거와 SIGTERM이 동시에 발생 → preStop sleep으로 시차 흡수

7. 리소스 관리 (requests/limits, QoS) ​

yaml
resources:
  requests: { cpu: 500m, memory: 512Mi }   # 스케줄링 기준
  limits:   { memory: 512Mi }              # 초과 시 제재
  • requests = 스케줄러가 노드 배치에 쓰는 값. 반드시 설정 (없으면 노드 과밀 → 연쇄 장애)
  • memory limit 초과 = OOMKilled, cpu limit 초과 = 스로틀링(죽진 않음)
  • 실무 권장: memory는 requests=limits 동일하게, cpu는 limits 생략(스로틀링 방지) 또는 여유있게

QoS 클래스 (노드 메모리 부족 시 축출 순서) ​

클래스조건축출 우선순위
Guaranteed모든 컨테이너 requests=limits마지막
Burstablerequests < limits (일부만 설정)중간
BestEffort아무것도 미설정가장 먼저 죽음
  • 네임스페이스 가드레일: LimitRange(파드 기본값/상한), ResourceQuota(네임스페이스 총량)
  • 1.33+: In-place Pod Resize — 재시작 없이 리소스 변경 가능

8. 스케줄링 — Pod를 원하는 노드에 배치 ​

스케줄러는 Filtering(배치 가능 노드 선별) → Scoring(최적 노드 점수화) 순으로 동작. 볼륨/리소스/토폴로지/셀렉터 필터 등이 관여

도구 선택 기준 ​

도구방향용도
nodeSelectorPod→Node단순 레이블 매칭 (GPU 노드 등)
nodeAffinityPod→Node조건식(In/NotIn/Exists), soft/hard 지정 가능
podAffinity / podAntiAffinityPod→Pod특정 파드와 같이/떨어뜨려 배치 (HA 필수: replica를 다른 노드로)
taint + tolerationNode→Pod노드가 파드를 밀어냄. 전용 노드풀(GPU, 배치 전용) 구성
topologySpreadConstraints분산zone/node 단위 균등 분산. anti-affinity보다 유연
priorityClass우선순위리소스 부족 시 낮은 우선순위 파드 선점(preemption)

hard vs soft ​

  • requiredDuringSchedulingIgnoredDuringExecution — 필수 (못 맞추면 Pending)
  • preferredDuringSchedulingIgnoredDuringExecution — 선호 (best effort)

실무 기본 세트: zone 분산 + 동일 노드 회피 ​

yaml
topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: ScheduleAnyway     # zone 분산은 soft
    labelSelector: { matchLabels: { app: order-api } }
  - maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule      # 노드 분산은 hard
    labelSelector: { matchLabels: { app: order-api } }

Taint 예시 (전용 노드풀) ​

bash
kubectl taint nodes gpu-node-1 dedicated=gpu:NoSchedule
  • effect: NoSchedule | PreferNoSchedule | NoExecute(기존 파드도 축출)

9. 오토스케일링 ​

도구대상기준
HPAPod 수CPU/메모리/커스텀 메트릭
VPAPod 리소스 크기사용량 히스토리 (HPA와 같은 메트릭에 동시 사용 금지)
KEDAPod 수 (0까지)이벤트 소스(Kafka lag, SQS, cron 등 60+) — 배치/컨슈머는 이거
Cluster Autoscaler / Karpenter노드 수Pending 파드. Karpenter가 노드풀 관리 없이 더 빠르고 유연 (AWS 표준)
yaml
# HPA 핵심
spec:
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource: { name: cpu, target: { type: Utilization, averageUtilization: 60 } }
  behavior:                      # 급격한 스케일인 방지
    scaleDown:
      stabilizationWindowSeconds: 300
  • HPA 쓰려면 Deployment에 replicas 고정값 빼기 (GitOps 충돌 방지)

10. 가용성 (PDB) ​

yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: order-api-pdb }
spec:
  minAvailable: 2          # 또는 maxUnavailable: 1
  selector: { matchLabels: { app: order-api } }
  • 노드 drain(업그레이드, 스팟 회수) 같은 자발적 중단에서 최소 가용 파드 수 보장
  • 없으면 노드 업그레이드 때 전 replica 동시 축출 가능 → 운영 서비스 전부 필수
  • 주의: minAvailable = replicas로 잡으면 drain이 영원히 안 끝남 (best-effort 보호지 하드 보장 아님)

11. 스토리지 (PV / PVC / StorageClass) ​

  • 구조: PV(볼륨 실체) ↔ PVC(사용자의 요청) — 파드와 스토리지를 분리(디커플링)
  • 실무에선 PV 수동 생성 거의 안 함 → StorageClass + 동적 프로비저닝이 기본
항목옵션메모
accessModesRWO(노드1개 rw) / ROX / RWX(다중노드 rw) / RWOP(파드1개)블록스토리지(EBS)는 RWO만. RWX 필요하면 NFS/EFS/CephFS
persistentVolumeReclaimPolicyRetain / Delete운영 데이터는 Retain (PVC 지워도 데이터 보존)
volumeBindingModeWaitForFirstConsumer / Immediate멀티 AZ에선 WaitForFirstConsumer (파드 뜨는 zone에 볼륨 생성)
allowVolumeExpansiontrue/falsetrue면 PVC 수정만으로 용량 확장
  • 스냅샷: VolumeSnapshot (CSI). 백업 체계는 Velero가 표준
  • 상태ful 워크로드는 가능하면 매니지드(RDS 등)로 빼는 게 운영 부담 최소화

12. 설정과 시크릿 ​

ConfigMapSecret
용도일반 설정자격증명, 인증서
주의1MB 제한base64일 뿐 암호화 아님 → etcd encryption at rest + RBAC 필수
  • 주입 방식: env / envFrom / 볼륨 마운트
    • 볼륨 마운트는 변경 시 자동 반영(kubelet sync 주기), env는 파드 재시작 필요
  • immutable: true — 변경 불가 처리 (실수 방지 + kubelet watch 부하 감소)
  • ConfigMap 변경 시 롤아웃 트리거: 해시를 어노테이션에 넣거나 (checksum/config), Reloader/Kustomize configMapGenerator 사용
  • 실무 시크릿 관리: External Secrets Operator(Vault/AWS Secrets Manager 연동) 또는 Sealed Secrets — 시크릿을 git에 평문으로 두지 말 것

13. 보안 기본기 ​

securityContext (파드/컨테이너 스펙에 기본 탑재 권장) ​

yaml
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities: { drop: ["ALL"] }
  seccompProfile: { type: RuntimeDefault }

기타 체크리스트 ​

  • RBAC: ServiceAccount별 최소 권한. 기본 SA에 권한 주지 말고, automountServiceAccountToken: false (API 안 쓰는 파드)
  • Pod Security Standards: 네임스페이스 레이블로 강제 — pod-security.kubernetes.io/enforce: restricted
  • 이미지: 태그 latest 금지(다이제스트/시맨틱 버전), 프라이빗 레지스트리 + 스캔(Trivy)
  • 정책 엔진 필요 시: Kyverno (OPA Gatekeeper보다 진입장벽 낮음)

14. 운영 kubectl 치트시트 ​

bash
# 상태 파악 (장애 시 이 순서로)
kubectl get events --sort-by=.lastTimestamp -A     # 최근 이벤트부터
kubectl get pods -o wide --field-selector=status.phase!=Running -A
kubectl describe pod <pod>                          # Events 섹션 확인
kubectl logs <pod> --previous                       # 죽기 직전 로그 (CrashLoop 필수)
kubectl top pods --sort-by=memory                   # 리소스 사용량

# 배포 관리
kubectl rollout status deploy/<name>
kubectl rollout undo deploy/<name>                  # 즉시 롤백
kubectl rollout restart deploy/<name>               # 재기동 (ConfigMap 변경 반영 등)
kubectl rollout history deploy/<name>

# 디버깅
kubectl exec -it <pod> -- sh
kubectl debug <pod> -it --image=nicolaka/netshoot   # 유틸 없는 distroless 디버깅
kubectl debug node/<node> -it --image=busybox       # 노드 진입
kubectl port-forward svc/<svc> 8080:80

# 노드 운영
kubectl cordon <node>                               # 신규 스케줄 차단
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
kubectl uncordon <node>

# 리소스 탐색
kubectl explain deploy.spec.strategy                # 필드 문서 즉석 확인
kubectl get <res> -o yaml | kubectl neat            # 깔끔한 yaml
kubectl api-resources                               # 리소스 약어 확인

자주 겪는 상태 → 원인 ​

상태1순위 의심
Pending리소스 부족(requests 과다), taint, PVC 바인딩 실패 → describe의 Events
CrashLoopBackOff앱 기동 실패 → logs --previous
OOMKilled (exit 137)memory limit 초과
ImagePullBackOff이미지 태그 오타, imagePullSecrets 누락
Evicted노드 디스크/메모리 압박
Readiness 실패로 트래픽 0probe 경로/포트 오타, 의존 서비스 다운

15. 프로덕션 매니페스트 최소 체크리스트 ​

배포 전 이것만은 확인:

  • [ ] resources.requests 설정 (memory는 limits까지)
  • [ ] readinessProbe + livenessProbe (+ 기동 느리면 startupProbe)
  • [ ] replicas ≥ 2 + topologySpreadConstraints 또는 podAntiAffinity
  • [ ] PodDisruptionBudget
  • [ ] graceful shutdown: preStop sleep + terminationGracePeriodSeconds
  • [ ] securityContext (nonRoot, drop ALL)
  • [ ] 이미지 태그 고정 (latest 금지)
  • [ ] HPA 쓰면 replicas 필드 제거
  • [ ] 시크릿 git 평문 금지 (ESO/Sealed Secrets)
  • [ ] NetworkPolicy default-deny + 화이트리스트
  • [ ] 로그는 stdout/stderr로 (파일 로깅 금지)

참고자료 ​