EKS 클러스터 리소스 부족 문제 해결 가이드

dongdorrong·5일 전
0

AWS

목록 보기
14/14

들어가며

클라우드 네이티브 환경에서 컨테이너 오케스트레이션을 담당하는 Amazon EKS는 현대적인 애플리케이션 배포의 핵심 인프라입니다. 하지만 클러스터 규모가 커지고 워크로드가 증가하면서 다양한 리소스 부족 문제에 직면하게 됩니다.

"어제까지 잘 돌아가던 서비스가 갑자기 Pod가 생성되지 않는다면?"

실제 운영 환경에서 자주 발생하는 이런 상황들을 해결하기 위해, 이 글에서는 가장 빈번하게 마주치는 세 가지 핵심 리소스 부족 문제와 그 실전 해결방안을 단계별로 살펴보겠습니다.

  • Pod IP 부족: "더 이상 IP를 할당할 수 없습니다"
  • CPU/메모리 부족: "노드에 여유 리소스가 없습니다"
  • Spot Instance 용량 부족: "요청한 인스턴스 타입을 사용할 수 없습니다"

각 문제별로 근본 원인부터 구체적인 해결책, 그리고 사전 예방 방법까지 실무에서 바로 적용할 수 있는 가이드를 제공합니다.

1. Pod IP 부족 문제 해결

문제 상황 및 증상

실제 에러 메시지:

Warning  FailedCreatePodSandBox  pod/my-app-xxx  Failed to create pod sandbox: 
rpc error: code = Unknown desc = failed to set up sandbox container: 
networkPlugin cni failed to set up pod "my-app-xxx_default" network: 
add cmd: failed to assign an IP address to container

문제 진단 방법:

# 1. 노드별 IP 사용량 확인
kubectl get nodes -o custom-columns=NAME:.metadata.name,PODS:.status.capacity.pods,ALLOCATABLE:.status.allocatable.pods

# 2. VPC CNI 로그 확인
kubectl logs -n kube-system -l k8s-app=aws-node --tail=100

# 3. ENI 사용 현황 확인
aws ec2 describe-network-interfaces --filters "Name=description,Values=aws-K8S-*"

EKS 클러스터에서 Pod 수가 증가하면서 IP 주소가 부족해지는 현상이 발생합니다. 이는 VPC CNI의 기본 설정으로 인해 각 노드가 할당받을 수 있는 IP 개수가 제한되기 때문입니다.

해결 방안

1.1 WARM_IP_TARGET 설정 조정

먼저 VPC CNI의 핵심 설정값들이 무엇을 의미하는지 알아보겠습니다:

주요 설정값 설명:

  • warm_ip_target: 각 노드에서 미리 확보해둘 여유 IP 개수 (기본값: 1)
  • minimum_ip_target: 노드당 최소 보장 IP 개수 (기본값: ENI당 IP 개수)
  • max_eni: 노드당 최대 ENI(Elastic Network Interface) 개수
  • warm_eni_target: 미리 준비해둘 여유 ENI 개수 (기본값: 1)
apiVersion: v1
kind: ConfigMap
metadata:
  name: amazon-vpc-cni
  namespace: kube-system
data:
  # Pod 생성 시 IP 부족으로 인한 지연을 방지하기 위해 미리 확보할 IP 개수
  warm_ip_target: "10"  # 기본값: 1
  # 노드당 최소한 보장할 IP 개수 (갑작스런 트래픽 증가 대비)
  minimum_ip_target: "5"
  # 노드당 최대 ENI 개수 제한 (인스턴스 타입별로 상한 존재)
  max_eni: "4"
  # 새로운 ENI 할당 시 미리 준비해둘 개수
  warm_eni_target: "1"

설정 효과 분석:

  • warm_ip_target을 10으로 설정하면 Pod 생성 시 IP 할당 지연이 크게 감소
  • 하지만 너무 높게 설정하면 IP 주소 낭비 발생 (비용 증가)
  • 클러스터 규모와 Pod 생성 패턴을 고려한 적절한 값 설정이 중요

1.2 Prefix Delegation 활성화

Prefix Delegation이란?
기존 방식에서는 각 ENI에 개별 IP 주소를 할당했지만, Prefix Delegation은 /28 서브넷 블록(16개 IP)을 한 번에 할당하여 IP 효율성을 극대화하는 기술입니다.

