Published on

EKS에서 EBS CSI Attach timeout으로 볼륨 못붙을 때

Authors

서버리스가 아닌 이상, EKS에서 상태가 꼬일 때 가장 체감이 큰 장애 중 하나가 EBS 볼륨이 안 붙어서(PV attach 실패) 워크로드가 멈추는 상황입니다. 특히 AttachVolume.Attach failed / timed out waiting for the condition 류의 이벤트가 반복되면, 애플리케이션 레벨이 아니라 스토리지 컨트롤 플레인(Controller) ↔ 노드 플레인(Node) 사이 어딘가에서 막히고 있다는 신호입니다.

이 글은 “EKS + EBS CSI” 조합에서 Attach timeout이 날 때, 로그/리소스/네트워크/권한/쿼터/토폴로지까지 원인을 체계적으로 분해해 재현 없이도 빠르게 수습하는 체크리스트를 제공합니다.

관련해서 Pod가 Pending에 걸려 전체가 멈춘 상황이라면, 스케줄링 관점의 원인도 함께 확인하세요: EKS Pod Pending 0/XX nodes available 원인별 해결


Attach timeout의 전형적인 증상

대표적으로 아래 조합으로 나타납니다.

  • Pod 상태: Pending 또는 ContainerCreating에서 오래 멈춤
  • 이벤트:
    • Warning FailedAttachVolume ... AttachVolume.Attach failed for volume ... timed out waiting for the condition
    • Warning FailedMount ... Unable to attach or mount volumes
  • VolumeAttachment 오브젝트가 생성되지만 attached: false로 유지
  • EC2 콘솔에서 해당 EBS가 in-use로 전환되지 않거나, 다른 인스턴스에 붙어 있는 상태로 남아있음

0) 먼저 “어디서 막혔는지”를 3분 안에 확정하기

Attach 타임아웃은 크게 3단계 중 하나입니다.

  1. 스케줄링 단계: Pod가 노드에 배치되지 못함(스토리지 토폴로지/노드 부족)
  2. Attach 단계: 컨트롤러가 EC2 Attach API 호출했는데 실패/지연
  3. Node stage/mount 단계: Attach는 됐는데 노드에서 디바이스 인식/마운트가 실패

아래 명령으로 단계부터 나눕니다.

# 1) Pod 이벤트
kubectl describe pod -n <ns> <pod>

# 2) PVC/PV 상태
kubectl get pvc -n <ns>
kubectl get pv | grep <pvc-or-pv-name>

# 3) VolumeAttachment 확인 (Attach 단계의 핵심)
kubectl get volumeattachment
kubectl describe volumeattachment <name>
  • VolumeAttachment없다 → 보통 스케줄링/프로비저닝 단계 문제
  • VolumeAttachment는 있는데 attached: false + 이벤트가 FailedAttachVolumeAttach 단계 문제(권한/EC2 API/토폴로지/이미 붙음)
  • attached: true인데 Pod는 FailedMount노드 마운트 단계 문제(노드 플러그인/OS/디바이스)

1) 가장 흔한 원인: 볼륨이 다른 노드에 이미 붙어 있음(멀티어태치 불가)

EBS는 기본적으로 RWO(단일 노드 Attach)입니다(io1/io2의 Multi-Attach 예외는 있지만 일반적으로 사용하지 않음). 아래 상황에서 자주 발생합니다.

  • 노드 장애/강제 종료로 detach가 지연
  • StatefulSet Pod가 다른 노드로 재스케줄되며 기존 attach가 남음
  • 이전 Pod가 termination 중인데 새 Pod가 먼저 뜸

확인 포인트:

# PV에서 volumeHandle(EBS volume id) 확인
kubectl describe pv <pv>

# AWS CLI로 현재 attachment 확인
aws ec2 describe-volumes --volume-ids <vol-xxxxxxxx> \
  --query 'Volumes[0].Attachments'

해결:

  • 먼저 기존 Pod/노드가 정말 죽었는지 확인
  • 더 이상 사용하지 않는 attachment라면 강제 detach(주의: 파일시스템 손상 가능)
aws ec2 detach-volume --volume-id <vol-xxxxxxxx> --force

운영 팁:

  • Stateful workload라면 PodDisruptionBudget, terminationGracePeriod, preStop 등을 조정해 “동시에 두 Pod가 같은 PVC를 잡는” 상황을 줄입니다.

2) 토폴로지(AZ) 불일치: 볼륨은 us-east-1a, 노드는 1b

