EKS 환경에서 Pod 장애 발생 시 요청을 이어받아 처리하는 방법

1. 개요

EKS 환경에서 Spring Boot 애플리케이션이 여러 개의 Pod에서 실행되고 있을 때,
특정 Pod가 요청을 처리하는 중 장애로 종료되면, 다른 Pod에서 동일 요청을 이어서 처리할 수 있는가?

이 문서에서는 일반적인 CRUD 요청과 파일 업로드 요청 모두에 대해
Pod 장애 발생 시에도 중단 없이 이어서 처리할 수 있는 방법을 설명합니다.


2. 첫 질문: Pod가 죽었을 때 요청이 이어서 처리될 수 있는가?

EKS 환경에서 Spring Boot 3.1.6 기반의 애플리케이션이 3개의 Pod에서 실행 중이며,
사용자의 요청이 Pod 1로 전달되어 처리 중인 상태에서 Pod 1이 종료되면,
Pod 2 또는 Pod 3에서 동일한 요청을 이어서 처리할 수 있는 방법이 있는가?

✅ 해결해야 할 문제

  1. CRUD 요청 처리 중 Pod 장애가 발생하면 트랜잭션이 어떻게 되는가?
  2. 파일 업로드 요청 중 Pod 장애가 발생하면 업로드된 데이터가 유실되지 않는가?
  3. Pod 장애 시에도 사용자 경험이 끊기지 않도록 요청을 복구할 수 있는가?
  4. 로드 밸런서가 장애 감지 후 자동으로 요청을 다른 Pod로 라우팅할 수 있는가?

3. 해결 방법

EKS 환경에서 Pod 장애 시에도 요청을 이어서 처리하려면,
아래 3가지 핵심 기술을 조합해서 구현해야 합니다.

✅ 1. 로드 밸런서(LB) + Connection Draining 설정

Pod 장애 시에도 기존 연결이 끊기지 않고 새로운 Pod로 자동 라우팅되도록 구성합니다.

  • AWS ALB, NLB를 사용하여 서버 장애 시에도 자동으로 요청을 재전송
  • Connection Draining을 활성화하여 장애 발생 시에도 기존 연결을 유지하도록 설정

📌 AWS LoadBalancer 설정 (Connection Draining 활성화)

apiVersion: v1
kind: Service
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-connection-draining-timeout: "60"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: my-app

✅ 효과

  • 특정 Pod가 죽더라도 기존 연결을 유지한 채 다른 Pod로 트래픽이 이동
  • aws-load-balancer-connection-draining-timeout 설정을 통해 일정 시간이 지나면 안전하게 연결 종료 가능

✅ 2. 일반적인 CRUD 요청 처리 중 장애 발생 시 복구 방법

일반적인 API 요청이 진행 중일 때, 트랜잭션이 완료되지 않은 상태에서 Pod가 죽으면 데이터 정합성이 깨질 수 있습니다. 이를 방지하려면:

1️⃣ 트랜잭션 관리 (Spring + DB)

  • 트랜잭션 로그를 Redis 또는 DB에 기록하여 중단된 요청을 감지
  • Pod가 죽더라도 트랜잭션이 롤백되도록 보장하여 데이터 정합성 유지
  • Kafka나 SQS 같은 비동기 메시지 큐를 활용하여 요청을 안전하게 처리

📌 Spring @Transactional 활용 예제

@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;

@Transactional
public void createOrder(Order order) {
orderRepository.save(order);
// Pod가 장애 발생 시, 트랜잭션이 롤백되어 데이터 정합성 유지
}
}

✅ 효과

  • Pod 장애 발생 시 자동 롤백으로 데이터 정합성 보장
  • 다른 Pod에서 동일 요청을 다시 처리 가능

2️⃣ Redis에 진행 상태 저장하여 요청 이어받기

CRUD 요청이 긴 시간이 걸리는 작업일 경우, 현재 요청의 상태를 Redis 또는 DB에 저장하여
Pod 장애 발생 후에도 다른 Pod에서 이어서 처리할 수 있도록 합니다.

📌 진행 상태 저장 및 복구 예제

@Autowired
private StringRedisTemplate redisTemplate;

public void saveRequestState(String requestId, String state) {
redisTemplate.opsForValue().set("request-state:" + requestId, state);
}

public String getRequestState(String requestId) {
return redisTemplate.opsForValue().get("request-state:" + requestId);
}

✅ 효과

  • Pod 장애 발생 후에도 요청 상태를 유지할 수 있음
  • 다른 Pod에서 요청을 이어서 처리 가능

✅ 3. 파일 업로드 중단 방지 (Resumable Upload)

파일 업로드 요청이 진행 중일 때 Pod 장애가 발생하면 기존 업로드된 파일을 유지하면서 이어서 업로드해야 합니다.

📌 파일 업로드 진행 상태를 Redis에 저장

@Autowired
private StringRedisTemplate redisTemplate;

public void saveUploadProgress(String fileName, long uploadedBytes) {
redisTemplate.opsForValue().set("upload-progress:" + fileName, String.valueOf(uploadedBytes));
}

public long getUploadProgress(String fileName) {
String value = redisTemplate.opsForValue().get("upload-progress:" + fileName);
return (value != null) ? Long.parseLong(value) : 0;
}

📌 파일 업로드 API (조각 단위로 저장)

@PostMapping("/upload")
public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam("fileName") String fileName,
@RequestParam("offset") long offset) {
try {
File targetFile = new File("/uploads/" + fileName);

// 기존 업로드된 부분 이후부터 이어서 저장
try (RandomAccessFile raf = new RandomAccessFile(targetFile, "rw")) {
raf.seek(offset);
raf.write(file.getBytes());
}

// 진행 상태 Redis 저장
long uploadedBytes = offset + file.getSize();
saveUploadProgress(fileName, uploadedBytes);

return ResponseEntity.ok(Map.of("uploadedBytes", uploadedBytes));
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("파일 저장 실패");
}
}

✅ 효과

  • Pod 장애 발생 시에도 업로드된 파일을 유지하면서 중단된 부분 이후부터 이어서 업로드 가능
  • AWS S3 Multipart Upload API를 활용하면 더욱 안정적인 방식으로 구현 가능

5. 결론

📌 Pod 장애 발생 시에도 CRUD 요청과 파일 업로드 요청을 안전하게 이어서 처리할 수 있도록 보장
📌 로드 밸런서 + Connection Draining을 활용하여 장애 감지 후 자동으로 요청을 다른 Pod로 전송
📌 CRUD 요청의 진행 상태를 Redis 또는 DB에 저장하여 장애 발생 후에도 복구 가능
📌 파일 업로드 요청은 중단된 부분 이후부터 이어서 업로드할 수 있도록 구현
📌 Kafka나 SQS 같은 메시지 큐를 활용하면 더욱 강력한 장애 대응이 가능

✅ 이 방법을 적용하면 IDC 환경에서 VIP를 사용하던 방식과 유사하게, Kubernetes 기반 클라우드 환경에서도 안정적인 요청 처리 및 장애 복구가 가능하도록 보장됩니다! 🚀

관련 글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다