CKA #6 Cluster Maintenance
Certified Kubernetes Administrator (CKA) with Practice Tests 강의를 듣고 몰랐던 내용, 알고 있어도 중요하다고 생각하는 내용 등을 추가적인 공부와 함께 간략히 정리한 글입니다.
저번 #5 Application LifeCycle를 공부하면서 집중력이 많이 떨어진 것 같아, #6부터는 필기 정리를 가미해서 공부하기로 했습니다. 역시 집중이 안될 땐 필기 정리를 하면 머리에 정보를 욱여넣을 수 있는… 그리고 6장은 DR 관련된 사항들이 많고, 현업에서 실제로 써본 적은 없었던 내용들이라 재밌게 공부했습니다.
현업에서 쿠버네티스 클러스터 버전 업그레이드는 EKS로만 해보고, kubeadm으로 업그레이드해본 적은 없는데 이 부분과 etcd 백업과 복원 파트가 도움이 많이 되었습니다.
Index
- CKA #2 Core Concepts, #3 Scheduling
- CKA #4 Logging & Monitoring, #5 Application LifeCycle Management
- CKA #6 Cluster Maintenance
- CKA #7 Security
- CKA #8 Storage
- CKA #9 Networking
Operating System Upgrades
몇 개의 노드와 파드를 제공하는 클러스터에서, 노드 중 하나가 다운되면 어떻게 될까? 파드에 접근이 불가능해진다. 파드를 어떻게 배치하냐에 따라 유저가 영향받을 수 있다. 여러 노드에 걸쳐 레플리카로 서비스되는 파드는 영향이 없을 수 있다. 하지만 다운된 노드에만 떠있는 파드가 있었다면 영향이 생길 것이다.
쿠버네티스는 이런 상황에서 어떻게 대처할까? 만약 노드가 다운된 즉시 다시 노드가 살아난다면 (kubelet이 켜지면서 온라인으로 돌아오는 경우) 다시 파드가 정상적으로 동작한다. 하지만 노드가 5분 이상 다운된다면, 쿠버네티스 클러스터는 해당 노드에 배치된 파드를 종료시키고, 다른 노드에 파드를 띄운다. 파드가 죽었다고 판단하는 타임아웃 시간(pod-eviction-timeout)은 기본값으로 5분이다.
따라서 노드에서 실행, 유지 관리할 일이 있다면, 다른 노드에 복제본이 있다는 점이 확실하다면 노드를 빠르게 재부팅키면서 업데이트 작업을 수행할 수 있다. 하지만 그 노드가 5분 안에 돌아올 수 있다는 보장이 없다. 따라서 더 안전한 방법이 필요하다. 한 노드 내의 모든 작업을 드레인하는 방법이다. 파드나 작업 내용이 다른 노드로 이동된다. 드레인 명령을 실행하면 노드에는 어떤 파드도 스케줄되지 않는다.
kubectl drain node-1
노드에 드레인 작업을 실행하고, 노드에 필요한 작업(OS 업데이트 등)을 수행하고 다시 kubelet을 띄워 클러스터에 연결해도, 여전히 파드는 스케줄되지 않는다. uncordon을 통해 노드가 다시 일할 수 있다는 것을 클러스터에 알려야 한다.
kubectl uncordon node-1
이 작업을 한다고 해서 다른 노드로 옮겨간 파드가 바로 다시 돌아오는 것은 아니다. 해당 파드가 재생성되거나 하면, 노드가 돌아올 수 있다.
cordon이라는 명령어도 있는데, 이 명령어는 drain과 달리 기존의 파드가 내려가지는 않지만, 새 파드가 스케줄되지 않도록 하는 명령어다.
k8s Versions
우린 쿠버네티스 클러스터를 만들 때 특정 버전의 쿠버네티스 버전을 설치한다. 쿠버네티스가 어떻게 소프트웨어 릴리즈를 관리할까?
예를 들어 버전 구성을 살펴보자. v1.24.3라는 버전이 있다고 하면, 앞의 1은 메이저 버전, 24는 마이너 버전, 3은 패치 버전이다.
- 마이너 버전: 새로운 기능 → 몇 달에 한 번 릴리즈됨
- 패치 버전: 버그 수리
- 쿠버네티스 v1.0은 2015년에 나왔다.
- v1.10.0-alpha → v1.10.0-beta → v1.10.0와 같이 알파-베타-정규 순으로 업데이트된다.
- 컨트롤 플레인 내의 구성 요소들은 다 같은 버전 정보를 공유한다. 하지만 etcd-cluster와 coreDNS는 다른 버전 구조다.
Cluster Upgrade Process
- 컨트롤 플레인 내의 구성 요소들이 모두 같은 버전일 필요는 없지만, kube-apiserver보다 높은 버전이면 안된다. (마이너 버전 기준)
- controller-manager와 scheduler는 kube-apiserver보다 한 단계 낮은 버전까지 사용할 수 있다.
- kubelet과 kube-proxy는 kube-apiserver보다 두 단계 낮은 버전까지 사용할 수 있다.
kubectl은 kube-apiserver보다 한 단계 높거나 한단계 낮은 버전까지 사용할 수 있다.
- 쿠버네티스 버전은 한 번에 마이너 버전 한 단계씩 순차적으로 업데이트하는걸 권장한다.
- 쿠버네티스 클러스터 업그레이드
- GCP AKS는 클릭 몇 번으로 쿠버네티스 클러스터를 업그레이드 할 수 있다.
- kubeadm →
kubeadm upgrade plan
명령어와kubeadm upgrade apply
를 사용하면 편하게 업그레이드 할 수 있다.
- 쿠버네티스 클러스터 업그레이드 방법 (kubeadm)
- 먼저 마스터 노드를 업그레이드하고,
- 그다음 워커 노드를 업그레이드한다.
- 마스터 노드를 업그레이드하는 동안, 마스터 노드의 구성요소는 다운된다. 물론 마스터 노드가 다운된다고 워커 노드가 영향 받는 것은 아니다. 워커 노드는 평소대로 동작한다. 하지만 관리 기능은 다운된다. kubectl이나 kube-api를 사용해 새 앱을 배포하거나 수정, 삭제할 수 없다. controller-manager도 다운되기 때문에 파드가 죽었을 때 파드가 재생성되지 않는다. 하지만 기존에 떠있던 파드는 동작하므로 사용자가 영향 받지 않는다. 업그레이드가 완료되고 마스터노드가 다시 살아나면 다시 정상적으로 작동한다.
- 이제 워커 노드는 마스터 노드보다 한 단계 낮은 버전이다. 여기까지는 쿠버네티스가 지원하는 범위이기 때문에 정상적인 형태다. 이제 워커 노드를 업그레이드할 차례다.
- 전략1. 한 번에 모든 워커 노드를 업그레이드 → 서비스가 다운타임이 생김
- 전략2. 순차적으로 워커 노드를 업그레이드 → 파드를 재배치하면서 워커 노드 순차적으로 업그레이드함
- 실제로 해보자.
- kubeadm upgrade plan 명령어를 입력하면, 업그레이드 관련 컴포넌트 정보를 얻을 수 있다.
- kubeadm은 kubelet을 업그레이드해주지 않는다.
- kubeadm은 쿠버네티스 클러스터 버전과 같이 동작한다.
- v1.11 → v1.13으로 가고 싶다면, 한 단계씩 올라가야한다.
apt-get upgrade -y kubeadm=1.12.0-00
을 입력해 kubeadm을 12 버전으로 올린다.kubeadm upgrade apply v1.12.0
을 입력해 쿠버네티스 클러스터 마스터 노드 업그레이드를 실행한다.kubectl get nodes
를 입력하면, 워커 노드의 버전이 v1.11.x 인 것을 확인할 수 있다. 각 워커 노드의 kubelet들의 버전이다.- 먼저 마스터 노드의 쿠블렛을 업그레이드 해준다.
apt-get upgrade -y kubelet=1.12.0-00
(있다면) kubectl get nodes
를 다시 입력해보면, 마스터 노드의 쿠블렛 버전이 v1.12.0으로 올라간 것을 볼 수 있다.- 이제 워커노드를 업그레이드할 차례인데, 순차적으로 워커 노드를 업그레이드할 때, 업그레이드하고자 하는 노드를 drain한다.
kubectl drain node-1
- 그리고, 해당 워커 노드에서 업그레이드를 진행한다.
apt-get upgrade -y kubeadm=1.12.0-00
apt-get upgrade -y kubelet=1.12.0-00
kubeadm upgrade node config --kubelet-version v1.12.0
systemctl restart kubelet
- 워커노드 업그레이드가 완료되면, 모든 워커노드에 해당 작업을 반복한다.
kubeadm에서 직접 버전 올리기
/etc/apt/sources.list.d/kubernetes.list
내의 내용을 바꾸어주어야 한다.
deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /
처음 열어보면 v1.29 부분이 현재 버전 정보로 되어있는데, 이걸 업그레이드하고자 하는 버전에 맞춰 적어주어야 한다.
root@controlplane:~# apt update
root@controlplane:~# apt-cache madison kubeadm
업그레이드할 수 있는 버전 정보를 확인한다.
root@controlplane:~# apt-get install kubeadm=1.29.0-1.1
업그레이드하고자 하는 버전을 설치한다.
root@controlplane:~# kubeadm upgrade plan v1.29.0
root@controlplane:~# kubeadm upgrade apply v1.29.0
컨트롤 플레인의 업그레이드를 진행한다. 업그레이드를 마쳤더라도, 컨트롤 플레인의 쿠블렛은 업그레이드되지 않았다. 쿠블렛도 목표버전에 맞게 설치한다.
root@controlplane:~# apt-get install kubelet=1.29.0-1.1
root@controlplane:~# systemctl daemon-reload
root@controlplane:~# systemctl restart kubelet
root@controlplane:~# kubectl uncordon controlplane
이후 워커 노드도 kubelet 업그레이드를 진행해준다.
Backup and Restore Methodologies
백업을 해야하는 컴포넌트들
- Resource Configuration → yaml 파일들 → Github에 올려서 팀이 관리할 수 있도록 하는 것이 좋음
- Github 등에 구성 파일을 백업해두면, 클러스터를 잃어도 새 클러스터에 다시 구성 요소들을 빠르게 배포할 수 있음
- 혹은 kube-apiserver에 직접 쿼리를 날려 구성 요소들의 정보를 전부 받아와 yaml로 추출하여 저장하는 방법이 있음
kubectl get all --all-namespaces -o yaml > all-deploy-services.yaml
- 이런 짓을 직접 할 필요는 없고, VELERO 같은 도구를 활용할 수 있음
- ETCD Cluster
- 클러스터 자체 정보와 노드 및 클러스터 내부에서 생성된 모든 리소스가 저장됨
- 앞의 리소스를 백업하는 대신 ETCD 자체를 백업하는 방법이 있음
- ETCD를 시작할 때 데이터가 저장되는 장소를 지정한다.
- 기본값은
--data-dir=/var/lib/etcd
- 기본값은
- ETCD는 자체적인 스냅샷도 지원함
ETCDCTL_API=3 etcdctl snapshot save snapshot.db
→snapshot.db
라는 파일 이름으로 저장됨 - 백업한 스냅샷을 복원하려면, 다음과 같은 방법이 있다.
service kube-apiserver stop ETCDCTL_API=3 etcdctl snapshot restore snapshot.db --data-dir /var/lib/etcd-from-backup systemctl daemon-reload systemctl restart kubelet service kube-apiserver start
- 인증서 파일을 지정하는 것을 잊지 말 것
ETCDCTL_API=3 etcdctl snapshot save snapshot.db \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/etcd/ca/crt \ --cert=/etc/etcd/etcd-server.crt \ --key=/etc/etcd/etcd-server.key
실제로 복구해보기
ETCDCTL_API=3 etcdctl --data-dir /var/lib/etcd-from-backup \
snapshot restore /opt/snapshot-pre-boot.db
백업해둔 ETCD 정보를 불러온다.
그리고 /etc/kubernetes/manifests/etcd.yaml
파일을 수정한다.
volumes:
- hostPath:
path: /var/lib/etcd-from-backup # etcd -> etcd-from-backup 으로 복구한 파일명으로 맞춰줌
type: DirectoryOrCreate
name: etcd-data
파일을 수정하고 나면 ETCD 팟은 자동으로 재시작된다. 팟은 static-pod 형태로 /etc/kubernetes/manifests
아래에 재생성된다.
- 유의사항1.
kube-controller-manager
과kube-scheduler
도 재시작된다.watch "crictl ps | grep etcd"
명령어를 통해 재시작되는 etcd 팟을 볼수 있다. - 유의사항2. etcd 파드가
Ready 1/1
가 되지 않으면kubectl delete pod -n kube-system etcd-controlplane
명령어를 입력하고 1분을 기다린다.
ETCD 관련 옵션의 주요 특징
--data-dir
은 실제 etcd 데이터들이 저장된 곳- kube-apiserver의
--etcd-servers
는 ETCD의 주소 엔드포인트₩- 그 외에도 kube-apiserver에서 설정하는 옵션들
--etcd-cafile=/etc/kubernetes/pki/etcd/ca.pem --etcd-certfile=/etc/kubernetes/pki/etcd/etcd.pem --etcd-keyfile=/etc/kubernetes/pki/etcd/etcd-key.pem
multiple cluster context switching
kubectl config use-context cluster1