Kubespray를 선택한 이유
회사에서 개발, 배포, 실습 환경 등 다양한 목적으로 서버를 사용하는데, 각자 서버를 개별적으로 관리하다 보니 자원 충돌이나 관리 부실 같은 문제들이 종종 발생했습니다. 이런 문제를 체계적으로 해결하고 싶었고, ‘If Kakao 2024’에서 카카오의 사내 서버 관리 방식을 흥미롭게 본 것이 계기가 되었습니다. 카카오는 Packer, Ansible 등 다양한 도구를 활용해 복잡하고 자동화된 프로비저닝 시스템을 구축했지만, 저희 상황에서는 그 정도까지는 과하다고 판단했습니다. 그래서 핵심인 쿠버네티스만 먼저 도입하여 서버 관리를 시작해보기로 했습니다.
쿠버네티스 클러스터를 구축하는 도구는 kubeadm, kops 등 여러 가지가 있지만, 저희는 Kubespray를 선택했습니다. 이유는 다음과 같습니다.
- Ansible 기반 자동화: 저희 팀은 이미 Ansible에 익숙했기 때문에, 플레이북 기반으로 설치와 구성을 자동화하는 Kubespray가 가장 편하게 다가왔습니다.
- 다양한 환경 지원: 베어메탈 서버부터 AWS, GCP 같은 클라우드 환경까지 폭넓게 지원해서, 현재의 사내 인프라뿐만 아니라 미래의 클라우드 확장까지 고려할 수 있었습니다.
- 유연한 커스터마이징: Ansible의 장점을 그대로 살려, 클러스터 설정을 저희 요구에 맞게 세밀하게 조정하기 용이했습니다.
간단한 쿠버네티스 관리 도구 비교표
특징 | kubeadm | Kubespray | kops |
---|---|---|---|
관리 방식 | CLI 도구 | Ansible 플레이북 기반 | CLI 도구 |
주요 지원 환경 | 온프레미스, 클라우드 | 온프레미스, 클라우드 (가장 폭넓음) | 주로 AWS, GCE 등 클라우드 |
자동화 수준 | 클러스터 초기화 및 노드 추가에 중점 | 설치, 구성, 업그레이드 등 전체 라이프사이클 관리 | 클라우드 네이티브 자동화 |
특징 | Kubernetes 공식 도구, 간단한 클러스터용 | 다양한 구성 요소 선택 가능, Ansible 익숙 사용자에게 적합 | 클라우드 환경에서 가장 간편함 |
실습 환경 구성하기 (Vagrant + VMware)
본격적으로 사내 서버에 적용하기 전에, 로컬에서 안전하게 테스트해볼 환경이 필요했습니다. Vagrant와 VMware를 이용해 1개의 마스터 노드와 2개의 워커 노드로 구성된 가상 클러스터 환경을 만들었습니다.
이 글은 Kubespray에 초점을 맞추고 있으므로, Vagrant 설정에 대한 상세한 설명은 생략합니다. 단, VM 사용 시 관련 라이선스를 꼭 확인하시기 바랍니다.
사전 준비
- VMware Fusion, Vagrant, 관련 플러그인 설치
- SSH 키 생성 (
~/.ssh/id_rsa.pub
)
Vagrantfile 작성
Ubuntu 24.04 LTS 이미지를 기반으로 3개의 VM(master, worker1, worker2)을 생성하는 Vagrantfile
을 작성했습니다. 각 노드에는 외부 통신용과 클러스터 내부 통신용으로 두 개의 네트워크 인터페이스를 할당했습니다.
Vagrantfile 전체 코드 보기
# -*- mode: ruby -*-# vi: set ft=ruby :
Vagrant.configure("2") do |config|BOX_IMAGE = "gutehall/ubuntu24-04"
# VM 구성NODES = [ { :hostname => "master", :ip => "192.168.56.10", :ip_internal => "10.3.0.1", :memory => 2048, :cpus => 2 }, { :hostname => "worker1", :ip => "192.168.56.11", :ip_internal => "10.3.0.2", :memory => 2048, :cpus => 2 }, { :hostname => "worker2", :ip => "192.168.56.12", :ip_internal => "10.3.0.3", :memory => 2048, :cpus => 2 }]
# 각 노드 설정NODES.each do |node| config.vm.define node[:hostname] do |nodeconfig| nodeconfig.vm.box = BOX_IMAGE nodeconfig.vm.hostname = node[:hostname]
nodeconfig.vm.provider "vmware_desktop" do |v| v.memory = node[:memory] v.cpus = node[:cpus] v.gui = false end
nodeconfig.ssh.insert_key = false
nodeconfig.vm.network "private_network", ip: node[:ip] nodeconfig.vm.network "private_network", ip: node[:ip_internal]
nodeconfig.vm.provision "shell" do |s| ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip s.args = [ssh_pub_key] s.inline = <<-SHELL mkdir -p /root/.ssh echo $1 >> /root/.ssh/authorized_keys mkdir -p /home/vagrant/.ssh echo $1 >> /home/vagrant/.ssh/authorized_keys chown -R vagrant:vagrant /home/vagrant/.ssh SHELL end endendend
이제 터미널에서 vagrant up
명령어를 실행하면, 설정된 3개의 VM이 자동으로 생성되고 실행됩니다.
Kubespray로 클러스터 구축하기
VM 환경이 준비되었으니, 이제 Kubespray를 사용해 쿠버네티스를 설치할 차례입니다.
1. Kubespray 저장소 복제 및 인벤토리 설정
먼저 Kubespray 소스 코드를 가져오고, 클러스터 구성을 정의할 인벤토리 파일을 준비합니다.
git clone <https://github.com/kubernetes-sigs/kubespray.git>cd kubespraycp -r inventory/sample inventory/mycluster
inventory/mycluster/inventory.ini
파일은 Ansible이 어떤 노드에 어떤 역할을 할당할지 알려주는 설계도와 같습니다. 저희는 Vagrant로 만든 환경에 맞춰 아래와 같이 수정했습니다.
# 노드 정보 정의node1 ansible_user=vagrant ansible_host=192.168.56.10 ip=10.3.0.1node2 ansible_user=vagrant ansible_host=192.168.56.11 ip=10.3.0.2node3 ansible_user=vagrant ansible_host=192.168.56.12 ip=10.3.0.3
# 컨트롤 플레인 그룹[kube_control_plane]node1
# etcd 그룹 (데이터 안정성을 위해 홀수 개 노드로 구성)[etcd]node1node2node3
# 워커 노드 그룹[kube_node]node2node3
ansible_host
: Ansible이 SSH로 접속할 IP (호스트-게스트 통신용)ip
: 쿠버네티스 내부 통신용 IP (내부 네트워크용)
2. Kubespray 실행 환경 설정
의존성 충돌을 피하기 위해 Python 가상 환경을 만들고 필요한 라이브러리를 설치합니다.
# kubespray 디렉토리에서 실행python3 -m venv venvsource venv/bin/activatepip install -U -r requirements.txt
3. 호스트 연결 확인 및 클러스터 배포
배포 전에 Ansible이 모든 노드에 정상적으로 SSH 접속이 가능한지 ping
모듈로 확인합니다.
ansible all -i inventory/mycluster/inventory.ini -m ping --private-key=~/.ssh/id_rsa
SUCCESS
응답을 확인했다면, 이제 cluster.yml
플레이북을 실행하여 클러스터 배포를 시작합니다.
ansible-playbook -i inventory/mycluster/inventory.ini cluster.yml -b -v --private-key=~/.ssh/id_rsa
제 M3 Pro 맥북 기준으로 약 20분 정도 소요되었습니다. PLAY RECAP
에 failed=0
이 표시되면 성공적으로 배포가 완료된 것입니다.
클러스터 접근 설정 (kubeconfig)
클러스터가 성공적으로 구축되었지만, kubectl
로 클러스터에 명령을 내리려면 인증 정보가 담긴 kubeconfig
파일이 필요합니다.
1. kubeconfig 파일 가져오기
이 파일은 기본적으로 마스터 노드의 /etc/kubernetes/admin.conf
에 생성됩니다. 먼저 마스터 노드에 접속하여 파일 소유권을 변경한 뒤, 로컬 PC로 복사해옵니다.
# 마스터 노드 접속 및 권한 변경sudo chown vagrant:vagrant /etc/kubernetes/admin.confexit
# 로컬 PC에서 파일 복사mkdir -p ~/.kubechmod 600 ~/.kube/config
팁: 여러 클러스터를 관리한다면, ~/.kube/config 파일을 직접 덮어쓰기보다
/.kube/mycluster.config처럼 별도 파일로 관리하고, export KUBECONFIG=/.kube/mycluster.config 환경 변수를 사용하는 것이 안전합니다.
2. kubeconfig 파일 수정
로컬로 가져온 kubeconfig
파일에는 클러스터 API 서버 주소가 내부 IP로 되어 있을 수 있습니다. 외부에서 접속하려면 이 주소를 실제 접속 가능한 IP로 수정해야 합니다.
실습 환경에서는 Vagrant가 VM에 할당한 NAT IP를 사용해야 합니다. 먼저 마스터 노드의 NAT IP를 확인합니다.
# 예시 출력: 192.168.63.148
이제 ~/.kube/config
파일을 열어 server
주소를 확인된 IP로 수정합니다.
# vi ~/.kube/config...clusters:- cluster: certificate-authority-data: ... server: <https://192.168.63.148:6443> # <-- 이 부분을 확인된 IP로 수정...
3. 클러스터 상태 확인
모든 설정이 끝났습니다. 이제 로컬 터미널에서 kubectl
명령어로 클러스터의 노드 상태를 확인해 봅니다.
kubectl get nodes
NAME STATUS ROLES AGE VERSIONnode1 Ready control-plane 165m v1.31.3node2 Ready <none> 164m v1.31.3node3 Ready <none> 164m v1.31.3
위와 같이 모든 노드가 Ready
상태로 보인다면, Kubespray를 이용한 쿠버네티스 클러스터 구축이 성공적으로 완료된 것입니다. 다음 포스팅에서는 이 클러스터 위에 CI/CD를 위한 GitHub Actions Runner를 배포해보겠습니다.