[Kubernetes] Cluster Upgrade


서론

Kubernetes는 최근 3개의 버전만을 공식 지원하기 때문에, 정기적인 업그레이드가 필요하다.

예를 들어 최신 버전이 1.13일 경우, 지원 대상은 1.13, 1.12, 1.11이며 1.10은 지원되지 않는다.

따라서 최신 버전(1.13)이 release되기 전에 1.10을 사용하고 있다면 1.11로 업그레이드를 해주는 것이 좋다.

만약 최신버전이 1.13이고 현재 버전이 1.10일 때 1.13버전으로 업그레이드를 해주고 싶은 경우

1.10 에서 1.13으로 한번에 가는 것이 아니라 1.10 → 1.11 → 1.12 → 1.13 으로 한 버전씩 업그레이드 해야 한다.

이렇게 정기적으로 업그레이드를 해줘야하는데 쿠버네티스 각 컴포넌트들의 버전 체계에 대해 알아보자.

본론

Version 체계

Kubernetes는 제어 플레인 컴포넌트들(Kube-apiserver, controller manager, kube-scheduler, kubelet, kube-proxy등)로 구성되어 있으며 이들은 서로 다른 버전을 가질 수 있다.

다른 제어 플레인 컴포넌트들이 kube-apiserve에 의존하므로 가장 높은 버전이 될 수 없다.

따라서 controller-manager와 scheduler는 kube-apiserver보다 한 버전 낮을 수 있고, kubelet과 kube-proxy는 두 버전 낮을 수 있다.

kubectl은 유연하게 동작하여 kube-apiserver보다 높거나 낮은 버전 모두 허용된다.

  • kubectl은 클라이언트 툴(Command Line Interface)로 사용자가 Kubernetes 클러스터에 명령을 내리는 도구이다.

Mannual Update(수동 업데이트)

클라우드의 경우 Google Kubernetes Engine(GKE)은 몇 번의 클릭만으로 클러스터 업그레이드를 쉽게 수행할 수 있으나 kubeadm과 같은 도구를 사용해 클러스터를 구성했다면, 각 컴포넌트를 직접 수동으로 업그레이드해야 한다.

클러스터 업그레이드는 마스터 노드를 먼저 업데이트하고 그 다음 워커 노드를 업데이트 한다.

마스터 노드 업데이트

마스터노드의 API 서버, 스케줄러, 컨트롤러 매니저 같은 제어 플레인 컴포넌트들이 잠시 중단되었어도 워커 노드에 배포된 모든 워크로드(Pod)가 도중에 죽지만 않는다면 정상적으로 사용자에게 서비스를 계속 제공한다.

하지만 마스터가 중단되어 있기 때문에, 클러스터 관리 기능은 모두 사용할 수 없다.

  • kubectl이나 다른 Kubernetes API로 클러스터에 접근 불가
  • 새 애플리케이션을 배포하거나 기존 애플리케이션을 삭제/수정 불가
  • Pod가 죽어도, 새 Pod가 자동으로 생성되지 않습니다.(Controller manager가 동작하지 않기 때문)

워커 노드 업데이트

워커 노드 업데이트에는 3가지 전략이 존재한다.

  1. 모든 워커 노드를 한 번에 업그레이드

이 경우 Pod들이 중단되고, 사용자들이 애플리케이션에 접근할 수 없게 된고 업그레이드가 완료되면 노드가 다시 올라오고, 새 Pod들이 스케줄되며 사용자 접근이 다시 가능해진다.

  1. 노드를 하나씩 순차적으로 업그레이드

먼저 첫 번째 노드를 업그레이드하면, 그 노드의 워크로드(Pod)들은 두 번째와 세 번째 노드로 옮겨지고, 사용자들은 그곳에서 서비스를 받는다.

첫 번째 노드가 업그레이드되어 다시 작동하면, 두 번째 노드를 업그레이드를 시작한다.

