들어가며#
이전 글에서 VNC와 KVM 환경을 구축했습니다. 이번 글에서는 실제로 VM 3개를 생성하고 Kubernetes 클러스터를 설치하는 과정을 다룹니다.
문제 발견: macvlan의 한계#
Part 1에서 WiFi 브릿지를 위해 macvlan을 설정했지만, 실제 VM에서 apt 업데이트가 불가능한 문제가 발생했습니다.
원인: WiFi는 Layer 2 브릿지를 완벽히 지원하지 않아, macvlan으로 설정한 VM이 외부 네트워크에 제대로 접근하지 못했습니다.
해결: NAT 네트워크(libvirt default)로 전환
1
2
3
| # macvlan 대신 NAT 네트워크 사용
# VM은 192.168.122.0/24 대역 사용
# 호스트를 통해 외부 통신
|
VM 생성 (3개 노드)#
VM 사양#
| VM | 역할 | IP | CPU | Memory | Disk |
|---|
| k8s-master | control-plane | 192.168.122.10 | 4 cores | 8GB | 50GB |
| k8s-worker1 | worker | 192.168.122.11 | 4 cores | 8GB | 50GB |
| k8s-worker2 | worker | 192.168.122.12 | 4 cores | 8GB | 50GB |
Ubuntu ISO 준비#
1
2
3
4
| # Ubuntu Server 24.04 ARM64 ISO 다운로드
mkdir -p ~/iso
cd ~/iso
wget https://cdimage.ubuntu.com/releases/24.04.4/release/ubuntu-24.04.4-live-server-arm64.iso
|
VNC로 VM 생성#
VNC 클라이언트로 접속 후 virt-manager 실행:
- virt-manager 실행
- “New Virtual Machine” 클릭
- 설정:
- Installation media: ubuntu-24.04.4-live-server-arm64.iso 선택
- Memory: 8192 MB
- CPUs: 4
- Storage: 50 GB
- Network: default (NAT)
- 3개 VM 생성 (k8s-master, k8s-worker1, k8s-worker2)
네트워크 고정 IP 설정#
DHCP로 할당받은 IP를 고정으로 변경합니다.
주의사항#
⚠️ 인터페이스 이름 확인: Ubuntu VM의 기본 네트워크 인터페이스는 enp1s0입니다 (eth0가 아님!)
1
2
3
4
| # 인터페이스 확인
ip link show
# 1: lo: ...
# 2: enp1s0: ... ← 이것 사용
|
netplan 설정#
각 VM에서 실행:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # /etc/netplan/99-static.yaml 생성
sudo tee /etc/netplan/99-static.yaml > /dev/null << 'EOF'
network:
version: 2
ethernets:
enp1s0:
dhcp4: false
addresses: [192.168.122.10/24] # VM마다 .10, .11, .12
routes:
- to: default
via: 192.168.122.1
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
EOF
# 권한 설정
sudo chmod 600 /etc/netplan/99-static.yaml
# 적용
sudo netplan apply
|
SSH 키 설정#
호스트에서 각 VM에 접속하기 위한 SSH 키 설정:
1
2
3
4
5
6
7
8
9
10
11
| # SSH 키 생성 (호스트)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ''
# 공개키 복사 (각 VM)
ssh-copy-id ubuntu@192.168.122.10
ssh-copy-id ubuntu@192.168.122.11
ssh-copy-id ubuntu@192.168.122.12
# sudo NOPASSWD 설정 (각 VM에서)
echo "ubuntu ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ubuntu
sudo chmod 440 /etc/sudoers.d/ubuntu
|
Kubernetes 설치#
1단계: 시스템 준비 (모든 노드)#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # 스왑 비활성화
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
# 커널 모듈 로드
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 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
|
2단계: containerd 설치 (모든 노드)#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 필수 패키지
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
# containerd 설치
sudo apt-get install -y containerd
# containerd 설정
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# SystemdCgroup 활성화
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# 재시작
sudo systemctl restart containerd
sudo systemctl enable containerd
|
3단계: Kubernetes 패키지 설치 (모든 노드)#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # GPG 키 추가
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | \
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 저장소 추가
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
# 패키지 설치
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
# 버전 고정
sudo apt-mark hold kubelet kubeadm kubectl
# kubelet 활성화
sudo systemctl enable kubelet
|
4단계: Master 노드 초기화#
k8s-master (192.168.122.10)에서만 실행:
1
2
3
4
| sudo kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=192.168.122.10 \
--control-plane-endpoint=192.168.122.10
|
출력된 join 명령어를 복사해둡니다:
1
2
| kubeadm join 192.168.122.10:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
|
5단계: kubectl 설정 (Master)#
1
2
3
| mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
6단계: Flannel CNI 설치 (Master)#
1
| kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
7단계: Worker 노드 Join#
k8s-worker1, k8s-worker2에서 실행:
1
2
3
| # Master에서 복사한 join 명령어 실행
sudo kubeadm join 192.168.122.10:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
|
노드 상태 확인#
1
| kubectl get nodes -o wide
|
예상 출력:
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane 5m v1.29.15
k8s-worker1 Ready <none> 4m v1.29.15
k8s-worker2 Ready <none> 4m v1.29.15
Pod 상태 확인#
1
| kubectl get pods --all-namespaces
|
모든 Pod가 Running 상태여야 합니다.
nginx 테스트 배포#
1
2
3
4
5
6
7
8
9
10
| # Deployment 생성
kubectl create deployment nginx-test --image=nginx
# Service 노출
kubectl expose deployment nginx-test --port=80 --type=NodePort
# 접속 테스트
NODEPORT=$(kubectl get svc nginx-test -o jsonpath='{.spec.ports[0].nodePort}')
curl http://192.168.122.10:$NODEPORT
# "Welcome to nginx!" 출력되면 성공
|
트러블슈팅#
Pod이 Pending 상태#
1
2
3
4
5
| # Pod 상세 정보 확인
kubectl describe pod <pod-name>
# 노드 이벤트 확인
kubectl get events --all-namespaces --sort-by='.lastTimestamp'
|
containerd 문제#
1
2
| sudo systemctl status containerd
sudo journalctl -u containerd -f
|
kubelet 문제#
1
2
| sudo systemctl status kubelet
sudo journalctl -u kubelet -f
|
클러스터 초기화 (재시작)#
1
2
3
4
5
6
7
8
| # Master 노드
sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
sudo rm -rf ~/.kube
# Worker 노드
sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
|
소요 시간#
| 단계 | 시간 |
|---|
| VM 3개 생성 | 20분 |
| 네트워크 설정 | 10분 |
| Kubernetes 패키지 설치 | 5분 |
| 클러스터 초기화 | 3분 |
| 검증 | 2분 |
| 총합 | 약 40분 |
Bonus: Ansible 자동화#
수동 설치가 번거롭다면 Ansible playbook으로 자동화할 수 있습니다. 전체 클러스터 구축을 10분 안에 완료할 수 있는 playbook을 작성할 수 있습니다.
필요한 파일:
inventory/hosts: 노드 IP 정보group_vars/all.yml: 설정 변수 (k8s 버전, 네트워크)k8s-cluster.yml: 메인 playbooktest-nginx.yml: nginx 테스트 playbook
실행 방법:
1
2
3
4
5
| # 클러스터 구축
ansible-playbook -i inventory/hosts k8s-cluster.yml
# nginx 테스트
ansible-playbook -i inventory/hosts test-nginx.yml
|
다음 단계#
Kubernetes 클러스터가 준비되었으니, 이제 실전 애플리케이션을 배포해볼 차례입니다:
- Persistent Volume 설정
- Ingress Controller 설치
- Monitoring (Prometheus + Grafana)
- CI/CD 파이프라인 구축
다음 글에서는 실제 애플리케이션 배포와 모니터링 환경 구축을 다루겠습니다.
참고 자료#