효과 비교:

  • 기존 방식: m5.large 노드 → 최대 29개 Pod
  • Prefix Delegation: m5.large 노드 → 최대 110개 Pod (약 3.8배 증가)
apiVersion: v1
kind: ConfigMap
metadata:
  name: amazon-vpc-cni
  namespace: kube-system
data:
  # Prefix Delegation 기능 활성화
  enable_prefix_delegation: "true"
  # 미리 할당받을 prefix 개수 (각 prefix = 16개 IP)
  warm_prefix_target: "1"
  # prefix 내에서 미리 확보할 IP 개수  
  warm_ip_target: "5"
  # prefix가 고갈되기 전 새 prefix를 요청할 임계점
  minimum_ip_target: "3"

주의사항:

  • 기존 노드에는 적용되지 않으므로 새로운 노드 그룹 생성 필요
  • 서브넷에 충분한 IP 공간이 있는지 사전 확인 필수

1.3 Custom Networking 구성

보안이나 IP 범위 분리가 필요한 경우:

apiVersion: v1
kind: ConfigMap
metadata:
  name: amazon-vpc-cni
  namespace: kube-system
data:
  aws_vpc_k8s_cni_custom_network_cfg: "true"
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
  name: pod-subnet-config
spec:
  subnet: subnet-xxxxxxxxx
  securityGroups:
    - sg-xxxxxxxxx

1.4 초기 설계 시 고려사항

  • 서브넷 크기 계산: 예상 Pod 수 × 1.5배 이상으로 설계
  • 가용영역별 분산: 최소 3개 AZ에 서브넷 분산 배치
  • CIDR 블록 예약: 향후 확장을 위한 여유 공간 확보

2. Resource Limits/Requests 부족 문제

문제 상황 및 증상

실제 에러 메시지:

Warning  FailedScheduling  pod/my-app-xxx  0/3 nodes are available: 
3 Insufficient cpu, 2 Insufficient memory.

문제 진단 방법:

# 1. 클러스터 전체 리소스 현황
kubectl top nodes

# 2. 특정 노드의 상세 리소스 정보
kubectl describe node <node-name>

# 3. Pending Pod 상세 정보 확인
kubectl describe pod <pod-name>

# 4. 리소스 사용률이 높은 Pod 찾기
kubectl top pods --all-namespaces --sort-by=cpu
kubectl top pods --all-namespaces --sort-by=memory

Pod 수가 증가하면서 노드의 CPU/메모리 리소스가 부족해져 Pod가 Pending 상태로 남는 문제가 발생합니다.

Kubernetes 1.33 In-Place Pod Resize (Beta)

Kubernetes 1.33부터는 Pod를 재시작하지 않고도 리소스를 조정할 수 있습니다:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
      limits:
        cpu: "200m"
        memory: "256Mi"
    # 1.33에서 추가된 필드
    resizePolicy:
    - resourceName: cpu
      restartPolicy: NotRequired
    - resourceName: memory
      restartPolicy: NotRequired

리소스 조정 명령:

kubectl patch pod example-pod --patch='
{
  "spec": {
    "containers": [{
      "name": "app",
      "resources": {
        "requests": {"cpu": "200m", "memory": "256Mi"},
        "limits": {"cpu": "400m", "memory": "512Mi"}
      }
    }]
  }
}'

1.33 이전 버전에서의 해결방안

2.1 Kyverno를 활용한 Right-sizing

Kyverno란?
Kyverno는 Kubernetes 네이티브 정책 엔진으로, YAML로 정책을 정의하여 클러스터 리소스를 관리할 수 있는 도구입니다. 복잡한 스크립트 언어 대신 친숙한 Kubernetes 문법을 사용하여 정책을 작성할 수 있습니다.

Kyverno의 주요 기능:

  • Validation: 리소스 생성/수정 시 규칙 준수 여부 검증
  • Mutation: 리소스 생성 시 자동으로 필드 추가/수정
  • Generation: 특정 리소스 생성 시 연관 리소스 자동 생성
  • Cleanup: 조건에 맞는 리소스 자동 정리
  • Policy Exceptions: 특정 상황에서 정책 예외 처리

Right-sizing이 필요한 이유:
많은 개발팀이 리소스 요청값을 과도하게 설정하거나 아예 설정하지 않아 클러스터 자원 낭비나 성능 문제가 발생합니다. Kyverno를 통해 이를 체계적으로 관리할 수 있습니다.

