목표 kubespray를 활용하여 새로운 노드를 추가하고 삭제한다.
노드 추가
기존 클러스터는 건드리지 않고 새로 추가된 노드만 단계적으로 합류 시킨다.
/root/kubespray/scale.yml/root/kubespray/playbook/scale.yml
새로운 워커노드 노드 추가하기
- inventory.ini 수정 (k8s-node5 추가)
1
2
3
4
5
6
7
8
9
10
11
12
13
| cat << EOF > /root/kubespray/inventory/mycluster/inventory.ini
[kube_control_plane]
k8s-node1 ansible_host=192.168.10.11 ip=192.168.10.11 etcd_member_name=etcd1
k8s-node2 ansible_host=192.168.10.12 ip=192.168.10.12 etcd_member_name=etcd2
k8s-node3 ansible_host=192.168.10.13 ip=192.168.10.13 etcd_member_name=etcd3
[etcd:children]
kube_control_plane
[kube_node]
k8s-node4 ansible_host=192.168.10.14 ip=192.168.10.14
k8s-node5 ansible_host=192.168.10.15 ip=192.168.10.15
EOF
|
1
2
3
4
5
6
7
| ansible-inventory -i /root/kubespray/inventory/mycluster/inventory.ini --graph
# ansible 연결 확인
ansible -i inventory/mycluster/inventory.ini k8s-node5 -m ping
# 모니터링
watch -d kubectl get node
|
1
2
3
| ansible-playbook -i inventory/mycluster/inventory.ini -v scale.yml --list-tasks
ANSIBLE_FORCE_COLOR=true ansible-playbook -i inventory/mycluster/inventory.ini -v scale.yml --limit=k8s-node5 -e kube_version="1.32.9" | tee kubespray_add_worker_node.log
|
1
2
3
4
5
6
7
| kubectl get node -owide
kubectl get pod -n kube-system -owide |grep k8s-node5
# 변경 정보 확인
ssh k8s-node5 tree /etc/kubernetes
ssh k8s-node5 tree /var/lib/kubelet
ssh k8s-node5 pstree -a
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: webpod
spec:
replicas: 2
selector:
matchLabels:
app: webpod
template:
metadata:
labels:
app: webpod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- sample-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: webpod
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: webpod
labels:
app: webpod
spec:
selector:
app: webpod
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30003
type: NodePort
EOF
|
1
2
3
4
| kubectl get pod -owide
kubectl scale deployment webpod --replicas 1
kubectl get pod -owide
kubectl scale deployment webpod --replicas 2
|
노드 삭제
/root/kubespray/remove-node.yml- `/root/kubespray/playbooks/remove_node.yml
새로 추가된 워커노드 삭제하기
워커 노드 삭제 순서
1) inventory.ini 수정 2) webpod 디플로이먼트에 pdb 설정 3) 노드삭제 수행 4) 노드삭제 실패 확인 5) webpod 디플로이먼트 pdb 삭제 6) 노드삭제 다시 수행 7) 노드삭제 성공 확인 8) inventory.ini 복구
inventory.ini 수정
1
2
3
4
5
6
7
8
9
10
11
12
13
| cat << EOF > /root/kubespray/inventory/mycluster/inventory.ini
[kube_control_plane]
k8s-node1 ansible_host=192.168.10.11 ip=192.168.10.11 etcd_member_name=etcd1
k8s-node2 ansible_host=192.168.10.12 ip=192.168.10.12 etcd_member_name=etcd2
k8s-node3 ansible_host=192.168.10.13 ip=192.168.10.13 etcd_member_name=etcd3
[etcd:children]
kube_control_plane
[kube_node]
k8s-node4 ansible_host=192.168.10.14 ip=192.168.10.14
k8s-node5 ansible_host=192.168.10.15 ip=192.168.10.15
EOF
|
webpod deployment에 pdb 설정
- 해당 정책은 최소 2개의 Pod가 Ready상태이어야함
- drain / eviction 시 단 하나의 Pod도 축출 불가
1
2
3
4
5
6
7
8
9
10
11
12
| cat <<EOF | kubectl apply -f -
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: webpod
namespace: default
spec:
maxUnavailable: 0
selector:
matchLabels:
app: webpod
EOF
|
노드 삭제 수행
1
| ansible-playbook -i inventory/mycluster/inventory.ini -v remove-node.yml -e node=k8s-node5
|
#### 실패확인
pdb삭제
1
| kubectl delete pdb webpod
|
노드 삭제 수행
1
| ansible-playbook -i inventory/mycluster/inventory.ini -v remove-node.yml -e node=k8s-node5
|
노드 삭제 성공 확인
inventory.ini 원래대로 돌려 놓기
1
2
3
4
5
6
7
8
9
10
11
12
13
| cat << EOF > /root/kubespray/inventory/mycluster/inventory.ini
[kube_control_plane]
k8s-node1 ansible_host=192.168.10.11 ip=192.168.10.11 etcd_member_name=etcd1
k8s-node2 ansible_host=192.168.10.12 ip=192.168.10.12 etcd_member_name=etcd2
k8s-node3 ansible_host=192.168.10.13 ip=192.168.10.13 etcd_member_name=etcd3
[etcd:children]
kube_control_plane
[kube_node]
k8s-node4 ansible_host=192.168.10.14 ip=192.168.10.14
k8s-node5 ansible_host=192.168.10.15 ip=192.168.10.15
EOF
|
1
| ANSIBLE_FORCE_COLOR=true ansible-playbook -i inventory/mycluster/inventory.ini -v scale.yml --limit=k8s-node5 -e kube_version="1.32.9" | tee kubespray_add_worker_node.log
|
- 확인 및 샘플 파드 재분배
1
| kubectl get node -owide
|
- 파드 배포
1
2
3
4
| kubectl get pod -owide
kubectl scale deployment webpod --replicas 1
kubectl get pod -owide
kubectl scale deployment webpod --replicas 2
|
비정상 노드 강제 삭제
먼저 실습을 위해 k8s-node5 노드를 비정상 상태로 만든다.
1
2
| ssh k8s-node5 systemctl stop kubelet
ssh k8s-node5 systemctl stop containerd
|
1
| watch -d kubectl get node
|
1
2
3
4
| kc describe node k8s-node5
#Taints:
# node.kubernetes.io/unreachable:NoExecute # node.kubernetes.io/unreachable:NoSchedule
|
1
| ansible-playbook -i inventory/mycluster/inventory.ini -v remove-node.yml -e node=k8s-node5 -e skip_confirmation=true
|
1
| cat roles/remove_node/pre_remove/defaults/main.yml
|
강제로 삭제하기
reset_nodes=false- 클러스터 제어부에서 메타데이터만 정리, 노드에 삭제 시도 안함
kubeadm reset ❌- 서비스 정리 ❌
- SSH 접속 ❌
allow_ungraceful_removal=true- drain / 정상 종료 못 해도 그냥 제거 허용, Pod eviction 실패 무시, kubelet 응답 없어도 계속 진행
- 위의 옵션을 주어 강제로 삭제 진행
1
| ansible-playbook -i inventory/mycluster/inventory.ini -v remove-node.yml -e node=k8s-node5 -e reset_nodes=false -e allow_ungraceful_removal=true -e skip_confirmation=true
|
(참고): 노드 제거 실행 TASK: cat roles/remove-node/post-remove/tasks/main.yml
1
2
| ssh k8s-node5 systemctl status kubelet --no-pager
ssh k8s-node5 tree /etc/kubernetes
|
k8s-node5 초기화
제거 대상 노드에서 kubeadm reset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| kubeadm reset -f
# 아래 업데이트 필요
# 디렉터리/파일 삭제
rm -rf /etc/cni/net.d
rm -rf /etc/kubernetes/
rm -rf /var/lib/kubelet
# iptables 정리
iptables -t nat -S
iptables -t filter -S
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X
# 서비스 중지
systemctl status containerd --no-pager
systemctl status kubelet --no-pager
# kubelet 서비스 중지 -> 제거해보자
systemctl stop kubelet && systemctl disable kubelet
# contrainrd 서비스 중지 -> 제거해보자
systemctl stop containerd && systemctl disable containerd
# reboot
reboot
|
host OS에서 k8s-node5 제거후 새로 생성
1
2
3
4
5
6
| # vagrant 로 k8s-node5 제거
vagrant destroy -f k8s-node5
vagrant status
# vagrant 로 k8s-node5 다시 생성(프로비저닝, 스크립트 반영)
vagrant up k8s-node5
|
admin-lb에서 워커노드 추가 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # k8s-node5 ping 통신 확인
ping -c 1 192.168.10.15
PING 192.168.10.15 (192.168.10.15) 56(84) bytes of data.
64 bytes from 192.168.10.15: icmp_seq=1 ttl=64 time=0.461 ms
# 실패!
ansible -i inventory/mycluster/inventory.ini k8s-node5 -m ping
# 성공!
sshpass -p 'qwe123' ssh-copy-id -o StrictHostKeyChecking=no root@192.168.10.15
nsible -i inventory/mycluster/inventory.ini k8s-node5 -m ping
# 워커 노드 추가 수행 : 3분 정도 소요
ANSIBLE_FORCE_COLOR=true ansible-playbook -i inventory/mycluster/inventory.ini -v scale.yml --limit=k8s-node5 -e kube_version="1.32.9" | tee kubespray_add_worker_node.log
# 확인
kubectl get node -owide
# 변경 정보 확인
ssh k8s-node5 tree /etc/kubernetes
ssh k8s-node5 tree /var/lib/kubelet
ssh k8s-node5 pstree -a
# 샘플 파드 분배
kubectl get pod -owide
kubectl scale deployment webpod --replicas 1
kubectl get pod -owide
kubectl scale deployment webpod --replicas 2
|