9. EKS 활용 사례 3 (Troubleshooting)

Update : 2025.08.07

EKS 디버깅 워크샵 – Amazon Q 기반 Kubernetes 문제 해결

이 가이드는 Amazon Q와 함께 마이크로서비스 기반 Kubernetes 애플리케이션에서 자주 발생하는 문제들을 어떻게 진단하고 수정하는지를 실습 중심으로 설명합니다.

각 시나리오는 다음 요소로 구성됩니다:

  • 초기 정상 상태

  • 문제를 의도적으로 유발하는 방법

  • 증상 및 에러 메시지

  • 문제 해결을 위한 Amazon Q 프롬프트

  • kubectl을 통한 결과 검증

1. Kubernetes 문제 해결 시나리오

1.1 Scenario 1: 잘못된 Service Selector

  • 초기 상태

UI 서비스가 정상적으로 Catalog 서비스에 연결되어 상품 목록을 불러옵니다.

  • 문제 유발 프롬프트:

cd ~/environment/eks-workshop-v2/
# 현재 catalog 서비스 정의 추출
kubectl get service catalog -n catalog -o yaml > catalog-service.yaml

# selector 값을 잘못된 값으로 변경
sed -i 's/app.kubernetes.io\/name: catalog/app.kubernetes.io\/name: catalog-wrong/g' catalog-service.yaml

# 변경된 서비스 적용
kubectl apply -f catalog-service.yaml
  • 증상

    • UI에서 상품 목록을 로드할 때 오류 발생

    • UI 파드 로그에서 catalog 서비스 연결 거부 메시지

    • catalog 서비스는 존재하지만, 트래픽이 파드로 전달되지 않음

  • Amazon Q 프롬프트 예시 :

Kubernetes 애플리케이션의 UI가 EKS 클러스터 내 catalog 서비스에 연결되지 않습니다.
catalog 파드는 실행 중이지만, 서비스가 트래픽을 해당 파드로 라우팅하지 않고 있습니다.
서비스 셀렉터(selector) 불일치 여부를 어떻게 확인하고, 이를 어떻게 수정할 수 있을까요?

실행 결과는 아래와 같습니다:

## ✅ Catalog 서비스 연결 문제 해결 완료!

UI가 catalog 서비스에 연결되지 않는 문제를 성공적으로 해결했습니다.

### 🔍 발견된 문제

서비스 셀렉터 불일치:
• **파드 레이블**: app.kubernetes.io/name: catalog ✅
• **서비스 셀렉터**: app.kubernetes.io/name: catalog-wrong ❌

### 🛠️ 해결 과정

1. 문제 진단: 파드 레이블과 서비스 셀렉터 비교
2. 엔드포인트 확인: <none> 상태로 파드 연결 안됨 확인
3. YAML 재적용: kubectl apply -k 명령어로 올바른 설정 적용
4. 연결 테스트: HTTP 200 응답으로 정상 동작 확인

### 📊 수정 결과

수정 전:
NAME      ENDPOINTS   AGE
catalog   <none>      72m


수정 후:
NAME      ENDPOINTS           AGE
catalog   10.11.74.186:8080   72m


### 🧪 연결 테스트 성공

bash
kubectl exec -n ui deployment/ui -- curl -s -o /dev/null -w "%{http_code}" http://catalog.catalog.svc:80/health
# 결과: 200 ✅


### 📋 진단 체크리스트

향후 유사한 문제 발생 시 사용할 수 있는 체크리스트:

1. 파드 레이블 확인: kubectl get pods -n <namespace> --show-labels
2. 서비스 셀렉터 확인: kubectl get service <name> -n <namespace> -o yaml
3. 엔드포인트 상태 확인: kubectl get endpoints <name> -n <namespace>
4. 연결 테스트: curl 명령어로 실제 연결 확인

📝 상세한 문제 해결 과정과 예방 조치는 ~/output/catalog-service-selector-fix.md 파일에 저장되었습니다.

이제 UI 애플리케이션이 catalog 서비스와 정상적으로 통신할 수 있습니다! 🎉

