도입부: 멀티 클러스터가 기본이 된 지금, 쿠버네티스를 수동으로 운영하면 드리프트·패치 지연·팀 병목이 빠르게 쌓입니다. 이 글에서는 Day0~Day2 전 구간을 선언적(Declarative)·자동화 중심으로 표준화해 “교체 가능한 클러스터”에 가까워지는 최소 기준을 정리합니다.
왜 “쿠버네티스 수명주기 자동화(Cluster Lifecycle Automation)”가 중요한가요?
클러스터 운영은 크게 다음 단계로 나뉩니다.
- Day0: 클러스터 생성(네트워크, IAM, 기본 설정)
- Day1: 필수 애드온 설치(ingress, CNI, CSI, metrics, DNS 등)와 정책 적용
- Day2: 업그레이드, 보안 패치, 확장, 장애 대응, 감사 대응, 폐기
문제는 클러스터 수가 늘수록 Day2 작업이 폭발한다는 점입니다. 수동 변경이 섞이면 다음 증상이 거의 필연적으로 발생합니다.
- 구성 드리프트(configuration drift): “A 클러스터엔 있는데 B엔 없다”가 일상이 됨
- 패치/업그레이드 지연: 위험을 알면서도 “이번 분기엔 바빠서…”가 반복됨
- 운영 병목: 특정 담당자/팀만 아는 절차가 생기며 확장이 막힘
그래서 목표는 하나입니다.
클러스터를 “아껴 쓰는 대상”이 아니라 표준 파이프라인으로 언제든 재생성/교체 가능한 인프라로 보는 관점입니다.
핵심 원칙: 수동 절차를 “선언적(Declarative) 적용”으로 치환하기
제가 인상 깊게 본 사례 중 하나가 kube-system 영역의 비핵심 컴포넌트를 다루는 방식 변화입니다.
- 과거:
systemd + 스크립트로 노드에 직접 올리고 순서대로 실행(= 암묵지/절차 중심) - 개선: CLM(Cluster Lifecycle Management) 코드에서 아티팩트별 매니페스트 폴더를 선언적으로 적용(= 상태/결과 중심)
여기서 포인트는 두 가지입니다.
- /manifests/APP/ 처럼 “아티팩트 단위”로 구조를 고정해 관리 난이도를 낮춥니다.
- 파일명/적용 순서를 가정하지 않는다는 원칙이 중요합니다. 운영 지식이 “실행 순서”에 묶이는 순간 자동화의 재사용성이 급격히 떨어지기 때문입니다.
“교체 가능한 클러스터”를 위한 최소 표준 4축
대화에서 정리했던 내용을 좀 더 블로그용으로 다듬으면, 최소 표준은 보통 아래 4축으로 수렴합니다.
1) IaC + CLM: 생성/업그레이드/폐기까지 파이프라인화
- Terraform/CloudFormation 같은 IaC로 인프라(네트워크, IAM, 노드풀) 를 만들고
- 클러스터 생성부터 버전 업그레이드, 폐기까지를 “사람의 체크리스트”가 아니라 파이프라인으로 둡니다.
이 축이 없으면 “교체 가능”이라는 말이 성립하기 어렵습니다. 교체하려면 늘 새로 만들 수 있어야 하니까요.
2) GitOps: 애드온·정책을 선언적으로 배포
클러스터에 들어갈 필수 구성(애드온/정책)을 Git이 진실의 원천(source of truth) 이 되게 만듭니다.
- “누가 언제 무엇을 바꿨는지”가 코드 리뷰/커밋으로 남음(감사 대응에도 유리)
- 장애 시에도 “클러스터를 새로 파서 Git을 붙이면 동일 상태”가 가능
특히 kube-system 주변의 컴포넌트(비핵심 포함)는 “한 번 설치하고 끝”이 아니라 지속적으로 변하므로, 수동 설치는 빠르게 한계가 옵니다.
3) Security baseline: IAM/RBAC·Network·Secrets 수명주기
보안은 도구보다 “원칙”이 표준화 포인트가 됩니다.
- IAM/RBAC 최소 권한 원칙
- 네트워크 기본 격리(기본 deny, 네임스페이스/테넌시 기준 등)
- Secrets/키 관리(KMS/HSM 연동 여부, 회전 주기, 접근 승인)
여기서 중요한 인사이트는 “모든 클러스터가 동일해야 한다”가 아니라, 달라도 되는 부분을 모듈/프로파일로 분리하되 관리 방식은 같아야 한다는 점입니다.
4) Ops baseline: 관측/감사/백업·DR
운영 자동화의 완성은 Day2에서 갈립니다.
- 로그/메트릭/트레이스(관측성)
- Kubernetes audit log 및 보관 정책(감사)
- 백업/복구(Recovery)와 DR 시나리오
이 축이 없으면, 클러스터가 늘어날수록 “운영 비용”이 아니라 “운영 불가능” 상태로 가기 쉽습니다.
구체적 구현 예시: “아티팩트별 매니페스트 폴더”로 선언적 적용하기
아래는 자료의 의도를 이해하기 쉽게 정리한 예시 구조입니다.
repo/
clm/
apply.sh
manifests/
coredns/
deployment.yaml
service.yaml
metrics-server/
components.yaml
external-dns/
rbac.yaml
deployment.yaml
그리고 적용은 “순서 가정 없이” 폴더 단위로 처리합니다(예: kustomize나 서버사이드 apply를 활용).
#!/usr/bin/env bash
set -euo pipefail
MANIFEST_ROOT="./manifests"
for app in "${MANIFEST_ROOT}"/*; do
[ -d "$app" ] || continue
echo "[APPLY] $(basename "$app")"
kubectl apply -f "$app"
done
- 장점: 운영자가 “이거 먼저 깔고 저거 나중에…” 같은 절차를 문서로 관리하지 않아도 됩니다.
- 주의: 리소스 간 의존성이 정말 존재한다면(예: CRD → CR), 그 의존성은 도구/구조로 명시(kustomize, helm, Argo CD sync waves 등)하는 쪽이 장기적으로 안전합니다. “사람이 기억하는 순서”로 두면 다시 수동 운영으로 회귀합니다.
제가 보는 인사이트: 표준화의 본질은 “동일함”이 아니라 “증명 가능함”입니다
대화 중에 “현실에선 클러스터 차이가 기능/규제 때문일 수도 있다”는 이야기가 나왔는데, 이 포인트가 꽤 중요합니다.
- 모든 클러스터를 하나의 스택으로 강제 통일하기는 어렵습니다.
- 대신 프로파일(예: regulated / standard / edge) 로 변동성을 관리하고,
- 어떤 프로파일이든 같은 방식으로 생성·변경·감사 증적을 남길 수 있어야 합니다.
결국 “교체 가능한 클러스터”는 기술 선택 이전에 운영 모델의 선택입니다.
수동 변경을 줄이고, 선언적 정의와 파이프라인으로 재현성을 확보하면 클러스터는 점점 “대체 가능한 infra”에 가까워집니다.
마무리
쿠버네티스 수명주기 자동화는 “도구를 하나 더 도입”하는 문제가 아니라, Day0~Day2를 선언적으로 표준화해 드리프트를 제거하는 운영 체계를 만드는 일입니다. 작은 시작이라면 /manifests/APP/ 같은 구조부터 잡고, GitOps와 CLM 파이프라인으로 “언제든 교체 가능”에 한 걸음씩 다가가 보시면 좋겠습니다.