리소스 요구사항 검증 정책:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-pod-resources
spec:
  validationFailureAction: enforce
  background: true
  rules:
  - name: validate-resources
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "Resource requests and limits are required"
      pattern:
        spec:
          containers:
          - name: "*"
            resources:
              requests:
                memory: "?*"
                cpu: "?*"
              limits:
                memory: "?*"
                cpu: "?*"

자동 리소스 할당 정책:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-resources
spec:
  background: true
  rules:
  - name: add-default-resources
    match:
      any:
      - resources:
          kinds:
          - Pod
    mutate:
      patchStrategicMerge:
        spec:
          containers:
          - (name): "*"
            resources:
              requests:
                +(memory): "128Mi"
                +(cpu): "100m"
              limits:
                +(memory): "256Mi"
                +(cpu): "200m"

과도한 리소스 요청 제한:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: limit-resources
spec:
  validationFailureAction: enforce
  rules:
  - name: check-cpu-limit
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "CPU limit cannot exceed 2 cores"
      pattern:
        spec:
          containers:
          - name: "*"
            resources:
              limits:
                cpu: "<=2000m"

2.2 Vertical Pod Autoscaler (VPA) 활용

VPA 설치 및 구성:

# VPA 설치
git clone https://github.com/kubernetes/autoscaler.git
cd autoscaler/vertical-pod-autoscaler/
./hack/vpa-install.sh

VPA 정책 설정:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Auto"  # Auto: 자동 적용, Off: 권장값만 제공, Initial: 최초 생성시만
  resourcePolicy:
    containerPolicies:
    - containerName: app
      maxAllowed:
        cpu: 1
        memory: 500Mi
      minAllowed:
        cpu: 100m
        memory: 50Mi
      # 리소스 조정 시 적용할 배율
      controlledResources: ["cpu", "memory"]

VPA 적용 전후 비교 시나리오:

적용 전 상황:

# 개발자가 임의로 설정한 리소스 (과도하게 할당)
resources:
  requests:
    cpu: "1000m"      # 실제 사용량: 200m
    memory: "2Gi"     # 실제 사용량: 512Mi
  limits:
    cpu: "2000m"
    memory: "4Gi"

VPA 분석 결과 확인:

kubectl describe vpa my-app-vpa

VPA 권장값 예시:

Recommendation:
  Container Recommendations:
    Container Name:  app
    Lower Bound:
      Cpu:     150m
      Memory:  256Mi
    Target:
      Cpu:     250m    # 실제 사용량 기반 권장값
      Memory:  512Mi   # 실제 사용량 기반 권장값
    Upper Bound:
      Cpu:     400m
      Memory:  1Gi

적용 후 결과:

# VPA가 자동 조정한 리소스 (효율적 할당)
resources:
  requests:
    cpu: "250m"       # 75% 절약
    memory: "512Mi"   # 75% 절약
  limits:
    cpu: "400m"       # 80% 절약
    memory: "1Gi"     # 75% 절약

효과 분석:

  • 리소스 효율성: CPU 75%, 메모리 75% 절약으로 더 많은 Pod 배치 가능
  • 비용 절감: 동일한 노드에서 4배 더 많은 워크로드 실행 가능
  • 성능 안정성: 실제 사용 패턴 기반으로 적절한 여유분 확보

3. Spot Instance 용량 부족 문제

문제 상황 및 증상

실제 에러 메시지:

# CloudWatch 이벤트 또는 EC2 콘솔에서 확인 가능
EC2 Auto Scaling group activity:
Status: Failed
StatusReason: We currently do not have sufficient m5.large capacity 
in the Availability Zone you requested (us-west-2a). 
Our system will be working on provisioning additional capacity.

# Karpenter 사용 시
Warning  FailedScheduling  pod/my-app-xxx  
no nodes available to schedule pod, 
insufficient capacity for instance type m5.large in zone us-west-2a

문제 진단 방법:

# 1. Auto Scaling Group 활동 히스토리 확인
aws autoscaling describe-scaling-activities --auto-scaling-group-name <asg-name>

# 2. Spot Instance 가격 및 가용성 확인
aws ec2 describe-spot-price-history --instance-types m5.large --availability-zone us-west-2a

# 3. Karpenter 노드 프로비저닝 로그 확인 (Karpenter 사용 시)
kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter

