Untitled

Helm 과 K8s 를 함께 사용하며 겪었던 Issue 를 정리한 글입니다.

Helm 이란

Helm 은 Kubernetes 사용을 좀 더 용이하게 도와주는 Package Manager 이다.

Kubernetes Cluster 를 이루고 있는 다양한 Object 들은 각각의 YAML 파일들로 작성되고 관리되는데, Cluster 의 규모가 커질 수록 관리해야하는 파일들의 수가 늘어날 수 밖에 없다.

이 때, Helm 은 Template 이라는 기능을 통해 변동성이 높은 값들을 변수로 작성할 수 있게 해주고 values.yaml 파일에서 해당 값들만 따로 관리할 수 있게 도와준다. Helm 은 Template 상의 변수들에 각각 대응하는 값들을 할당해 각각의 K8s Object 설정 템플릿들을 동적으로 YAML 파일로 변환해준다. (문서 참조)

그리고 생성된 YAML 파일들의 번들을 Chart 라고 부르며, 해당 Chart 들을 Cloud Repository 에 push 하고 download 할 수 있다.

Issue 설명

NodeJS App 의 Docker image 를 K8s cluster 에 띄우는 것엔 특별한 문제가 없었다.

그런데, helm install mynode ./ 로 Helm Chart 를 생성하고 K8s Deployment 를 생성했더니 아래와 같은 현상이 나타났다.

Untitled 1

Pod 들이 Running 중이지만, READY 상태가 아니라고 표시되고 있다.

Untitled 2

Pod 을 describe 해보니 LivenessReadiness 를 체크하는 connection 이 refuse 된다고 한다.

이때부터 끝을 알 수 없는 삽질을 시작하게 되었다.

Helm 없이 K8s cluster 에 띄워보고 Docker image 도 새로 빌드해보고.. Helm 만 없으면 너무 잘 동작한다…

minikube service { service name } --url 명령어로 해당 NodePort Service 에 접속할 수 있는 tunnel 과 url 을 생성해 접속해도 404 에러가 반환되었다.

Pod 이 READY 상태가 아니라는 것은 Pod 내부에 하나 이상의 container 가 아직 traffic 을 accept 할 수 없는 상태라는 뜻이다 (글 가장 아래에 설명). 즉, Service 를 설정해두어도 연결이 불가능하다.

Issue 해결하기

비교 Test 를 위해 values.yaml 파일의 Docker image 를 mynode image 가 아닌 nginx:latest 로 변경해보았다.

Untitled 3

Untitled 4

문제 없이 Pod 들이 Ready 상태로 잘 표시된다. 마찬가지로, mynode image 또한 Helm 없이 Local 에서 K8s cluster 에 띄우면 이와 같이 Pod 들이 정상적으로 READY 표시가 된다.

즉, nginxmynode 이미지가 livenessreadiness 체크에 응답하는 방식에 차이가 있는 것 같다.


그 후, ‘K8s 에서 App 의 Health Check’ 와 관련된 새로운 문서 를 찾게 되었고 이를 통해 app 내에 직접 livenessreadiness 체크에 대한 올바른 응답을 주도록 만들 수 있다는 것을 알게 되었다.

해당 문서를 따라 health-connect 이라는 package (nodejs 용 open source package) 를 사용했고, README 를 따라 이런 식으로 liveness 와 readiness check 를 각각 원하는 url 에서 응답하는 코드를 추가해줬다.

Untitled 5

마찬가지로, Helm 의 template 인 deployment.yaml 에도 livenessProbereadinessProbe 의 정보를 명확히 넣어준다. (port 는 containerPort 와 동일하게)

Untitled 6

K8s 문서 에 따르면, initialDelaySeconds 는 첫번째 probe (확인)을 시도하기까지 delay (초 단위) 를 설정해주는 field 라고 한다. stackoverflow 글을 참고해서 5초로 설정해주었다. (values.yaml 에 설정)

Untitled 7


이제 다시 helm install 을 실행해 Chart 를 생성하고 K8s cluster 에 deployment 를 띄워본다.

Untitled 8

성공!!! 🤩


minikube service { service name } --url 명령어로 해당 NodePort Service 에 접속할 수 있는 tunnel 과 url 을 생성해보자.

Untitled 9

잘 동작한다. :)

새롭게 알게된 것들

Helm 에서만 해당 이슈가 발생하던 이유 : 나중에 비교를 해보니, Helm 에서 기본으로 제공하는 deployment.yaml Template 과 내가 직접 만들어 사용하던 deployment.yaml 파일에 차이가 있었다.바로 livenessProbe 과 readinessProbe 설정의 유무인데, 이 probe 를 원하지 않는다면 해당 설정을 제거하면 되고, 그럼 probe 기능 없이 (위의 이슈도 없이) Pod 을 띄워 사용할 수 있다.

이 부분,

Untitled 10


문서에서 livenessProbe 와 readinessProbe 에 대해 읽어보았다.

  • livenessProbe : K8s Node 의 Agent 인 kubelet 은 container 들이 설정된 대로 잘 동작하도록 관리하는데, livenessProbe 을 통해 container 를 언제 restart 할 것인지 결정한다고 한다.예를 들어, app 이 여전히 실행중이지만 더 이상 진행될 수 없는 deadlock 이 발생한 경우에도 livenessProbe 를 통해 탐지하고 container 를 restart 할 수 있다고 한다. 이를 통해, container 에 bug 가 발생해도 restart 통해 다시 사용 가능 상태로 돌릴 수 있다.

  • readinessProbe : kubelet 은 readinessProbe 을 통해 container 의 ready 상태를 확인한다고 한다. container 의 ready 상태란 when a container is ready to start accepting traffic 이고 Pod 의 ready 상태란 모든 container 들이 ready 상태일 때를 의미한다.