markdown 예시

  • 문제 검증 및 복구

# 서비스의 selector 확인
kubectl get service catalog -n catalog -o jsonpath='{.spec.selector}' | jq

# 파드 라벨 확인
kubectl get pods -n catalog -l app.kubernetes.io/name=catalog -o jsonpath='{.items[0].metadata.labels}' | jq

# 서비스에 바인딩된 엔드포인트 확인
kubectl get endpoints catalog -n catalog

1.2 Scenario 2: 리소스 제약 (Resource Constraints)

  • 초기 상태 : Carts 서비스가 충분한 CPU 및 메모리 리소스를 갖고 정상적으로 동작함.

  • 문제 유발 프롬프트:

# carts 디플로이먼트 추출
kubectl get deployment carts -n carts -o yaml > carts-deployment.yaml

# 리소스 제한을 극단적으로 낮게 설정
sed -i 's/memory: 1Gi/memory: 1Mi/g' carts-deployment.yaml
sed -i 's/cpu: 250m/cpu: 1m/g' carts-deployment.yaml

# 변경 적용
kubectl apply -f carts-deployment.yaml
  • 증상

    • carts 파드가 CrashLoopBackOff 상태로 반복 재시작됨

    • 이벤트에 OOMKilled(메모리 부족으로 종료) 로그 발생

    • 애플리케이션 응답 지연 또는 중단

  • 실행 결과는 아래와 같습니다:

명령을 실행했고, carts 디플로이먼트의 리소스 제한을 극단적으로 낮게 설정했습니다. 그 결과 새로운 파드가 시작되지 못하고 있습니다.

## 실행 결과 분석

1. 리소스 제한 변경:
   • 메모리 제한: 1Gi → 1Mi (1024MB에서 1MB로 감소)
   • CPU 요청: 250m → 1m (250밀리코어에서 1밀리코어로 감소)

2. 디플로이먼트 상태:
   • 롤링 업데이트 중: 새 ReplicaSet carts-bc5d58f66가 생성됨
   • 이전 파드 carts-7c95cd549d-4mjjb는 여전히 실행 중
   • 새 파드 carts-bc5d58f66-2bhsz는 Pending 상태

3. 새 파드 문제:
   • 이벤트 로그에서 중요한 오류 발견:
  

   Failed to create pod sandbox: rpc error: code = Unknown desc = failed to create containerd task: 
   failed to create shim task: OCI runtime create failed: runc create failed: 
   unable to start container process: container init was OOM-killed (memory limit too low?): unknown
   


## 문제 원인

새 파드가 시작되지 못하는 이유는 메모리 제한이 너무 낮기 때문입니다. 1Mi(1MB)는 Java 애플리케이션이 실행되기에 극단적으로 부족한 메모리입니다. 컨테이너 초기화 과
정에서 OOM(Out Of Memory) 오류가 발생하여 파드가 시작되지 못하고 있습니다.

이로 인해 롤링 업데이트가 완료되지 못하고, 이전 파드와 새 파드가 동시에 존재하는 상태가 되었습니다. 이전 파드는 여전히 정상 작동하지만, 새 파드는 시작되지 못하고
있습니다.

이러한 상황은 실제 환경에서 리소스 제한을 잘못 설정했을 때 발생할 수 있는 전형적인 문제입니다. 특히 Java 애플리케이션은 최소한의 메모리가 필요하며, 1MB는 JVM이 
시작하기에도 부족한 양입니다.
  • Amazon Q 프롬프트 예시 :

EKS 클러스터의 carts 파드가 계속 OOMKilled 오류로 크래시되고 있습니다.
파드 이벤트를 확인해보니 메모리 문제로 종료되고 있는 것으로 보입니다.
현재 설정된 리소스 제한을 확인하고, 적절한 값으로 업데이트하려면 어떻게 해야 하나요?
  • 실행 결과는 아래와 같습니다:

## ✅ Carts 파드 OOMKilled 오류 해결 완료!

EKS 클러스터의 carts 파드가 OOMKilled 오류로 크래시되는 문제를 성공적으로 해결했습니다.

