쿠버네티스

multipass를 이용하여 로컬 환경에 쿠버네티스 클러스터 구축하기

알쓸개잡 2024. 7. 4. 22:11

쿠버네티스를 처음 접하는 경우 로컬 환경에 kubernetes 클러스터를 구축하는 것은 다소 복잡하고 어려울 수 있다.

이번 포스팅에서는 multipass 도구를 활용하여 간편하게 로컬 환경에 쿠버네티스 클러스터를 구축하는 방법을 소개하고자 한다. 

multipass는 경량의 VM 관리 도구로 간단한 명령어 몇 가지로 다양한 VM을 쉽게 생성하고 관리할 수 있다. 이를 통해 쿠버네티스 클러스터를 로컬 환경에서 쉽고 빠르게 설정할 수 있다.

 

multipass 사용법 알아보기

multipass를 활용하기 때문에 multipass 사용법에 대해서 알아야 한다.

아래 포스팅을 참고하기 바란다.

2024.07.02 - [ETC] - Multipass 사용법: 간편하게 가상 머신 관리하기

 

--cloud-init 옵션에 적용할 yaml 작성하기

multipass는 가상 인스턴스를 생성 시에 필요한 여러 명령들을 실행시킬 수 있다.

이를 통해서 쿠버네티스 구성에 필요한 패키지와 관련 파일들을 생성할 것이다.

클러스터 구성 스펙은 다음과 같다.

  • 쿠버네티스 클러스터는 control plane 역할을 하는 master 노드와 작업을 수행하는 worker 노드, 두 개의 VM으로 구성할 것이다.
  • 각 노드의 OS는 우분투 20.04 버전을 사용할 것이다.
  • 쿠버네티스 버전 1.28을 설치할 것이다.

master 노드 cloud-init yaml

# master-init.yaml
package_update: true
package_upgrade: true
packages:
  - docker.io
  - apt-transport-https
  - ca-certificates
  - curl
  - ntpdate

runcmd:
  - sudo ntpdate ntp.ubuntu.com
  - sudo systemctl enable docker
  - sudo systemctl start docker
  - sudo mkdir -p /etc/apt/keyrings
  - 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 update
  - sudo apt install -y kubelet kubeadm kubectl
  - sudo apt-mark hold kubelet kubeadm kubectl
  - sudo systemctl enable kubelet
  - sudo kubeadm init
  - mkdir -p /home/ubuntu/.kube
  - sudo cp -i /etc/kubernetes/admin.conf /home/ubuntu/.kube/config
  - sudo chown -R ubuntu:ubuntu /home/ubuntu/.kube
  - sudo kubeadm token create --print-join-command > /home/ubuntu/kubeadm_join_cmd.sh
  - sudo chown ubuntu:ubuntu /home/ubuntu/kubeadm_join_cmd.sh
  - chmod +x /home/ubuntu/kubeadm_join_cmd.sh
  - |
    sudo bash -c 'cat <<EOF > /home/ubuntu/k8s-post-init.sh
    #!/bin/bash
    export KUBECONFIG=/home/ubuntu/.kube/config
    sleep 60
    kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
    kubectl taint nodes --all node-role.kubernetes.io/control-plane-
    EOF'
  - sudo chown ubuntu:ubuntu /home/ubuntu/k8s-post-init.sh
  - sudo chmod +x /home/ubuntu/k8s-post-init.sh
  - sudo -u ubuntu /home/ubuntu/k8s-post-init.sh

위 yaml 파일은 가상 인스턴스에 다음과 같은 작업을 수행한다.

  • apt update 수행
  • apt upgrade 수행
  • docker.io, apt-transport-https, ca-certificates, curl, ntpupdate 패키지 설치
  • 쿠버네티스 관련 패키지인 kubeadm, kubectl, kubelet를 설치하기 위한 gpg  키 등록
  • 쿠버네티스 관련 apt repository 등록
  • kubeadm, kubelet, kubectl 설치
  • worker 노드를 쿠버네티스 클러스터에 참여시키기 위한 토큰 생성 및 join 스크립트 파일 생성
  • 쿠버네티스 네트워크 구성을 위한 calico CNI 설치 (k8s-post-init.sh 실행)
  • master 노드에 pod 스케줄링을 허용하기 위한 명령 실행 (k8s-post-init.sh 실행)

데비안 12와 우분투 22.04 이하 버전의 경우 /ec/apt/keyrings 디렉터리가 없으므로 생성해 줘야 한다.
이제 더이상 쿠버네티스 패키지 레포지토리로 apt.kubernetes.io와 yum.kubernetes.io 는 사용되지 않는다.
대신 pkgs.k8s.io를 사용한다.
관련 내용은 아래 링크를 참고하기 바란다.

