06B. Vagrant와 kubeadm으로 가상머신에 클러스터 구축하기
06B. Vagrant와 kubeadm으로 가상머신에 클러스터 구축하기 관련
.VirtualBox와 Vagrant 설치가 끝났으면 본격적으로 쿠버네티스 클러스터를 구축해보겠습니다. 이번에 구축할 클러스터의 형태는 다음과 같습니다.
- Vagrant로 VirtualBox 가상머신 생성
- Vagrant로
containerd
및kubeadm
설치 - master 노드에 worker 노드를 수동으로 연결
노드
클러스터를 구성하는 서버(머신)를 노드(node)라고 부릅니다. 노드는 물리서버일 수도 있고, 가상머신일 수도 있습니다.
Vagrantfile
작성하기
이제 Vagrant 코드를 작성해보겠습니다. 다음 내용을 Vagrantfile
로 저장합니다.
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.boot_timeout = 3000
config.vm.define "master" do |master|
master.vm.box = "ubuntu/jammy64"
master.vm.network "private_network", ip: "192.168.56.10"
master.vm.hostname = "master"
master.vm.provider "virtualbox" do |v|
v.memory = 4096
v.cpus = 4
end
master.vm.provision "0", type: "shell", preserve_order: true, privileged: true, inline: <<-EOC
cat <<-'EOF' >/etc/modules-load.d/kubernetes.conf
br_netfilter
EOF
sudo modprobe br_netfilter
cat <<-'EOF' >/etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
sudo apt update
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y containerd.io
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
cat <<-'EOF' >/etc/default/kubelet
KUBELET_EXTRA_ARGS=--node-ip=192.168.56.10
EOF
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/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.28/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
OUTPUT_FILE=/vagrant/join.sh
rm -rf $OUTPUT_FILE
rm -rf /vagrant/.kube
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint=192.168.56.10 --apiserver-advertise-address=192.168.56.10
sudo kubeadm token create --print-join-command > $OUTPUT_FILE
chmod +x $OUTPUT_FILE
mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
cp -R $HOME/.kube /vagrant/.kube
cp -R $HOME/.kube /home/vagrant/.kube
sudo chown -R vagrant:vagrant /home/vagrant/.kube
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
kubectl completion bash >/etc/bash_completion.d/kubectl
echo 'alias k=kubectl' >/home/vagrant/.bashrc
EOC
end
(1..3).each do |i|
config.vm.define "worker#{i}" do |worker|
worker.vm.box = "ubuntu/jammy64"
worker.vm.network "private_network", ip: "192.168.56.1#{i}"
worker.vm.hostname = "worker#{i}"
worker.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
worker.vm.provision "0", type: "shell", preserve_order: true, privileged: true, inline: <<-EOC
cat <<-'EOF' >/etc/modules-load.d/kubernetes.conf
br_netfilter
EOF
sudo modprobe br_netfilter
cat <<-'EOF' >/etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
sudo apt update
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository -y "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y containerd.io
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
cat <<-'EOF' >/etc/default/kubelet
KUBELET_EXTRA_ARGS=--node-ip=192.168.56.1#{i}
EOF
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/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.28/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
EOC
end
end
end
애플 실리콘 M 시리즈
맥의 CPU가 인텔이 아닌 애플 실리콘 M 시리즈라면 다음 Vagrantfile
을 사용합니다.
Vagrantfile
Vagrant.configure("2") do |config|
config.vm.boot_timeout = 3000
config.vm.define "master" do |master|
master.vm.box = "jharoian3/ubuntu-22.04-arm64"
master.vm.box_version = "0.3"
master.vm.network "private_network", ip: "192.168.56.10"
master.vm.hostname = "master"
master.vm.provider "parallels" do |v|
v.memory = 4096
v.cpus = 4
end
master.vm.provision "0", type: "shell", preserve_order: true, privileged: true, inline: <<-EOC
swapoff -a
sed -i '/swap/ s/^/#/' /etc/fstab
cat <<-'EOF' >/etc/modules-load.d/kubernetes.conf
br_netfilter
EOF
sudo modprobe br_netfilter
cat <<-'EOF' >/etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
sudo apt update
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository -y "deb [arch=arm64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y containerd.io
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
cat <<-'EOF' >/etc/default/kubelet
KUBELET_EXTRA_ARGS=--node-ip=192.168.56.10
EOF
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/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.28/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
OUTPUT_FILE=/vagrant/join.sh
rm -rf $OUTPUT_FILE
rm -rf /vagrant/.kube
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint=192.168.56.10 --apiserver-advertise-address=192.168.56.10
sudo kubeadm token create --print-join-command > $OUTPUT_FILE
chmod +x $OUTPUT_FILE
mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
cp -R $HOME/.kube /vagrant/.kube
cp -R $HOME/.kube /home/vagrant/.kube
sudo chown -R vagrant:vagrant /home/vagrant/.kube
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
kubectl completion bash >/etc/bash_completion.d/kubectl
echo 'alias k=kubectl' >/home/vagrant/.bashrc
EOC
end
(1..3).each do |i|
config.vm.define "worker#{i}" do |worker|
worker.vm.box = "jharoian3/ubuntu-22.04-arm64"
worker.vm.box_version = "0.3"
worker.vm.network "private_network", ip: "192.168.56.1#{i}"
worker.vm.hostname = "worker#{i}"
worker.vm.provider "parallels" do |v|
v.memory = 2048
v.cpus = 2
end
worker.vm.provision "0", type: "shell", preserve_order: true, privileged: true, inline: <<-EOC
swapoff -a
sed -i '/swap/ s/^/#/' /etc/fstab
cat <<-'EOF' >/etc/modules-load.d/kubernetes.conf
br_netfilter
EOF
sudo modprobe br_netfilter
cat <<-'EOF' >/etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
sudo apt update
sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository -y "deb [arch=arm64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
sudo apt install -y containerd.io
containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
cat <<-'EOF' >/etc/default/kubelet
KUBELET_EXTRA_ARGS=--node-ip=192.168.56.1#{i}
EOF
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/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.28/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
EOC
end
end
end
Parallels를 사용하므로 다음 명령으로 가상머신을 생성합니다.
vagrant up --provider=parallels
Minikube 클러스터
Minikube 클러스터를 생성했다면 다음 명령으로 먼저 Minikube 클러스터를 삭제합니다.
minikube delete
Avast Antivirus 감시 제어 문제
Avast Antivirus 등 안티바이러스 프로그램이 설치되어 있는 경우 vagrant up
명령을 실행했을 때 다음과 같은 메시지가 출력되면서 에러가 발생할 수 있습니다. 따라서 Avast 감시 제어 기능을 반드시 끄도록 합니다.
# Bringing machine 'master' up with 'virtualbox' provider...
# Bringing machine 'worker1' up with 'virtualbox' provider...
# Bringing machine 'worker2' up with 'virtualbox' provider...
# Bringing machine 'worker3' up with 'virtualbox' provider...
# ==> master: Box 'ubuntu/jammy64' could not be found. Attempting to find and install...
# master: Box Provider: virtualbox
# master: Box Version: >= 0
# The box 'ubuntu/jammy64' could not be found or
# could not be accessed in the remote catalog. If this is a private
# box on HashiCorp's Vagrant Cloud, please verify you're logged in via
# `vagrant login`. Also, please double-check the name. The expanded
# URL and error message are shown below:
#
# URL: ["https://vagrantcloud.com/ubuntu/jammy64"]
# Error: schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - 해당 함수에서 인증서에 대한 파기 여부를 검사하지 못했습니다.
vagrant up
명령으로 가상머신을 생성합니다. 시간이 꽤 오래 걸리므로 느긋하게 기다립니다.
vagrant up
SSH auth method: Private Key에서 멈추는 경우
vagrant up
명령으로 가상머신을 생성할 때 SSH auth method: Private Key
에서 멈추는 경우가 많습니다.
vagrant up
명령 실행이 끝났으면 vagrant status
명령을 입력하여 가상머신의 상태를 확인합니다. 다음과 같이 표시되면 정상적으로 생성된 것입니다.
vagrant status
#
# Current machine states:
#
# master running (virtualbox)
# worker1 running (virtualbox)
# worker2 running (virtualbox)
# worker3 running (virtualbox)
#
# This environment represents multiple VMs. The VMs are all listed
# above with their current state. For more information about a specific
# VM, run `vagrant status NAME`.
마스터 노드 확인하기
.Vagrantfile
안에 내장된 스크립트로 kubeadm
실행에 필요한 설정을 하고 패키지들을 설치했습니다. master 노드에는 제어 플레인(Control Plane)이 구축된 상태고, worker1, 2, 3 노드에는 kubeadm
만 설치된 상태입니다.
다음 명령을 실행하여 master 노드 안으로 들어갑니다.
vagrant ssh master
#
# Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-52-generic x86_64)
#
# * Documentation: https://help.ubuntu.com
# * Management: https://landscape.canonical.com
# * Support: https://ubuntu.com/advantage
#
# System information as of Sun Nov 6 17:35:51 UTC 2022
#
# System load: 0.5947265625 Users logged in: 0
# Usage of /: 9.0% of 38.70GB IPv4 address for cni0: 10.244.0.1
# Memory usage: 37% IPv4 address for enp0s3: 10.0.2.15
# Swap usage: 0% IPv4 address for enp0s8: 192.168.56.10
# Processes: 124
#
#
# 11 updates can be applied immediately.
# 10 of these updates are standard security updates.
# To see these additional updates run: apt list --upgradable
#
#
# Last login: Sun Nov 6 11:51:31 2022 from 10.0.2.2
# vagrant@master:~$
윈도우에서 vagrant ssh master 실행 시 Permission denied (publickey) 에러 발생 문제
윈도우에서 vagrant ssh master
명령을 실행했을 때 vagrant@127.0.0.1: Permission denied (publickey). 와 같은 에러가 발생하는 경우가 있습니다. 이때는 $env:VAGRANT_PREFER_SYSTEM_BIN += 0
명령을 실행한 뒤 vagrant ssh master
명령을 실행하면 됩니다.
PowerShell
$env:VAGRANT_PREFER_SYSTEM_BIN += 0
vagrant ssh master
master 노드 안으로 들어왔습니다. kubectl
도 설치해놓았으므로 kubectl get node
명령으로 노드 목록을 출력해봅니다.
kubectl get node
#
# NAME STATUS ROLES AGE VERSION
# master Ready control-plane 7m40s v1.28.4
master 노드 하나만 생성되어 있고 롤은 제어 플레인(control-plane)인 것을 볼 수 있습니다. 앞으로 vagrant ssh
로 들어간 노드에서 빠져나올 때는 Ctrl+D 키를 입력하면 됩니다.
쿠버네티스 클러스터 구축하기
이제터 들어갑니다.
vagrant ssh worker1
cd /vagrant/
sudo ./join.sh
#
# [preflight] Running pre-flight checks
# [WARNING SystemVerification]: missing optional cgroups: blkio
# [preflight] Reading configuration from the cluster...
# [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
# [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
# [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
# [kubelet-start] Starting the kubelet
# [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
#
# 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.
.join.sh
파일은 master 노드를 생성한 뒤 kubeadm join
명령을 미리 저장해둔 파일입니다. 이 부분은 뒤에서 자세히 설명하겠습니다.
위 명령들을 worker2, worker3에도 똑같이 실행합니다.
쿠버네티스 클러스터 확인하기
vagrant ssh master
명령을 실행하여 다시 master 노드로 들어갑니다. 그리고 kubectl get node
명령을 실행해봅니다.
vagrant ssh master
kubectl get node
#
# NAME STATUS ROLES AGE VERSION
# master Ready control-plane 19m v1.28.4
# worker1 Ready <none> 5m18s v1.28.4
# worker2 Ready <none> 68s v1.28.4
# worker3 Ready <none> 31s v1.28.4
master, worker1, 2, 3 노드가 모두 Ready
상태인 것을 확인할 수 있습니다. 이렇게 쿠버네티스 클러스터 구축이 끝났습니다.
.kube
디렉터리 설정하기
.Vagrantfile
이 들어있는 폴더를 보면 join.sh
파일 말고도 .kube
폴더가 들어있는 것을 볼 수 있습니다. 이 폴더를 호스트의 사용자 계정 폴더(디렉터리로) 복사하면 노드 바깥에서도 kubectl
로 클러스터를 제어할 수 있습니다.
.kube 디렉터리 백업
아래 명령을 실행하면 기존 .kube/config
파일을 삭제하거나 덮어쓰게 됩니다. 따라서 기존 .kube
디렉터리는 백업해주시기 바랍니다.
Copy-Item -Force -Recurse .\.kube C:\Users\${env:UserName}\
cp -R ./.kube ~/
이제 kubectl
명령이 잘 실행되는지 테스트해봅니다.
kubectl get node
#
# NAME STATUS ROLES AGE VERSION
# master Ready control-plane 23m v1.28.4
# worker1 Ready <none> 91s v1.28.4
# worker2 Ready <none> 60s v1.28.4
# worker3 Ready <none> 31s v1.28.4
윈도우에서 Unable to connect to the server: net/http: TLS handshake timeout 에러 발생
윈도우에서 kubectl get node
명령을 실행했을 때 Unable to connect to the server: net/http: TLS handshake timeout 에러가 발생한다면, $env:VAGRANT_PREFER_SYSTEM_BIN += 0
을 실행한 뒤 kubectl get node
명령을 실행해줍니다.
PowerShell
$env:VAGRANT_PREFER_SYSTEM_BIN += 0
kubectl get node