[kubernetes] kubeadm 에서 클러스터 버전 업그레이드 예제

728x90

버전 차이(skew) 정책

공식 문서: https://kubernetes.io/ko/releases/version-skew-policy/

kubelet 을 제외하고 쿠버네티스 모든 구성 요소들은 컨테이너로 구성되어 있고 버전을 업그레이드 할 때 이미지를 교체하는 것이기 때문에 모든 컨테이너를 종료하고 교체한 이미지로 컨테이너를 띄우기 때문에 쿠버네티스에 다운 타임이 발생한다.

그러면 무중단 시스템을 위해 버전을 업그레이드하기 위해서는 어떻게 해야하는지가 이 문서에 나와 있다.

지원되는 버전

쿠버네티스 버전은 x.y.z 로 표현되는데, 여기서 x 는 메이저 버전, y 는 마이너 버전, z 는 패치 버전을 의미

쿠버네티스 프로젝트는 최근 세 개의 마이너 릴리스 (1.24, 1.23, 1.22) 에 대한 릴리스 분기를 유지한다. 쿠버네티스 1.19 이상은 약 1년간의 패치 지원을 받는다. 쿠버네티스 1.18 이상은 약 9개월의 패치 지원을 받는다.

지원되는 버전 차이

고가용성 클러스터에서 마스터 api-server 버전이 다를 경우 각각의 api-server 는 통신할 수 없다. 만약 최신 api-server 버전이 1.24 일 경우 1.23, 1.22 를 지원한다.

예:

  • 최신 kube-apiserver는 1.24 이다.
  • 다른 kube-apiserver 인스턴스는 1.24 및 1.23 을 지원한다.

kubelet은 kube-apiserver보다 최신일 수 없으며, 2단계의 낮은 마이너 버전까지 지원한다.

예:

  • kube-apiserver가 1.24 이다.
  • kubelet은 1.241.23 및 1.22 을 지원한다.

예:

  • kube-apiserver 인스턴스는 1.24 및 1.23 이다.(즉, 마스터가 2대)
  • kubelet은 1.23 및 1.22 을 지원한다(1.24 는 kube-apiserver의 1.23 인스턴스보다 최신 버전이기 때문에 지원하지 않는다).

kube-controller-manager, kube-scheduler 그리고 cloud-controller-manager 는 그들과 통신하는 kube-apiserver 인스턴스보다 최신 버전이면 안 된다. kube-apiserver 마이너 버전과 일치할 것으로 예상하지만, 최대 한 단계 낮은 마이너 버전까지는 허용한다(실시간 업그레이드를 지원하기 위해서).

  • kube-apiserver은 1.24 이다.
  • kube-controller-manager, kube-scheduler 그리고 cloud-controller-manager는 1.24 과 1.23 을 지원한다.

예:

  • kube-apiserver 인스턴스는 1.24 및 1.23 이다.(즉, 마스터가 2대)
  • kube-controller-manager, kube-scheduler 그리고 cloud-controller-manager는 모든 kube-apiserver 인스턴스로 라우팅하는 로드 밸런서와 통신한다.
  • kube-controller-manager, kube-scheduler 그리고 cloud-controller-manager는 1.23 에서 지원한다(1.24 는 kube-apiserver 인스턴스의 1.23 버전보다 최신이기 때문에 지원하지 않는다).

kubectl은 kube-apiserver의 한 단계 마이너 버전(이전 또는 최신) 내에서 지원한다.

예:

  • kube-apiserver은 1.24 이다.
  • kubectl은 1.251.24 및 1.23 을 지원한다.

kubectl 를 먼저 업그레이드하고 그 후에 api-server 업그레이드를 하거나 api-server 를 업그레이드하고 kubectl 를 업그레이드할 수 있기 때문이다.

k8s 클러스터 업그레이드 예제

아래 순서대로 업그레이드를 진행한다.

kube-apiserver 업그레이드

