Elasticsearch Lucene Write Lock 문제 해결 가이드 - CSI 장애와 StatefulSet 복구
게시:
- 단일 CSI를 활용하여 Elasticsearch Volume 운영 시 CSI에 이상이 생기면 모든 인덱스에서 Lucene write.lock 충돌이 발생하여 클러스터 마비가 발생할 수 있습니다.
- 각 PVC에서 오염된
write.lock파일을 제거하면 해결 가능합니다.- 단일 CSI를 사용하는 구조는 이런 위험에 상시 노출됨. 아키텍처 레벨에서 근본적인 해결이 필요합니다. (Network Storage → Local NVMe)
문제 개요
Elasticsearch Pods가 Ready 상태가 되지 않으며, 모든 인덱스에서 Lucene write.lock 파일 충돌.
- 갑작스러운 CSI(Container Storage Interface) 이상에 따른 PVC Volume Mount 실패
- Elasticsearch Pod들이 비정상 종료되면서 Lucene
write.lock파일이 남아있는 상황
핵심 에러 메시지
org.apache.lucene.store.LockObtainFailedException: Lock held by another program:
/usr/share/elasticsearch/data/indices/.../write.lock
주요 증상
- 모든 Elasticsearch Pod: 0/1 Ready 상태
- 여러 인덱스에서 동시에 lock 획득 실패
- Shard recovery 지속 실패
NAME READY STATUS RESTARTS AGE IP
elasticsearch-master-0 0/1 Running 0 2m19s 10.244.2.8
elasticsearch-master-1 0/1 Running 0 2m19s 10.244.1.64
elasticsearch-master-2 0/1 Running 0 2m19s 10.244.0.159
원인 분석
1. 사고 발생 시나리오
- 예고없는 CSI 업데이트가 진행되었음을 사후 확인되었습니다.
- 이로 인해 Elasticsearch PVC Volume mount가 실패하였고,
- Elasticsearch Pod가 비정상 종료되면서 write.lock이 PVC에 삭제되지 않고 남았습니다.
CSI Policy 기습 업데이트
↓
PVC Volume Mount 실패
↓
Elasticsearch Pod 비정상 종료 (SIGKILL)
↓
Lucene write.lock 파일이 정상 삭제되지 않고 PVC에 남음
↓
Pod 재시작 시 기존 lock 파일로 인해 시작 실패
2. Lock 파일이 남게 된 이유
- CSI 정책 업데이트로 Elasticsearch PVC 볼륨 마운트 실패. 이로 인해 Pod에 SIGKILL 전송
- 변경된 CSI 정책으로 PVC에 접근 불가하게 되어
write.lock을 삭제할 수 없어서 오염된write.lock파일이 볼륨에 남게 되었습니다.
정상 종료 시:
# Elasticsearch 정상 종료 프로세스
1. SIGTERM 수신
2. 새로운 요청 거부
3. 진행 중인 작업 완료 대기
4. write.lock 파일 삭제
5. 프로세스 종료
비정상 종료 시 (CSI Policy 업데이트):
# 이번 사고 시나리오
1. CSI Policy 변경 적용
2. Volume Mount 즉시 실패
3. Pod에 SIGKILL 전송 (강제 종료)
4. write.lock 삭제 프로세스 실행 불가
5. 손상된 lock 파일이 PVC에 남음
해결 방법
lock 해제 임시 Pod로 각 PVC에 마운트하여 접근하여 write.lock 파일을 찾아 삭제합니다.
단, CSI Policy 이슈 해결이 선행되어야 합니다.
1단계: StatefulSet 안전하게 스케일 다운
# 현재 Pod 상태 모니터링 시작
kubectl -n <namespace> get pods -l app=elasticsearch-master -w
# 모든 Elasticsearch Pod 정상 종료
kubectl -n <namespace> scale statefulset elasticsearch-master --replicas=0
# Pod 완전 종료 확인 (최대 2분 대기)
kubectl -n <namespace> get pods -l app=elasticsearch-master
2단계: Lock 파일 정리
임시 Pod로 각 PVC에서 write.lock 파일을 삭제합니다.
# PVC 목록 확인
kubectl -n <namespace> get pvc | grep elasticsearch
# 각 PVC에 대해 lock 파일 삭제
for i in 0 1 2; do
kubectl -n <namespace> run es-lock-cleaner-$i \
--rm -it --restart=Never \
--image=busybox \
--overrides="{
\"spec\": {
\"containers\": [{
\"name\": \"cleaner\",
\"image\": \"busybox\",
\"command\": [
\"sh\", \"-c\",
\"find /usr/share/elasticsearch/data -name 'write.lock' -delete && echo 'Cleaned locks for master-$i'\"
],
\"volumeMounts\": [{
\"name\": \"data\",
\"mountPath\": \"/usr/share/elasticsearch/data\"
}]
}],
\"volumes\": [{
\"name\": \"data\",
\"persistentVolumeClaim\": {
\"claimName\": \"elasticsearch-master-elasticsearch-master-$i\"
}
}]
}
}"
done
동작 원리:
- busybox 이미지로 경량 임시 Pod 생성
- 각 PVC를 마운트하여 접근
find명령으로 모든 write.lock 파일 검색 및 삭제--rm플래그로 작업 완료 후 자동 삭제
CSI Policy 이슈가 있는 경우:
# 임시 Pod도 Mount 실패할 수 있음
# 이 경우 먼저 CSI Policy 수정 필요
kubectl -n <namespace> describe pod es-lock-cleaner-0 | grep -A 10 "Events:"
3단계: StatefulSet 스케일 업
# Elasticsearch 재시작
kubectl -n <namespace> scale statefulset elasticsearch-master --replicas=3
# Pod 상태 실시간 모니터링
kubectl -n <namespace> get pods -l app=elasticsearch-master -w
# 30-60초 대기 후 로그 확인
kubectl -n <namespace> logs elasticsearch-master-0 --tail=50
정상 시작 확인:
- Pod STATUS: Running
- READY: 1/1
- Volume Mount 성공
- Lock 에러 없음
4단계: 클러스터 상태 검증
# 클러스터 헬스 체크
kubectl -n <namespace> exec elasticsearch-master-0 -- \
curl -s -u elastic:password 'localhost:9200/_cluster/health?pretty'
# Shard 상태 확인
kubectl -n <namespace> exec elasticsearch-master-0 -- \
curl -s -u elastic:password 'localhost:9200/_cat/shards?v'
# 노드 상태 확인
kubectl -n <namespace> exec elasticsearch-master-0 -- \
curl -s -u elastic:password 'localhost:9200/_cat/nodes?v'
정상 상태 기준:
{
"cluster_name": "elasticsearch",
"status": "green",
"number_of_nodes": 3,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}
트러블슈팅 팁
CSI 관련 이슈 진단
# 1. CSI Driver Pod 상태 확인
kubectl -n <csi-driver-namespace> get pods -o wide
# 2. CSI Driver 로그 확인
kubectl -n <csi-driver-namespace> logs <csi-driver-pod> --tail=200 | grep -i error
# 3. Volume Attachment 상태 확인
kubectl get volumeattachment
# 4. Node에서 마운트 포인트 확인
kubectl debug node/<node-name> -it --image=busybox
# Container 내에서:
# mount | grep elasticsearch
# df -h | grep elasticsearch
# 5. Storage Class 확인
kubectl get storageclass -o yaml
# 6. PV 상태 확인
kubectl get pv | grep elasticsearch
kubectl describe pv <pv-name>
일반적인 CSI 관련 에러 패턴
1. fsGroup 권한 문제
# 에러 메시지
MountVolume.SetUp failed: rpc error: code = Internal desc = failed to apply fsGroup
# 해결: SecurityContext 조정
securityContext:
fsGroup: 1000
runAsUser: 1000
2. Volume Mount 타임아웃
# 에러 메시지
Unable to attach or mount volumes: timed out waiting for the condition
# 해결: CSI Driver 재시작 또는 Node 재부팅
kubectl rollout restart daemonset/<csi-driver> -n kube-system
3. Storage Backend 연결 실패
# 에러 메시지
rpc error: code = DeadlineExceeded desc = context deadline exceeded
# 해결: 스토리지 백엔드 네트워크 확인
# NetApp ONTAP 예시:
ping <storage-management-ip>
telnet <storage-data-lif> 2049 # NFS
댓글남기기