본문 바로가기
공부/Kubernetes

[ingress-nginx] restart 시 downtime 해결 - minReadySeconds

by haejang 2023. 11. 29.
728x90
728x90

 

 

#  요약

NLB 에서 IP Type의 Target이 정상적으로 Register되는데 3분 이상이 걸리는 이슈가 있다.

-> deployment restart로 신규 파드가 정상적으로 뜨더라도, NLB에서 3분동안은 바라볼 수 없음

-> 그 사이에 기존 파드들이 죽기 시작하면 순단이 생김

-> minReadySeconds를 적절한 시간으로 조정하여 해결

 

 

# 현재 구조

EKS Cluster 안에서 ingress-nginx 를 사용중이며, Service Annotation을 통해 (정확히는 aws-loadbalancer-controller를 통해) AWS NLB가 생성되어 매핑되어 있다.

이 때, NLB 의 Target으로 ingress-nginx controller pod들의 ip가 등록되어 있음

 

# restart를 하는 이유

node group을 업데이트함

-> 기존 node group을 cordon 시킨채로 deployment restart를 해 ingress-nginx controller pod들의 안전한 재배치를 해주려고 함

 

# 문제 현상 (AS-IS / downtime 발생)

ingress-nginx deployment의 배포 전략은 k8s 기본값을 따라간다.

- RollingUpdate 사용

- strategy는 둘 다 25%

pod는 2개를 사용하므로, restart 발생 시 기존 파드들을 A, 신규 파드들을 B라고 한다면

1. B-1 생성 시작

2. B-1 생성 완료 (RUNNING 상태 진입)

3. B-2 생성 시작 & A-1 삭제 시작

4. B-2 생성 완료

5. A-2 삭제 시작

순으로 진행된다.

-> 그러나 5번 순서에서 자꾸 순단이 생겼다. (503 에러 발생)

 

# 원인 고민

1. Graceful Shutdown이 안되는걸까?

아니다. ingress-nginx는 내부적으로 graceful shutdown을 지원한다.

default 동작으로 pod terminate 시 wait-shutdown 명령 실행됨

 

2. Terminating 상태의 기존 Pod(A)로 트래픽을 보내는걸까?

아니다. Pod가 Terminate되기 시작함과 동시에 NLB에서 Target Deregister가 진행된다. (Draining 상태 진입)

 

# 정답

 

순단이 생길 때 NLB의 Target Group을 관찰해보니,

신규 Pod들이 아직 Initial중인데 기존 Pod들이 Draining되기 시작한다.

즉, 신규 Pod들이 정상적으로 RUNNING중임과는 별개로 LB의 Target으로 등록되는데에 시간이 더 걸림

-> 그 사이에 기존 Pod들이 죽기 시작하면 순단 발생

따라서 마지막 남은 A-2 Pod가 Terminate되기 시작할 때 (NLB Target Group에서 Draining될 때) NLB 입장에서는 멀쩡한 Target이 없으므로 트래픽이 길을 잃게 됨.

 

# 그럼 도대체 왜 이렇게 오래 걸리냐?

진짜 왜냐? 이해가 가지 않는다.

https://github.com/kubernetes-sigs/aws-load-balancer-controller/issues/1834

 

NLB IP Target registration is extremely slow · Issue #1834 · kubernetes-sigs/aws-load-balancer-controller

I've configured an NLB with IP targets to point to an instance of Traefik 2 and noticed that when I have pod readiness gates enabled, it might take upwards of 5 minutes for a single target to regis...

github.com

 

요런 이슈도 있는걸 보면, NLB에서 IP Type의 Target을 등록할 때 3-5분 걸리는게 이전부터 있는 이슈였나보다.

(나도 정확하게 재보진 않았지만 3분정도 걸린 것 같다)

 

# 아무튼 그래서 제로 다운타임을 위해서..

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#min-ready-seconds

 

Deployments

A Deployment manages a set of Pods to run an application workload, usually one that doesn't maintain state.

kubernetes.io

 

minReadySeconds에는 새로 생성된 pod가 사용 가능하다고 판단하는 시간을 지정할 수 있다. -> 120으로 설정했다.

120이라고 설정하면, pod가 최소 2대이므로 최대 4분(240초)의 시간을 확보할 수 있으므로 3분정도 걸리는 target register 시간을 커버할 수 있다고 생각했다.

-> 이는 정확했지만 아무래도 안정성이 최우선인 prod 환경에서는 240-300 정도로 늘릴 생각까지도 하고 있다.

다만 마구잡이로 늘리는건 또 부담스러운게, 트래픽이 갑자기 많아져서 autoscaling이 되어야 할 때에도 느리게 등록될 테니까 그렇다.

뭐가 되었든, minReadySeconds 를 120 이상으로 설정한 이후로는 restart를 해도 순단이 없는 것을 확인했다.

 

restart 하는 도중 부하테스트. 전부 200이 떨어진다.

 

이 문제로 생각보다 많이 고통받았었어서... 다른 사람들은 고통받지 않길 바라며...

 

그리고 아직 이해가 안가는 부분들이 있어서...

더 근본적인 문제 해결법을 아시는 분이나 NLB에서 IP Target을 더 빨리 등록시키는 법 등을 아시는 분은 댓글 달아주시면 감사하겠습니다.

 

 

끝!

 

 

 

728x90
728x90

댓글