사전 요구 사항:

  • 단일 인스턴스 클러스터에서 기존 kube-apiserver 인스턴스는 1.23 이어야 한다.
  • HA 클러스터에서 모든 kube-apiserver 인스턴스는 1.23 또는 1.24 이어야 한다(이것은 kube-apiserver 인스턴스 간의 가장 최신과 오래된 버전의 차이를 최대 1개의 마이너 버전의 차이로 보장한다).
  • 이 서버와 통신하는 kube-controller-manager, kube-scheduler 그리고 cloud-controller-manager의 버전은 1.23 이어야 한다(이것은 기존 API서버 버전보다 최신 버전이 아니고 새로운 API서버 버전의 마이너 1개의 버전 내에 있음을 보장한다).
  • 모든 kubelet 인스턴스는 버전 1.23 또는 1.22 이어야 한다(이것은 기존 API서버 버전보다 최신 버전이 아니며, 새로운 API서버 버전의 2개의 마이너 버전 내에 있음을 보장한다).
  • 등록된 어드미션 웹훅은 새로운 kube-apiserver 인스턴스가 전송하는 데이터를 처리할 수 있다:

kube-apiserver를 1.24 으로 업그레이드

kube-controller-manager, kube-scheduler 그리고 cloud-controller-manager 업그레이드

사전 요구 사항:

  • kube-apiserver 인스턴스는 1.24 이여야 한다(HA 클러스터에서 kube-apiserver 인스턴스와 통신할 수 있는 구성 요소를 업그레이드 전에 모든 kube-apiserver 인스턴스는 업그레이드되어야 한다).

kube-controller-manager, kube-scheduler 및 cloud-controller-manager 를 1.24 으로 업그레이드한다.

kubelet 업그레이드

컨트롤 플레인에서 먼저 업그레이드를 하고 후에 워커 노드에서 kubelet 업그레이드를 한다.

kubelet → docker → container 이런 방식으로 kubelet 이 컨테이너를 제어한다.

그렇기 때문에 kubelet 을 업그레이드하면 컨테이너가 중지된다. 그래서 업그레이드를 하기 전에 컨테이너를 제거해야 한다. 이를 드레인이라

사전 요구 사항:

  • kubelet과 통신하는 kube-apiserver 인스턴스는 1.24 이어야 한다.

필요에 따라서 kubelet 인스턴스를 1.24 으로 업그레이드할 수 있다(또는 1.23 아니면 1.22 으로 유지할 수 있음).

kubelet → docker → container 이런 방식으로 kubelet 이 컨테이너를 제어한다.

그렇기 때문에 kubelet 을 업그레이드하면 컨테이너가 중지된다. 그래서 업그레이드를 하기 전에 컨테이너를 제거해야 한다. 컨테이너를 제거하는 작업을 드레인이라고 한다.

참고: kubelet 마이너 버전 업그레이드를 수행하기 전에, 해당 노드의 파드를 드레인(drain)해야 한다. 인플레이스(In-place) 마이너 버전 kubelet 업그레이드는 지원되지 않는다.

경고: 클러스터 안의 kubelet 인스턴스를 kube-apiserver의 버전보다 2단계 낮은 버전으로 실행하는 것을 권장하지 않는다: • kube-apiserver를 업그레이드한다면 한 단계 낮은 버전으로 업그레이드해야 한다. • 이것은 관리되고 있는 3단계의 마이너 버전보다 낮은 kubelet을 실행할 가능성을 높인다.

kube-proxy 업그레이드

  • kube-proxy는 반드시 kubelet과 동일한 마이너 버전이어야 한다.
  • kube-proxy는 반드시 kube-apiserver 보다 최신 버전이면 안 된다.
  • kube-proxy는 kube-apiserver 보다 2단계 낮은 마이너 버전 이내여야 한다.

예:

kube-proxy 버전이 1.22 인 경우:

  • kubelet 버전도 반드시 1.22 와 동일한 마이너 버전이어야 한다.
  • kube-apiserver 버전은 반드시 1.22 에서 1.24 사이 이어야 한다.