Kubernetes Legacy Package Repositories Will Be Frozen

pkgs.k8s.io: Introducing Kubernetes Community-Owned Package

 

worker 노드 cloud-init yaml

# worker-init.yaml
package_update: true
package_upgrade: true
packages:
  - docker.io
  - apt-transport-https
  - ca-certificates
  - curl
  - ntpdate

runcmd:
  - sudo ntpdate ntp.ubuntu.com
  - sudo systemctl enable docker
  - sudo systemctl start docker
  - sudo mkdir -p /etc/apt/keyrings
  - 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 update
  - sudo apt install -y kubelet kubeadm kubectl
  - sudo systemctl enable kubelet

위 yaml 파일은 가상 인스턴스에 다음과 같은 작업을 수행한다.

  • apt update 수행
  • apt upgrade 수행
  • docker.io, apt-transport-https, ca-certificates, curl, ntpupdate 패키지 설치
  • 쿠버네티스 관련 패키지인 kubeadm, kubectl, kubelet를 설치하기 위한 gpg  키 등록
  • 쿠버네티스 관련 apt repository 등록
  • kubeadm, kubelet, kubectl 설치

worker 노드의 경우 관련 패키지 설치만 한다.

 

master VM 인스턴스 생성

$> multipass launch focal --name master --memory 2G --disk 10G --cpus 2 --cloud-init <master-init.yaml 파일 경로>

위 명령은 master-init.yaml 적용과 함께 memory 2G, disk 10G, 2 cpu core 리소스를 갖는 인스턴스를 생성한다.

물론 memory, disk, cpu core 수는 적절한 값으로 지정하면 되겠다.

master-init.yaml을 적용하면 master 노드 인스턴스의 /home/ubuntu/kubeadm_join_cmd.sh 파일이 생성된다.

kubeadm_join_cmd.sh 파일은 worker 노드에서 실행하여 쿠버네티스 클러스터에 worker 노드를 참여시키는 역할을 할 것이다.

 

master 인스턴스 생성 후 multipass shell master 명령으로 master 쉘에 접속하여

kubelet, kubeadm, kubectl 이 정상적으로 설치되었는지, 그리고 kubeadm_join_cmd.sh, k8s-post-init.sh 파일이 존재하는지 확인해 보기 바란다.

$> ~/ multipass shell master
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-187-generic aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Thu Jul  4 21:57:48 KST 2024

  System load:             0.51
  Usage of /:              40.5% of 9.52GB
  Memory usage:            45%
  Swap usage:              0%
  Processes:               161
  Users logged in:         0

...

ubuntu@master:~$ ll
total 44
drwxr-xr-x 5 ubuntu ubuntu 4096 Jul  4 20:09 ./
drwxr-xr-x 3 root   root   4096 Jul  4 20:06 ../
-rw------- 1 ubuntu ubuntu  114 Jul  4 21:49 .bash_history
-rw-r--r-- 1 ubuntu ubuntu  220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu 3771 Feb 25  2020 .bashrc
drwx------ 2 ubuntu ubuntu 4096 Jul  4 20:06 .cache/
drwxr-xr-x 3 ubuntu ubuntu 4096 Jul  4 20:09 .kube/
-rw-r--r-- 1 ubuntu ubuntu  807 Feb 25  2020 .profile
drwx------ 2 ubuntu ubuntu 4096 Jul  4 20:06 .ssh/
-rwxr-xr-x 1 ubuntu ubuntu  200 Jul  4 20:08 k8s-post-init.sh*
-rwxr-xr-x 1 ubuntu ubuntu  168 Jul  4 20:08 kubeadm_join_cmd.sh*
ubuntu@master:~$ which kubeadm
/usr/bin/kubeadm
ubuntu@master:~$ which kubelet
/usr/bin/kubelet
ubuntu@master:~$ which kubectl
/usr/bin/kubectl

 

worker VM 인스턴스 생성

$> multipass launch focal --name worker --memory 2G --disk 10G --cpus 2 --cloud-init <worker-init.yaml 파일 경로>

위 명령 역시 worker-init.yaml 적용과 함께 memory 2G, disk 10G, 2 cpu core 리소스를 갖는 인스턴스를 생성한다.

worker 인스턴스 역시 생성 후 multipass shell worker 명령으로 worker 쉘에 접속하여 kubectl, kubeadm, kubelet 이 설치되었는지 확인해 보기 바란다.