EBS는 AZ 종속입니다. PVC가 특정 AZ에 생성됐는데, 스케줄러가 다른 AZ의 노드에 Pod를 배치하려 하면 attach가 안 됩니다. EBS CSI는 보통 topology-aware provisioning을 하지만, 다음 케이스에서 엇갈립니다.

  • StorageClass에 volumeBindingMode: Immediate (권장: WaitForFirstConsumer)
  • 노드 그룹이 여러 AZ인데, PV가 한 AZ에 고정
  • 수동으로 만든 PV가 특정 AZ에 존재

점검:

# PV의 노드 어피니티(어느 AZ에 있는지)
kubectl get pv <pv> -o jsonpath='{.spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].values}'

# 노드의 AZ
kubectl get nodes -L topology.kubernetes.io/zone

권장 StorageClass 예시:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3-wffc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: gp3
  fsType: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true

이미 만들어진 PVC가 문제라면:

  • 데이터가 없으면 PVC/PV 재생성
  • 데이터가 있으면 스냅샷 → 타 AZ 복구 또는 동일 AZ로 Pod를 강제 스케줄(nodeAffinity)하는 방식으로 수습합니다.

3) EBS CSI 컨트롤러/노드 플러그인 장애(또는 애드온 버그)

EBS CSI는 보통 다음 파드로 구성됩니다.

  • ebs-csi-controller (Deployment)
  • ebs-csi-node (DaemonSet)

둘 중 하나가 죽거나, 특정 노드의 node plugin이 비정상이면 attach/mount가 지연됩니다.

점검:

kubectl -n kube-system get pods -l app.kubernetes.io/name=aws-ebs-csi-driver -o wide

# 컨트롤러 로그
kubectl -n kube-system logs deploy/ebs-csi-controller -c ebs-plugin --tail=200

# 특정 노드의 node plugin 로그
kubectl -n kube-system logs ds/ebs-csi-node -c ebs-plugin --tail=200

자주 보이는 단서:

  • UnauthorizedOperation / AccessDenied → IRSA/권한 문제(다음 섹션)
  • context deadline exceeded가 EC2 API 호출에서 반복 → 네트워크/NAT/VPC 엔드포인트/레이트리밋
  • 특정 노드에서만 mount 실패 → 노드 디바이스/커널/NVMe 매핑 문제

운영 관점 해결:

  • EKS Add-on으로 관리 중이면 드라이버 버전 업/롤백을 고려
  • ebs-csi-node가 특정 노드에서만 문제면 해당 노드를 cordon/drain 후 교체가 가장 빠른 경우가 많습니다.

4) IRSA/권한 문제: Attach API 호출 자체가 막힘

EBS CSI Controller는 AWS API를 호출합니다(AttachVolume, DetachVolume, CreateVolume 등). IRSA 설정이 틀리면 attach가 “시도는 하는데 계속 실패”로 남습니다.

점검 포인트:

  • ebs-csi-controller의 ServiceAccount에 올바른 role annotation이 있는지
  • role에 AmazonEBSCSIDriverPolicy(또는 동등 커스텀 정책)가 붙었는지
kubectl -n kube-system get sa ebs-csi-controller-sa -o yaml | sed -n '1,120p'

aws iam list-attached-role-policies --role-name <role-name>

IRSA 자체가 꼬여 WebIdentityToken류 에러가 뜨면 아래 글의 체크리스트가 그대로 도움이 됩니다: EKS IRSA 설정 후 WebIdentityToken 오류 해결


5) EC2 API까지의 네트워크 경로 문제(프라이빗 서브넷/NAT/VPCE)

컨트롤러 파드가 EC2 API 엔드포인트에 도달하지 못하면 attach가 타임아웃으로 보일 수 있습니다. 특히 클러스터가 프라이빗 서브넷에 있고 NAT/엔드포인트 구성이 애매할 때 발생합니다.

확인 방법:

  • 컨트롤러 파드에서 AWS API 호출이 되는지(간단히 STS/EC2)
  • VPC Interface Endpoint를 쓴다면 com.amazonaws.<region>.ec2 / sts 등이 올바른 서브넷/SG로 열려 있는지

디버그용 임시 파드 예시:

kubectl run -n kube-system net-debug --rm -it --image=public.ecr.aws/aws-cli/aws-cli:2.15.0 -- bash

# 파드 내부에서
aws sts get-caller-identity
aws ec2 describe-volumes --max-items 1
  • 여기서도 타임아웃이면 스토리지 문제가 아니라 네트워크/엔드포인트 문제일 확률이 큽니다.

(참고로 “DNS는 되는데 HTTPS만 실패” 류의 네트워크 미스매치는 다른 증상에서도 자주 보입니다. 비슷한 결로 점검하려면: EKS Pod DNS는 되는데 HTTPS만 실패할 때 점검)


6) EBS/EC2 쿼터 및 노드 단위 볼륨 제한

