전체 목차

 

이전 챕터에서 쿠버네티스 클러스터를 설치하기 위한 시스템 준비를 완료 했습니다.

이번에는 containerd 및 쿠버네티스 클러스터에서 필요한 kubelet, kubeadm, kubectl 등 필수 패키지를 설치하겠습니다.

  • containerd : Container Runtime, 실제 컨테이너를 실행하고 관리하는 하위 런타임, 쿠버네티스의 명령을 받아 이미지를 다운로드 하고 컨테이너를 띄우는 것을 담당합니다.
  • kubelet : 각 노드마다 상주하는 핵심 데몬입니다. 마스터의 명령을 받아 컨테이너가 잘 돌아가는지 감시합니다.
  • kubeadm : 쿠버네티스 클러스터를 쉽고 표준화된 방식으로 설치/설정해주는 도구입니다. 마스터 노드를 초기화(init)하거나 워커노드를 조인(join)시킬 때 사용합니다.
  • kubectl : 사용자가 쿠버네티스에 멸령을 내릴 때 쓰는 터미널 도구입니다. API 서버와 통신하여 pod를 띄우거나, 상태를 확인하고, 로그를 보는 등의 명령을 전달 하는 도구입니다. CLI 환경에서 운영할 때 가장 많이 사용하게 됩니다.

1. containerd 설치 (모든 노드)

1.1. 설치

basscraft@master:~$ sudo apt update
... 생략 ...
basscraft@master:~$ sudo apt install -y containerd
... 생략 ...

 

버전 확인

basscraft@master:~$ containerd --version
containerd github.com/containerd/containerd 1.7.28
basscraft@master:~$

containerd 1.7.28 설치 확인

 

1.2. 기본 설정 파일 생성

먼저 디렉토리를 생성 합니다.

basscraft@master:~$ sudo mkdir -p /etc/containerd

 

basscraft@master:~$ containerd config default | sudo tee /etc/containerd/config.toml
... 생략 ...

 

1.3. SystemdCgroup 활성화

/etc/containerd/config.toml 파일에서 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] 아래에 근처에 SystemdCgroup = false 를 찾아서  true로 변경 (systemd_group 아님)

... 생략 ...
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            BinaryName = ""
            CriuImagePath = ""
            CriuPath = ""
            CriuWorkPath = ""
            IoGid = 0
            IoUid = 0
            NoNewKeyring = false
            NoPivotRoot = false
            Root = ""
            ShimCgroup = ""
            SystemdCgroup = true  # false => true 로 변경
... 생략 ...

이 설정이 누락되면 etcd와 kubelet이 충돌을 일으킴

 

1.4. containerd 서비스 재시작 및 활성화

basscraft@master:~$ sudo systemctl restart containerd
basscraft@master:~$ sudo systemctl enable containerd

 

상태 확인

