들어가며: 왜 쿠버네티스인가?
웹 서비스를 만들었다고 상상해보세요. 처음에는 사용자가 100명이었지만, 갑자기 10만 명으로 늘어났습니다. 서버 한 대로는 감당이 안 되죠. 서버를 10대, 100대로 늘려야 하는데, 이걸 어떻게 관리할까요? 바로 이 문제를 해결하는 것이 쿠버네티스(Kubernetes, K8s) 입니다.
쿠버네티스는 컨테이너화된 애플리케이션을 자동으로 배포하고, 확장하고, 관리해주는 오케스트레이션 플랫폼입니다. 구글이 내부에서 사용하던 Borg 시스템을 오픈소스화한 것으로, 현재 클라우드 네이티브 생태계의 사실상 표준(de facto standard)입니다.
📦 1단계: 컨테이너 이해하기
컨테이너란?
컨테이너는 애플리케이션과 그 실행에 필요한 모든 것(라이브러리, 설정 파일 등)을 하나의 패키지로 묶은 것입니다.
비유: 컨테이너는 이사 갈 때 쓰는 박스와 같습니다. 박스 안에 물건을 담아두면, 어떤 집(서버)으로 옮기든 똑같이 작동합니다.
가상머신(VM) vs 컨테이너:
- VM: 각자 독립된 OS를 가지고 있어 무겁고 느림 (집을 통째로 옮기는 것)
- 컨테이너: OS 커널을 공유하여 가볍고 빠름 (필요한 물건만 담은 박스)
Docker와의 관계
Docker는 컨테이너를 만들고 실행하는 도구입니다. 쿠버네티스는 이런 컨테이너들을 대규모로 관리하는 도구죠.
딥먹 주제:
- Docker 이미지 레이어 구조와 최적화 기법
- Container Runtime Interface (CRI): Docker, containerd, CRI-O 비교
- OCI (Open Container Initiative) 표준
- Multi-stage build를 통한 이미지 크기 최적화
🎯 2단계: 파드(Pod) - 쿠버네티스의 최소 단위
파드란?
파드는 하나 이상의 컨테이너를 묶은 그룹입니다. 쿠버네티스에서 배포할 수 있는 가장 작은 단위죠.
왜 컨테이너가 아니라 파드를 단위로 쓸까?
실제 애플리케이션은 여러 프로세스가 협력해서 동작합니다. 예를 들어:
- 메인 웹 서버 컨테이너
- 로그를 수집하는 사이드카 컨테이너
- 설정 파일을 동기화하는 어댑터 컨테이너
이런 컨테이너들은 같은 네트워크와 스토리지를 공유해야 하는데, 파드가 이를 가능하게 합니다.
파드의 특징:
- 파드 내 컨테이너들은 localhost로 통신 가능 (같은 네트워크 네임스페이스)
- 파드는 하나의 IP 주소를 공유
- 파드는 임시적(ephemeral) - 언제든 삭제되고 재생성될 수 있음
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
spec:
containers:
- name: web-server
image: nginx:1.21
ports:
- containerPort: 80
- name: log-collector
image: fluentd:v1.14
딥먹 주제:
- 파드의 라이프사이클과 상태(Pending, Running, Succeeded, Failed)
- Init 컨테이너와 사이드카 패턴
- 파드 네트워킹: CNI(Container Network Interface) 플러그인
- 파드 간 통신: Service Mesh (Istio, Linkerd)
- 파드 스케줄링: Node Affinity, Taints and Tolerations
- 리소스 QoS 클래스: Guaranteed, Burstable, BestEffort
🎮 3단계: 디플로이먼트(Deployment) - 선언적 배포 관리
디플로이먼트란?
디플로이먼트는 파드를 관리하는 상위 컨트롤러입니다. “내 애플리케이션의 파드를 3개 유지해줘”라고 선언하면, 쿠버네티스가 자동으로 이를 보장합니다.
핵심 개념: 선언적(Declarative) 관리
전통적 방식(명령형):
- 서버 A에 접속
- 애플리케이션 설치
- 서버 B에 접속
- 애플리케이션 설치
- …
쿠버네티스 방식(선언적):
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-app
spec:
replicas: 3 # "파드 3개를 원해"
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.21
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"“파드 3개”라고 선언하면, 쿠버네티스가 알아서:
- 파드가 죽으면 자동으로 재시작
- 노드가 다운되면 다른 노드에 파드 재배치
- 트래픽에 따라 자동으로 스케일링 (HPA 사용 시)
롤링 업데이트와 롤백
새 버전 배포 시, 한 번에 모든 파드를 교체하면 서비스 다운타임이 발생합니다. 디플로이먼트는 점진적으로 파드를 교체합니다.
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # 최대 1개까지 동시에 죽일 수 있음
maxSurge: 1 # 최대 1개까지 추가로 생성 가능프로세스:
- 새 버전 파드 1개 생성
- 준비되면 이전 버전 파드 1개 종료
- 반복…
문제가 생기면 이전 버전으로 즉시 롤백:
bash
kubectl rollout undo deployment/my-web-app딥먹 주제:
- ReplicaSet의 역할과 디플로이먼트와의 관계
- Blue-Green 배포, Canary 배포 전략
- StatefulSet: 상태를 가진 애플리케이션 관리 (데이터베이스 등)
- DaemonSet: 모든 노드에 파드 배포 (모니터링 에이전트 등)
- Job과 CronJob: 배치 작업 관리
- Horizontal Pod Autoscaler (HPA)와 Vertical Pod Autoscaler (VPA)
- Cluster Autoscaler: 노드 자동 확장
🌐 4단계: 서비스(Service) - 네트워킹의 핵심
문제 상황
파드는 생성/삭제될 때마다 IP가 바뀝니다. 프론트엔드가 백엔드 파드에 접속하려면 어떻게 해야 할까요?
서비스란?
서비스는 파드들의 고정된 진입점을 제공합니다. 로드밸런서 역할도 하죠.
서비스 타입:
- ClusterIP (기본값): 클러스터 내부에서만 접근 가능
yaml
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
type: ClusterIP
selector:
app: backend # 이 라벨을 가진 파드들에게 트래픽 전달
ports:
- port: 80
targetPort: 8080- NodePort: 모든 노드의 특정 포트로 외부 접근 가능
yaml
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30000 # 30000-32767 범위- LoadBalancer: 클라우드 로드밸런서 자동 생성 (AWS ELB, GCP LB 등)
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080- ExternalName: 외부 서비스에 대한 DNS alias
Ingress: 고급 라우팅
Ingress는 HTTP/HTTPS 트래픽을 위한 7계층 로드밸런싱을 제공합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: myapp.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80딥먹 주제:
- kube-proxy의 동작 원리: iptables vs IPVS 모드
- CoreDNS와 서비스 디스커버리
- Headless Service와 StatefulSet
- Ingress Controller 비교: NGINX, Traefik, HAProxy, Contour
- Service Mesh: Istio, Linkerd를 통한 고급 트래픽 관리
- Network Policy: 파드 간 통신 제어
- CNI 플러그인: Calico, Flannel, Weave, Cilium
💾 5단계: 볼륨(Volume) - 데이터 영속성
문제 상황
파드는 언제든 재시작될 수 있습니다. 컨테이너 내부에 저장한 데이터는 사라지죠. 데이터베이스나 파일 저장이 필요하다면?
볼륨의 종류
1. emptyDir: 파드가 살아있는 동안만 유지되는 임시 볼륨
spec:
containers:
- name: app
volumeMounts:
- name: cache
mountPath: /cache
volumes:
- name: cache
emptyDir: {}용도: 임시 캐시, 컨테이너 간 데이터 공유
2. hostPath: 노드의 파일시스템 마운트
volumes:
- name: logs
hostPath:
path: /var/log/myapp
type: Directory주의: 파드가 다른 노드로 옮겨가면 데이터 접근 불가
3. PersistentVolume (PV)와 PersistentVolumeClaim (PVC)
진짜 영속적인 스토리지를 위한 방법입니다.
개념 분리:
- PV: 실제 스토리지 (관리자가 생성)
- PVC: 스토리지 요청 (개발자가 생성)
# PVC 생성 (개발자)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-pvc
spec:
accessModes:
- ReadWriteOnce # 한 번에 하나의 노드만 읽기/쓰기 가능
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd
---
# 파드에서 사용
spec:
containers:
- name: postgres
volumeMounts:
- name: db-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: db-storage
persistentVolumeClaim:
claimName: database-pvcStorageClass: 동적 프로비저닝
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp3
iopsPerGB: "50"딥먹 주제:
- Volume Plugin: CSI (Container Storage Interface)
- AccessMode 상세: RWO, ROX, RWX
- StatefulSet과 VolumeClaimTemplate
- Snapshot과 클론
- 스토리지 벤더 비교: AWS EBS, GCE PD, Azure Disk, Ceph, GlusterFS
- Local Persistent Volume과 노드 친화성
- Volume expansion과 제약사항
🔐 6단계: ConfigMap & Secret - 설정과 민감 정보 관리
ConfigMap: 설정 데이터
애플리케이션 설정을 코드와 분리하는 것은 12-Factor App의 기본 원칙입니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "postgres.default.svc.cluster.local"
database_port: "5432"
log_level: "INFO"
config.json: |
{
"feature_flags": {
"new_ui": true
}
}사용 방법:
- 환경 변수로 주입
spec:
containers:
- name: app
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database_host- 전체를 환경 변수로
envFrom:
- configMapRef:
name: app-config- 파일로 마운트
volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: app-configSecret: 민감한 정보
Secret은 ConfigMap과 비슷하지만, base64로 인코딩되고 메모리에만 저장됩니다.
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4= # admin을 base64 인코딩
password: cGFzc3dvcmQxMjM= # password123더 안전하게:
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password=password123사용:
spec:
containers:
- name: app
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password주의사항:
- Secret은 base64일 뿐, 암호화가 아닙니다!
- etcd 암호화를 반드시 활성화해야 합니다
- RBAC로 접근 제어 필수
딥먹 주제:
- etcd 암호화 설정 (encryption-at-rest)
- External Secrets Operator: AWS Secrets Manager, HashiCorp Vault 연동
- Sealed Secrets: GitOps를 위한 암호화된 Secret
- Secret 자동 로테이션
- Image Pull Secret과 Private Registry 연동
- Service Account Token과 IRSA (AWS), Workload Identity (GCP)
🎛️ 7단계: 네임스페이스(Namespace) - 리소스 격리
네임스페이스란?
네임스페이스는 가상의 클러스터를 만드는 것과 같습니다. 하나의 물리적 클러스터를 논리적으로 분할합니다.
기본 네임스페이스:
default: 기본 작업 공간kube-system: 쿠버네티스 시스템 컴포넌트kube-public: 모두에게 공개되는 리소스kube-node-lease: 노드 하트비트 정보
사용 사례:
- 환경 분리: dev, staging, production
- 팀 분리: team-a, team-b
- 프로젝트 분리: project-x, project-y
apiVersion: v1
kind: Namespace
metadata:
name: development
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: development # 이 네임스페이스에 생성리소스 쿼터 설정:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: development
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
persistentvolumeclaims: "5"
pods: "50"딥먹 주제:
- LimitRange: 개별 파드/컨테이너 리소스 제한
- Network Policy를 통한 네임스페이스 간 격리
- RBAC와 네임스페이스 기반 권한 관리
- Multi-tenancy 아키텍처 패턴
- Hierarchical Namespace Controller (HNC)
🏗️ 쿠버네티스 아키텍처: 내부 동작 원리
Control Plane (마스터 노드)
1. API Server (kube-apiserver)
- 모든 요청의 진입점
- RESTful API 제공
- 인증, 인가, Admission Control 수행
- etcd와 유일하게 통신하는 컴포넌트
2. etcd
- 분산 키-밸류 저장소
- 클러스터의 모든 상태 정보 저장
- Raft 알고리즘으로 데이터 일관성 보장
3. Scheduler (kube-scheduler)
- 파드를 어느 노드에 배치할지 결정
- 리소스, Affinity, Taints 등 고려
- 실제 배치는 kubelet이 수행
4. Controller Manager (kube-controller-manager)
- 다양한 컨트롤러들의 집합
- Deployment Controller, ReplicaSet Controller, Node Controller 등
- 선언된 상태(desired state)와 현재 상태(current state)를 지속적으로 비교하여 조정
5. Cloud Controller Manager
- 클라우드 제공자별 기능 통합
- LoadBalancer 타입 서비스 생성 시 실제 클라우드 LB 생성 등
Worker Node
1. Kubelet
- 각 노드의 에이전트
- API Server로부터 파드 명세를 받아 컨테이너 런타임에 전달
- 파드와 컨테이너의 상태를 모니터링하고 API Server에 보고
2. Kube-proxy
- 네트워크 프록시
- Service의 가상 IP를 실제 파드 IP로 변환
- iptables 또는 IPVS 규칙 관리
3. Container Runtime
- 실제 컨테이너를 실행
- Docker, containerd, CRI-O 등
딥먹 주제:
- Control Plane 고가용성 (HA) 구성
- etcd 백업과 복구 전략
- Custom Scheduler 개발
- Admission Webhook: 커스텀 검증 및 변경 로직
- Operator Pattern: Custom Resource Definition (CRD)과 Custom Controller
- API Aggregation Layer
- 쿠버네티스 소스 코드 분석 (특히 Controller 패턴)
🔍 8단계: 관찰성 (Observability)
로깅
중앙 집중식 로깅 필요성: 파드는 언제든 삭제될 수 있어, 로그를 외부에 저장해야 합니다.
일반적인 스택: EFK
- Elasticsearch: 로그 저장 및 검색
- Fluentd/Fluent Bit: 로그 수집 및 전달
- Kibana: 로그 시각화
최신 트렌드: Loki
- Grafana Labs의 경량 로그 시스템
- 로그 자체가 아닌 메타데이터만 인덱싱하여 저장 공간 절약
모니터링
Prometheus + Grafana
Prometheus는 쿠버네티스 환경에서 사실상 표준인 모니터링 도구입니다.
apiVersion: v1
kind: Service
metadata:
name: my-app
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"주요 메트릭:
- CPU, 메모리 사용량
- 네트워크 I/O
- 파드 재시작 횟수
- 애플리케이션별 커스텀 메트릭
추적 (Tracing)
분산 추적의 필요성: 마이크로서비스 환경에서 하나의 요청이 여러 서비스를 거칩니다. 어디서 느려지는지 추적이 필요합니다.
도구:
- Jaeger
- Zipkin
- OpenTelemetry (표준화된 계측 프레임워크)
딥먹 주제:
- Metrics Server와 리소스 메트릭 파이프라인
- Custom Metrics와 External Metrics (HPA 고급 활용)
- PromQL 쿼리 언어 마스터
- Grafana 대시보드 설계 Best Practice
- Thanos/Cortex: Prometheus 장기 저장 및 HA
- OpenTelemetry Collector 활용
- eBPF 기반 관찰성 도구: Cilium, Pixie
🛡️ 9단계: 보안
RBAC (Role-Based Access Control)
쿠버네티스는 누가, 무엇을, 어떻게 할 수 있는지 세밀하게 제어합니다.
주요 리소스:
- ServiceAccount: 파드가 사용하는 계정
- Role/ClusterRole: 권한 정의
- Role: 네임스페이스 내 권한
- ClusterRole: 클러스터 전체 권한
- RoleBinding/ClusterRoleBinding: 사용자/그룹/ServiceAccount에 권한 부여
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-reader
namespace: development
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: development
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: development
subjects:
- kind: ServiceAccount
name: app-reader
namespace: development
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioPod Security Standards
파드가 할 수 있는 것을 제한합니다.
세 가지 레벨:
- Privileged: 제한 없음
- Baseline: 기본적인 보안 (권장)
- Restricted: 매우 엄격 (프로덕션 권장)
apiVersion: v1
kind: Namespace
metadata:
name: secure-app
labels:
pod-security.kubernetes.io/enforce: restricted주요 제약사항 (Restricted):
- root로 실행 불가
- privileged 컨테이너 불가
- hostPath 볼륨 불가
- hostNetwork, hostPID, hostIPC 불가
Network Policy
파드 간 통신을 방화벽처럼 제어합니다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432딥먹 주제:
- OPA (Open Policy Agent)와 Gatekeeper: 정책 기반 거버넌스
- Admission Controller 커스터마이징
- Pod Security Admission과 이전 PodSecurityPolicy 마이그레이션
- mTLS와 Service Mesh 보안
- 이미지 서명 및 검증: Notary, Cosign
- Runtime Security: Falco, Aqua, Sysdig
- Secrets 관리: HashiCorp Vault, External Secrets Operator
- Supply Chain Security: SLSA Framework
🚀 10단계: 최신 인프라 트렌드와 쿠버네티스
GitOps
개념: Git을 Single Source of Truth로 사용하는 배포 방식
도구:
- ArgoCD: 가장 인기있는 GitOps CD 도구
- Flux: CNCF 졸업 프로젝트
- Jenkins X: CI/CD 통합
작동 방식:
- 개발자가 Git에 매니페스트 파일 커밋
- ArgoCD가 Git 저장소를 지속적으로 모니터링
- 변경 감지 시 자동으로 클러스터에 적용
- 드리프트 감지 및 자동 동기화
장점:
- 코드 리뷰를 통한 변경 검토
- 완벽한 변경 이력 (Git log)
- 쉬운 롤백 (Git revert)
- 재해 복구 용이
Service Mesh
문제: 마이크로서비스가 수백 개가 되면 네트워킹 복잡도 폭발
Service Mesh가 제공하는 것:
- 서비스 간 mTLS 자동 적용
- 트래픽 관리 (Circuit Breaker, Retry, Timeout)
- Canary 배포, A/B 테스트
- 상세한 메트릭과 추적
인기 있는 Service Mesh:
- Istio: 가장 기능이 풍부하지만 복잡
- Linkerd: 가볍고 사용하기 쉬움
- Consul: HashiCorp 제품, 멀티 클라우드 지원
Serverless on Kubernetes
Knative
- 쿠버네티스 위에서 서버리스 워크로드 실행
- 트래픽이 없으면 파드를 0으로 스케일 다운
- 자동 스케일링과 리비전 관리
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: hello-world
spec:
template:
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
env:
- name: TARGET
value: "Knative"장점:
- 비용 절감 (사용하지 않을 때 리소스 0)
- 자동 스케일링 (0 → 수천 개 파드)
- 블루-그린 배포 자동화
다른 옵션:
- OpenFaaS: Function as a Service
- Fission: 빠른 콜드 스타트에 최적화
- Kubeless: 경량 FaaS 프레임워크
Platform Engineering과 Internal Developer Platform (IDP)
개념: 개발자가 인프라 복잡성을 신경 쓰지 않고 코드에만 집중할 수 있도록 추상화 레이어 제공
도구:
- Backstage: Spotify가 만든 개발자 포털
- Crossplane: 인프라를 쿠버네티스 리소스처럼 관리
- Porter: CNAB 기반 애플리케이션 패키징
- Humanitec: 플랫폼 오케스트레이션
예시: Crossplane
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
metadata:
name: my-postgres
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t3.micro
engine: postgres
engineVersion: "13.7"
masterUsername: admin
allocatedStorage: 20개발자는 AWS 콘솔 없이 쿠버네티스 매니페스트만으로 RDS 인스턴스를 생성할 수 있습니다.
FinOps와 비용 최적화
쿠버네티스에서 비용이 폭발하는 이유:
- 리소스 요청(request)과 실제 사용량의 차이
- 과도한 오버프로비저닝
- 유휴 리소스 방치
비용 최적화 도구:
1. Kubecost
- 네임스페이스, 파드, 레이블별 비용 추적
- Right-sizing 권장사항 제공
- 실시간 비용 알림
2. Goldilocks
- VPA를 활용한 리소스 request/limit 권장
3. Karpenter (AWS)
- 노드를 자동으로 프로비저닝/디프로비저닝
- Cluster Autoscaler보다 빠르고 효율적
- 워크로드 요구사항에 맞는 인스턴스 타입 자동 선택
모범 사례:
spec:
containers:
- name: app
resources:
requests: # 스케줄링 기준
memory: "128Mi"
cpu: "100m"
limits: # 상한선
memory: "256Mi"
cpu: "200m"딥먹 주제:
- Vertical Pod Autoscaler (VPA) 실전 활용
- Spot/Preemptible 인스턴스 활용 전략
- Multi-tenancy 환경에서의 Fair Scheduling
- Resource Bin Packing과 Fragmentation 해결
- 클라우드별 비용 구조 이해 (AWS EKS, GKE, AKS)
🏭 11단계: 실전 아키텍처 패턴
1. 멀티 클러스터 전략
왜 여러 클러스터를 운영하나?
- 환경 분리 (dev, staging, prod)
- 지역 분산 (글로벌 서비스)
- 장애 격리 (blast radius 최소화)
- 규정 준수 (데이터 주권)
멀티 클러스터 관리 도구:
KubeFed (Kubernetes Federation)
- 여러 클러스터를 하나처럼 관리
- 리소스를 여러 클러스터에 자동 배포
Rancher
- 웹 UI로 여러 클러스터 통합 관리
- RBAC, 모니터링, 로깅 통합
ArgoCD Application Sets
- GitOps 방식으로 여러 클러스터에 배포
- 템플릿을 통한 설정 통합
2. Blue-Green 배포
개념: 두 개의 동일한 환경(Blue, Green)을 유지하고 순간적으로 전환
yaml
# Blue 환경
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
version: blue # Blue로 트래픽 전달
ports:
- port: 80
---
# Green 환경 배포 (새 버전)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-green
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: green
template:
metadata:
labels:
app: my-app
version: green
spec:
containers:
- name: app
image: myapp:v2.0검증 후 Service의 selector를 version: green으로 변경하면 즉시 전환됩니다.
3. Canary 배포
개념: 새 버전을 일부 사용자에게만 먼저 배포하고 점진적으로 확대
Argo Rollouts를 사용한 Canary:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10 # 10%에게 배포
- pause: {duration: 5m}
- setWeight: 30 # 30%로 확대
- pause: {duration: 5m}
- setWeight: 70
- pause: {duration: 5m}
template:
spec:
containers:
- name: app
image: myapp:v2.0Istio/Linkerd를 사용한 고급 Canary:
- 특정 사용자 그룹에게만 배포 (헤더 기반 라우팅)
- A/B 테스트
- 자동 rollback (에러율 임계값 초과 시)
4. 마이크로서비스 통신 패턴
동기 통신 (Synchronous):
- REST API (Service + Ingress)
- gRPC (고성능 RPC 프레임워크)
비동기 통신 (Asynchronous):
- 메시지 큐: RabbitMQ, Apache Kafka, NATS
- 이벤트 스트리밍: Kafka Streams, Apache Flink
예시: Kafka 기반 이벤트 드리븐 아키텍처
yaml
# Kafka 클러스터 (Strimzi Operator 사용)
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
name: my-cluster
spec:
kafka:
replicas: 3
listeners:
- name: plain
port: 9092
type: internal
tls: false
zookeeper:
replicas: 3딥먹 주제:
- Circuit Breaker 패턴 구현 (Istio, Resilience4j)
- Saga 패턴: 분산 트랜잭션 관리
- Event Sourcing과 CQRS
- API Gateway 패턴 (Kong, Ambassador, Gloo)
- Service Mesh의 Traffic Splitting 고급 활용
🔧 12단계: 개발 워크플로우와 도구
1. 로컬 개발 환경
Minikube
- 가장 간단한 로컬 쿠버네티스
- 단일 노드 클러스터
bash
minikube start --cpus 4 --memory 8192
minikube dashboard # 웹 UI 실행Kind (Kubernetes in Docker)
- Docker 컨테이너로 쿠버네티스 노드 실행
- 멀티 노드 클러스터 지원
- CI/CD 파이프라인에 적합
bash
kind create cluster --config kind-config.yamlk3d (k3s in Docker)
- 경량 쿠버네티스 k3s를 Docker에서 실행
- 가장 빠른 시작 시간
bash
k3d cluster create dev --servers 1 --agents 2Docker Desktop Kubernetes
- Mac/Windows에서 가장 쉬운 설정
- 개발용으로 충분
2. 개발 가속 도구
Skaffold
- 코드 변경 → 빌드 → 배포 자동화
yaml
apiVersion: skaffold/v4beta1
kind: Config
build:
artifacts:
- image: myapp
docker:
dockerfile: Dockerfile
deploy:
kubectl:
manifests:
- k8s/*.yamlbash
skaffold dev # 파일 변경 감지하여 자동 재배포Tilt
- 더 강력한 개발 경험
- 웹 UI 제공
- 멀티 서비스 개발에 최적화
Telepresence
- 로컬 코드를 클러스터에 연결
- 클러스터의 다른 서비스와 직접 통신하면서 로컬에서 디버깅
bash
telepresence connect
telepresence intercept my-service --port 8080
# 이제 my-service로 가는 트래픽이 로컬 8080으로 옴
3. Helm - 쿠버네티스 패키지 매니저
Helm Chart란?
- 쿠버네티스 리소스들의 템플릿 묶음
- 값(values)을 주입하여 재사용 가능
기본 구조:
my-chart/
Chart.yaml # 차트 메타데이터
values.yaml # 기본값
templates/ # 쿠버네티스 매니페스트 템플릿
deployment.yaml
service.yaml
ingress.yaml
템플릿 예시 (deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-{{ .Chart.Name }}
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
ports:
- containerPort: {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 10 }}values.yaml:
replicaCount: 3
image:
repository: myapp
tag: "1.0.0"
service:
port: 8080
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"사용:
# 차트 설치
helm install my-release ./my-chart
# 값을 오버라이드하여 설치
helm install my-release ./my-chart \
--set replicaCount=5 \
--set image.tag=2.0.0
# 업그레이드
helm upgrade my-release ./my-chart
# 롤백
helm rollback my-release 1
딥먹 주제:
- Helm Hooks: 배포 전후 작업 실행
- Helm 서브차트와 의존성 관리
- Helmfile: 여러 차트를 선언적으로 관리
- Helm OCI 레지스트리 활용
- Kustomize vs Helm 비교 및 선택 기준
- Helm Chart 보안 스캐닝 (Checkov, Kubesec)
4. Kustomize - 선언적 커스터마이제이션
Helm과의 차이:
- 템플릿 언어 없음
- 기본 YAML에 패치를 덧붙이는 방식
- kubectl에 내장되어 있음
디렉토리 구조:
base/
deployment.yaml
service.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
patch-replicas.yaml
prod/
kustomization.yaml
patch-replicas.yaml
base/kustomization.yaml:
resources:
- deployment.yaml
- service.yamloverlays/prod/kustomization.yaml:
bases:
- ../../base
patchesStrategicMerge:
- patch-replicas.yaml
namespace: production
namePrefix: prod-
commonLabels:
environment: production배포:
kubectl apply -k overlays/prod/딥먹 주제:
- Strategic Merge Patch vs JSON Patch
- Kustomize Components: 재사용 가능한 패치 조각
- Kustomize + ArgoCD 통합
- Sealed Secrets와 Kustomize 통합
📊 13단계: 실전 문제 해결과 디버깅
1. 파드가 시작되지 않을 때
체크리스트:
# 1. 파드 상태 확인
kubectl get pods
# 상태: Pending, CrashLoopBackOff, ImagePullBackOff, Error
# 2. 자세한 정보 확인
kubectl describe pod <pod-name>
# Events 섹션을 주의깊게 확인
# 3. 로그 확인
kubectl logs <pod-name>
kubectl logs <pod-name> --previous # 이전 컨테이너의 로그
# 4. 특정 컨테이너 로그 (파드에 여러 컨테이너가 있을 때)
kubectl logs <pod-name> -c <container-name>주요 에러와 해결:
ImagePullBackOff:
- 원인: 이미지를 pull할 수 없음
- 해결:
- 이미지 이름/태그 확인
- Private 레지스트리라면 imagePullSecrets 설정
spec:
imagePullSecrets:
- name: regcredCrashLoopBackOff:
- 원인: 컨테이너가 시작 후 계속 종료됨
- 해결:
- 로그에서 에러 확인
- livenessProbe 설정 확인 (너무 빠르게 체크하는지)
- 애플리케이션 시작 시간 고려한 initialDelaySeconds 설정
Pending:
- 원인: 스케줄링 불가
- 해결:
kubectl describe pod에서 스케줄링 실패 이유 확인- 리소스 부족: 노드 추가 또는 request 줄이기
- PVC가 Bound되지 않음: 스토리지 클래스 확인
- Node Selector/Affinity 조건 확인
2. 네트워킹 문제 디버깅
파드 간 통신이 안 될 때:
# 1. 대상 파드의 IP 확인
kubectl get pod <pod-name> -o wide
# 2. 네트워크 테스트 파드 실행
kubectl run -it --rm debug --image=nicolaka/netshoot --restart=Never -- /bin/bash
# 파드 내에서:
curl http://<target-pod-ip>:8080
nslookup <service-name>
ping <pod-ip>Service가 작동하지 않을 때:
# 1. Service의 Endpoints 확인
kubectl get endpoints <service-name>
# 비어있다면 selector가 파드와 매치되지 않음
# 2. 파드의 라벨 확인
kubectl get pods --show-labels
# 3. Service selector와 비교
kubectl get service <service-name> -o yaml | grep -A 5 selectorNetworkPolicy 문제:
# NetworkPolicy 목록 확인
kubectl get networkpolicy
# 특정 NetworkPolicy 상세 확인
kubectl describe networkpolicy <policy-name>3. 리소스 부족 문제
노드의 리소스 상태 확인:
kubectl top nodes
kubectl describe node <node-name>
# Allocated resources 섹션 확인파드의 실제 리소스 사용량:
kubectl top pods
kubectl top pods --containers # 컨테이너별OOMKilled (Out of Memory):
kubectl describe pod <pod-name>
# Last State: Terminated, Reason: OOMKilled 확인해결: memory limit 증가
CPU Throttling:
# Prometheus 쿼리
rate(container_cpu_cfs_throttled_seconds_total[5m])해결: CPU limit 증가 또는 제거 고려
4. 디버깅용 임시 컨테이너 (Ephemeral Containers)
쿠버네티스 1.23+에서 지원:
kubectl debug <pod-name> -it --image=busybox --target=<container-name>파드를 재시작하지 않고 디버깅 도구가 포함된 컨테이너를 추가합니다.
5. 유용한 디버깅 명령어 모음
# 모든 리소스 확인
kubectl get all -n <namespace>
# 최근 이벤트 확인
kubectl get events --sort-by='.lastTimestamp'
# 특정 레이블의 파드만 확인
kubectl get pods -l app=myapp
# YAML 출력
kubectl get pod <pod-name> -o yaml
# JSONPath로 특정 필드 추출
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'
# 리소스 사용량 정렬
kubectl top pods --sort-by=memory
# 파드를 JSON으로 편집
kubectl edit pod <pod-name>
# 파드에 쉘로 접속
kubectl exec -it <pod-name> -- /bin/bash
# 파일 복사
kubectl cp <pod-name>:/path/to/file ./local-file딥먹 주제:
- ksniff를 사용한 패킷 캡처
- kubectl-debug 플러그인
- eBPF 기반 실시간 디버깅 (kubectl-trace)
- Stern을 사용한 멀티 파드 로그 스트리밍
- kubectx/kubens: 컨텍스트와 네임스페이스 빠른 전환
- k9s: 터미널 UI로 클러스터 관리
🎓 14단계: 학습 로드맵과 자격증
학습 경로
1단계: 기초 (1-2개월)
- Docker 기본 개념과 사용법
- 쿠버네티스 아키텍처 이해
- 파드, 디플로이먼트, 서비스 실습
- minikube로 로컬 환경 구축
2단계: 중급 (2-3개월)
- ConfigMap, Secret, Volume
- Ingress, NetworkPolicy
- RBAC 기본
- Helm 사용법
- 기본적인 트러블슈팅
3단계: 고급 (3-6개월)
- 커스텀 컨트롤러 개발
- Operator 패턴
- Service Mesh 도입
- 멀티 클러스터 관리
- 고급 모니터링과 관찰성
4단계: 전문가 (6개월+)
- 대규모 프로덕션 운영 경험
- 성능 최적화와 비용 절감
- 보안 강화
- 커뮤니티 기여
공식 자격증
1. CKA (Certified Kubernetes Administrator)
- 난이도: 중급
- 내용: 클러스터 설치, 트러블슈팅, 네트워킹 등
- 형식: 실습 시험 (터미널에서 직접 작업)
- 추천: 운영/인프라 엔지니어
2. CKAD (Certified Kubernetes Application Developer)
- 난이도: 중급
- 내용: 애플리케이션 배포, 설정 관리, 관찰성
- 형식: 실습 시험
- 추천: 개발자, DevOps 엔지니어
3. CKS (Certified Kubernetes Security Specialist)
- 난이도: 고급 (CKA 필수)
- 내용: 클러스터 보안, Supply Chain Security
- 형식: 실습 시험
- 추천: 보안 엔지니어, 시니어 SRE
추천 학습 리소스
공식 문서:
- kubernetes.io/docs (가장 정확하고 최신)
책:
- “Kubernetes in Action” - Marko Lukša
- “Kubernetes Up & Running” - Kelsey Hightower
- “Programming Kubernetes” - 고급 주제
온라인 강의:
- Udemy: Mumshad Mannambeth의 CKA/CKAD 강의
- A Cloud Guru
- Linux Foundation 공식 교육
실습 플랫폼:
- Killercoda (무료 실습 환경)
- Killer.sh (자격증 모의고사)
- KodeKloud (인터랙티브 실습)
커뮤니티:
- CNCF Slack
- Kubernetes Slack
- Reddit r/kubernetes
- 한국 쿠버네티스 사용자 그룹
🏢 15단계: 실전 프로덕션 체크리스트
배포 전 필수 확인사항
1. 고가용성 (High Availability)
yaml
spec:
replicas: 3 # 최소 3개 (홀수 권장)
# Anti-affinity로 다른 노드에 분산
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: myapp
topologyKey: kubernetes.io/hostname2. 헬스 체크
spec:
containers:
- name: app
# 애플리케이션 준비 확인
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
# 애플리케이션 살아있는지 확인
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
# 시작 시간이 긴 앱을 위한 체크
startupProbe:
httpGet:
path: /health/startup
port: 8080
failureThreshold: 30
periodSeconds: 103. 리소스 관리
resources:
requests: # 스케줄링 기준, 보장되는 최소 리소스
memory: "256Mi"
cpu: "250m"
limits: # 상한선
memory: "512Mi"
cpu: "500m" # CPU limit는 신중하게 (throttling 주의)4. Graceful Shutdown
spec:
terminationGracePeriodSeconds: 30
containers:
- name: app
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"] # 연결 드레이닝5. PodDisruptionBudget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: myapp-pdb
spec:
minAvailable: 2 # 또는 maxUnavailable: 1
selector:
matchLabels:
app: myapp노드 업그레이드, 스케일 다운 시에도 최소한의 파드를 유지합니다.
6. 보안
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL7. 이미지 관리
spec:
containers:
- name: app
image: myregistry.com/myapp:v1.2.3 # 명시적 태그, latest 금지
imagePullPolicy: IfNotPresent모니터링 필수 지표
골든 시그널 (Google SRE):
- Latency: 요청 응답 시간
- Traffic: 초당 요청 수 (RPS)
- Errors: 에러율
- Saturation: 리소스 사용률
쿠버네티스 특화 지표:
- 파드 재시작 횟수
- 파드 OOMKilled 횟수
- PVC 사용률
- 노드 CPU/메모리 사용률
- 네트워크 I/O
- API Server 응답 시간
알림 설정 예시:
# Prometheus Alert 규칙
groups:
- name: kubernetes
rules:
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
annotations:
summary: "Pod {{ $labels.pod }} is crash looping"
- alert: HighMemoryUsage
expr: container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.9
for: 5m
annotations:
summary: "Container {{ $labels.container }} memory usage > 90%"백업과 재해 복구
etcd 백업 (가장 중요):
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
snapshot save /backup/etcd-snapshot.dbVelero: 애플리케이션 백업
# 네임스페이스 전체 백업
velero backup create my-backup --include-namespaces production
# 복구
velero restore create --from-backup my-backup딥먹 주제:
- Chaos Engineering: Chaos Mesh, Litmus
- Progressive Delivery: Flagger + Istio
- Cost-aware autoscaling
- 멀티 테넌시 보안 강화
- Zero-trust networking
- 컴플라이언스 자동화 (PCI-DSS, HIPAA, SOC 2)
작성일: 2025-11-03