# 4. 클러스터 오토스케일러 로그 확인 (CA 사용 시)
kubectl logs -n kube-system -l app=cluster-autoscaler

주요 문제 상황:

  • InsufficientInstanceCapacity: 특정 AZ에서 요청한 인스턴스 타입의 Spot 용량 부족
  • SpotFleetRequestConfigurationInvalid: Spot Fleet 설정 오류
  • SchedulingDisabled: 노드 그룹이 일시적으로 스케일링 비활성화 상태
  • UnfulfillCapacity: 요청한 용량을 충족할 수 없음

해결 방안

3.1 다양한 인스턴스 타입 사용

전략 설명:
Spot Instance의 가용성을 높이기 위해서는 다양한 인스턴스 패밀리와 크기를 조합해야 합니다. 한 가지 타입에 의존하면 해당 타입의 용량이 부족할 때 전체 시스템이 영향을 받습니다.

Karpenter 설정 (권장):

apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: diversified-spot-nodepool
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"]
        # 다양한 인스턴스 패밀리 포함
        - key: node.kubernetes.io/instance-type
          operator: In
          values: 
            # 범용 인스턴스 (M 시리즈)
            - "m5.large"
            - "m5.xlarge"
            - "m5a.large"
            - "m5a.xlarge"
            - "m5n.large"
            - "m5n.xlarge"
            # 컴퓨팅 최적화 (C 시리즈)
            - "c5.large"
            - "c5.xlarge"
            - "c5a.large"
            - "c5a.xlarge"
            - "c5n.large"
            - "c5n.xlarge"
            # 메모리 최적화 (R 시리즈)
            - "r5.large"
            - "r5.xlarge"
        # 다중 AZ 지원
        - key: topology.kubernetes.io/zone
          operator: In
          values: 
            - "us-west-2a"
            - "us-west-2b"
            - "us-west-2c"
      nodeClassRef:
        apiVersion: karpenter.k8s.aws/v1beta1
        kind: EC2NodeClass
        name: default
  # 중단 정책 설정
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 30s
    expireAfter: 2160h # 90일

Auto Scaling Group 설정:

# ASG 사용 시 Launch Template 설정
apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-autoscaler-status
  namespace: kube-system
data:
  nodes.max: "100"
  # 다양한 인스턴스 타입 지원을 위한 MixedInstancesPolicy 활용

3.2 Spot Instance 중단 대응 전략

Spot Instance 중단 신호 처리:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: spot-interrupt-handler
  namespace: kube-system
spec:
  selector:
    matchLabels:
      app: spot-interrupt-handler
  template:
    metadata:
      labels:
        app: spot-interrupt-handler
    spec:
      serviceAccount: spot-interrupt-handler
      hostNetwork: true
      containers:
      - name: spot-interrupt-handler
        image: amazon/aws-node-termination-handler:v1.19.0
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: SPOT_INTERRUPT_THRESHOLD
          value: "120" # 2분 전 미리 알림
        volumeMounts:
        - name: proc
          mountPath: /host/proc
          readOnly: true
      volumes:
      - name: proc
        hostPath:
          path: /proc
      tolerations:
      - operator: Exists

Pod Disruption Budget 설정:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 2  # 최소 2개 Pod는 항상 유지
  selector:
    matchLabels:
      app: my-app

3.3 Mixed Instance Policy (ASG 사용 시)

{
  "InstancesDistribution": {
    "OnDemandAllocationStrategy": "prioritized",
    "OnDemandBaseCapacity": 2,
    "OnDemandPercentageAboveBaseCapacity": 20,
    "SpotAllocationStrategy": "diversified",
    "SpotInstancePools": 4,
    "SpotMaxPrice": "0.50"
  },
  "LaunchTemplate": {
    "LaunchTemplateSpecification": {
      "LaunchTemplateId": "lt-xxxxxxxxx",
      "Version": "$Latest"
    },
    "Overrides": [
      {
        "InstanceType": "m5.large",
        "WeightedCapacity": 1
      },
      {
        "InstanceType": "m5.xlarge",
        "WeightedCapacity": 2
      },
      {
        "InstanceType": "c5.large",
        "WeightedCapacity": 1
      }
    ]
  }
}

3.4 실시간 모니터링 및 알림 시스템

CloudWatch 기반 Spot Instance 모니터링:

