kubernetes 를 핸즈온으로 공부하려면 로컬 머신에서 멀티 노드 클러스터를 구축하는게 가장 편리하다는 판단을 했다. 그래서 여러 가이드를 찾아보면서 처음에는 multipass 라는 가상화 도구를 사용해서 시도해보고, 그 다음에는 kind 라는 docker 컨테이너에 올리는 kubernetes 도구도 사용해봤는데, 내공이 부족하여 실패하였다. 결국 docker desktop 에서 간단히 활성화 할 수 있는 kind 로의 프로비저닝 방식을 사용하여 구축에 성공했다.
하지만, ingress 를 실습할 차례가 왔고, kind 방식으로는 네트워크 구성이 실제 멀티 노드 클러스터 환경과 달라서 실습이 불가능함을 깨달았다. 그래서, 실제 완전한 리눅스 OS와 동일하게 구성할 수 있는 UTM 가상화 도구를 사용해서 멀티 노드 클러스터를 구축했고, 그 과정을 기술한다.
1. UTM 설치
UTM 이라는 가상 머신 구축 도구를 m1 맥북에 설치한다.
2. 가상머신 생성
가상머신 3대를 Ubuntu 24.04.3 LTS OS를 설치하며 생성한다.
1대는 control plane 이고, 나머지 2대는 worker node 용도이다.
시스템 자원은 본인이 사용하는 컴퓨팅 리소스에 맞게 할당한다.
3. 클립보드 붙여넣기 설정
개발 편의성을 위해 호스트 머신과 각 게스트 머신간 복붙을 가능하게 하여야 한다.
CLI 만 사용중이라면 아래 두가지 방법이 있다.(spice-vdagent 는 GUI 용 클립보드 공유 에이전트이므로 상관하지 않는다.)
1) 리눅스 터미널에 openssh 를 설치하여 맥북에서 직접 ssh 접속
2) 가상머신의 display 장치를 삭제하고 직렬 포트 장치로 사용
직렬 포트 장치가 간단하지만, CLI 가 이상하게 표시되는 현상이 종종 있으므로, ssh 접속하는 방법이 사용성이 더 낫다.
4. hostname 설정(모든 노드)
아래 커맨드를 통해서 각 노드에 hostname 을 지정해준다.
$ sudo hostnamectl set-hostname <새 호스트명>
아래 커맨드를 통해서 정상적으로 hostname 이 설정되었는지 확인한다.
$ cat /etc/hostname
# 또는
$ hostname
# 또는
$ hostnamectl
5. /etc/hosts 수정(모든 노드)
각 노드에서 아래 명령어를 실행하여 enp0s1 장치의 inet 에 기재된 ip 를 확인한다.
$ sudo ip addr
각 노드의 /etc/hosts 파일에 나머지 노드의 ip 를 hostname 과 매핑해준다.
# master01 노드의 /etc/hosts 예시
...
127.0.1.1 master01
192.168.64.6 worker01
192.168.64.7 worker02
...
6. swapoff 및 영구 swapoff 적용(모든 노드)
아래 커맨드를 사용하여 각 노드에서 swapoff 를 적용한다.
$ sudo swapoff -a
아래 커맨드를 사용해 /etc/fstab 파일을 수정하여 부팅시마다 swapoff 가 자동 적용되도록 설정한다.(swap 설정을 주석처리하여 영구 비활성화)
$ sudo sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
7. 커널 네트워크에 브릿지 트래픽 허용(모든 노드)
아래 커맨드를 실행하여 브릿지 네트워크로부터 들어오는 트래픽을 허용한다.
$ cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# 설정 적용
$ sudo sysctl --system
8. containerd 설치(모든 노드)
아래 커맨드를 순차적으로 실행하여 각 노드에 containerd 를 설치한다.
# 1) 필요한 의존성 패키지 설치
$ sudo apt update
$ sudo apt install -y ca-certificates curl gnupg lsb-release
# 2) Docker의 APT repo 대신 Ubuntu 기본 repo 에서 containerd 설치
$ sudo apt install -y containerd
# 3) 기본 config 생성
$ sudo mkdir -p /etc/containerd
$ sudo containerd config default | sudo tee /etc/containerd/config.toml
# 4) 시스템에 맞춰 cgroup 설정(기본적으로 systemd cgroup 사용 권장)
# /etc/containerd/config.toml 에서 아래를 확인/적용:
# SystemdCgroup = true
$ sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml || true
# 5) pause:3.10 버전으로 수정(선택)
# (이건 kubernetes 1.31.3 버전과의 호환성을 위함이며, 사용하는 kubernetes 버전의 호환성을 확인하여 맞춰주시길 바랍니다.)
$ sudo sed -i 's|sandbox_image = "registry.k8s.io/pause:3.8"|sandbox_image = "registry.k8s.io/pause:3.10"|' \
/etc/containerd/config.toml
# 6) containerd 재시작/활성화
$ sudo systemctl restart containerd
$ sudo systemctl enable containerd
9. kubeadm, kubelet, kubectl 설치(모든 노드)
아래 커맨드를 순차적으로 실행하여 각 노드에 kubeadm, kubelet, kubectl 를 설치한다.
# 1) 필요한 의존성 패키지 설치
$ sudo apt-get update
$ sudo apt-get install -y apt-transport-https ca-certificates curl
# 2) APT 저장소의 서명 키(GPG key)를 보관할 디렉터리를 생성
$ sudo mkdir -p /etc/apt/keyrings
# 3) Kubernetes APT 저장소의 GPG 서명 키 다운로드 및 변환하여 저장(v1.31)
$ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 4) Kubernetes APT 저장소 등록
$ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /" | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update
# 5) 설치 (버전 고정 원하면 =<버전> 지정)
$ sudo apt-get install -y \
kubelet=1.31.3-1.1 \
kubeadm=1.31.3-1.1 \
kubectl=1.31.3-1.1
# 6) 자동 업그레이드 되지 않도록 버전 고정
$ sudo apt-mark hold kubelet kubeadm kubectl
# 7) kubelet 서비스 재시작
$ sudo systemctl enable kubelet && sudo systemctl restart kubelet
10. VM에 브릿지 네트워크 설정(모든 노드)
UTM 에서 네트워크 장치 추가 > 브릿지 네트워크 > 실제 접속중인 네트워크 인터페이스 선택 하고 저장한다.
노드 접속 후 아래 커맨드를 실행하여 enp0s2 장치에 inet 이 잡혔는지 확인한다.
$ sudo ip addr
안잡혔다면 아래 커맨드로 /etc/netplan/*.yaml 파일에 설정을 추가하고 적용한다.
# /etc/netplan/*.yaml 파일을 열어서 아래처럼 enp0s2 에 dhcp4 설정 추가
network:
version: 2
ethernets:
enp0s1:
dhcp4: true
enp0s2:
dhcp4: true
$ sudo netplan apply
sudo ip addr 을 실행하여 enp0s2 가 아직 DOWN 상태라면 아래 커맨드를 실행한다.
$ sudo ip link set enp0s2 up
11. 각 노드에 필요한 패키지들 설치
아래 커맨드를 실행하여 각 노드에 추가 패키지를 설치한다.
# k8s 구성 및 운영에 필요한 패키지들 설치
$ sudo apt-get update
$ sudo apt-get install -y \
conntrack \
ipset \
iptables \
ebtables \
ethtool \
socat \
ipvsadm
12. control-plane 초기화(master01 노드)
master 노드에서 아래 커맨드를 순차적으로 실행하여 kubernetes control plane 초기화를 진행한다.
# 초기화 실행. <MASTER_NODE_BRIDGE_IP> 에는 master 노드의 브릿지 네트워크 ip를 넣는다.
$ sudo kubeadm init --kubernetes-version=1.31.3 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=<MASTER_NODE_BRIDGE_IP>
# 성공 후 출력되는 메시지 가이드에 따라 진행하면 됩니다.(아래는 예시)
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
# flannel CNI 로 파드 네트워크 구성시 예시
$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
# flannel 파드 네트워크 제거 예시(CNI 파드 네트워크 구성중 문제 발생시 제거하고 다시 설치해야 할 때)
$ kubectl delete -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml --ignore-not-found=true
Then you can join any number of worker nodes by running the following on each as root:
# 아래 join 커맨드를 복사해놓고, 각 worker node 에서 실행해줍니다.
kubeadm join...
# 가이드에는 없는데, node join 후 control plane 에서 containerd 를 재시작 해줘야 함
$ sudo systemctl restart containerd
만약 중간에 실패하거나 다시 init 하려면 아래 커맨드로 reset 실행 후 다시 init 진행한다.
$ sudo kubeadm reset -f
$ sudo systemctl stop kubelet
$ sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X
$ sudo rm -rf /etc/cni/net.d & \
sudo ipvsadm --clear & \
sudo rm -rf $HOME/.kube/config & \
sudo rm -rf $HOME/.kube/cache
만약 flannel pod(DaemonSet) 가 생성되지 않는다면 모든 노드(master/worker)에서 아래 순서대로 실행한다.
# 모듈 로드
$ sudo modprobe br_netfilter
$ sudo modprobe overlay
# 부팅시 유지
$ cat <<'EOF' | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# 필요한 sysctl 설정 적용
cat <<'EOF' | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
EOF
$ sudo sysctl --system
master 노드에서 아래 명령어로 flannel 재시작 후 파드를 확인한다.
# flannel 재시작
$ kubectl -n kube-flannel rollout restart ds/kube-flannel-ds
# 정상 확인
$ kubectl -n kube-flannel get pods -o wide
$ kubectl -n kube-system get pods
13. host 머신에서 가상머신으로 공유 폴더 설정하기(선택)
UTM 에서 가상머신 편집 > 공유에서 아래를 설정한다.
- 디렉터리 공유 모드: VirtFS
- 경로: 공유폴더 지정
가상머신 부팅 및 로그인 후 아래 커맨드를 실행한다.
$ sudo mkdir /media/<공유폴더이름>
$ sudo mount -t 9p -o trans=virtio share /media/<공유폴더이름> -oversion=9p2000.L
$ sudo vi /etc/fstab
# 최하단에 아래 내용 추가하고 저장
share /media/<공유폴더이름> 9p trans=virtio,version=9p2000.L,rw,_netdev,nofail 0 0
이제 가상머신을 재실행하면 아래 경로에서 공유폴더를 확인 가능하다.
- /media/<공유폴더이름>
참고로, 공유폴더 외부에서 공유폴터 내부로 심볼릭 링크 된 파일은 가상머신에서 내용을 볼 수 없다.
'Linux' 카테고리의 다른 글
| [Linux] Debian 리눅스에서 apt update 및 install 불가 현상 해결 (1) | 2025.08.07 |
|---|---|
| [LINUX] 자주쓰는 dd 명령어 옵션 정리 (0) | 2025.05.04 |
| [LINUX] swap file 사용하기 (0) | 2025.05.04 |
| [LINUX] swap partition 사용하기 (0) | 2025.05.04 |
| [LINUX] swap 이해하기 및 활성/비활성하기 (디스크 스왑, 파일 스왑) (0) | 2025.05.04 |




