1. 개요
Kafka 컨슈머를 Amazon EKS 환경에서 운영할 때, Pod가 생성 및 삭제되면서 중복 소비, 메시지 누락, Rebalance 지연 등의 문제가 발생할 수 있습니다. 이 글에서는 Kafka 컨슈머의 동작 방식과 안정적인 운영 방법을 정리합니다.
2. Kafka 컨슈머와 EKS의 배포 방식
EKS에서는 Rolling Update 방식으로 새로운 버전의 Pod를 배포하면 기존 Pod가 바로 종료되지 않고 새로운 Pod가 추가됩니다.
기본 동작 흐름
- Pod 1 (
20250101
)이 컨슈머 그룹을 구성하여 메시지를 처리 중 - 새로운 Pod 2 (
20250102
)가 배포됨 (기존 Pod는 아직 종료되지 않음) - Kafka는 새로운 컨슈머를 감지하고 Rebalance 진행
- 두 개의 Pod(
20250101
,20250102
)이 동시에 메시지를 소비할 가능성이 있음
이러한 상황을 적절히 해결하지 않으면 중복 처리 또는 이전 버전의 컨슈머가 메시지를 소비하는 문제가 발생할 수 있습니다.
3. 중복 소비 및 메시지 누락 방지 방법
모든 컨슈머가 동일한 group.id
를 사용
Kafka에서는 동일한 group.id
를 사용하는 컨슈머들은 메시지를 나누어 가져갑니다.
해결 방법:
spring:
kafka:
consumer:
group-id: my-consumer-group
문제점: 새로운 컨슈머가 추가되면 Rebalance가 발생하여 기존 컨슈머가 처리 중이던 메시지가 중단될 수도 있음.
group.instance.id
를 사용하여 컨슈머 고정
Kafka는 기본적으로 컨슈머가 그룹에 추가될 때마다 Rebalance를 수행합니다. 하지만 group.instance.id
를 설정하면 특정 컨슈머를 고정적으로 유지할 수 있습니다.
해결 방법:
spring:
kafka:
consumer:
group-id: my-consumer-group
properties:
group.instance.id: ${HOSTNAME}
문제점: 기존 Pod(
20250101
)이 강제 종료되지 않으면 신규 Pod(20250102
)가 메시지를 가져갈 수 없음.
4. 컨슈머가 갑자기 죽었을 때(Rebalance 지연 문제)
문제: 기존 컨슈머(20250101
)가 정상적으로 종료되지 않으면 새로운 컨슈머(20250101-1
)가 메시지를 가져가지 못함
Kafka는 group.instance.id
를 기억하기 때문에, 기존 컨슈머가 강제로 종료되면 새로운 컨슈머가 메시지를 가져갈 수 없는 상태가 발생합니다.
해결 방법:
session.timeout.ms
값을 낮춰서 컨슈머 제거 속도 높이기
spring:
kafka:
consumer:
properties:
session.timeout.ms: 10000 # 10초 내 응답 없으면 컨슈머 제거
이렇게 하면 컨슈머가 갑자기 죽어도 10초 내에 새로운 컨슈머가 메시지를 가져갈 수 있음.
group.instance.id
사용하지 않기 (일반적인 컨슈머 그룹 유지)
해결 방법:
spring:
kafka:
consumer:
group-id: my-consumer-group
auto-offset-reset: earliest
이렇게 하면 Pod가 죽으면 새로운 Pod가 자동으로 메시지를 가져감. 단, Rebalance가 빈번하게 발생할 수 있음.
Kubernetes 헬스 체크(livenessProbe) 추가하여 비정상 Pod 자동 제거
해결 방법 (
deployment.yaml
):
livenessProbe:
exec:
command:
- sh
- -c
- "pgrep java || exit 1"
initialDelaySeconds: 10
periodSeconds: 5
비정상적인 컨슈머를 Kubernetes가 감지하여 자동으로 제거하도록 설정.
5. 결론
문제 | 해결 방법 |
---|---|
중복 소비 문제 | 동일한 group.id 사용하여 컨슈머 간 메시지 분배 |
이전 컨슈머가 메시지를 계속 가져가는 문제 | group.instance.id 활용하여 컨슈머 고정 |
기존 컨슈머가 죽었을 때 새로운 컨슈머가 메시지를 가져가지 못하는 문제 | session.timeout.ms 조정하여 빠르게 제거 |
컨슈머가 비정상적으로 멈출 경우 | Kubernetes livenessProbe 설정 |
Kafka 컨슈머를 EKS에서 안정적으로 운영하려면, group.instance.id
를 활용하면서도 빠른 컨슈머 제거가 가능하도록 session.timeout.ms
를 조정하는 것이 중요합니다. 또한, Kubernetes 헬스 체크를 활용하면 컨슈머 장애 시 자동으로 복구할 수 있습니다.
이 글이 Kafka 컨슈머 운영에 도움이 되길 바랍니다!