# CloudWatch 알람 설정 (AWS CLI)
aws cloudwatch put-metric-alarm \
  --alarm-name "SpotInstanceTermination" \
  --alarm-description "Spot instance termination detected" \
  --metric-name "SpotInstanceTerminating" \
  --namespace "AWS/EC2Spot" \
  --statistic "Sum" \
  --period 300 \
  --threshold 1 \
  --comparison-operator "GreaterThanOrEqualToThreshold" \
  --evaluation-periods 1 \
  --alarm-actions "arn:aws:sns:us-west-2:123456789012:spot-alerts"

Prometheus + Grafana 모니터링:

apiVersion: v1
kind: ConfigMap
metadata:
  name: spot-monitoring-rules
  namespace: monitoring
data:
  spot-rules.yml: |
    groups:
    - name: spot-instances
      rules:
      # Spot Instance 중단 예측
      - alert: SpotInstanceInterruptionWarning
        expr: aws_spot_instance_interruption_warning > 0
        for: 30s
        labels:
          severity: warning
        annotations:
          summary: "Spot instance interruption warning"
          description: "Spot instance {{ $labels.instance_id }} will be terminated in 2 minutes"
      
      # 노드 용량 부족
      - alert: InsufficientSpotCapacity
        expr: increase(kube_node_status_condition{condition="Ready",status="false"}[10m]) > 2
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Multiple spot instances unavailable"
          description: "{{ $value }} nodes became unavailable in the last 10 minutes"
      
      # 클러스터 오토스케일러 실패
      - alert: ClusterAutoscalerFailure
        expr: increase(cluster_autoscaler_failed_scale_ups_total[15m]) > 0
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "Cluster autoscaler failed to scale up"
          description: "Autoscaler failed to provision nodes: {{ $labels.reason }}"

Slack 알림 통합:

apiVersion: v1
kind: ConfigMap
metadata:
  name: alertmanager-config
data:
  alertmanager.yml: |
    global:
      slack_api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
    
    route:
      group_by: ['alertname']
      group_wait: 10s
      group_interval: 10s
      repeat_interval: 1h
      receiver: 'spot-alerts'
    
    receivers:
    - name: 'spot-alerts'
      slack_configs:
      - channel: '#eks-alerts'
        title: 'EKS Spot Instance Alert'
        text: |
          {{ range .Alerts }}
          *Alert:* {{ .Annotations.summary }}
          *Description:* {{ .Annotations.description }}
          *Severity:* {{ .Labels.severity }}
          {{ end }}

실전 운영 가이드 및 모범 사례

1. 사전 예방적 모니터링 체계

핵심 메트릭 모니터링:

# 일일 점검 스크립트 예시
#!/bin/bash

echo "=== EKS 클러스터 리소스 현황 체크 ==="

# 1. 노드별 Pod 밀도 확인
echo "1. 노드별 Pod 사용률:"
kubectl get nodes -o custom-columns=NAME:.metadata.name,PODS:.status.capacity.pods,ALLOCATABLE:.status.allocatable.pods | awk 'NR==1 || $2/$3 > 0.8'

# 2. IP 주소 사용률 확인
echo "2. VPC CNI IP 사용 현황:"
kubectl get pods -n kube-system -l k8s-app=aws-node -o jsonpath='{range .items[*]}{.spec.nodeName}{"\t"}{.status.containerStatuses[0].restartCount}{"\n"}{end}'

# 3. 리소스 사용률 Top 10
echo "3. CPU 사용률 상위 Pod:"
kubectl top pods --all-namespaces --sort-by=cpu | head -10

echo "4. 메모리 사용률 상위 Pod:"
kubectl top pods --all-namespaces --sort-by=memory | head -10

# 5. Pending Pod 확인
echo "5. Pending 상태 Pod:"
kubectl get pods --all-namespaces --field-selector=status.phase=Pending

예측적 용량 계획:

  • 일간 사용 패턴 분석: 피크 시간대 리소스 요구량 파악
  • 월간 성장률 추적: 워크로드 증가 추세 모니터링
  • 계절성 고려: 비즈니스 특성에 따른 주기적 변동 반영

2. 비용 최적화 전략

Spot/On-Demand 비율 최적화:

# 권장 비율: Spot 70%, On-Demand 30%
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: cost-optimized-nodepool
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"]
      # Spot Instance 우선, 부족 시 On-Demand로 대체
      nodeClassRef:
        apiVersion: karpenter.k8s.aws/v1beta1
        kind: EC2NodeClass
        name: default
  # 비용 최적화를 위한 빠른 스케일 다운
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 10s

