tech/k8s

[k8s] 무중단 배포를 위한 설정들

daniel_lab 2024. 1. 2. 23:12

deployment 를 통한 배포시 타이밍적으로 "API 요청을 받을 수 없는 상태의 pod에 API 요청이 가는" 상황이 일시적으로 발생하는것으로 확인되었다.

원인은 "서비스에서 pod를 제외한 후 pod를 terminating 시키는 것이 아니라, pod를 죽인 후 service에서 제외시키는" 것 때문이다.

이 문제를 k8s의 의도한 바를 토대로 해결하기 위해서는, 어플리케이션에서 graceful shutdown 구현이 필요하다. 사실 정확하게는 graceful shutdown 을 구현한다해도 무조건적으로 service가 어플리케이션 트래픽을 끊는 시간보다 늦게 종료처리될것이라는 보장을 어떻게 하는지에 대해선 정확한 이해를 하지 못했다.

쉽게 해결하는 방법은 pod 를 terminating 시키는 시간을 임의적으로 미루는 것이다. 이렇게하면 pod 를 죽이는 시간이 뒤로 미뤄지기 때문에 service에서 제외하는 타이밍이 상대적으로 빨라져서 문제가 해결된다.

kubernetes에서는 pod 라이프사이클중에 hook을 설정할 수 있고 이 기능을 이용해 위 내용을 구현하는 것이 가능하다. pod가 종료되기 직전 실행되는 prestop hook을 이용하면 된다. prestop 훅은 pod에 SIGTERM을 보내기 전에 실행되기 때문에 prestop을 이용하여 앱과 별개로 graceful shutdown의 효과를 내는 것이다. Prestop 훅의 실행이 완료되기 전까지는 컨테이너에 SIGTERM을 보내지 않기 때문에 앱의 구현과는 별개로 종료되기 전에 대기시간을 주는 것이 가능하게된다. 하지만 이렇게 prestop 훅으로 대기시간을 주더라도 terminationGracePeriodSeconds 시간을 초과한다면 프로세스 종료가 일어날 수 있어 이 시간을 prestop 훅의 대기시간보다 길게 주도록 한다.

결과적으로 preStop 을 통해 pod의 deletion 타이밍을 40초 정도 늦추고,
terminationGracePeriodSeconds 를 60으로 설정하여(기본30) 60초 후에 강제 종료가 발생하도록 설정한 후에야 배포시 일시적인 트래픽처리불능상태가 해결 되었다.

    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: ~~~
          lifecycle:
            preStop:
              exec:
                command:
                  - /bin/sh
                  - -c
                  - sleep 40

참고

Graceful Shutdown을 위한 preStop, terminationGracePeriodSeconds 설정
https://jenakim47.tistory.com/80

kubernetes를 이용한 서비스 무중단 배포
https://tech.kakao.com/2018/12/24/kubernetes-deploy/

Kubernetes 환경 서비스 무중단 배포
https://halfmoon95.tistory.com/entry/Kubernetes-%ED%99%98%EA%B2%BD-%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EB%B0%B0%ED%8F%AC