옵저버빌리티 및 모니터링
옵저버빌리티 스택 아키 텍처
Container Insights 설정
# Container Insights Add-on 설치
aws eks create-addon \
--cluster-name <cluster-name> \
--addon-name amazon-cloudwatch-observability
# 설치 확인
kubectl get pods -n amazon-cloudwatch
메트릭 디버깅: PromQL 쿼리
CPU Throttling 감지
sum(rate(container_cpu_cfs_throttled_periods_total{namespace="production"}[5m]))
/ sum(rate(container_cpu_cfs_periods_total{namespace="production"}[5m])) > 0.25
CPU Throttling 임계값
25% 이상의 throttling은 성능 저하를 유발합니다. CPU limits를 제거하거나 증가시키는 것을 고려하세요. 많은 조직이 CPU limits를 설정하지 않고 requests만 설정하는 전략을 채택하고 있습니다.
OOMKilled 감지
kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} > 0
Pod 재시작률
sum(rate(kube_pod_container_status_restarts_total[15m])) by (namespace, pod) > 0
Node CPU 사용률 (80% 초과 경고)
100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
Node 메모리 사용률 (85% 초과 경고)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
로그 디버깅: CloudWatch Logs Insights
에러 로그 분석
fields @timestamp, @message, kubernetes.container_name, kubernetes.pod_name
| filter @message like /ERROR|FATAL|Exception/
| sort @timestamp desc
| limit 50
레이턴시 분석
fields @timestamp, @message
| filter @message like /latency|duration|elapsed/
| parse @message /latency[=:]\s*(?<latency_ms>\d+)/
| stats avg(latency_ms), max(latency_ms), p99(latency_ms) by bin(5m)
특정 Pod의 에러 패턴 분석
fields @timestamp, @message
| filter kubernetes.pod_name like /api-server/
| filter @message like /error|Error|ERROR/
| stats count() by bin(1m)
| sort bin asc
OOMKilled 이벤트 추적
fields @timestamp, @message
| filter @message like /OOMKilled|oom-kill|Out of memory/
| sort @timestamp desc
| limit 20
컨테이너 재시작 이벤트
fields @timestamp, @message, kubernetes.pod_name
| filter @message like /Back-off restarting failed container|CrashLoopBackOff/
| stats count() by kubernetes.pod_name
| sort count desc
알림 규칙: PrometheusRule 예제
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: kubernetes-alerts
spec:
groups:
- name: kubernetes-pods
rules:
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) * 60 * 5 > 0
for: 1h
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping"
description: "Pod {{ $labels.pod }}이 15분간 재시작이 감지되었습니다."
- alert: PodOOMKilled
expr: kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} > 0
for: 0m
labels:
severity: critical
annotations:
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} OOMKilled"
description: "Pod {{ $labels.pod }}이 메모리 부족으로 종료되었습니다. 메모리 limits 조정이 필요합니다."
- name: kubernetes-nodes
rules:
- alert: NodeNotReady
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Node {{ $labels.node }} is NotReady"
- alert: NodeHighCPU
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.instance }} CPU usage above 80%"
- alert: NodeHighMemory
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
for: 10m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.instance }} memory usage above 85%"
ADOT (AWS Distro for OpenTelemetry) 디버깅
ADOT는 AWS에서 관리하는 OpenTelemetry 배포판으로, 트레이스, 메트릭, 로그를 수집하여 다양한 AWS 서비스(X-Ray, CloudWatch, AMP 등)로 전송합니다.
# ADOT Add-on 상태 확인
aws eks describe-addon --cluster-name $CLUSTER \
--addon-name adot --query 'addon.{status:status,version:addonVersion}'
# ADOT Collector Pod 확인
kubectl get pods -n opentelemetry-operator-system
kubectl logs -n opentelemetry-operator-system -l app.kubernetes.io/name=opentelemetry-operator --tail=50
# OpenTelemetryCollector CR 확인
kubectl get otelcol -A
kubectl describe otelcol -n $NAMESPACE $COLLECTOR_NAME
ADOT 일반적인 문제
| 증상 | 원인 | 해결 방법 |
|---|---|---|
Operator Pod CrashLoopBackOff | CertManager 미설치 | ADOT operator의 webhook 인증서 관리에 CertManager가 필요. kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml |
| Collector에서 AMP로 전송 실패 | IAM 권한 부족 | IRSA/Pod Identity에 aps:RemoteWrite 권한 추가 |
| X-Ray 트레이스 미수신 | IAM 권한 부족 | IRSA/Pod Identity에 xray:PutTraceSegments, xray:PutTelemetryRecords 권한 추가 |
| CloudWatch 메트릭 미수신 | IAM 권한 부족 | IRSA/Pod Identity에 cloudwatch:PutMetricData 권한 추가 |
Collector Pod OOMKilled | 리소스 부족 | 대량 트레이스/메트릭 수집 시 Collector의 resources.limits.memory 증가 |
ADOT 권한 분리
AMP remote write, X-Ray, CloudWatch에 각각 다른 IAM 권한이 필요합니다. Collector가 여러 백엔드로 데이터를 전송하는 경우 모든 필요 권한이 IAM Role에 포함되어 있는지 확인하세요.