Attach timeout이지만 실제 원인은 “더 이상 붙일 수 없음”일 때가 있습니다.

  • 계정/리전 EBS 볼륨 수, IOPS, 스냅샷 등 서비스 쿼터
  • 인스턴스 타입별 EBS 볼륨 attach 개수 제한
  • 노드에 이미 많은 PVC가 붙어 있어 추가 attach가 실패

점검:

# 노드에 현재 어떤 PV들이 붙어 있는지(대략)
kubectl describe node <node> | sed -n '/Non-terminated Pods:/,/Allocated resources:/p'

# 서비스 쿼터는 콘솔 또는 CLI로 확인 가능(예: Service Quotas)
aws service-quotas list-service-quotas --service-code ebs | head

해결:

  • 노드 스펙을 상향(더 많은 EBS attach 지원)
  • 워크로드를 더 많은 노드로 분산
  • 불필요한 PVC 정리/스토리지 아키텍처 변경(EFS, S3, 로컬 캐시 등)

7) KMS 암호화 볼륨인데 키 정책/권한이 빠짐

StorageClass에서 KMS 키로 암호화하는 경우, EBS CSI role에 KMS 권한이 없거나 키 정책이 제한적이면 Create/Attach 단계에서 실패합니다. 이벤트는 attach timeout처럼 보이지만 로그에는 KMS 관련 AccessDenied가 남는 경우가 많습니다.

점검:

  • PV/PVC/StorageClass에 encrypted/kmsKeyId 설정 여부
  • controller 로그에서 kms: 관련 에러

해결:

  • IRSA role에 kms:Encrypt/Decrypt/GenerateDataKey/DescribeKey/CreateGrant 등 최소 권한 부여
  • KMS Key policy에 해당 role principal 허용

8) 실전 트러블슈팅: “리소스 5개만” 보면 결론이 난다

Attach timeout을 빠르게 끝내려면 아래 5가지를 한 화면에 모으는 게 좋습니다.

  1. Pod 이벤트
kubectl describe pod -n <ns> <pod> | sed -n '/Events:/,$p'
  1. PVC/PV
kubectl get pvc -n <ns> <pvc> -o wide
kubectl describe pv <pv>
  1. VolumeAttachment
kubectl get volumeattachment | grep -i <pv-or-vol-id>
kubectl describe volumeattachment <va>
  1. EBS CSI controller 로그(권한/네트워크/EC2 API 에러가 가장 잘 보임)
kubectl -n kube-system logs deploy/ebs-csi-controller -c ebs-plugin --since=30m | tail -n 200
  1. AWS에서 볼륨 attachment 상태
aws ec2 describe-volumes --volume-ids <vol-xxxxxxxx> \
  --query 'Volumes[0].{State:State,AZ:AvailabilityZone,Attachments:Attachments,Tags:Tags}'

이 5개를 보면 보통 아래로 귀결됩니다.

  • Attach가 아예 안 됨 → 권한/네트워크/쿼터/AZ
  • Attach는 됨 → 노드 플러그인/OS/마운트
  • 이미 다른 데 붙음 → 강제 detach 또는 워크로드 롤링 전략 개선

9) 재발 방지 체크리스트(운영 설정)

StorageClass는 가능하면 WFFC

멀티 AZ 노드 그룹이라면 WaitForFirstConsumer가 사실상 표준입니다.

노드 교체 전략

특정 노드에서만 attach/mount가 반복되면 드레인 후 인스턴스 교체가 MTTR을 크게 줄입니다.

kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data

StatefulSet 롤링과 종료 유예

동일 PVC를 두 Pod가 동시에 잡으려는 순간이 생기지 않게:

  • terminationGracePeriodSeconds 충분히 확보
  • readiness/liveness를 과격하게 잡지 않기
  • 필요 시 PDB로 동시 축출 제한

관측 포인트

  • kube-system의 ebs-csi-controller/node 로그 수집
  • VolumeAttachment 상태 변화 알림
  • EC2 AttachVolume API 오류/레이트리밋 모니터링

마무리

EKS에서 EBS CSI Attach timeout은 증상만 보면 비슷하지만, 실제 원인은 (1) 이미 붙어 있음, (2) AZ 불일치, (3) CSI 컴포넌트/노드 문제, (4) IRSA 권한, (5) AWS API 네트워크, (6) 쿼터/제한, (7) KMS로 비교적 명확하게 갈립니다.

가장 효율적인 접근은 “Pod 이벤트 → VolumeAttachment → CSI 로그 → AWS 볼륨 상태” 순서로, Kubernetes 오브젝트와 AWS 실상을 동시에 대조하는 것입니다. 이 루틴만 잡아두면 재현이 어려운 간헐 장애도 대부분 10~20분 안에 원인을 특정할 수 있습니다.