이번에는 워크로드가 첫 번째와 세 번째 노드로 이동한다.

마지막으로 세 번째 노드를 업그레이드할 때는, 워크로드가 첫 번째와 두 번째 노드에 분산된다.

이 과정을 통해 모든 노드를 새로운 버전으로 업그레이드하게 된다.

  1. 새로운 버전의 노드를 클러스터에 추가한다.

이 방법은 클라우드 환경처럼 새로운 노드를 쉽게 프로비저닝하고, 기존 노드를 제거할 수 있는 환경에서 특히 편리하다.

새로운 소프트웨어 버전을 가진 노드를 클러스터에 추가하고, 워크로드(Pod)를 새 노드로 옮긴 후, 기존 노드를 제거한다.

결국에는 모든 노드가 새로운 소프트웨어 버전을 갖도록 교체하는 방식이다.

Kubeadm을 통한 업그레이드

kubeadm에는 클러스터 업그레이드를 도와주는 upgrade 명령어가 있다.

kubeadm upgrade plan 명령어를 통해 현재 클러스터 버전, kubeadm 도구 버전, 현재 Kubernetes의 최신 안정 버전 등 업그레이드 관련 다양한 정보를 볼 수 있다.

kubeadm은 kubelet을 설치하거나 업그레이드하지 않기 때문에 각 노드의 kubelet버전은 수동으로 업그레이드해야 한다.

주의할점은 클러스터를 업그레이드하기 전에 kubeadm 자체도 업그레이드해야 한다.

kubeadm 도구 역시 Kubernetes와 동일한 버전 정책을 따른다.

만약 쿠버네티스를 1.11버전에서 1.12로 올리고싶다면 kubeadm도 1.12로 업데이트해줘야 한다는 뜻이다.

순서는 마스터노드를 먼저 업데이트 후 워커노드를 업데이트 하는 순임으로 마스터노드를 먼저 업데이트 해보자.

Master Node Upgrade

kubeadm upgrade apply v1.12.0 명령어를 입력하면 마스토 노드의 컨트롤 플레인 컴포넌트들이 업데이트 된다.

kubectl get nodes를 하면 Version이 뜨는걸 볼 수 있는데, 이것은 각 노드에 설치된 kubelet 버전을 표시하는 것으로 API 서버 자체의 버전은 보여주지 않는다.(kubelet은 클러스터를 업데이트해도 업데이트 되지 않기 때문에 수동으로 업데이트 시켜줘야함)

클러스터 업데이트 후 마스터노드에서 kubelet을 수동으로 업데이트 해주면 아래처럼 나타난다.

Worker Node Upgrade

이제 워커노드의 kubelet을 업데이트 해면 끝난다.

이를 위해서는 업데이트할 워커노드의 워크로드(Pod)를 다른 노드로 옮겨야한다.

kubectl drain 명령어를 사용하면 해당 노드의 모든 Pod를 안전하게 종료하고, 다른 노드로 재스케줄할 수 있다. 또한 이 명령어를 사용하면 노드를 자동으로 cordon 처리하여 새로운 Pod가 스케줄되지 않도록 한다.

kubectl drain {node_name}

그 다음, 마스터 노드에서와 마찬가지로 워커 노드의 kubeadm과 kubelet 패키지를 업그레이드한다.

apt-get upgrade -y kubeadm=1.12.0-00
apt-get upgrade -y kubelet=1.12.0-00

마스터노드에서는 kubeadm upgrade apply 명령어를 통해 아래 명령어 작업을 포함하므로 별도로 실행할 필요가 없지만 워커노드를 업데이트할 때는 해줘야 한다.

kubeadm upgrade node config --kubelet-version

그리고 kubelet을 재시작해준다.

systemctl restart kubelet

이후 업데이트가 끝나면 Drain 명령어로 Cordon 처리가된 노드를 uncordon해준다.

kubectl uncordon {node_name}