### 🔍 발견된 문제

극도로 부족한 메모리 할당:
• **현재 설정**: 1Mi (1 메가바이트) ❌
• **Java 애플리케이션 최소 요구량**: ~300Mi
• **권장 설정**: 1Gi (1 기가바이트) ✅

### 🚨 OOMKilled 발생 원인

Failed to create pod sandbox: OCI runtime create failed: 
runc create failed: unable to start container process: 
container init was OOM-killed (memory limit too low?)


Java Spring Boot 애플리케이션이 JVM 초기화 과정에서 1Mi 메모리 제한을 초과하여 Linux OOM Killer에 의해 강제 종료되었습니다.

### 🛠️ 해결 과정

1. 문제 진단: 이벤트 로그에서 OOMKilled 오류 확인
2. 리소스 설정 확인: 현재 메모리 제한이 1Mi로 설정됨 발견
3. 원본 파일 확인: YAML 파일에는 올바른 1Gi 설정이 있음 확인
4. 설정 재적용: kubectl apply -k 명령어로 올바른 설정 적용

### 📊 수정 결과

✅ 업데이트된 리소스 설정:
json
{
  "limits": {
    "memory": "1Gi"
  },
  "requests": {
    "cpu": "250m",
    "memory": "1Gi"
  }
}


✅ 현재 실제 사용량:
• **메모리**: 262Mi (할당량의 25.6%)
• **CPU**: 2m (할당량의 0.8%)
• **상태**: Running ✅
• **헬스 체크**: 200 OK ✅

### 🎯 주요 성과

| 지표 | 개선 전 | 개선 후 |
|------|---------|---------|
| 파드 시작 성공률 | 0% | 100% |
| 메모리 가용성 | 0Mi | 762Mi |
| 애플리케이션 응답 | 실패 | 200 OK |
| 시스템 안정성 | 불안정 | 안정 |

### 📋 Java 애플리케이션 리소스 권장사항

메모리 할당 가이드라인:
• **최소 요구량**: 512Mi
• **권장 설정**: 1Gi
• **JVM 힙 비율**: 75% (MaxRAMPercentage=75.0)
• **안전 마진**: 실제 사용량의 2-3배

📝 상세한 문제 해결 과정과 예방 조치는 ~/output/carts-oom-fix.md 파일에 저장되었습니다.

이제 carts 파드가 안정적으로 실행되며 충분한 메모리 여유를 확보했습니다! 🎉

markdown 에시

  • 검증 명령어

# carts 네임스페이스 내 파드 상태 확인
kubectl get pods -n carts

# 현재 설정된 리소스 제한 확인
kubectl get deployment carts -n carts -o jsonpath='{.spec.template.spec.containers[0].resources}' | jq

# 파드 재시작 횟수 확인 (복구되었을 경우 낮아야 함)
kubectl get pods -n carts -o jsonpath='{.items[*].status.containerStatuses[0].restartCount}'
  • 결과 확인

NAME                              READY   STATUS    RESTARTS   AGE
carts-7dc65cd8ff-lgl4z            1/1     Running   0          2m4s
carts-dynamodb-68bd8f6f6d-p7rmz   1/1     Running   0          25m
{
  "limits": {
    "memory": "1536Mi"
  },
  "requests": {
    "cpu": "250m",
    "memory": "1Gi"
  }
}

1.3 Scenario 3: 의존성 누락 (Missing Dependencies)

  • 초기 상태

Orders 서비스는 RabbitMQ 서비스에 의존하여 메시지 큐 기능을 수행.

  • 문제 유발

# rabbitmq checkout을 0으로 스케일 다운
kubectl -n checkout scale deployment checkout --replicas=0
  • 증상

    • checkout 서비스와 Redis연결 이슈 발생

  • Amazon Q 프롬프트 예시:

EKS 클러스터의 checkout 서비스에서 오류가 발생하고 있습니다.
checkout 파드가 실행 중인지 확인하고, 실행 중이 아니라면 어떻게 복구할 수 있을까요?
  • 실행 결과는 아래와 같습니다:

