지금까지 Kubernetes의 Pod, Deployment, Service, ConfigMap, Secret, PVC, Helm을 각각 살펴봤다면 이제 이 기술들을 하나의 실제 서비스에 적용해 볼 차례다.
이번 실습에서는 다음과 같은 웹 서비스를 Kubernetes에 구축한다.
Internet
|
v
[ HTTPS :443 ]
|
v
[ Kubernetes ]
|
Ingress
|
v
Nginx
|
v
FastAPI Service
|
+----------+----------+
| |
v v
FastAPI Pod FastAPI Pod
| |
+----------+----------+
|
+-----------+-----------+
| |
v v
PostgreSQL Redis
|
v
PVC
그리고 다음 기능까지 적용한다.
Ingress
HTTPS
Helm
ConfigMap
Secret
PVC
Resource Request / Limit
HPA
Health Check
로그 확인
장애 테스트
Rollback
이 정도까지 구성하면 단순한 Kubernetes 실습을 넘어 실제 운영 환경의 기본적인 형태를 이해할 수 있다.
전체 구조부터 이해하는 것이 중요하다.
Client
|
| HTTPS
v
+-------------+
| Ingress |
+-------------+
|
v
+-------------+
| Nginx |
+-------------+
|
| HTTP
v
+-------------------+
| FastAPI Service |
+-------------------+
|
+-----------+-----------+
| |
v v
+-------------+ +-------------+
| FastAPI Pod | | FastAPI Pod |
+-------------+ +-------------+
|
+-----+-----+
| |
v v
+-------------+ +---------+
| PostgreSQL | | Redis |
+-------------+ +---------+
|
v
PVC
여기서 각각의 역할은 다음과 같다.
| 구성요소 | 역할 |
|---|---|
| Ingress | 외부 HTTP/HTTPS 요청 진입점 |
| Nginx | Reverse Proxy |
| FastAPI | Backend API |
| PostgreSQL | 영구 데이터 저장 |
| Redis | Cache / Session |
| ConfigMap | 일반 설정 |
| Secret | 비밀번호 등 민감 정보 |
| PVC | 데이터 영구 저장 |
| HPA | Pod 자동 확장 |
| Helm | 전체 애플리케이션 패키징 |
실제 운영에서는 다음과 같은 Kubernetes 환경을 사용할 수 있다.
Kubernetes Cluster
Control Plane
|
+----------------+
| |
v v
Worker Node 1 Worker Node 2
| |
+--------+-------+
|
Applications
학습 환경이라면 다음과 같은 환경에서도 실습할 수 있다.
Minikube
Kind
K3s
RKE2
Kubernetes on Rocky Linux
Cloud Kubernetes
실습 전에 Kubernetes 연결을 확인한다.
kubectl cluster-info
Node 확인:
kubectl get nodes
예:
NAME STATUS ROLES
master Ready control-plane
worker01 Ready <none>
worker02 Ready <none>
모든 Node가 Ready 상태인지 확인한다.
운영 환경에서는 애플리케이션을 별도의 Namespace에서 관리하는 것이 좋다.
kubectl create namespace myapp
확인:
kubectl get namespace
이후 대부분의 리소스는:
namespace: myapp
에서 실행한다.
먼저 FastAPI 애플리케이션을 Docker Image로 만들어야 한다.
프로젝트:
backend/
├── app/
│ ├── main.py
│ └── database.py
├── requirements.txt
└── Dockerfile
간단한 FastAPI 코드:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {
"message": "Kubernetes FastAPI"
}
@app.get("/health")
def health():
return {
"status": "ok"
}
/health API는 Kubernetes Health Check에 사용한다.
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Image 생성:
docker build -t myapp-backend:1.0.0 .
실제 Kubernetes 클러스터가 여러 Node로 구성되어 있다면 모든 Node에서 Image를 사용할 수 있도록 Container Registry에 Push하는 것이 일반적이다.
예:
Docker Registry
|
+-- myapp-backend:1.0.0
+-- myapp-backend:1.1.0
+-- myapp-backend:1.2.0
PostgreSQL은 데이터가 중요한 서비스다.
이번 실습에서는 Kubernetes의 PVC를 사용한다.
PostgreSQL
|
v
PersistentVolumeClaim
|
v
PersistentVolume
|
v
Storage
PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: myapp
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
생성:
kubectl apply -f postgres-pvc.yaml
확인:
kubectl get pvc -n myapp
DB 비밀번호는 Secret으로 관리한다.
apiVersion: v1
kind: Secret
metadata:
name: postgres-secret
namespace: myapp
type: Opaque
stringData:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: change-this-password
POSTGRES_DB: appdb
적용:
kubectl apply -f postgres-secret.yaml
확인:
kubectl get secret -n myapp
주의할 점이 있다.
kubectl get secret
으로는 실제 Secret 값이 그대로 보이지 않지만, Kubernetes Secret을 단순히 "암호화된 비밀번호 저장소"라고 생각하면 안 된다.
운영 환경에서는 별도의 Secret Management 시스템을 사용하는 것도 고려해야 한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:17
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_DB
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-pvc
FastAPI에서 PostgreSQL에 접근하려면 Service가 필요하다.
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: myapp
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
Kubernetes 내부에서는:
postgres:5432
로 접근할 수 있다.
애플리케이션 설정과 비밀번호를 분리해야 한다.
예를 들어:
apiVersion: v1
kind: ConfigMap
metadata:
name: backend-config
namespace: myapp
data:
APP_ENV: "production"
REDIS_HOST: "redis"
REDIS_PORT: "6379"
DB_HOST: "postgres"
DB_PORT: "5432"
DB_NAME: "appdb"
여기에는 비밀번호를 넣지 않는다.
구분하면 다음과 같다.
ConfigMap
|
+-- DB_HOST
+-- DB_PORT
+-- REDIS_HOST
+-- APP_ENV
Secret
|
+-- DB_PASSWORD
+-- API_KEY
+-- JWT_SECRET
Redis Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: myapp
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7
ports:
- containerPort: 6379
Service:
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: myapp
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
FastAPI에서는:
redis://redis:6379
로 Redis에 연결한다.
이제 핵심인 FastAPI를 배포한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: myapp
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: myregistry/myapp-backend:1.0.0
ports:
- containerPort: 8000
envFrom:
- configMapRef:
name: backend-config
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1
memory: 512Mi
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 15
periodSeconds: 20
운영 Kubernetes에서 매우 중요한 부분이다.
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1
memory: 512Mi
의미는 다음과 같다.
requests
|
+-- Kubernetes 스케줄링 기준
limits
|
+-- 사용할 수 있는 최대 자원
CPU:
250m = 0.25 CPU
1 = 1 CPU
Memory:
256Mi
512Mi
이 값을 설정하지 않으면 특정 Pod가 CPU나 Memory를 과도하게 사용할 가능성이 있다.
운영 환경에서는 애플리케이션 특성에 맞게 Request와 Limit을 설정하는 것이 중요하다.
apiVersion: v1
kind: Service
metadata:
name: backend
namespace: myapp
spec:
selector:
app: backend
ports:
- port: 8000
targetPort: 8000
type: ClusterIP
Service를 통해:
backend:8000
으로 접근할 수 있다.
Nginx는 Reverse Proxy 역할을 한다.
Client
|
v
Nginx
|
v
FastAPI
Nginx 설정:
server {
listen 80;
location / {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
이 설정을 ConfigMap으로 관리할 수 있다.
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: myapp
data:
default.conf: |
server {
listen 80;
location / {
proxy_pass http://backend:8000;
}
}
Nginx Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: myapp
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
volumes:
- name: nginx-config
configMap:
name: nginx-config
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: myapp
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
type: ClusterIP
이제 외부에서 직접 Nginx Pod에 접근하지 않는다.
외부 진입점은 Ingress가 담당한다.
Ingress는 외부 HTTP/HTTPS 요청을 Kubernetes Service로 연결하는 역할을 한다.
Internet
|
v
Ingress
|
v
Nginx Service
|
v
Nginx Pod
|
v
FastAPI Service
예를 들어:
api.example.com
으로 접속하면:
api.example.com
|
v
Ingress
|
v
nginx:80
으로 전달한다.
Ingress 리소스만 생성한다고 실제 요청을 처리하는 것은 아니다.
Ingress Controller가 필요하다.
대표적인 구현이:
NGINX Ingress Controller
Traefik
HAProxy
Kong
Cloud Load Balancer
등이다.
실습 환경에서는 NGINX Ingress Controller 또는 사용하는 Kubernetes 배포판에서 제공하는 Ingress Controller를 설치할 수 있다.
설치 후:
kubectl get pods -A
로 Controller가 정상적으로 실행되는지 확인한다.
예:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: myapp
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
이제:
https://api.example.com
이라는 요청이 Kubernetes로 들어오게 된다.
운영 환경에서는 HTTP보다 HTTPS를 사용하는 것이 일반적이다.
구조:
Client
|
| HTTPS :443
v
Ingress
|
| HTTP
v
Nginx
|
v
FastAPI
TLS 인증서는 Kubernetes Secret으로 관리할 수 있다.
apiVersion: v1
kind: Secret
metadata:
name: myapp-tls
namespace: myapp
type: kubernetes.io/tls
data:
tls.crt: ...
tls.key: ...
Ingress:
spec:
tls:
- hosts:
- api.example.com
secretName: myapp-tls
실제 운영에서는 인증서 자동 발급과 갱신을 위해 Cert-Manager + Let's Encrypt 조합을 많이 사용한다.
HPA는 Horizontal Pod Autoscaler다.
쉽게 말하면:
CPU 증가
|
v
Pod 증가
반대로:
CPU 감소
|
v
Pod 감소
하도록 자동 조절한다.
예:
평상시
FastAPI
|
+-- Pod 1
+-- Pod 2
트래픽 증가
FastAPI
|
+-- Pod 1
+-- Pod 2
+-- Pod 3
+-- Pod 4
+-- Pod 5
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: backend-hpa
namespace: myapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: backend
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
의미:
최소 Pod = 2
최대 Pod = 10
CPU 평균 사용률 > 70%
|
v
Pod 증가
HPA를 사용하려면 Kubernetes Metrics API가 정상적으로 제공되어야 한다.
일반적인 Kubernetes 실습 환경에서는 Metrics Server를 설치한다.
확인:
kubectl top pods -n myapp
정상적으로 CPU/Memory가 표시되는지 확인한다.
kubectl get hpa -n myapp
예:
NAME TARGETS MINPODS MAXPODS REPLICAS
backend-hpa 15%/70% 2 10 2
트래픽이 증가하면:
REPLICAS
2
↓
4
↓
6
↓
8
처럼 증가할 수 있다.
운영 중에는 다음 명령어를 자주 사용한다.
kubectl get pods -n myapp
kubectl get svc -n myapp
kubectl get deployment -n myapp
kubectl get ingress -n myapp
kubectl get pvc -n myapp
kubectl get hpa -n myapp
전체를 한 번에 확인하려면:
kubectl get all -n myapp
장애가 발생하면 가장 먼저 로그를 확인한다.
kubectl logs deployment/backend -n myapp
특정 Pod:
kubectl logs backend-xxxx -n myapp
실시간 로그:
kubectl logs -f backend-xxxx -n myapp
이전 컨테이너 로그:
kubectl logs backend-xxxx -n myapp --previous
--previous는 컨테이너가 재시작된 경우 이전 컨테이너의 로그를 확인할 때 매우 유용하다.
kubectl logs deployment/nginx -n myapp
접속 문제가 발생했다면 Nginx 로그를 확인한다.
Client
|
v
Ingress
|
v
Nginx
|
v
FastAPI
어느 구간에서 문제가 발생했는지를 찾아야 한다.
kubectl describe pod backend-xxxx -n myapp
특히 마지막 부분의:
Events:
를 확인해야 한다.
예:
FailedScheduling
FailedMount
ImagePullBackOff
Back-off restarting failed container
Unhealthy
등의 메시지가 나타날 수 있다.
Kubernetes 장애 분석에서 describe는 매우 중요한 명령이다.
일부러 잘못된 Image를 지정해 보자.
image:
repository: myregistry/myapp-backend
tag: "999.999"
배포:
helm upgrade myapp ./myapp -n myapp
Pod를 확인한다.
kubectl get pods -n myapp
다음과 같이 나타날 수 있다.
backend-xxxx 0/1 ImagePullBackOff
원인을 확인한다.
kubectl describe pod backend-xxxx -n myapp
Events에서 Image를 가져오지 못한 원인을 확인한다.
이번에는 애플리케이션이 시작하자마자 종료되도록 만들어 본다.
예를 들어 잘못된 환경변수를 설정하거나 애플리케이션 실행 명령을 잘못 지정한다.
결과:
backend-xxxx
0/1
CrashLoopBackOff
로그:
kubectl logs backend-xxxx -n myapp
재시작 횟수:
kubectl get pod -n myapp
예:
NAME READY STATUS RESTARTS
backend-xxx 0/1 CrashLoopBackOff 7
이 경우:
kubectl logs
kubectl describe pod
두 가지를 함께 확인한다.
FastAPI의 /health를 일시적으로 잘못된 경로로 변경한다.
readinessProbe:
httpGet:
path: /wrong-health
port: 8000
Pod 자체는 실행된다.
STATUS: Running
하지만:
READY: 0/1
이 될 수 있다.
이것은 매우 중요한 개념이다.
Running
≠
Traffic 받을 준비 완료
즉:
Pod Running
|
v
Readiness 성공?
|
+--+--+
| |
Yes No
| |
Traffic Traffic
허용 차단
Liveness Probe가 실패하면 Kubernetes가 컨테이너를 재시작할 수 있다.
확인:
kubectl get pods -n myapp
재시작 횟수가 증가하는지 확인한다.
RESTARTS
0
1
2
3
이때:
kubectl describe pod
에서 Probe 실패 이벤트를 확인한다.
PostgreSQL Pod를 삭제해 보자.
kubectl delete pod postgres-xxxx -n myapp
Deployment에서 관리하고 있다면 새로운 Pod가 생성된다.
kubectl get pods -n myapp
데이터가 PVC에 저장되어 있다면 새로운 Pod가 기존 Persistent Volume을 다시 연결할 수 있다.
PostgreSQL Pod
|
X
장애
|
v
새 PostgreSQL Pod
|
v
기존 PVC
|
v
기존 데이터
이것이 Kubernetes에서 Persistent Storage가 중요한 이유다.
단, Pod 재생성 테스트가 데이터베이스 백업이나 고가용성을 보장하는 것은 아니다.
운영 환경에서는 별도의 백업과 복구 전략이 반드시 필요하다.
Redis Pod를 삭제한다.
kubectl delete pod -l app=redis -n myapp
새로운 Redis Pod가 생성되는지 확인한다.
kubectl get pods -n myapp
Redis를 단순 캐시 용도로 사용한다면 재생성에 따른 데이터 손실을 허용할 수 있다.
반대로 중요한 데이터를 Redis에 저장한다면 별도의 Persistence와 고가용성 설계를 해야 한다.
실제 운영에서는 개별 YAML을 하나씩 적용하는 것보다 Helm Chart로 관리하는 것이 편리하다.
myapp/
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-prod.yaml
└── templates/
├── backend.yaml
├── backend-service.yaml
├── postgres.yaml
├── postgres-service.yaml
├── redis.yaml
├── redis-service.yaml
├── nginx.yaml
├── nginx-service.yaml
├── ingress.yaml
├── configmap.yaml
├── secret.yaml
├── pvc.yaml
└── hpa.yaml
배포:
helm install myapp ./myapp \
-n myapp \
--create-namespace \
-f values-prod.yaml
업데이트:
helm upgrade myapp ./myapp \
-n myapp \
-f values-prod.yaml
운영 환경에 바로 배포하지 않는 것이 좋다.
먼저:
helm lint ./myapp
그리고:
helm template myapp ./myapp \
-f values-prod.yaml
결과를 확인한다.
그 다음:
helm upgrade --install myapp ./myapp \
-n myapp \
--create-namespace \
-f values-prod.yaml \
--dry-run
환경과 Helm 버전에 따라 --dry-run 출력에는 클러스터 조회가 필요한 리소스의 검증 차이가 있을 수 있으므로 실제 배포 전 최종 검증도 수행해야 한다.
helm status myapp -n myapp
그리고:
kubectl get pods -n myapp
kubectl get svc -n myapp
kubectl get ingress -n myapp
kubectl get pvc -n myapp
kubectl get hpa -n myapp
전체 상태를 확인한다.
운영 배포에서 가장 중요한 기능 중 하나다.
배포 이력을 확인한다.
helm history myapp -n myapp
예:
REVISION STATUS
1 deployed
2 deployed
3 deployed
3번 배포에서 장애가 발생했다면:
helm rollback myapp 2 -n myapp
그리고:
helm status myapp -n myapp
으로 확인한다.
운영에서 중요한 것은 "장애가 발생하지 않게 만드는 것"뿐만 아니라 장애가 발생했을 때 빠르게 이전 정상 상태로 돌아가는 것이다.
운영 서버에서 API 접속 장애가 발생했다고 가정해 보자.
가장 먼저 전체 상태를 확인한다.
kubectl get pods -n myapp
문제가 있는 Pod가 있다면:
kubectl describe pod <pod-name> -n myapp
로그 확인:
kubectl logs <pod-name> -n myapp
Deployment:
kubectl get deployment -n myapp
Service:
kubectl get svc -n myapp
Ingress:
kubectl get ingress -n myapp
Endpoint:
kubectl get endpoints -n myapp
또는 환경에 따라 EndpointSlice를 확인한다.
kubectl get endpointslice -n myapp
그리고 애플리케이션 내부에서 직접 테스트한다.
kubectl exec -it <backend-pod> -n myapp -- curl http://localhost:8000/health
실무에서는 다음 순서가 매우 유용하다.
사용자 접속 실패
|
v
Ingress 확인
|
v
Nginx 확인
|
v
Service 확인
|
v
Endpoint 확인
|
v
Pod 상태 확인
|
v
Application Log
|
v
DB / Redis 연결 확인
즉 단순히:
kubectl logs
만 보는 것이 아니다.
어느 계층에서 문제가 발생했는지 찾는 것이 핵심이다.
실제 서비스라면 여기서 끝나지 않는다.
다음 기능들을 추가하는 것이 좋다.
Monitoring
Logging
Alerting
Backup
RBAC
NetworkPolicy
PodDisruptionBudget
Security Context
Image Security Scan
ResourceQuota
NetworkPolicy
Secret Management
모니터링:
Prometheus
Grafana
로그:
Loki
ELK / EFK
알림:
Alertmanager
Slack
Email
등을 사용할 수 있다.
최종적으로 다음과 같은 형태를 생각하면 된다.
Internet
|
| HTTPS
v
+----------------+
| Ingress |
+----------------+
|
v
+----------------+
| Nginx |
+----------------+
|
v
+----------------+
| FastAPI Service|
+----------------+
|
+--------------+--------------+
| |
v v
+-----------+ +-----------+
| FastAPI | | FastAPI |
| Pod | | Pod |
+-----------+ +-----------+
|
+----+----+
| |
v v
PostgreSQL Redis
|
v
PVC
Kubernetes Operations
---------------------
Helm
HPA
ConfigMap
Secret
Health Check
Monitoring
Logging
Backup
Rollback
Pod:
kubectl get pods -n myapp
로그:
kubectl logs -f <pod> -n myapp
상세 정보:
kubectl describe pod <pod> -n myapp
Deployment:
kubectl get deployment -n myapp
Service:
kubectl get svc -n myapp
Ingress:
kubectl get ingress -n myapp
PVC:
kubectl get pvc -n myapp
HPA:
kubectl get hpa -n myapp
리소스:
kubectl top pods -n myapp
Helm:
helm list -n myapp
helm status myapp -n myapp
helm history myapp -n myapp
Rollback:
helm rollback myapp 2 -n myapp
이번 실습을 실제로 진행한다면 다음 순서가 가장 좋다.
1. Kubernetes Cluster 준비
|
v
2. Namespace 생성
|
v
3. Docker Image 생성
|
v
4. Container Registry Push
|
v
5. PostgreSQL + PVC
|
v
6. Redis
|
v
7. ConfigMap / Secret
|
v
8. FastAPI Deployment
|
v
9. FastAPI Service
|
v
10. Nginx
|
v
11. Ingress
|
v
12. HTTPS
|
v
13. HPA
|
v
14. Helm Package
|
v
15. DEV 배포
|
v
16. PROD 배포
|
v
17. 장애 테스트
|
v
18. 로그 분석
|
v
19. Rollback
|
v
20. Monitoring / Backup
이번 실습에서 가장 중요한 것은 Kubernetes 명령어 자체가 아니다.
하나의 서비스를 여러 개의 Kubernetes 리소스로 나누고 이들을 어떻게 연결해서 운영하는지 이해하는 것이다.
FastAPI 하나만 보면 단순하다.
FastAPI
하지만 실제 운영 환경에서는:
Ingress
|
Nginx
|
Service
|
Deployment
|
Pod
|
ConfigMap / Secret
|
PostgreSQL / Redis
|
PVC
처럼 여러 계층이 연결된다.
여기에:
HPA
Health Check
Resource Limit
Monitoring
Logging
Backup
Rollback
을 추가하면서 비로소 운영 가능한 Kubernetes 서비스에 가까워진다.
특히 시스템 엔지니어 입장에서 중요한 것은 장애가 발생했을 때 다음 질문에 답할 수 있는 것이다.
1. Pod가 정상인가?
2. Container가 정상적으로 시작했는가?
3. Readiness Probe가 성공했는가?
4. Service가 올바른 Pod를 바라보고 있는가?
5. Endpoint가 존재하는가?
6. Nginx가 Backend로 연결되는가?
7. Ingress가 올바른 Service로 전달하는가?
8. HTTPS 인증서가 정상인가?
9. FastAPI가 PostgreSQL에 연결되는가?
10. FastAPI가 Redis에 연결되는가?
11. PVC가 정상적으로 Mount 되었는가?
12. CPU/Memory가 부족하지 않은가?
13. HPA가 정상적으로 동작하는가?
14. 최근 배포에서 문제가 발생하지 않았는가?
15. 필요하다면 Helm Rollback이 가능한가?
이 질문을 순서대로 확인할 수 있다면 Kubernetes 장애 대응 능력은 크게 향상된다.
결국 Kubernetes 운영의 핵심은 배포 자체가 아니라 배포 이후의 안정적인 운영과 장애 대응이다.