$> multipass shell worker
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-187-generic aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Thu Jul  4 22:00:08 KST 2024

  System load:             0.18
  Usage of /:              31.9% of 9.52GB
  Memory usage:            22%
  Swap usage:              0%
  Processes:               139
  Users logged in:         0
...

ubuntu@worker:~$ which kubectl
/usr/bin/kubectl
ubuntu@worker:~$ which kubelet
/usr/bin/kubelet
ubuntu@worker:~$ which kubeadm
/usr/bin/kubeadm

 

focal 은 우분투 20.04 버전의 alias 이름으로 multipass find 명령으로 확인할 수 있다.
결국 위 명령은 master, worker 노드 모두 우분투 20.04 버전에 구성하게 된다.

 

master와 worker 인스턴스를 생성한 뒤 multipass ls(혹은 list) 명령을 통해서 인스턴스 목록을 확인한다.

$> multipass ls
Name                    State             IPv4             Image
master                  Running           192.168.64.11    Ubuntu 20.04 LTS
                                          172.17.0.1
                                          172.16.219.64
worker                  Running           192.168.64.12    Ubuntu 20.04 LTS
                                          172.17.0.1
                                          172.16.171.64

각 인스턴스에 표시되는 ip 정보는 호스트마다 다르게 지정될 것이다.

master 노드에서 생성한 kubeadm_join_cmd.sh를 worker 노드에서 실행

앞서 언급했듯이 master 노드에서 생성한 kubeadm_join_cmd.sh 파일을 worker 노드에서 실행시켜 쿠버네티스 클러스터에 worker 노드를 등록해야 한다.

이를 위해서는 master 노드에 있는 kubeadm_join_cmd.sh 파일을 worker 노드에 전달을 해야 하는데 여기서는 multipass transfer 기능을 사용하여 파일을 전송하도록 하겠다.

아래 두 개의 명령을 통해서 손쉽게 파일을 전달할 수 있다.

# master 노드의 /home/ubuntu/kubeadm_join_cmd.sh 파일을 호스트의 현재 디렉토리로 가져옴
$> multipass transfer master:/home/ubuntu/kubeadm_join_cmd.sh ./

# 호스트에서 kubeadm_join_cmd.sh 파일을 worker 노드의 /home/ubuntu 경로에 전송함.
$> multipass transfer kubeadm_join_cmd.sh worker:/home/ubuntu

 

worker 노드에 전송된 kubeadm_join_cmd.sh 파일을 실행시킨다.

# worker 인스턴스 쉘에 접속
$> multipass shell worker

# kubeadm_join_cmd.sh 실행
ubuntu@worker:~$ sudo ./kubeadm_join_cmd.sh
[preflight] Running pre-flight checks
[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.

위와 같이 메시지가 출력되면 실행은 성공한 것이다.

 

master 노드(control plane) 확인

control plane 역할을 하는 master 노드에 접속하여 node의 상태와 생성된 pod 들을 확인해 보자.

ubuntu@master:~$ kubectl get node -o wide
NAME     STATUS   ROLES           AGE    VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
master   Ready    control-plane   113m   v1.28.11   192.168.64.11   <none>        Ubuntu 20.04.6 LTS   5.4.0-187-generic   containerd://1.7.12
worker   Ready    <none>          51m    v1.28.11   192.168.64.12   <none>        Ubuntu 20.04.6 LTS   5.4.0-187-generic   containerd://1.7.12

node 정보를 확인했을 때 master, worker 두 개가 등록되었고 STATUS가 모두 Ready 상태면 성공이다.

 

 

pod를 확인해 보자.

ubuntu@master:~$ kubectl get pod -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-658d97c59c-mhqrf   1/1     Running   0          116m
kube-system   calico-node-9vhb9                          1/1     Running   0          54m
kube-system   calico-node-nkrgb                          1/1     Running   0          116m
kube-system   coredns-5dd5756b68-cr5cl                   1/1     Running   0          117m
kube-system   coredns-5dd5756b68-t4nmc                   1/1     Running   0          117m
kube-system   etcd-master                                1/1     Running   0          117m
kube-system   kube-apiserver-master                      1/1     Running   0          117m
kube-system   kube-controller-manager-master             1/1     Running   0          117m
kube-system   kube-proxy-ftz22                           1/1     Running   0          54m
kube-system   kube-proxy-s9btb                           1/1     Running   0          117m
kube-system   kube-scheduler-master                      1/1     Running   0          117m

쿠버네티스 동작에 필요한 pod들이 모두 Running 상태라면 성공이다.

 

끝.