리소스 Right-sizing 자동화:

# VPA 권장값 적용 스크립트
#!/bin/bash
for deployment in $(kubectl get deployments --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'); do
  namespace=$(echo $deployment | cut -d' ' -f1)
  name=$(echo $deployment | cut -d' ' -f2)
  
  # VPA 권장값 확인
  recommendation=$(kubectl get vpa ${name}-vpa -n $namespace -o jsonpath='{.status.recommendation.containerRecommendations[0].target}' 2>/dev/null)
  
  if [ ! -z "$recommendation" ]; then
    echo "Deployment $namespace/$name 리소스 조정 권장: $recommendation"
  fi
done

3. 고가용성 및 장애 복구

Multi-AZ 배포 전략:

# Pod Anti-Affinity를 활용한 분산 배치
apiVersion: apps/v1
kind: Deployment
metadata:
  name: high-availability-app
spec:
  replicas: 6
  template:
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - high-availability-app
              topologyKey: topology.kubernetes.io/zone
          - weight: 50
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - high-availability-app
              topologyKey: kubernetes.io/hostname

자동 장애 복구 메커니즘:

# Health Check 및 자동 재시작
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: app
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 2

마무리

EKS 클러스터 운영에서 리소스 부족 문제는 피할 수 없는 도전과제입니다. 하지만 이 글에서 살펴본 것처럼, 각 문제의 근본 원인을 이해하고 적절한 해결책을 적용한다면 충분히 극복할 수 있습니다.

핵심 포인트 요약:

  1. Pod IP 부족은 VPC CNI 설정 최적화와 Prefix Delegation으로 해결
  2. 리소스 부족은 Kubernetes 1.33의 혁신적인 기능과 Kyverno/VPA를 통한 지능적 관리로 대응
  3. Spot Instance 이슈는 다양화 전략과 적극적인 모니터링으로 안정성 확보

운영 철학:

  • 사전 예방이 사후 대응보다 중요합니다
  • 모니터링 없는 최적화는 추측에 불과합니다
  • 자동화된 정책이 휴먼 에러를 방지합니다

특히 Kubernetes 1.33의 in-place pod resize 기능은 게임 체인저가 될 것입니다. Pod 재시작 없이 리소스를 조정할 수 있다는 것은 제로 다운타임 운영의 새로운 가능성을 열어줍니다.

체크리스트: 리소스 부족 문제 해결 로드맵

📋 즉시 실행 가능한 액션 아이템

1단계: 현재 상태 진단 (30분)

  • 클러스터 리소스 사용률 확인
  • Pending Pod 원인 분석
  • VPC CNI 설정 현황 점검
  • Spot Instance 중단 이력 확인

2단계: 긴급 대응 (1시간)

  • 임계 상황 시 수동 노드 추가
  • 리소스 과다 사용 Pod 식별 및 조치
  • 불필요한 워크로드 일시 중단

3단계: 중장기 개선 (1주일)

  • VPC CNI Prefix Delegation 적용
  • Kyverno 정책 기반 리소스 관리 도입
  • VPA 설치 및 권장값 분석
  • 다양한 인스턴스 타입으로 노드 그룹 다변화

4단계: 운영 체계 구축 (1개월)

  • 모니터링 대시보드 구축
  • 알림 시스템 설정
  • 자동화 스크립트 배포
  • 정기 점검 프로세스 수립

🎯 성공 지표

기술적 지표:

  • Pod 생성 시간 < 30초
  • 노드 사용률 70-80% 유지
  • Spot Instance 중단 시 복구 시간 < 5분

비즈니스 지표:

  • 인프라 비용 20% 절감
  • 서비스 가용성 99.9% 이상
  • 장애 대응 시간 50% 단축

앞으로도 지속적인 모니터링과 용량 계획을 통해 안정적이고 비용 효율적인 EKS 클러스터를 운영하시길 바라며, 이 가이드가 여러분의 클러스터 운영에 실질적인 도움이 되기를 희망합니다.

궁금한 점이나 추가적인 도움이 필요하시면 언제든 댓글로 남겨주세요! 🚀


📚 참고 자료:

profile
DevOps 엔지니어 / 열심히 해서 잘하자

0개의 댓글