basscraft@master:~$ sudo systemctl status containerd
● containerd.service - containerd container runtime
     Loaded: loaded (/usr/lib/systemd/system/containerd.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-12-18 15:27:31 UTC; 7min ago
       Docs: https://containerd.io
   Main PID: 35979 (containerd)
      Tasks: 18
     Memory: 15.0M (peak: 16.3M)
        CPU: 359ms
     CGroup: /system.slice/containerd.service
             └─35979 /usr/bin/containerd

... 생략 ...

 

Active: active (running) 상태 확인

2. Kubernetes 유틸리티 설치 (모든 노드)

2.1. 필수 패키지 설치

$ sudo apt update
... 생략 ...
$ sudo apt install -y apt-transport-https ca-certificates curl gpg
... 생략 ...

 

2.2. Kubernetes 공식 저장소 추가 (Ubuntu 24.04 권장)

구글 클라우드 퍼블릭 서명 키 다운로드

$ sudo mkdir -p -m 755 /etc/apt/keyrings
$ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes.gpg

 

쿠버네티스 저장소 추가

$ echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

2.3. kubelet / kubeadm / kubectl 설치

$ sudo apt update
$ sudo apt install -y kubelet kubeadm kubectl

 

설치 확인

$ kubelet --version
Kubernetes v1.30.14

$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"30", GitVersion:"v1.30.14", GitCommit:"9e18483918821121abdf9aa82bc14d66df5d68cd", GitTreeState:"clean", BuildDate:"2025-06-17T18:34:53Z", GoVersion:"go1.23.10", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl version --client
Client Version: v1.30.14
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3

 

자동 업그레이드 방지 (필수)

클러스터 구성 중 버전이 바뀌는 사고 방지

$ sudo apt-mark hold kubelet kubeadm kubectl containerd
kubelet set on hold.
kubeadm set on hold.
kubectl set on hold.
containerd set on hold.

 

2.4. kubelet 서비스 상태 확인

$ systemctl status kubelet
○ kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: inactive (dead)
       Docs: https://kubernetes.io/docs/
$

kubeadm init 전이기 때문에 active (running) 이 아니어도 정상입니다.

여기까지 쿠버네티스 클러스터를 구성하는데 필요한 기초 패키지를 설치 했습니다.

 

3. 마스터 노드 초기화 (마스터 노드 만 실행)

kubeadm init 로 마스터 노드를 준비합니다.

3.1. kubeadm init

basscraft@master:~$ sudo kubeadm init \
  --apiserver-advertise-address=192.168.2.100 \
  --pod-network-cidr=10.244.0.0/16
  
  ... 생략 ...
  
  Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.2.100:6443 --token nkceea.ry6d7lihycx2u6y3 \
        --discovery-token-ca-cert-hash sha256:보안삭제
basscraft@master:~$

Pod 네트워크는 각 노드의 물리적 네트워크와 곂치면 안됩니다.

이를 위해 사설 IP로 pod 네트워크 범위를 지정해 줍니다.

 

성공시 마지막에 나오는 kubeadm join 192.168.2.100:6443 --token ... 값을 복사해서 보관합니다.

(나중에 워커 노드를 연결 할 때 사용)

 

3.2. kubectl 권한 설정

관리자 (여기서는 basscraft ) 계정의 홈디렉토리 하위에 .kube 디렉토리를 만들고 /etc/kubernetes/admin.conf 파일을 복사 합니다.

admin.conf 파일은 root 소유 이므로 sudo 권한이 필요 하며 복사 후에 관리자 계정 소유로 변경(chown) 해줍니다.

basscraft@master:~$ mkdir -p $HOME/.kube
basscraft@master:~$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
basscraft@master:~$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

3.3 Pod 네트워크 Flannel 설치

Fannel 은 서로 다른 노드에 흩어져 있는 포드들이 마치 하나의 스위칭 허브에 연결된 것처럼 통신할 수 있게 해주는 L3 가상 네트워크를 제공합니다.

basscraft@master:~$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
basscraft@master:~$

모두 정상 생성되었습니다.

3.4. 상태 확인

Fannel 설치 후 1~2분 정도 지나고 상태를 확인합니다.

 

마스터 노드가 Ready 상태인지 확인합니다.

basscraft@master:~$ kubectl get nodes
NAME     STATUS   ROLES           AGE   VERSION
master   Ready    control-plane   10m   v1.30.14
basscraft@master:~$

 

모든 시스템 Pod가 Running 상태인지 확인합니다.

basscraft@master:~$ kubectl get pods -A
NAMESPACE      NAME                             READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-s8tg8            1/1     Running   0          3m7s
kube-system    coredns-55cb58b774-g7f5v         1/1     Running   0          10m
kube-system    coredns-55cb58b774-h2sqz         1/1     Running   0          10m
kube-system    etcd-master                      1/1     Running   0          10m
kube-system    kube-apiserver-master            1/1     Running   0          10m
kube-system    kube-controller-manager-master   1/1     Running   0          10m
kube-system    kube-proxy-vcp94                 1/1     Running   0          10m
kube-system    kube-scheduler-master            1/1     Running   0          10m
basscraft@master:~$

모두 Running 상태로 확인 됩니다.

 

참고 : Fannel 설치 후 각 pod들이 Running 상태가 되기 까지는 약 1~2분 정도 시간이 걸립니다.

 

 

4. 방화벽 설정

이제 워커노드를 설정하기 전에 방화벽 관련 설정을 먼저 하겠습니다.

사설 네트워크 환경이더라도 만일을 위해 방화벽은 항상 활성화 시켜두는 것이 좋습니다.

4.1. 우분투 방화벽(ufw) 설치

방화벽이 설치 되지 않았으면 설치 합니다.

$ sudo ufw status
sudo: ufw: command not found
$ sudo apt install -y ufw

 

방화벽이 활성화 되어 있지 않으면 활성화 합니다.

basscraft@master:~$ sudo ufw status
Status: inactive
basscraft@master:~$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
basscraft@master:~$ sudo ufw status
Status: active
basscraft@master:~$

 

4.2. 마스터 노드 포트 정책

마스터 노드에 필요한 포트들 입니다.

  • 22/tcp : SSH 접속용
  • 6443/tcp : Kubernetes API Server (Kubernetes의 중앙 제어 API)
  • 10250/tcp : Kuberlet API 통신
  • 2379/tcp : etcd Client API (Kubernetes 상태 데이터 저장소 접근)
  • 2380/tcp : etcd Peer Port (etcd 노드 간 복제/동기화 통신)
  • 10257/tcp, 10259/tcp : 스케쥴러 및 컨트롤러 매니저
  • 8285/udp, 8472/udp : Fannel CNI 통신 (Pod 간 통신용)
$ sudo ufw allow from 192.168.2.0/24 to any port 22 proto tcp comment 'Local Network'
$ sudo ufw allow from 192.168.2.0/24 to any port 6443 proto tcp comment 'K8s kube-apiserver'
$ sudo ufw allow from 192.168.2.0/24 to any port 10250 proto tcp comment 'K8s kubelet API'
$ sudo ufw allow from 192.168.2.100 to any port 2379 proto tcp comment 'K8s etcd client (local)'
$ sudo ufw allow from 192.168.2.100 to any port 2380 proto tcp comment 'K8s etcd peer (local)'
$ sudo ufw allow from 192.168.2.0/24 to any port 10257 proto tcp comment 'K8s Scheduler & Controller'
$ sudo ufw allow from 192.168.2.0/24 to any port 10259 proto tcp comment 'K8s Scheduler & Controller'
$ sudo ufw allow from 192.168.2.0/24 to any port 8285 proto udp comment 'K8s Flannel CNI'
$ sudo ufw allow from 192.168.2.0/24 to any port 8472 proto udp comment 'K8s Flannel CNI'
$ sudo ufw allow from 192.168.2.0/24

$ sudo ufw reload
Firewall reloaded

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       192.168.2.0/24             # Local Network
6443/tcp                   ALLOW       192.168.2.0/24             # K8s kube-apiserver
2379/tcp                   ALLOW       192.168.2.100              # K8s etcd client (local)
2380/tcp                   ALLOW       192.168.2.100              # K8s etcd peer (local)
10257/tcp                  ALLOW       192.168.2.0/24             # K8s Scheduler & Controller
10259/tcp                  ALLOW       192.168.2.0/24             # K8s Scheduler & Controller
8285/udp                   ALLOW       192.168.2.0/24             # K8s Flannel CNI
8472/udp                   ALLOW       192.168.2.0/24             # K8s Flannel CNI
10250/tcp                  ALLOW       192.168.2.0/24             # K8s kubelet API
Anywhere                   ALLOW       192.168.2.0/24

$

 

4.3. 워커 노드 포트 정책

워커 노드에 필요한 포트들 입니다.

  • 10250/tcp : Kubelet HTTPS API (마스터가 워커 노드의 kubelet을 관리 하기 위한 포트, Master -> Worker)
  • 8472/udp, 8285/udp : Flannel VXLAN Overlay Network ( 노드 간 Pod-to-Pod 오버레이 네트워크, Worker <-> Worker, Worker <-> Master)
  • 30000–32767/tcp : Kubernetes NodePort Service Range (외부(로컬 네트워크)에서 서비스 접근, 외부 -> Worker)
$ sudo ufw allow from 192.168.2.0/24 to any port 22 proto tcp comment 'SSH'
$ sudo ufw allow from 192.168.2.100 to any port 10250 proto tcp comment 'K8s kubelet API'
$ sudo ufw allow from 192.168.2.0/24 to any port 8285 proto udp comment 'K8s Flannel VXLAN'
$ sudo ufw allow from 192.168.2.0/24 to any port 8472 proto udp comment 'K8s Flannel VXLAN'
$ sudo ufw allow from 192.168.2.0/24 to any port 30000:32767 proto tcp comment 'K8s NodePort range'
$ sudo ufw allow from 192.168.2.0/24

$ sudo ufw reload
Firewall reloaded


$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       192.168.2.0/24             # Local Network
10250/tcp                  ALLOW       192.168.2.100              # K8s kubelet API
8285/udp                   ALLOW       192.168.2.0/24             # K8s Flannel VXLAN
8472/udp                   ALLOW       192.168.2.0/24             # K8s Flannel VXLAN
30000:32767/tcp            ALLOW       192.168.2.0/24             # K8s NodePort range
Anywhere                   ALLOW       192.168.2.0/24

$

 

5. 토큰 생성 (마스터 노드에서 실행)

3.1. kubeadm init 에서 생성된 토큰을 사용하므로 반드시 새로 생성할 필요는 없습니다.

kubeadm init 에서 생성된 토큰을 사용해 보았는데 정상적으로 실행되지 않아서 토큰을 새로 생성했습니다.

basscraft@master:~$ kubeadm token create --print-join-command
kubeadm join 192.168.2.100:6443 --token 보안삭제 --discovery-token-ca-cert-hash sha256:보안삭제
basscraft@master:~$

 

6. 워커노드 Join (워커노드에서 실행)

6.1. 포트 활성화 확인

마스터 노드의 kube-apiserver 포트로 접속이 가능한지 확인

basscraft@node1:~$ nc -zv 192.168.2.100 6443
Connection to 192.168.2.100 6443 port [tcp/*] succeeded!
basscraft@node1:~$

정상 적으로 접속 가능 합니다.

 

6.2 각 워커노드에서 Join 실행

basscraft@node1:~$ sudo kubeadm join 192.168.2.100:6443 \
  --token 보안삭제 \
  --discovery-token-ca-cert-hash sha256:보안삭제
... 생략 ...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

basscraft@node1:~$

This node has joined the cluster 로 정상 Join 확인

 

7. 노드 상태 확인 (마스터 노드에서 실행)

7.1. 노드 상태 확인

워커노드 Join 후 최초 상태 NotReady -> 30초 ~ 1분후 Ready 상태로 바뀝니다.

basscraft@master:~$ kubectl get nodes -o wide
NAME     STATUS     ROLES           AGE     VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                                                                                                                                     KERNEL-VERSION     CONTAINER-RUNTIME
master   Ready      control-plane   88m     v1.30.14   192.168.2.100   <none>        Ubuntu 24.04.3 L                                                                                                                        TS   6.8.0-90-generic   containerd://1.7.28
node1    NotReady   <none>          7m25s   v1.30.14   192.168.2.101   <none>        Ubuntu 24.04.3 L                                                                                                                        TS   6.8.0-1043-raspi   containerd://1.7.28
node2    NotReady   <none>          7m25s   v1.30.14   192.168.2.102   <none>        Ubuntu 24.04.3 L                                                                                                                        TS   6.8.0-1043-raspi   containerd://1.7.28
node3    NotReady   <none>          7m24s   v1.30.14   192.168.2.103   <none>        Ubuntu 24.04.3 L                                                                                                                        TS   6.8.0-1043-raspi   containerd://1.7.28
basscraft@master:~$ kubectl get pods -n kube-flannel -o wide
NAME                    READY   STATUS     RESTARTS   AGE     IP              NODE     NOMINATED NODE                                                                                                                           READINESS GATES
kube-flannel-ds-86ntt   1/1     Running    0          79m     192.168.2.100   master   <none>                                                                                                                                   <none>
kube-flannel-ds-kqf8s   0/1     Init:1/2   0          8m55s   192.168.2.102   node2    <none>                                                                                                                                   <none>
kube-flannel-ds-llb5r   0/1     Init:1/2   0          8m54s   192.168.2.103   node3    <none>                                                                                                                                   <none>
kube-flannel-ds-mrxfx   0/1     Init:1/2   0          8m55s   192.168.2.101   node1    <none>                                                                                                                                   <none>
basscraft@master:~$

 

시간이 지나도 Ready 상태로 바뀌지 않은 경우 각 워커노드에서 서비스를 재시작 함 => 워커 노드의 사양이 떨어져서 약 10분 정도 소요됨

basscraft@node1:~$ sudo systemctl restart containerd
basscraft@node1:~$ sudo systemctl restart kubelet

 

이후 마스터 노드에서 정상 확인함

basscraft@master:~$ kubectl get nodes -o wide
NAME     STATUS   ROLES           AGE    VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
master   Ready    control-plane   106m   v1.30.14   192.168.2.100   <none>        Ubuntu 24.04.3 LTS   6.8.0-90-generic   containerd://1.7.28
node1    Ready    <none>          25m    v1.30.14   192.168.2.101   <none>        Ubuntu 24.04.3 LTS   6.8.0-1043-raspi   containerd://1.7.28
node2    Ready    <none>          25m    v1.30.14   192.168.2.102   <none>        Ubuntu 24.04.3 LTS   6.8.0-1043-raspi   containerd://1.7.28
node3    Ready    <none>          25m    v1.30.14   192.168.2.103   <none>        Ubuntu 24.04.3 LTS   6.8.0-1043-raspi   containerd://1.7.28
basscraft@master:~$

STATUS Ready 면 정상

 

7.2. Flannel 정상 동작 확인

basscraft@master:~$ kubectl get pods -n kube-flannel
NAME                    READY   STATUS    RESTARTS   AGE
kube-flannel-ds-86ntt   1/1     Running   0          101m
kube-flannel-ds-kqf8s   1/1     Running   0          30m
kube-flannel-ds-llb5r   1/1     Running   0          30m
kube-flannel-ds-mrxfx   1/1     Running   0          30m
basscraft@master:~$

STATUS 가 Running 면 정상

 

8. 클러스터 동작 검증 (마스터 노드)

8.1. 테스트 Deployment 배포

테스트로 nginx 앱을 배포해 보겠습니다.

basscraft@master:~$ kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
basscraft@master:~$

 

8.2. Pod 분산 확인

basscraft@master:~$ kubectl get pods -o wide
NAME                    READY   STATUS              RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
nginx-bf5d5cf98-ccswm   0/1     ContainerCreating   0          19s   <none>   node1   <none>           <none>
basscraft@master:~$

 

8.3. NodePort로 외부 접근 테스트

basscraft@master:~$ kubectl expose deployment nginx \
  --type=NodePort \
  --port=80
service/nginx exposed
basscraft@master:~$
basscraft@master:~$ kubectl get svc nginx
NAME    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.96.14.96   <none>        80:30625/TCP   24s
basscraft@master:~$

 

8.4. 브라우저에서 접근 확인

http://192.168.2.101:30625

http://192.168.2.102:30625

http://192.168.2.103:30625

 

여기까지 쿠버네티스 클러스터의 기본 설정 및 동작을 검증해 봤습니다.

9. 안전한 종료 (마스터 노드에서 실행)

전원을 종료하거나 쿠버네티스 클러스터를 재시작 해야 하는 경우, 항상 워커 노드 → 마지막에 마스터 노드 순서로 종료 해야 합니다. 마스터를 먼저 끄면 etcd 비정상 종료, 클러스터 상태 손상 위험이 있습니다.

 

모든 노드는 마스터에서 제어/상태 관리 합니다.

 

9.1. 종료 순서

node1 -> node2 -> node3 -> master

basscraft@master:~$ kubectl drain node1 --ignore-daemonsets --delete-emptydir-data
node/node1 cordoned
Warning: ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-mrxfx, kube-system/kube-proxy-qsqf6
node/node1 drained
basscraft@master:~$ kubectl drain node2 --ignore-daemonsets --delete-emptydir-data
node/node2 cordoned
Warning: ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-kqf8s, kube-system/kube-proxy-mh887
node/node2 drained
basscraft@master:~$ kubectl drain node3 --ignore-daemonsets --delete-emptydir-data
node/node3 cordoned
Warning: ignoring DaemonSet-managed Pods: kube-flannel/kube-flannel-ds-llb5r, kube-system/kube-proxy-drf7w
node/node3 drained
basscraft@master:~$

 

9.2. 종료 상태 확인

basscraft@master:~$ kubectl get nodes
NAME     STATUS                     ROLES           AGE    VERSION
master   Ready                      control-plane   133m   v1.30.14
node1    Ready,SchedulingDisabled   <none>          52m    v1.30.14
node2    Ready,SchedulingDisabled   <none>          52m    v1.30.14
node3    Ready,SchedulingDisabled   <none>          52m    v1.30.14
basscraft@master:~$

STATUS : Ready,SchedulingDisabled
ROLES : <none> 

정상 적용된 상태

 

9.3. 개별 노드 상세 확인

basscraft@master:~$ kubectl describe node node1
... 생략 ...
Unschedulable:      true
... 생략 ...

 

9.4. Pod 이동 여부 확인

basscraft@master:~$ kubectl get pods -A -o wide
NAMESPACE      NAME                             READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
default        nginx-bf5d5cf98-bjv8r            1/1     Running   0          8m38s   10.244.0.4      master   <none>           <none>
kube-flannel   kube-flannel-ds-86ntt            1/1     Running   0          130m    192.168.2.100   master   <none>           <none>
kube-flannel   kube-flannel-ds-kqf8s            1/1     Running   0          59m     192.168.2.102   node2    <none>           <none>
kube-flannel   kube-flannel-ds-llb5r            1/1     Running   0          59m     192.168.2.103   node3    <none>           <none>
kube-flannel   kube-flannel-ds-mrxfx            1/1     Running   0          59m     192.168.2.101   node1    <none>           <none>
kube-system    coredns-55cb58b774-68ccv         1/1     Running   0          140m    10.244.0.3      master   <none>           <none>
kube-system    coredns-55cb58b774-8vbcd         1/1     Running   0          140m    10.244.0.2      master   <none>           <none>
kube-system    etcd-master                      1/1     Running   0          140m    192.168.2.100   master   <none>           <none>
kube-system    kube-apiserver-master            1/1     Running   0          140m    192.168.2.100   master   <none>           <none>
kube-system    kube-controller-manager-master   1/1     Running   0          140m    192.168.2.100   master   <none>           <none>
kube-system    kube-proxy-drf7w                 1/1     Running   0          59m     192.168.2.103   node3    <none>           <none>
kube-system    kube-proxy-krvpq                 1/1     Running   0          140m    192.168.2.100   master   <none>           <none>
kube-system    kube-proxy-mh887                 1/1     Running   0          59m     192.168.2.102   node2    <none>           <none>
kube-system    kube-proxy-qsqf6                 1/1     Running   0          59m     192.168.2.101   node1    <none>           <none>
kube-system    kube-scheduler-master            1/1     Running   0          140m    192.168.2.100   master   <none>           <none>
basscraft@master:~$

 

10. 워커노드 종료 (각 워커노드에서 실행)

basscraft@node1:~$ sudo shutdown -h now
[sudo] password for basscraft:

Broadcast message from root@node1 on pts/1 (Fri 2025-12-19 03:46:32 KST):

The system will power off now!

basscraft@node1:~$

11. 마스터 노드 종료 (마스터 노드에서 실행)

11.1. 테스트용 이미지 삭제 (선택)

basscraft@master:~$ kubectl delete deployment nginx
basscraft@master:~$ kubectl delete svc nginx 2>/dev/null

 

11.2. 마스터 노드 전원 종료

basscraft@master:~$ sudo shutdown -h now
[sudo] password for basscraft:

Broadcast message from root@master on pts/1 (Fri 2025-12-19 03:46:32 KST):

The system will power off now!

basscraft@master:~$

 

 

12. 안전한 가동 (마스터 노드)

12.1. 마스터 부팅

마스터 OS 부팅이 완료 된 후 각 노드의 상태를 살펴 보면 connection refused 상태 입니다.

basscraft@master:~$ kubectl get nodes
E0119 07:15:36.459161   61933 memcache.go:265] couldn't get current server API group list: Get "https://192.168.2.100:6443/api?timeout=32s": dial tcp 192.168.2.100:6443: connect: connection refused
E0119 07:15:36.459663   61933 memcache.go:265] couldn't get current server API group list: Get "https://192.168.2.100:6443/api?timeout=32s": dial tcp 192.168.2.100:6443: connect: connection refused
E0119 07:15:36.461289   61933 memcache.go:265] couldn't get current server API group list: Get "https://192.168.2.100:6443/api?timeout=32s": dial tcp 192.168.2.100:6443: connect: connection refused
E0119 07:15:36.461578   61933 memcache.go:265] couldn't get current server API group list: Get "https://192.168.2.100:6443/api?timeout=32s": dial tcp 192.168.2.100:6443: connect: connection refused
E0119 07:15:36.463066   61933 memcache.go:265] couldn't get current server API group list: Get "https://192.168.2.100:6443/api?timeout=32s": dial tcp 192.168.2.100:6443: connect: connection refused
The connection to the server 192.168.2.100:6443 was refused - did you specify the right host or port?
basscraft@master:~$

12.2. 워커 부팅

워커 OS 부팅이 완료 되었다면 마스터 노드에서 아래 명령으로 각 노드를 활성화 시킵니다.

basscraft@master:~$ kubectl uncordon node1
basscraft@master:~$ kubectl uncordon node2
basscraft@master:~$ kubectl uncordon node3

 

개별 또는 아래 처럼 일괄 도 가틍합니다.

basscraft@master:~$ kubectl uncordon node1 node2 node3

 

node/node1 uncordoned

node/node2 uncordoned

node/node3 uncordoned

 

메시지가 나오면 정상 적으로 연결이 된 것 입니다.

 

12.3. 확인

basscraft@master:~$ kubectl get nodes
NAME     STATUS   ROLES           AGE   VERSION
master   Ready    control-plane   42h   v1.30.14
node1    Ready    <none>          41h   v1.30.14
node2    Ready    <none>          41h   v1.30.14
node3    Ready    <none>          41h   v1.30.14
basscraft@master:~$

끝.

+ Recent posts