정리하자면 순서는 다음과 같다.

  1. kube-apiserver
  2. kube-controller-manager, kube-scheduler, cloud-controller-manager
  3. kubelet(Control Plane → Worker Node)
  4. kube-proxy(Control Plane → Worker Node)

Controle Plane(api → cm, ccm, sched → let, proxy) → Worker Node(let, proxy)

kubeadm 클러스터 업그레이드

공식 문서: https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/

추상적인 업그레이드 작업 절차는 다음과 같다.

  1. 기본 컨트롤 플레인 노드를 업그레이드한다.
  2. 추가 컨트롤 플레인 노드를 업그레이드한다.
  3. 워커(worker) 노드를 업그레이드한다.

업그레이드할 버전 결정

OS 패키지 관리자를 사용하여 쿠버네티스의 최신 패치 릴리스 버전(1.24)을 찾는다.

ubuntu, debian 또는 Hypriot OS

apt update
apt-cache madison kubeadm
# 목록에서 최신 버전(1.24)을 찾는다
# 1.24.x-00과 같아야 한다. 여기서 x는 최신 패치이다.

"kubeadm upgrade" 호출

첫 번째 컨트롤 플레인 노드의 경우

  • kubeadm 업그레이드
# 1.24.x-00에서 x를 최신 패치 버전으로 바꾼다.
apt-mark unhold kubeadm && \\
apt-get update && apt-get install -y kubeadm=1.24.x-00 && \\
apt-mark hold kubeadm
  • 다운로드하려는 버전이 잘 받아졌는지 확인한다.
  • kubeadm version
  • 업그레이드 계획을 확인한다.이 명령은 클러스터를 업그레이드할 수 있는지를 확인하고, 업그레이드할 수 있는 버전을 가져온다. 또한 컴포넌트 구성 버전 상태가 있는 표를 보여준다.
  • kubeadm upgrade plan
  • 업그레이드할 버전을 선택하고, 적절한 명령을 실행한다. 예를 들면 다음과 같다.명령이 완료되면 다음을 확인해야 한다.
  • [upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.24.x". Enjoy! [upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
  • *# 이 업그레이드를 위해 선택한 패치 버전으로 x를 바꾼다.* sudo kubeadm upgrade apply v1.24.x
  • CNI 제공자 플러그인을 수동으로 업그레이드한다.CNI 제공자가 데몬셋(DaemonSet)으로 실행되는 경우 추가 컨트롤 플레인 노드에는 이 단계가 필요하지 않다.
  • CNI(컨테이너 네트워크 인터페이스) 제공자는 자체 업그레이드 지침을 따를 수 있다. 애드온 페이지에서 사용하는 CNI 제공자를 찾고 추가 업그레이드 단계가 필요한지 여부를 확인한다.

다른 컨트롤 플레인 노드의 경우

첫 번째 컨트롤 플레인 노드와 동일하지만 다음을 사용한다.

sudo kubeadm upgrade node

아래 명령 대신 위의 명령을 사용한다.

sudo kubeadm upgrade apply

kubeadm upgrade plan 을 호출하고 CNI 공급자 플러그인을 업그레이드할 필요가 없다.

노드 드레인

  • Prepare the node for maintenance by marking it unschedulable and evicting the workloads:
# <node-to-drain>을 드레인하는 노드의 이름으로 바꾼다.
kubectl drain <node-to-drain> --ignore-daemonsets

kubelet과 kubectl 업그레이드

  • 모든 컨트롤 플레인 노드에서 kubelet 및 kubectl을 업그레이드한다.
# replace x in 1.24.x-00의 x를 최신 패치 버전으로 바꾼다
apt-mark unhold kubelet kubectl && \\
apt-get update && apt-get install -y kubelet=1.24.x-00 kubectl=1.24.x-00 && \\
apt-mark hold kubelet kubectl
  • kubelet을 다시 시작한다.
sudo systemctl daemon-reload
sudo systemctl restart kubelet

노드 uncordon

  • 노드를 스케줄 가능으로 표시하여 노드를 다시 온라인 상태로 전환한다.
*# <node-to-drain>을 드레인하는 노드의 이름으로 바꾼다.*
kubectl uncordon <node-to-drain>

워커 노드 업그레이드

워커 노드의 업그레이드 절차는 워크로드를 실행하는 데 필요한 최소 용량을 보장하면서, 한 번에 하나의 노드 또는 한 번에 몇 개의 노드로 실행해야 한다.

kubeadm 업그레이드

  • 모든 워커 노드에서 kubeadm을 업그레이드한다.
# 1.24.x-00의 x를 최신 패치 버전으로 바꾼다
apt-mark unhold kubeadm && \\
apt-get update && apt-get install -y kubeadm=1.24.x-00 && \\
apt-mark hold kubeadm

"kubeadm upgrade" 호출

  • 워커 노드의 경우 로컬 kubelet 구성을 업그레이드한다.
sudo kubeadm upgrade node

노드에 적용된 cordon 해제

  • 스케줄 가능(schedulable)으로 표시하여 노드를 다시 온라인 상태로 만든다.
# <node-to-drain>을 노드의 이름으로 바꾼다.
kubectl uncordon <node-to-drain>

클러스터 상태 확인

모든 노드에서 kubelet을 업그레이드한 후 kubectl이 클러스터에 접근할 수 있는 곳에서 다음의 명령을 실행하여 모든 노드를 다시 사용할 수 있는지 확인한다.

kubectl get nodes

모든 노드에 대해 STATUS 열에 Ready 가 표시되어야 하고, 버전 번호가 업데이트되어 있어야 한다.

정리

  1. Control Plane 의 kubeadm 업그레이드
  2. Control Plane 의 kubeadm 으로 api, cm, sched 업그레이드
  3. Control Plane 의 kubelet, kubectl 업그레이드
  4. Worker Node 의 kubeadm 업그레이드
  5. Worker Node 의 kubeadm 으로 업그레이드
  6. Worker Node 의 kubelet, kubectl 업그레이드

작동 원리

kubeadm upgrade apply 는 다음을 수행한다.

  • 클러스터가 업그레이드 가능한 상태인지 확인한다.
    • API 서버에 접근할 수 있다
    • 모든 노드가 Ready 상태에 있다
    • 컨트롤 플레인이 정상적으로 동작한다
  • 버전 차이(skew) 정책을 적용한다.
  • 컨트롤 플레인 이미지가 사용 가능한지 또는 머신으로 가져올 수 있는지 확인한다.
  • 컴포넌트 구성에 버전 업그레이드가 필요한 경우 대체 구성을 생성하거나 사용자가 제공한 것으로 덮어 쓰기한다.
  • 컨트롤 플레인 컴포넌트 또는 롤백 중 하나라도 나타나지 않으면 업그레이드한다.
  • 새로운 CoreDNS 와 kube-proxy 매니페스트를 적용하고 필요한 모든 RBAC 규칙이 생성되도록 한다.
  • API 서버의 새 인증서와 키 파일을 작성하고 180일 후에 만료될 경우 이전 파일을 백업한다.

kubeadm upgrade node 는 추가 컨트롤 플레인 노드에서 다음을 수행한다.

  • 클러스터에서 kubeadm ClusterConfiguration 을 가져온다.
  • 선택적으로 kube-apiserver 인증서를 백업한다.
  • 컨트롤 플레인 컴포넌트에 대한 정적 파드 매니페스트를 업그레이드한다.
  • 이 노드의 kubelet 구성을 업그레이드한다.

kubeadm upgrade node 는 워커 노드에서 다음을 수행한다.

  • 클러스터에서 kubeadm ClusterConfiguration 을 가져온다.
  • 이 노드의 kubelet 구성을 업그레이드한다.
728x90