[HomeLab] 맨땅에 헤딩: Kubeadm으로 Kubernetes 클러스터 직접 구축하기 (Rocky Linux 9)
요약 (Abstract)
클라우드(EKS, GKE)의 편안함을 뒤로하고, 인프라 엔지니어의 야성을 되찾기 위해 홈 서버(VMware) 위에 Kubernetes 클러스터를 직접 구축합니다. Rocky Linux 9 환경에서 Containerd 런타임 구성부터 Kubeadm Init, 그리고 Calico CNI 설치까지의 전 과정을 'Copy & Paste' 수준으로 상세히 기록합니다.
1. 구축 환경 및 아키텍처 (Architecture)
단순한 기능 테스트가 아닌, 실제 운영 환경과 유사한 Multi-Node 클러스터를 구성합니다. Master 노드 1대와 Worker 노드 2대로 구성하여 추후 스케줄링 및 부하 분산 테스트가 가능하도록 설계했습니다.
- OS: Rocky Linux 9.4 (Minimal Install)
- Container Runtime: containerd
- Kubernetes Version: v1.28 (안정성 고려)
- CNI: Calico
[유효하지 않은 URL 삭제됨]
| Hostname | Role | vCPU | RAM | IP (Private) | 비고 |
| k8s-master | Control Plane | 2 | 4GB | 192.168.75.110 | API Server, Scheduler |
| k8s-worker1 | Worker | 4 | 8GB | 192.168.75.111 | 실제 워크로드 실행 |
| k8s-worker2 | Worker | 4 | 8GB | 192.168.75.112 | 실제 워크로드 실행 |
2. 사전 준비 (Prerequisites) - 모든 노드 공통
쿠버네티스는 까다로운 친구입니다. OS 설정을 완벽하게 맞추지 않으면 설치 중간에 반드시 에러를 뱉어냅니다. 아래 작업은 마스터와 워커 모든 노드에서 수행해야 합니다.
2.1. Swap 비활성화 (필수)
Kubelet이 메모리를 정확하게 관리하기 위해 스왑 메모리를 꺼야 합니다.
Bash
# 일시적 끄기
sudo swapoff -a
# 영구적 끄기 (fstab 주석 처리)
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
2.2. SELinux 및 방화벽 설정
실습의 편의를 위해 방화벽을 내리고 SELinux를 Permissive로 설정합니다. (운영 환경에서는 포트 오픈 권장)
Bash
# SELinux Permissive 모드
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# Firewalld 중지
sudo systemctl stop firewalld
sudo systemctl disable firewalld
2.3. 커널 모듈 로드 및 브리지 설정
컨테이너 간 통신을 위해 커널 모듈을 로드하고 네트워크 설정을 변경합니다.
Bash
# 모듈 로드
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 커널 파라미터 적용
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
3. 런타임 및 K8s 도구 설치 - 모든 노드 공통
3.1. Containerd 설치
Docker 대신 K8s 표준 런타임인 containerd를 설치합니다.
Bash
# Docker Repository 추가 (Containerd 패키지 포함)
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# Containerd 설치
sudo dnf install -y containerd.io
# 기본 설정 파일 생성 및 Systemd Cgroup 활성화
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl enable --now containerd
3.2. Kubeadm, Kubelet, Kubectl 설치
Bash
# Kubernetes Repo 추가
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
EOF
# 패키지 설치
sudo dnf install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
4. 클러스터 초기화 (Init) - Master Node Only
이제 대망의 클러스터 생성입니다. 마스터 노드에서만 수행합니다.
Bash
# 클러스터 초기화 (Pod Network CIDR은 Calico 기본값 사용)
sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=192.168.75.110
성공적으로 완료되면 아래와 같은 **"Join Command"**가 출력됩니다. 이 명령어는 워커 노드 연결에 필요하니 따로 복사해둡니다.
4.1. Kubectl 권한 설정
Bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
4.2. CNI (Calico) 설치
네트워크 플러그인이 없으면 노드는 NotReady 상태로 남습니다. Calico를 설치해줍니다.
Bash
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml
5. 워커 노드 연결 (Join) - Worker Node Only
이제 **워커 노드(Worker1, Worker2)**로 이동하여, 아까 복사해둔 Join 명령어를 붙여넣습니다.
Bash
# 예시 (반드시 본인의 마스터 노드에서 출력된 명령어를 사용하세요)
sudo kubeadm join 192.168.75.110:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<HASH>
6. 구축 검증 (Verification)
다시 마스터 노드로 돌아와 모든 노드가 정상적으로 연결되었는지 확인합니다.
Bash
kubectl get nodes
모든 노드의 STATUS가 **Ready**로 변했다면 구축 성공입니다!
7. 마치며
이제 제 홈랩에는 3개의 노드로 이루어진 든든한 쿠버네티스 클러스터가 생겼습니다. EKS 버튼 하나면 되는 세상이라지만, 직접 설정 파일과 씨름하며 띄운 클러스터는 그 애착이 다릅니다.
다음 포스트에서는 이 클러스터 위에 ArgoCD를 올리고 GitOps 환경을 구축하는 과정을 다뤄보겠습니다. 드디어 본격적인 DevOps의 시작입니다.