kubernetes는 EOL이 굉장히 빠르다.
그렇다면 EOL이되면 더 이상 못쓰는걸까?
정답을보면 아니다.
kubernetes 공식문서상으로보면 upgrade 를 지원하고있다.
Docs :: https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/
그렇다면 실제로 그런지 확인을 해보겠습니다.
제가 검증하려는 환경은 다음과 같습니다.
$ sudo kubectl get node
NAME STATUS ROLES AGE VERSION
compute01 Ready <none> 22d v1.28.7
compute02 Ready <none> 22d v1.28.7
control01 Ready control-plane 22d v1.28.7
control02 Ready control-plane 22d v1.28.7
control03 Ready control-plane 22d v1.28.7
master 3대 cluster 2대의 서버입니다.
kubernetes version은 1.28.7
우선 전제적인 조건으로 "외부와의 통신이 되어야한다" 라는 점을 우선 깔고 가는게 좋을 것 같다.
그런 전제조건을 세운 이유는, 외부통신이 가능하다면, repo를 구성하지않아도 kubernetes repo에서 kubernetes 패키지를 가져 올 수 있기 때문이다.
다만, 외부통신이 안되는 보안이 엄격한 환경이라면 미리 repo를 준비해야둬야한다.
k8s의 version upgrade는 마이너버전을 올리는 식으로 진행할 예정이다.
따라서, 1.28.7의 다음 마이너버전의 마지막 1.29.10으로 업그레이드 할 예정이다.
우선 repo부터 구성해보겠습니다.
$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
repo를 구성하였다면, 설치되는 패키지를 보자.
$ sudo yum install kubeadm-'1.29.10-*' kubelet-'1.29.10-*' kubectl-'1.29.10-*' --disableexcludes=kubernetes
Failed to set locale, defaulting to C.UTF-8
Last metadata expiration check: 0:08:59 ago on Wed Oct 30 13:12:48 2024.
Dependencies resolved.
==============================================================================================================================================================================================================
Package Architecture Version Repository Size
==============================================================================================================================================================================================================
Upgrading:
kubeadm x86_64 1.29.10-150500.1.1 kubernetes 9.8 M
kubectl x86_64 1.29.10-150500.1.1 kubernetes 10 M
kubelet x86_64 1.29.10-150500.1.1 kubernetes 19 M
Transaction Summary
==============================================================================================================================================================================================================
Upgrade 3 Package
Total download size: 9.8 M
Is this ok [y/N]: y
...
Complete!
kubeadm, kubectl kubelet 을 1.29.10으로 설치하였다면, kubernetes의 upgrade plan을 보자
$ sudo kubeadm upgrade plan
COMPONENT CURRENT TARGET
kubelet 2 x v1.28.7 v1.29.10
...
COMPONENT CURRENT TARGET
kube-apiserver v1.28.7 v1.29.10
kube-controller-manager v1.28.7 v1.29.10
kube-scheduler v1.28.7 v1.29.10
kube-proxy v1.28.7 v1.29.10
CoreDNS v1.8.6 v1.11.1
You can now apply the upgrade by executing the following command:
kubeadm upgrade apply v1.29.10
...
upgrade를 하기 전 kube-scheduler를 수정해야한다.
사유는 kubernets 1.28 버전 이후부터 kube-scheduler의 apiVersion이 변경되었기 때문이다.
이걸 미리 수정안하고 version upgrade를 하면...kube-scheduler가 동작을 하지못한다.
[user@control-01 ~]$ sudo vi /etc/kubernetes/kubescheduler-config.yaml
-apiVersion: kubescheduler.config.k8s.io/v1beta3
+apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
clientConnection:
kubeconfig: "/etc/kubernetes/scheduler.conf"
leaderElection:
leaseDuration: 15s
renewDeadline: 10s
AS-IS : kubescheduler.config.k8s.io/v1beta3
TO-BE : kubescheduler.config.k8s.io/v1
이제 업그레이드 모의 테스트 및 업그레이드를 진행해보자.
[user@control-01 ~]$ sudo kubeadm upgrade apply v1.25.16 --certificate-renewal=false --dry-run |less
...
[upgrade/successful] Finished dryrunning successfully!
--certificate-renewal=false 옵션을 주어 인증서를 새로 갱신하지 않고 기존 것으로 사용하도록 하자.
kubernetes upgrade 진행
[user@control-01 ~]$ sudo kubeadm upgrade apply v1.29.10 --certificate-renewal=false
[upgrade/config] Making sure the configuration is correct:
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1030 13:27:16.107257 3431200 utils.go:69] The recommended value for "clusterDNS" in "KubeletConfiguration" is: [10.233.0.10]; the provided value is: [169.254.25.10]
[preflight] Running pre-flight checks.
[upgrade] Running cluster health checks
[upgrade/version] You have chosen to change the cluster version to "v1.29.10"
[upgrade/versions] Cluster version: v1.28.7
[upgrade/versions] kubeadm version: v1.29.10
[upgrade] Are you sure you want to proceed? [y/N]: y
...
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.29.10". Enjoy!
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
마찬가지로 모의 업데이트 했을때와 동일하게 --certificate-renewal=false 옵션을 주어 인증서를 새로 갱신하지 않고 기존 것으로 사용하도록 하자.
또한, 업그레이드 중에는 kube-apiserver가 중단될 수 있다. 이점은 미리 참고하자.
upgrade 간 pod가 재기동되는데, 이때 모니터링을 잘 해둬야한다.
[user@control01 ~]$ sudo kubectl get po -n kube-system -w
문제가 발생하면 언제든 돌아갈 수 있도록.
pod가 모두 정상적으로 동작한다면, kubelet 서비스를 재시작하자.
[user@control01 ~]$ sudo systemctl daemon-reload
[user@control01 ~]$ sudo systemctl restart kubelet
해당 작업 이후에도 모든 kube-system pod들이 재시작되므로 kubectl 명령어가 수행되지 않을 수 있습니다.(길게는 약 5분)
이 과정에서 공식문서는 drain을 통하여 안정적으로 진행하지만 금번 문서에서는 drain을 진행하지않고 한다.
version이 업그레이드가 잘 되었는지 확인하자.
[user@control01 ~]$ sudo kubectl get node
NAME STATUS ROLES AGE VERSION
compute01 Ready <none> 23d v1.28.7
compute02 Ready <none> 23d v1.28.7
control01 Ready control-plane 23d v1.29.10
control02 Ready control-plane 23d v1.28.7
control03 Ready control-plane 23d v1.28.7
control01의 master node의 버전이 v1.28.7 -> v1.29.10 으로 upgrade가 되었다.
이제 남은 Master node인 control2, contorl3도 동일하게 진행한다.
그럼 worker node는 어떻게 해야할까?
work node도 동일하게 우선 repo부터 구성하자.
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.29/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
kubeadm 패키지 설치
[user@compute01 ~]$ sudo yum install -y kubeadm-'1.29.10-*' kubelet-'1.29.10-*' --disableexcludes=kubernetes
...
Complete!
worker node의 kubeadm을 upgrade
[user@compute01 ~]$ sudo kubeadm upgrade node --certificate-renewal=false
[upgrade] Reading configuration from the cluster...
[upgrade] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1030 14:24:56.807820 1657159 utils.go:69] The recommended value for "clusterDNS" in "KubeletConfiguration" is: [10.233.0.10]; the provided value is: [169.254.25.10]
[preflight] Running pre-flight checks
[preflight] Skipping prepull. Not a control plane node.
[upgrade] Skipping phase. Not a control plane node.
[upgrade] Backing up kubelet config file to /etc/kubernetes/tmp/kubeadm-kubelet-config1361617122/config.yaml
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[upgrade] The configuration for this node was successfully updated!
[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.
완료되었다면 daemon 재시작!
[user@compute01 ~]$ sudo systemctl daemon-reload
[user@compute01 ~]$ sudo systemctl restart kubelet
worker node 버전 확인
[clex@control01 ~]$ sudo kubectl get node
NAME STATUS ROLES AGE VERSION
compute01 Ready <none> 23d v1.29.10
compute02 Ready <none> 23d v1.29.10
control01 Ready control-plane 23d v1.29.10
control02 Ready control-plane 23d v1.29.10
control03 Ready control-plane 23d v1.29.10
다들 v1.29.10 으로 잘 올라왔다.
그럼 이제 1.30으로 가보자
Master node부터 업그레이드를 진행한다.
$ cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
패키지 설치
[user@control01 ~]$ sudo yum install kubeadm-'1.30.0-*' kubelet-'1.30.0-*' kubectl-'1.30.0-*' --disableexcludes=kubernetes
Failed to set locale, defaulting to C.UTF-8
Last metadata expiration check: 0:09:49 ago on Wed Oct 30 14:33:34 2024.
Dependencies resolved.
==============================================================================================================================================================================================================
Package Architecture Version Repository Size
==============================================================================================================================================================================================================
Upgrading:
cri-tools x86_64 1.30.1-150500.1.1 kubernetes 8.6 M
kubeadm x86_64 1.30.0-150500.1.1 kubernetes 10 M
kubectl x86_64 1.30.0-150500.1.1 kubernetes 10 M
kubelet x86_64 1.30.0-150500.1.1 kubernetes 17 M
Transaction Summary
==============================================================================================================================================================================================================
Upgrade 4 Packages
Total download size: 46 M
Is this ok [y/N]: y
...
Complete!
kubernets upgrade plan을 살펴보자
[user@control01 ~]$ sudo kubeadm upgrade plan
COMPONENT NODE CURRENT TARGET
kubelet control-01 v1.29.10 v1.30.6
kubelet control-02 v1.29.10 v1.30.6
kubelet control-03 v1.29.10 v1.30.6
Upgrade to the latest stable version:
COMPONENT NODE CURRENT TARGET
kube-apiserver control-01 v1.29.10 v1.30.6
kube-controller-manager control-01 v1.29.10 v1.30.6
kube-scheduler control-01 v1.29.10 v1.30.6
kube-proxy 1.29.10 v1.30.6
CoreDNS v1.8.6 v1.11.1
...
You can now apply the upgrade by executing the following command:
kubeadm upgrade apply v1.30.6
모의 업그레이드 진행
[user@control01 ~]$ sudo kubeadm upgrade apply v1.30.0 --certificate-renewal=false --dry-run |less
...
[upgrade/successful] Finished dryrunning successfully!
kubernets upgrade
[user@control01 ~]$ sudo kubeadm upgrade apply v1.30.0 --certificate-renewal=false
[upgrade/config] Making sure the configuration is correct:
[preflight] Running pre-flight checks.
[upgrade/config] Reading configuration from the cluster...
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[upgrade] Running cluster health checks
[upgrade/version] You have chosen to change the cluster version to "v1.30.0"
[upgrade/versions] Cluster version: v1.29.10
[upgrade/versions] kubeadm version: v1.30.0
[upgrade] Are you sure you want to proceed? [y/N]:y
...
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.30.0". Enjoy!
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
이전 upgrade 와 마찬가지로 pod monitoring 후 daemon을 재기동하자.
# pod 상태 확인
[user@control01 ~]$ sudo kubectl get po -n kube-system -w
# daemon 재기동
[user@control01 ~]$ sudo systemctl daemon-reload
[user@control01 ~]$ sudo systemctl restart kubelet
버전을 확인해보자.
[user@control01 ~]$ sudo kubectl get node
NAME STATUS ROLES AGE VERSION
compute01 Ready <none> 23d v1.29.10
compute02 Ready <none> 23d v1.29.10
control01 Ready control-plane 23d v1.30.0
control02 Ready control-plane 23d v1.29.10
control03 Ready control-plane 23d v1.29.10
음! 잘올라왔다.
자 이제 worker node를 진행해보자.
repo생성
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
kubeadm 설치
[user@compute01 ~]$ sudo yum install -y kubeadm-'1.30.00-*' kubelet-'1.30.0-*' --disableexcludes=kubernetes
...
Complete!
upgrade kubeadm worker node
[user@compute01 ~]$ sudo kubeadm upgrade node --certificate-renewal=false
[upgrade] Reading configuration from the cluster...
[upgrade] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1030 14:24:56.807820 1657159 utils.go:69] The recommended value for "clusterDNS" in "KubeletConfiguration" is: [10.233.0.10]; the provided value is: [169.254.25.10]
[preflight] Running pre-flight checks
[preflight] Skipping prepull. Not a control plane node.
[upgrade] Skipping phase. Not a control plane node.
[upgrade] Backing up kubelet config file to /etc/kubernetes/tmp/kubeadm-kubelet-config1361617122/config.yaml
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[upgrade] The configuration for this node was successfully updated!
[upgrade] Now you should go ahead and upgrade the kubelet package using your package manager.
kubelet 재기동
[user@compute01 ~]$ sudo systemctl daemon-reload
[user@compute01 ~]$ sudo systemctl restart kubelet
kubernetes version확인
[user@control01 ~]$ sudo kubectl get node
NAME STATUS ROLES AGE VERSION
compute01 Ready <none> 23d v1.30.0
compute02 Ready <none> 23d v1.30.0
control01 Ready control-plane 23d v1.30.0
control02 Ready control-plane 23d v1.30.0
control03 Ready control-plane 23d v1.30.0
자 이러면 kubernets version이 1.28.7 -> 1.30으로 모두 올라왔다.
이제 안심하고 외부통신을 단절하면될까?
아니다. 절대 아니다.
이 작업이 완료되었으면 우린 가장 중요한 작업을 해야한다.
외부통신을 계속 열어둘 것이면 상관없지만, 다시 닫아야하는 경우엔 upgrade 된 이미지들을 모두 사설 registry로 옮겨야한다.
그렇지 않으면 pod가 imagepullbackoff이 발생하니까...
여기서 무슨 pod에 대해서 사설 registry로 바라보게 할거냐?
나는 이렇게 list를 짜보았다.
image list
kube-apiserver
kube-contoller-manager
kube-proxy
kube-scheduler
core-dns
해당 이미지들에 대해서 tagging과 push가 되었다면, 이제 동작중인 kubernetes 에서도 바라 볼 이미지를 바꿔줘야한다.
kube-apiserver
$ sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
...
- --tls-private-key-file=/etc/kubernetes/ssl/apiserver.key
image: registry.k8s.io/kube-apiserver:v1.30.0
imagePullPolicy: IfNotPresent
livenessProbe:
...
kube-controller-manager
$ sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml
...
- --use-service-account-credentials=true
image: registry.k8s.io/kube-controller-manager:v1.30.0
imagePullPolicy: IfNotPresent
livenessProbe:
...
kube-scheduler
$ sudo vi /etc/kubernetes/manifests/kube-scheduler.yaml
...
- --leader-elect=true
image: registry.k8s.io/kube-scheduler:v1.30.0
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
...
core-dns
$ sudo kubectl edit deploy -n kube-system coredns
...
- args:
- -conf
- /etc/coredns/Corefile
image: registry.k8s.io/coredns/coredns:v1.8.6
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 5
...
kube-proxy
$ sudo kubectl edit ds -n kube-system kube-proxy
...
fieldPath: spec.nodeName
image: registry.k8s.io/kube-proxy:v1.30.0
imagePullPolicy: IfNotPresent
...
이미지 들을 모두 사설 registry로 바라보도록 수정한다면 외부통신이 단절되어도 pod는 정상적으로 돌게된다.
이로써 kuberntes upgrade 가 완료되었다.