1. Kubernetes란?
Kubernetes(K8s)는 컨테이너화된 애플리케이션의 배포, 확장, 자가 치유를 자동화하는 오픈소스 오케스트레이션 플랫폼입니다. Google이 내부 시스템 Borg를 기반으로 개발하고 CNCF에 기부했습니다.
| 기능 | 설명 |
|---|---|
| 자동 배포 & 롤백 | 선언적 설정으로 롤링 업데이트, 문제 시 자동 롤백 |
| 자가 치유 | Pod 비정상 종료 시 자동 재시작, 노드 장애 시 재스케줄링 |
| 수평 스케일링 | CPU/메모리 기반 Pod 수 자동 조정 (HPA) |
| 서비스 디스커버리 | DNS 기반 서비스 간 통신, 로드 밸런싱 |
| 설정 관리 | ConfigMap/Secret으로 환경 설정 분리 |
2. 아키텍처
| 구성 요소 | 역할 |
|---|---|
| Control Plane | |
| kube-apiserver | 모든 요청의 진입점. kubectl과 통신 |
| etcd | 클러스터 상태 저장소 (분산 key-value) |
| kube-scheduler | Pod를 어떤 노드에 배치할지 결정 |
| kube-controller-manager | 원하는 상태 유지 (ReplicaSet, Deployment 등) |
| Worker Node | |
| kubelet | 노드 에이전트. Pod 실행 및 상태 보고 |
| kube-proxy | 네트워크 규칙 관리 (Service 라우팅) |
| Container Runtime | containerd / CRI-O (실제 컨테이너 실행) |
3. kubectl 설치 & 기본 명령어
# 설치 (macOS)
brew install kubectl
kubectl version --client
# 로컬 개발 클러스터
brew install minikube
minikube start
minikube dashboard # 웹 UIbash
# ── 자주 쓰는 kubectl 명령어 ────────────────────────
kubectl get pods # 현재 네임스페이스 Pod
kubectl get pods -n kube-system # 특정 네임스페이스
kubectl get pods -A # 전체 네임스페이스
kubectl get pods -o wide # 노드 정보 포함
kubectl get all # Pod,Service,Deployment 한 번에
kubectl describe pod # 상세 이벤트 확인
kubectl logs -f --tail=100 # 로그 스트리밍
kubectl logs -c # 멀티컨테이너 Pod 특정 컨테이너
kubectl exec -it -- bash # 컨테이너 접속
kubectl apply -f manifest.yaml # 선언적 적용 (생성/업데이트)
kubectl delete -f manifest.yaml # 삭제
kubectl delete pod --grace-period=0 # 강제 삭제
kubectl port-forward pod/ 8080:80 # 로컬 포트 포워딩
# 컨텍스트 관리
kubectl config get-contexts
kubectl config use-context prod-cluster bash
4. Pod
Pod는 K8s의 최소 배포 단위입니다. 하나 이상의 컨테이너를 묶어 같은 네트워크와 스토리지를 공유합니다. 직접 Pod를 만들기보다 Deployment를 통해 관리합니다.
apiVersion: v1
kind: Pod
metadata:
name: myapp
labels:
app: myapp
version: "1.0"
spec:
containers:
- name: app
image: myapp:1.0.0
ports:
- containerPort: 3000
resources:
requests: # 스케줄러가 노드 선택에 사용
cpu: "100m" # 0.1 vCPU
memory: "128Mi"
limits: # 초과 시 OOMKilled / CPU Throttle
cpu: "500m"
memory: "512Mi"
env:
- name: NODE_ENV
value: production
livenessProbe: # 비정상이면 재시작
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe: # 준비 완료 전 트래픽 차단
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5yaml
5. Deployment & 롤링 업데이트
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: myapp
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 최대 초과 Pod (1개 추가 생성)
maxUnavailable: 0 # 최대 중단 Pod (무중단 배포)
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:2.0.0 # 이미지 버전만 바꾸면 롤링 업데이트
resources:
requests: { cpu: "100m", memory: "128Mi" }
limits: { cpu: "500m", memory: "512Mi" }
livenessProbe:
httpGet: { path: /health, port: 3000 }
periodSeconds: 10yaml
# 롤링 업데이트 & 롤백
kubectl set image deployment/myapp app=myapp:2.1.0 # 이미지 업데이트
kubectl rollout status deployment/myapp # 업데이트 상태 확인
kubectl rollout history deployment/myapp # 히스토리
kubectl rollout undo deployment/myapp # 이전 버전으로 롤백
kubectl rollout undo deployment/myapp --to-revision=2 # 특정 버전으로bash
6. Service
Service는 Pod 그룹에 안정적인 DNS 이름과 IP를 부여하고 로드 밸런싱을 담당합니다.
# ClusterIP (기본): 클러스터 내부에서만 접근
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp # 이 라벨을 가진 Pod로 트래픽 전달
ports:
- port: 80 # Service 포트
targetPort: 3000 # Pod 포트
type: ClusterIP
---
# NodePort: 노드 IP + 포트로 외부 접근
spec:
type: NodePort
ports:
- port: 80
targetPort: 3000
nodePort: 30080 # 30000-32767 범위
---
# LoadBalancer: 클라우드 LB 자동 생성 (AWS ELB, GCP LB 등)
spec:
type: LoadBalancer
ports:
- port: 443
targetPort: 3000yaml
7. ConfigMap & Secret
# ConfigMap — 비민감 설정
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
APP_ENV: production
LOG_LEVEL: info
config.yaml: |
server:
port: 3000
timeout: 30s
---
# Secret — 민감 데이터 (Base64 인코딩)
apiVersion: v1
kind: Secret
metadata:
name: myapp-secret
type: Opaque
data:
DB_PASSWORD: c2VjcmV0MTIz # echo -n 'secret123' | base64
API_KEY: bXlhcGlrZXk=yaml
# Pod에서 ConfigMap / Secret 사용
spec:
containers:
- name: app
# 방법 1: 환경변수로
envFrom:
- configMapRef:
name: myapp-config
- secretRef:
name: myapp-secret
# 방법 2: 특정 키만 선택
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: myapp-config
key: LOG_LEVEL
# 방법 3: 볼륨으로 마운트 (설정 파일)
volumeMounts:
- name: config-vol
mountPath: /etc/app
volumes:
- name: config-vol
configMap:
name: myapp-configyaml
# kubectl로 빠르게 생성
kubectl create configmap myapp-config \
--from-literal=APP_ENV=production \
--from-file=config.yaml
kubectl create secret generic myapp-secret \
--from-literal=DB_PASSWORD=secret123bash
8. Ingress
Ingress는 클러스터 외부의 HTTP/HTTPS 트래픽을 내부 Service로 라우팅합니다. nginx-ingress-controller 설치가 선행되어야 합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-prod # TLS 자동 발급
spec:
ingressClassName: nginx
tls:
- hosts: [myapp.example.com]
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port: { number: 80 }
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port: { number: 80 }yaml
9. HPA (수평 자동 스케일링)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # CPU 60% 초과 시 스케일 아웃
- type: Resource
resource:
name: memory
target:
type: AverageValue
averageValue: 400Miyaml
# HPA 상태 확인
kubectl get hpa
kubectl describe hpa myapp-hpa
# Metrics Server 설치 (HPA 필수 의존성)
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yamlbash
10. Helm
Helm은 Kubernetes 패키지 매니저입니다. 복잡한 애플리케이션을 재사용 가능한 Chart로 패키징합니다.
# 설치
brew install helm
# 공개 차트 사용
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo bitnami/postgresql
# 설치 & 커스터마이징
helm install my-pg bitnami/postgresql \
--namespace database \
--create-namespace \
--set auth.postgresPassword=secret \
--set primary.persistence.size=20Gi
# 업그레이드 / 롤백
helm upgrade my-pg bitnami/postgresql --set image.tag=16.2.0
helm rollback my-pg 1
# 상태 확인
helm list -A
helm history my-pgbash
# 나만의 Helm Chart 생성
helm create myapp # 기본 구조 생성
# myapp/
# ├── Chart.yaml # 차트 메타데이터
# ├── values.yaml # 기본값
# └── templates/ # YAML 템플릿
# values.yaml
image:
repository: myapp
tag: "1.0.0"
replicaCount: 3
service:
type: ClusterIP
port: 80
# templates/deployment.yaml
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
replicas: {{ .Values.replicaCount }}
# 배포
helm install myapp ./myapp -f prod-values.yaml
helm template myapp ./myapp # 렌더링만 미리보기yaml
11. 다음 단계
K8s 심화 주제
• GitOps: ArgoCD / Flux로 Git 기반 선언적 배포 자동화
• 서비스 메시: Istio / Linkerd — 트래픽 제어, mTLS, 관찰 가능성
• 모니터링: Prometheus + Grafana 스택
• 로깅: EFK(Elasticsearch + Fluent Bit + Kibana)
• CKA / CKAD 자격증: 실무 K8s 역량 공인 자격증
연계 가이드: Docker 가이드 · Linux 가이드 · 📊 Prometheus+Grafana 가이드
• GitOps: ArgoCD / Flux로 Git 기반 선언적 배포 자동화
• 서비스 메시: Istio / Linkerd — 트래픽 제어, mTLS, 관찰 가능성
• 모니터링: Prometheus + Grafana 스택
• 로깅: EFK(Elasticsearch + Fluent Bit + Kibana)
• CKA / CKAD 자격증: 실무 K8s 역량 공인 자격증
연계 가이드: Docker 가이드 · Linux 가이드 · 📊 Prometheus+Grafana 가이드