프로덕션 배포
Caffeine 애플리케이션을 프로덕션 환경에 배포합니다.
🎯 학습 목표
- 프로덕션 환경 구성
- Kubernetes 배포
- 모니터링 및 로깅
- 보안 설정
예상 소요 시간: 90분
📋 사전 요구사항
- 엣지 애플리케이션 튜토리얼 완료
- Kubernetes 클러스터 (minikube, EKS, AKS 등)
- kubectl 설치
- Helm 3.x
Step 1: 프로덕션 설정
appsettings.Production.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Caffeine": {
"ServerUrl": "https://caffeine-server.production.svc.cluster.local:5001",
"ApiKey": "${CAFFEINE_API_KEY}",
"Timeout": "00:01:00",
"RetryCount": 5
},
"Redis": {
"ConnectionString": "redis-master.production.svc.cluster.local:6379,password=${REDIS_PASSWORD}"
},
"InfluxDB": {
"Url": "http://influxdb.production.svc.cluster.local:8086",
"Token": "${INFLUXDB_TOKEN}",
"Org": "nexcode",
"Bucket": "caffeine-prod"
},
"Kafka": {
"BootstrapServers": "kafka-0.kafka-headless.production.svc.cluster.local:9092"
}
}
Step 2: Kubernetes 매니페스트
Deployment
k8s/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: edge-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: edge-app
template:
metadata:
labels:
app: edge-app
spec:
containers:
- name: edge-app
image: nexcode/edge-app:2.0.1
ports:
- containerPort: 80
env:
- name: ASPNETCORE_ENVIRONMENT
value: "Production"
- name: CAFFEINE_API_KEY
valueFrom:
secretKeyRef:
name: caffeine-secrets
key: api-key
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: redis-secrets
key: password
- name: INFLUXDB_TOKEN
valueFrom:
secretKeyRef:
name: influxdb-secrets
key: token
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
Service
k8s/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: edge-app
namespace: production
spec:
type: LoadBalancer
selector:
app: edge-app
ports:
- protocol: TCP
port: 80
targetPort: 80
Ingress
k8s/ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: edge-app
namespace: production
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- edge.nexcode.co.kr
secretName: edge-app-tls
rules:
- host: edge.nexcode.co.kr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: edge-app
port:
number: 80
Step 3: Secrets 관리
k8s/secrets.yaml:
apiVersion: v1
kind: Secret
metadata:
name: caffeine-secrets
namespace: production
type: Opaque
stringData:
api-key: "sk_prod_abc123xyz"
---
apiVersion: v1
kind: Secret
metadata:
name: redis-secrets
namespace: production
type: Opaque
stringData:
password: "your-redis-password"
---
apiVersion: v1
kind: Secret
metadata:
name: influxdb-secrets
namespace: production
type: Opaque
stringData:
token: "your-influxdb-token"
보안 주의: 실제 환경에서는 Sealed Secrets, External Secrets Operator, 또는 HashiCorp Vault 사용 권장
Step 4: Helm Chart 배포
helm/values.yaml:
replicaCount: 3
image:
repository: nexcode/edge-app
tag: "2.0.1"
pullPolicy: IfNotPresent
service:
type: LoadBalancer
port: 80
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: edge.nexcode.co.kr
paths:
- path: /
pathType: Prefix
tls:
- secretName: edge-app-tls
hosts:
- edge.nexcode.co.kr
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 512Mi
cpu: 500m
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
monitoring:
enabled: true
serviceMonitor:
enabled: true
# Helm 배포
helm install edge-app ./helm \
--namespace production \
--create-namespace \
--values helm/values.yaml
# 배포 확인
kubectl get pods -n production
kubectl get svc -n production
kubectl get ingress -n production
Step 5: 모니터링 설정
Prometheus ServiceMonitor
k8s/servicemonitor.yaml:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: edge-app
namespace: production
spec:
selector:
matchLabels:
app: edge-app
endpoints:
- port: http
path: /metrics
interval: 30s
Grafana 대시보드
{
"dashboard": {
"title": "Edge App Monitoring",
"panels": [
{
"title": "CPU Usage",
"targets": [
{
"expr": "rate(container_cpu_usage_seconds_total{pod=~\"edge-app.*\"}[5m])"
}
]
},
{
"title": "Memory Usage",
"targets": [
{
"expr": "container_memory_usage_bytes{pod=~\"edge-app.*\"}"
}
]
},
{
"title": "Request Rate",
"targets": [
{
"expr": "rate(http_requests_total{app=\"edge-app\"}[5m])"
}
]
}
]
}
}
Step 6: 로깅 설정
Serilog 구성
Program.cs:
using Serilog;
using Serilog.Sinks.Elasticsearch;
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.Enrich.WithProperty("Application", "EdgeApp")
.Enrich.WithProperty("Environment", builder.Environment.EnvironmentName)
.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://elasticsearch:9200"))
{
AutoRegisterTemplate = true,
IndexFormat = $"edge-app-{DateTime.UtcNow:yyyy.MM}"
})
.CreateLogger();
builder.Host.UseSerilog();
Step 7: CI/CD 파이프라인
.github/workflows/deploy.yml:
name: Deploy to Production
on:
push:
tags:
- 'v*'
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: '10.0.x'
- name: Build
run: dotnet build -c Release
- name: Test
run: dotnet test --no-build -c Release
- name: Docker Build
run: |
docker build -t nexcode/edge-app:${{ github.ref_name }} .
docker push nexcode/edge-app:${{ github.ref_name }}
- name: Deploy to Kubernetes
run: |
helm upgrade edge-app ./helm \
--namespace production \
--set image.tag=${{ github.ref_name }} \
--wait
Step 8: 헬스 체크 구현
HealthChecks/CaffeineHealthCheck.cs:
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Caffeine.Client;
public class CaffeineHealthCheck : IHealthCheck
{
private readonly CaffeineClient _client;
public CaffeineHealthCheck(CaffeineClient client)
{
_client = client;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
// 서버 연결 확인
var connected = await _client.ConnectAsync(cancellationToken);
if (connected)
{
return HealthCheckResult.Healthy("Caffeine 서버 연결 정상");
}
return HealthCheckResult.Unhealthy("Caffeine 서버 연결 실패");
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("Caffeine 서버 오류", ex);
}
}
}
Program.cs:
builder.Services.AddHealthChecks()
.AddCheck<CaffeineHealthCheck>("caffeine")
.AddRedis(builder.Configuration["Redis:ConnectionString"]!)
.AddInfluxDB(builder.Configuration["InfluxDB:Url"]!);
app.MapHealthChecks("/health");
app.MapHealthChecks("/ready");
🎓 배운 내용
1. Kubernetes 배포
- Deployment, Service, Ingress
- Secrets 관리
- Resource limits
- Health checks
2. 모니터링
- Prometheus metrics
- Grafana 대시보드
- Elasticsearch 로깅
3. CI/CD
- GitHub Actions
- Docker 빌드
- Helm 배포
🔍 운영 체크리스트
배포 전
- 모든 테스트 통과
- Secrets 설정 완료
- Resource limits 설정
- Health checks 구현
- 모니터링 대시보드 준비
배포 후
- Pod 상태 확인
- 로그 확인
- 메트릭 확인
- 알람 설정
- 백업 설정
🚀 다음 단계
축하합니다! 프로덕션 배포를 완료했습니다.
추가 학습:
완료 시간: 약 90분
난이도: ⭐⭐⭐⭐ 전문가
이전: ← 엣지 애플리케이션