## ✅ Checkout 서비스 복구 완료!

EKS 클러스터의 checkout 서비스 오류를 성공적으로 진단하고 복구했습니다.

### 🔍 발견된 문제

Checkout 애플리케이션 파드 완전 중단:
• **디플로이먼트 상태**: 0/0 (파드 없음) ❌
• **서비스 엔드포인트**: <none> (연결 불가) ❌
• **근본 원인**: 레플리카 수가 3에서 0으로 의도치 않게 축소됨

### 🚨 서비스 중단 영향

• **사용자 경험**: 결제 기능 완전 중단
• **연결 테스트**: Exit Code 7 (Connection Failed)
• **비즈니스 영향**: 주문 완료 불가

### 🛠️ 복구 과정

1. 문제 진단: 파드 상태 → 디플로이먼트 상태 → 이벤트 로그 순차 확인
2. 원인 파악: 디플로이먼트가 2분 전에 3개에서 0개로 스케일 다운됨
3. 설정 복구: kubectl apply -k 명령어로 올바른 설정 재적용
4. 결과 검증: 모든 파드 Ready 상태 및 서비스 연결 확인

### 📊 복구 결과

✅ 완전 복구 달성:
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
checkout   3/3     3            3           149m


✅ 파드 상태:
• 3개 checkout 파드 모두 Running 상태
• 3개의 서로 다른 워커 노드에 분산 배치
• Redis 캐시와 정상 연결

✅ 서비스 연결:
• 엔드포인트: 3개 파드 IP 모두 등록
• 헬스 체크: 200 OK 응답
• 복구 시간: 약 30초

### 🎯 주요 성과

| 지표 | 복구 전 | 복구 후 |
|------|---------|---------|
| 서비스 가용성 | 0% | 100% |
| 실행 중인 파드 | 0개 | 3개 |
| 응답 성공률 | 0% | 100% |
| 복구 시간 | N/A | 30초 |

### 📋 체계적인 진단 체크리스트

향후 유사한 문제 발생 시 사용할 수 있는 진단 절차:

1. 파드 상태 확인: kubectl get pods -n checkout
2. 디플로이먼트 상태 확인: kubectl get deployment -n checkout
3. 상세 정보 확인: kubectl describe deployment checkout -n checkout
4. 이벤트 로그 분석: kubectl get events -n checkout
5. 연결 테스트: curl 명령어로 실제 연결 확인

📝 상세한 복구 과정과 예방 조치는 ~/output/checkout-service-recovery.md 파일에 저장되었습니다.

이제 checkout 서비스가 3개 레플리카로 고가용성을 확보하며 정상적으로 운영되고 있습니다! 🎉

markdown 결과 예시

  • 검증 명령어:

# checkout 파드 상태 확인
kubectl get pods -n checkout
# 디플로이먼트 상태 확인
kubectl get deployment -n checkout
# 상세 정보 확인
kubectl describe deployment checkout -n checkout
# 이벤트 로그 분석
kubectl describe deployment checkout -n checkout | grep -A 20 "Events:"
  • 실행 결과는 아래와 같습니다:

$kubectl get pods -n checkout
NAME                              READY   STATUS    RESTARTS   AGE
checkout-54c6cd5685-h4vbh         1/1     Running   0          6m19s
checkout-54c6cd5685-scc5g         1/1     Running   0          6m19s
checkout-54c6cd5685-wf9q9         1/1     Running   0          6m19s
checkout-redis-7fb554999b-rrs4q   1/1     Running   0          156m

$ kubectl get deployment -n checkout
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
checkout         3/3     3            3           156m
checkout-redis   1/1     1            1           156m

$ kubectl describe deployment checkout -n checkout | grep -A 20 "Events:"
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  12m    deployment-controller  Scaled down replica set checkout-54c6cd5685 to 0 from 3
  Normal  ScalingReplicaSet  9m41s  deployment-controller  Scaled up replica set checkout-54c6cd5685 to 3 from 0

Last updated