1.7 Kubernetes 지원 버전 및 업그레이드
OKE 지원 버전
Kubernetes 지원 버전
Kubernetes 버전은 x.y.z로 표현되며, 각각 x는 메이저, y는 마이너, z는 패치 버전을 뜻하며, 오픈소스 Kubernetes도 현재 버전과 그 이전 2개 버전까지를 지원하고 있습니다. OKE 또한 OKE가 지원하는 최신버전 기준으로 그 이전 2개의 마이너 버전까지 지원하고 있습니다. 금일자 기준 지원하는 버전은 다음과 같습니다.
- 1.26.2
- 1.25.4
- 1.24.1
신규 버전 출시 후에 30일 동안만 그 이전 버전중 제일 낮은 버전을 지원하고 있습니다. 예를 들어 OKE에서 1.26.2 버전이 2023년 4월 26일에 출시되고 기존 버전인 1.23.4는 통상 30일 기준으로, 2023년 6월 1일까지만 지원합니다. 현재 지원 버전은 다음 링크를 참조합니다.
- OCI Documentation > Container Engine > Supported Versions of Kubernetes
버전 관리 단위
OKE 클러스터는 Control Plane과 Worker Node로 구성되며, Control Plane의 버전이 정해지면, Worker Node는 Control Plane과 같거나 그 이하 버전을 사용할 수 있습니다. 물론 호환되는 버전 안에서 사용할 수 있습니다.
Worker Node는 Node Pool 단위로 버전을 가질 수 있습니다. 여러 Node Pool을 만들어 각각 다른 버전을 가질 수 있습니다.
Node Pool 단위 버전 혼합
테스트를 위해 1.24.1, 1.25.4, 1.26.2 버전이 사용 가능한 상태에서 1.25.4 버전의 OKE 클러스터를 기준으로 테스트를 진행합니다.
- 테스트 환경
- OKE 클러스터 - oke-cluster-1 버전: 1.25.4
- Control Plane 버전: 1.25.4
- Node Pool - poo1 버전: 1.25.4
OKE 클러스터 상세화면으로 이동합니다.
왼쪽 아래 Resources > Node Pools 로 이동합니다.
현재 pool1이 1.25.4 버전이 있습니다. 추가 Node Pool 생성을 위해 Add Node Pool을 클릭합니다.
새 Node Pool 생성을 위한 정보를 입력합니다.
Name: 새 Node Pool 이름
Version: 일반 버전 혼합을 확인하기 위해 1.24.1 버전은 선택합니다.
- 사용 가능한 버전을 보면, 현재 OKE 클러스터 버전 이하만 선택 가능한 걸 알 수 있습니다.
- 대상 클러스터의 Control Plane의 상위 버전인 1.26.2 버전은 보이지 않습니다.
- 나머지 항목은 처음 생성시와 비슷하게 생성시 필요한 정보를 입력합니다. 다음은 예시입니다.
- Placement Configuration: Worker Node가 위치한 AD와 Node용 서브넷 지정
- Shape: VM.Standard.E3.Flex
- 제일 아래 Advanced Options:
- Add an SSH Key: Node에 SSH로 접근하기 위한 Publich Key
생성을 요청하면 실제 Node VM이 만들어지고, 준비되는 데 까지 앞서 설치시와 같이 약간의 시간이 걸립니다.
Node Pool을 추가 생성하면 그림과 같이 동일 OKE 클러스터에 두 가지 버전의 혼합을 지원하여, 앞서 Node Pool 추가시 본것 처럼 Pool 단위 Node Shape, 위치(AD, 서브넷)을 달리 할 수 있습니다.
kubectl로 노드를 조회해도 동일한 결과가 나옵니다.
$ kubectl get nodes -L name --sort-by=.metadata.labels.name NAME STATUS ROLES AGE VERSION NAME 10.0.10.107 Ready node 19h v1.25.4 oke-cluster-1 10.0.10.143 Ready node 19h v1.25.4 oke-cluster-1 10.0.10.39 Ready node 19h v1.25.4 oke-cluster-1 10.0.10.120 Ready node 2m9s v1.24.1 pool2 10.0.10.21 Ready node 2m13s v1.24.1 pool2 10.0.10.8 Ready node 2m22s v1.24.1 pool2
OKE 클러스터 버전 업그레이드
업그레이드 절차
OKE 새 버전이 출시되면 버전 업그레이드는 다음 절차를 따릅니다.
- Control Plane 업그레이드
- OCI 서비스 콘솔에서 OKE 클러스터 단위를 업그레이드하면 Control Plane만 업그레이드됨
- 오라클이 관리하는 영역으로 다운타임 없이 자동으로 업그레이드 됨
- OKE 클러스터를 업그레이드 하면, 즉 Control Plane이 업그레이드하면 이전 버전으로 다시 다운그레이드 할 수 없음
- Worker Node 업그레이드
- OCI 서비스 콘솔에서 Node Pool 단위로 업그레이드
- 업그레이드 방식
- in-place 업그레이드
- 대상이 되는 기존 Node Pool은 OCI 콘솔에서 버전 업그레이드, 이미 만들어진 기존 Node들이 자동으로 업그레이드 되지 않음
- kubectl drain 명령으로 특정 노드를 컨테이너 스케줄에서 제외함
- OCI 서비스 콘솔에서 drain한 Node를 종료(Terminate) 시킴
- Node 자가치유에 의해 신규 Node가 자동으로 생성되며, 신규노드는 Node Pool에서 지정한 업그레이드 된 버전으로 생성됨
- 해당 Node Pool에 있는 나머지 기존 노드에 대해서도 동일한 순서대로 모두 진행
- out-of-place 업그레이드
- 신규 버전의 Node Pool 추가 생성
- kubectl 명령으로 기존 Node Pool에 있는 Node 제거, Kubernetes에 의해 컨테이너가 모두 이동하면, Node 삭제하는 방식으로 하나씩 진행
- 기존 Node가 모두 제거되면, 기존 Node Pool 삭제
- in-place 업그레이드
Control Plane 업그레이드
위와 같이 1.25.4 버전을 사용 중에 새로운 버전이 출시되었다고 가정합니다. 그러면 앞서 설명한 것과 같이 기술지원 정책에 따라 기존 버전은 30일간 지원하기 때문에, 그동안 버전 검증후 업그레이드가 필요합니다.
- OCI Documentation > Container Engine > Supported Versions of Kubernetes
업그레이드가 가능하면, OKE 클러스터 상세 화면에서 New Kubernetes vesion available 버튼이 활성화 됩니다.
버튼을 클릭하면 다음과 같이 안내 문구와 함께 업그레이드를 시작할 수 있습니다. 최신 버전인 v1.26.2를 선택하도록 하겠습니다.
버전을 선택하고 아래 Upgrade 버튼을 클릭하여 업그레이드를 시작합니다.
클러스터 상태가 UPDATING으로 표시되고 업그레이드가 진행됩니다. 오라클이 관리하는 Control Plane에 대한 업그레이드가 시작되며, 내부적으로 순차적으로 진행됩니다. 실제 애플리케이션이 동작하는 Worker Node는 서비스 중지 없이 업그레이드 됩니다.
테스트 시점에는 10~15분 후에 업그레이드 완료되었습니다.
Worker Node 업그레이드 - in-place 업그레이드
OKE 클러스터가 업그레이드로 인해 Control Plane 만 업그레이드 된 상태이며, 이제 Node Pool 단위로 업그레이드 가능한 상태입니다. in-place 업그레이드 방식은 Node Pool 업그레이드 -> 기존 Node Drain > POD 이동 확인 -> 기존 Node VM 종료 순으로 업그레이드 합니다.
Node Pool 업그레이드
업그레이드 하려는 Node Pool의 상세 페이지로 이동합니다.
수정을 위해 Edit를 클릭하면, 오른쪽에 수정 페이지가 뜹니다.
Version 항목에, 클러스터 버전과 Node Pool의 버전이 표시되며, 업그레이드 가능한 버전이 표시됩니다.
클러스터와 동일한 1.26.2로 선택하고 Save Change를 클릭하여 저장합니다.
Resources > Work Requests에 가서 보면, 15초 정도 지난뒤 Node Pool 업그레이드가 완료됩니다.
아직 실제 Worker Node가 업그레이드 된 것은 아닙니다.
Resources > Nodes에 가서 보면 기존 버전 그대로입니다.
Node Drain 시키기 - kubectl 명령 사용
kubectl 명령으로 Worker Node와 배포된 POD를 확인합니다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION 10.0.10.107 Ready node 19h v1.25.4 10.0.10.143 Ready node 19h v1.25.4 10.0.10.39 Ready node 19h v1.25.4 $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-bvs-pvc-5fd5849fd4-jst2z 1/1 Running 0 17h 10.244.0.133 10.0.10.143 <none> <none> nginx-docker-hub-5bfd857f89-9rh8q 1/1 Running 0 18h 10.244.1.3 10.0.10.39 <none> <none> nginx-fss-pvc-56695486fd-kdh9j 1/1 Running 0 9s 10.244.0.138 10.0.10.143 <none> <none> nginx-fss-pvc-56695486fd-rgd44 1/1 Running 0 9s 10.244.1.8 10.0.10.39 <none> <none> nginx-fss-pvc-56695486fd-t5f2b 1/1 Running 0 9s 10.244.0.10 10.0.10.107 <none> <none> nginx-ocir-56d7b8d55c-65d22 1/1 Running 0 17h 10.244.0.5 10.0.10.107 <none> <none>
아래와 같이
kubectl drain <node_name> --ignore-daemonsets --delete-emptydir-data
명령으로 하나의 노드를 스케줄에서 제외시킵니다.emptydir을 사용하는 Pod가 있는 경우 drain시 에러가 발생합니다. emptydir을 임시데이터를 사용하는 용도임으로 –delete-emptydir-data 옵션을 통해 drain 시킵니다. 테스트시는 elasticsearch가 설치된 상태에서 관련 이슈가 발생하였습니다.
참고: https://pet2cattle.com/2021/08/cannot-delete-pods-with-local-storage
$ kubectl drain 10.0.10.107 --ignore-daemonsets --delete-emptydir-data node/10.0.10.107 cordoned WARNING: ignoring DaemonSet-managed Pods: kube-system/csi-oci-node-xqf8t, kube-system/kube-flannel-ds-c27k6, kube-system/kube-proxy-6dbvv, kube-system/proxymux-client-p9wrj evicting pod kube-system/kube-dns-autoscaler-59c7bdff6d-x6kj5 evicting pod default/nginx-fss-pvc-56695486fd-t5f2b evicting pod default/nginx-ocir-56d7b8d55c-65d22 evicting pod kube-system/coredns-68db8f8bcc-dg698 pod/kube-dns-autoscaler-59c7bdff6d-x6kj5 evicted pod/nginx-ocir-56d7b8d55c-65d22 evicted pod/nginx-fss-pvc-56695486fd-t5f2b evicted pod/coredns-68db8f8bcc-dg698 evicted node/10.0.10.107 drained
아래와 같이 107번 노드가 컨테이너 스케줄링에서 제외된 것을 볼 수 있습니다. POD가 다른 Node로 다 이동한 걸 확인후 다음 작업으로 진행합니다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION 10.0.10.107 Ready,SchedulingDisabled node 20h v1.25.4 10.0.10.143 Ready node 20h v1.25.4 10.0.10.39 Ready node 20h v1.25.4 $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-bvs-pvc-5fd5849fd4-jst2z 1/1 Running 0 17h 10.244.0.133 10.0.10.143 <none> <none> nginx-docker-hub-5bfd857f89-9rh8q 1/1 Running 0 18h 10.244.1.3 10.0.10.39 <none> <none> nginx-fss-pvc-56695486fd-kdh9j 1/1 Running 0 106s 10.244.0.138 10.0.10.143 <none> <none> nginx-fss-pvc-56695486fd-rgd44 1/1 Running 0 106s 10.244.1.8 10.0.10.39 <none> <none> nginx-fss-pvc-56695486fd-w2l8j 1/1 Running 0 45s 10.244.0.139 10.0.10.143 <none> <none> nginx-ocir-56d7b8d55c-7kf7k 1/1 Running 0 45s 10.244.1.9 10.0.10.39 <none> <none>
종료할 Node의 노드 이름을 확인합니다.
$ kubectl get nodes -L displayName NAME STATUS ROLES AGE VERSION DISPLAYNAME 10.0.10.107 Ready,SchedulingDisabled node 20h v1.25.4 oke-c4vz7x3dqla-n6c3mexun6a-s2b2igkyisa-1 10.0.10.143 Ready node 20h v1.25.4 oke-c4vz7x3dqla-n6c3mexun6a-s2b2igkyisa-2 10.0.10.39 Ready node 20h v1.25.4 oke-c4vz7x3dqla-n6c3mexun6a-s2b2igkyisa-0
Node Pool의 Nodes 목록에서 종료할 노드의 액션 메뉴에서 Delete node를 선택합니다.
팝업 창이 뜹니다. 노드 삭제후, 신규 노드가 다시 생성되도록 Do not decrese node pool size를 선택한 후 Delete를 클릭합니다.
Node 자가치유에 의해 신규 Node가 자동으로 생성됩니다. 생성된 신규노드는 Node Pool에서 지정한 업그레이드 된 버전으로 생성됩니다.
kubectl 명령으로 노드를 조회하면, 1.26.2 버전으로 신규 노드(.211번 노드)가 생성되었습니다.
$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 10.0.10.143 Ready node 20h v1.25.4 10.0.10.143 <none> Oracle Linux Server 8.7 5.15.0-6.80.3.1.el8uek.x86_64 cri-o://1.25.1-111.el8 10.0.10.211 Ready node 2m14s v1.26.2 10.0.10.211 <none> Oracle Linux Server 8.7 5.15.0-6.80.3.1.el8uek.x86_64 cri-o://1.26.2-142.el8 10.0.10.39 Ready node 20h v1.25.4 10.0.10.39 <none> Oracle Linux Server 8.7 5.15.0-6.80.3.1.el8uek.x86_64 cri-o://1.25.1-111.el8
나머지 기존 노드에 대해서 순서대로 모두 진행합니다.
완료 결과
oke_admin@cloudshell:~ (ap-seoul-1)$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME 10.0.10.128 Ready node 6m10s v1.20.11 10.0.10.128 <none> Oracle Linux Server 7.9 5.4.17-2102.206.1.el7uek.x86_64 cri-o://1.20.2 10.0.10.146 Ready node 35s v1.20.11 10.0.10.146 <none> Oracle Linux Server 7.9 5.4.17-2102.206.1.el7uek.x86_64 cri-o://1.20.2 10.0.10.170 Ready node 23m v1.20.11 10.0.10.170 <none> Oracle Linux Server 7.9 5.4.17-2102.206.1.el7uek.x86_64 cri-o://1.20.2
Node Drain 시키기 - OCI 콘솔 UI 사용
OCI Documentation > Release Notes > Support for worker node deletion, along with new cordon and drain options 기능이 2022년 6월 28일 출시되어 Worker Node 삭제시 Cordon, Drain 옵션이 추가 되었습니다. 앞서 커맨드로 실행했던 작업을 콘솔 UI에서 Node 삭제시 자동으로 함께 수행할 수 있게 되었습니다.
Node Pool에서 대상 노드에 대해 액션 메뉴에서 Delete node를 선택합니다.
팝업 창이 뜹니다. 노드 삭제후, 신규 노드가 다시 생성되도록 Do not decrese node pool size를 선택한 후 Delete를 클릭합니다. 창에 표시된 것처럼 Cordon and drain이 자동으로 수행된후 Node가 삭제됩니다.
아래와 같이 Node가 스케줄에서 제외되는 것을 볼 수 있습니다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION 10.0.10.211 Ready node 18m v1.26.2 10.0.10.253 Ready node 12m v1.26.2 10.0.10.39 Ready,SchedulingDisabled node 20h v1.25.4 $ ... $ kubectl get nodes NAME STATUS ROLES AGE VERSION 10.0.10.211 Ready node 22m v1.26.2 10.0.10.253 Ready node 16m v1.26.2 10.0.10.73 Ready node 82s v1.26.2
커맨드로 노드 Drain을 수작업으로 수행할지, 콘솔 UI에서 수행할 지는 관리 선호도에 따라 선택하여 사용하면 됩니다.
Worker Node 업그레이드 - out-of-place 업그레이드
OKE 클러스터가 업그레이드로 인해 Control Plane 만 업그레이드 된 상태이며, 이제 Node Pool 단위로 업그레이드 가능한 상태입니다. out-of-place 업그레이드 방식은 업그레이드 버전의 Node Pool 신규 생성 -> 기존 Node Pool의 모든 노드 Drain -> 기존 Node Pool 삭제 순으로 업그레이드 합니다.
새 버전의 Node Pool 만들기
OKE 클러스터 상세 페이지로 이동합니다.
Resources > Node Pools 로 이동합니다.
그림과 같이 기존 버전의 Node Pool이 있는 상태에서 신규 Node Pool 추가를 위해 Add Node Pool을 클릭합니다.
신규 Node Pool 정보를 입력하여 생성합니다.
- Name
- Version: 새 버전 선택
- Placement Configuration
- AD
- Subnet: Worker Node 서브넷 선택
- Shape and image: Node VM 유형
- Node count: 노드 수
- 제일 아래 Advanced Options:
- Add an SSH key: Node VM에 SSH 접속시 사용할 키의 Private Key
Add를 클릭하여 Node Pool을 생성합니다.
신규 Node가 모두 준비 될때 까지 기다립니다.
기존 Node Pool의 모든 노드 Drain
구동 중인 앱들이 기존 Node Pool에서 동작하고 있습니다.
$ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-bvs-pvc-5fd5849fd4-q5dwd 1/1 Running 0 29m 10.244.1.136 10.0.10.193 <none> <none> nginx-docker-hub-5bfd857f89-9pljn 1/1 Running 0 29m 10.244.1.139 10.0.10.193 <none> <none> nginx-fss-pvc-56695486fd-bdgnl 1/1 Running 0 29m 10.244.1.132 10.0.10.193 <none> <none> nginx-fss-pvc-56695486fd-zbgg9 1/1 Running 0 29m 10.244.1.131 10.0.10.193 <none> <none> nginx-fss-pvc-56695486fd-zv2v6 1/1 Running 0 29m 10.244.1.137 10.0.10.193 <none> <none> nginx-ocir-56d7b8d55c-jqrz7 1/1 Running 0 29m 10.244.1.130 10.0.10.193 <none> <none> $ kubectl get nodes -L name --sort-by=.metadata.labels.name NAME STATUS ROLES AGE VERSION NAME 10.0.10.117 Ready node 19m v1.25.4 pool1 10.0.10.126 Ready node 19m v1.25.4 pool1 10.0.10.193 Ready node 19m v1.25.4 pool1 10.0.10.115 Ready node 5m17s v1.26.2 pool2 10.0.10.136 Ready node 5m14s v1.26.2 pool2 10.0.10.25 Ready node 5m23s v1.26.2 pool2
아래와 같이
kubectl drain <node_name> --ignore-daemonsets --delete-emptydir-data
명령으로 하나의 노드를 스케줄에서 제외시킵니다.$ kubectl drain 10.0.10.117 --ignore-daemonsets --delete-emptydir-data node/10.0.10.117 cordoned WARNING: ignoring DaemonSet-managed Pods: kube-system/csi-oci-node-wfzll, kube-system/kube-flannel-ds-95kzs, kube-system/kube-proxy-fmb4d, kube-system/proxymux-client-xvl4p evicting pod kube-system/coredns-68db8f8bcc-l6c2p pod/coredns-68db8f8bcc-l6c2p evicted node/10.0.10.117 drained
아래와 같이 117번 노드가 컨테이너 스케줄링에서 제외된 것을 볼 수 있습니다. POD가 다른 Node로 다 이동한 걸 확인후 다음 작업으로 진행합니다.
$ kubectl get nodes -L name --sort-by=.metadata.labels.name NAME STATUS ROLES AGE VERSION NAME 10.0.10.117 Ready,SchedulingDisabled node 21m v1.25.4 pool1 10.0.10.126 Ready node 21m v1.25.4 pool1 10.0.10.193 Ready node 21m v1.25.4 pool1 10.0.10.115 Ready node 7m33s v1.26.2 pool2 10.0.10.136 Ready node 7m30s v1.26.2 pool2 10.0.10.25 Ready node 7m39s v1.26.2 pool2 $ kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-bvs-pvc-5fd5849fd4-q5dwd 1/1 Running 0 32m 10.244.1.136 10.0.10.193 <none> <none> nginx-docker-hub-5bfd857f89-9pljn 1/1 Running 0 32m 10.244.1.139 10.0.10.193 <none> <none> nginx-fss-pvc-56695486fd-bdgnl 1/1 Running 0 32m 10.244.1.132 10.0.10.193 <none> <none> nginx-fss-pvc-56695486fd-zbgg9 1/1 Running 0 32m 10.244.1.131 10.0.10.193 <none> <none> nginx-fss-pvc-56695486fd-zv2v6 1/1 Running 0 32m 10.244.1.137 10.0.10.193 <none> <none> nginx-ocir-56d7b8d55c-jqrz7 1/1 Running 0 32m 10.244.1.130 10.0.10.193 <none> <none>
나머지 기존 Node Pool에 있는 Node들도 drain합니다.
$ kubectl get nodes -L name --sort-by=.metadata.labels.name NAME STATUS ROLES AGE VERSION NAME 10.0.10.117 Ready,SchedulingDisabled node 22m v1.25.4 pool1 10.0.10.126 Ready,SchedulingDisabled node 22m v1.25.4 pool1 10.0.10.193 Ready,SchedulingDisabled node 23m v1.25.4 pool1 10.0.10.115 Ready node 8m49s v1.26.2 pool2 10.0.10.136 Ready node 8m46s v1.26.2 pool2 10.0.10.25 Ready node 8m55s v1.26.2 pool2
기존 Node Pool 삭제
기존 Node Pool에 있는 모든 Node들이 drain되어 더이상 사용되지 않습니다.
OCI 서비스 콘솔에서 OKE 클러스터 상세페이지로 이동합니다.
Resources > Node Pools로 이동하여 기존 Node Pool을 삭제합니다.
팝업 창이 뜹니다. 확인후 Delete를 클릭합니다.
업그레이드가 완료되었습니다.
$ kubectl get nodes -L name --sort-by=.metadata.labels.name NAME STATUS ROLES AGE VERSION NAME 10.0.10.115 Ready node 16m v1.26.2 pool2 10.0.10.136 Ready node 16m v1.26.2 pool2 10.0.10.25 Ready node 16m v1.26.2 pool2
기존 Node Pool의 모든 노드 Drain - OCI 콘솔 UI 사용
Node Pool 삭제 팝업 창에서 본건 처럼 Node Pool 삭제시에도 신규 기능을 통해 속한 Node에 대해 Cordon, Drain 기능을 제공합니다.
이 또한 커맨드로 노드 Drain을 수작업으로 수행한 후, 최종적으로 Node Pool을 삭제하는 방식을 사용할지, 단번에 OCI 콘솔에서 Node Pool을 삭제하여 자동으로 Cordon, Drain을 수행하게 할 지는 관리자 선호도에 따라 선택하여 사용하면 됩니다. 업그레이드 시 발생하는 문제 등을 고려하여 관리자에 따라 커맨드를 선호할 수도 있을 것 같아 함께 표시하였습니다.
이 글은 개인으로서, 개인의 시간을 할애하여 작성된 글입니다. 글의 내용에 오류가 있을 수 있으며, 글 속의 의견은 개인적인 의견입니다.