Post

(k8s) 쿠버네티스 설치

(k8s) 쿠버네티스 설치

📝 작성 배경

인프런에서 진행 중인 워밍업 클럽 스터디에 참여하고 있는데, 이번 주 미션 중 하나는 “자신의 PC에 VM을 통해 Linux를 설치하고, 쿠버네티스를 직접 구성해보는 것”이었다. 미션을 진행하면서 여러 가지 문제들이 발생했는데, 이를 해결했던 방법들을 기록해두면 좋을 것 같아 이 글을 작성하게 되었다.

🚨 lima-vm 사용 방법은 공식 문서를 참고.

PC 환경

  • OS: macOS 15.4.1 24E263 arm64
  • CPU: Apple M3 Pro
  • Memory: 36GB

k8s

  • Version: v1.30
  • CRI: containerd(1.7.27-3.1.el9)
  • CNI: Flannel

Etc.

  • VM: Lima-vm
  • Linux: Rocky-9 (Red Hat 계열)

☸️ 쿠버네티스 설치

Rocky Linux 기본 설정

  1. 타임존 설정 확인
    • 설정 명령어: timedatectl set-timezone Asia/Seoul
    • 확인 명령어: timedatectl
1
2
3
4
5
6
7
8
[crispin@lima-linux crispin]$ timedatectl
               Local time: Sun 2025-06-01 18:00:11 KST
           Universal time: Sun 2025-06-01 09:00:11 UTC
                 RTC time: Sun 2025-06-01 09:00:12
                Time zone: Asia/Seoul (KST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
  • 타임존 확인 시 이미 Asia/Seoul 되어 있다면 별도의 설정을 해 줄 필요는 없다. 만약 다른 타임존으로 설정 되어 있다면 설정 명령어를 사용

Kubeadm 설치 전 사전작업

  1. 방화벽 해제 확인
    • 설정 명령어: systemctl stop firewalld && systemctl disable firewalld
    • 확인 명령어: systemctl status firewalld
1
2
[crispin@lima-linux crispin]$ systemctl status firewalld
Unit firewalld.service could not be found.
  • lima-vm 을 사용해서 VM 을 띄우는 경우 별도의 설정이 없다면, 경량화된 이미지를 사용하기 때문에 별도의 firewalld 이 설정되어 있지 않다. 만약 다른 tool 을 사용하거나 미리 설정을 통해 방화벽을 설치 했다면 실습 편의상 방화벽을 해제 시키는 편이 편하다.
    1. 메모리 swap 비 활성화 확인
    • 설정 명령어: swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab
    • 확인 명령어: free -h, cat /etc/fstab | grep swap
  • free -h 명렁어
1
2
3
4
[crispin@lima-linux crispin]$ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.5Gi       406Mi       6.1Gi       8.0Mi       1.1Gi       7.1Gi
Swap:             0B          0B          0B
  • 방화벽과 마찬가지로 lima-vm 을 사용하면 별도의 설정을 하지 않는다면, swap 메모리 설정이 되어 있지 않다.

CRI(container runtime interface) 설치

  1. iptables 세팅
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

# 재부팅하지 않고 sysctl 파라미터 적용하기
sudo sysctl --system
  • 확인 명령어: cat /etc/modules-load.d/k8s.conf && cat /etc/sysctl.d/k8s.conf && lsmod | grep overlay && lsmod | grep br_netfilter
1
2
3
4
5
6
7
8
9
[crispin@lima-linux crispin]$ cat /etc/modules-load.d/k8s.conf && cat /etc/sysctl.d/k8s.conf && lsmod | grep overlay && lsmod | grep br_netfilter
overlay
br_netfilter
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
overlay               176128  0
br_netfilter           32768  0
bridge                303104  1 br_netfilter
  1. containerd.id 설치
    • docker repo 설정 명령어: yum install -y yum-utils , yum-config-manager --add-repo [https://download.docker.com/linux/centos/docker-ce.repo](https://download.docker.com/linux/centos/docker-ce.repo)
1
2
3
4
5
6
7
8
9
[crispin@lima-linux crispin]$ sudo yum install -y yum-utils
Last metadata expiration check: 0:27:12 ago on Sun 01 Jun 2025 05:56:20 PM KST.
Package yum-utils-4.3.0-16.el9.noarch is already installed.
Dependencies resolved.
Nothing to do.
Complete!

[crispin@lima-linux crispin]$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
  • docker repo 설정 확인 명령어: yum repolist enabled
1
2
3
4
5
6
[crispin@lima-linux crispin]$ yum repolist enabled
repo id                     repo name
appstream                   Rocky Linux 9 - AppStream
baseos                      Rocky Linux 9 - BaseOS  
docker-ce-stable            Docker CE Stable - aarch64
extras                      Rocky Linux 9 - Extras
  • 설치 가능한 버전의 containerd.io 리스트 확인 명령어: yum list containerd.io --showduplicates | sort -r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[crispin@lima-linux crispin]$ yum list containerd.io --showduplicates | sort -r
Rocky Linux 9 - Extras                           14 kB/s |  17 kB     00:01
Rocky Linux 9 - BaseOS                          2.3 MB/s | 2.5 MB     00:01
Rocky Linux 9 - AppStream                       8.6 MB/s | 7.4 MB     00:00
Docker CE Stable - aarch64                      704 kB/s |  71 kB     00:00
containerd.io.aarch64              1.7.27-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.26-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.25-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.24-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.23-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.22-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.21-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.20-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.19-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.7.18-3.1.el9               docker-ce-stable
containerd.io.aarch64              1.6.9-3.1.el9                docker-ce-stable
# ...
  • containerd 설치 명령어: yum install -y containerd.io-{version}
    • containerd 버전에 따른 k8s 호환성 정보 확인은 해당 페이지를 참고
    • 해당 포스팅에서는 1.7.27-3.1.el9 버전을 설치
  • containerd 설치 확인 명령어: systemctl status containerd
1
2
3
4
5
[crispin@lima-linux crispin]$ systemctl status containerd
○ containerd.service - containerd container runtime
     Loaded: loaded (/usr/local/lib/systemd/system/containerd.service; disabled; preset: disabled)
     Active: inactive (dead)
       Docs: https://containerd.io
  • 여기서부터 뭔가 조금씩 달라지는 부분이 발생한다. 우선 Active 상태가 active (running) 상태가 아닌 inactive (dead) 상태로 되어 있다. 그리고 /usr/local/lib/systemd/system/containerd.servicedisabled 로 되어 있다.
  • 위 두가지 부분에 대해 별도로 검색해보고 수정을 했어야 했다. 그럼 해결 방법을 보자.
    • inactive (dead) 상태
      • 원인: containerd 가 실행되지 않은 상태로 별도의 명령어를 통해 실행시켜야 함.
      • 명령어
        • containerd 실행 명령어: sudo systemctl enable containerd
        • 부팅 시 자동 시작 설정 명령어: sudo systemctl enable containerd
    • disabled 상태
      • 원인: 서비스 파일이 일반적이 경로가 아닐 경우 systemd 가 인식하지 못하는 문제
      • 명령어
        • 데몬 리로드: sudo systemctl daemon-reload
        • 서비스 활성화: sudo systemctl enable containerd.service
        • 서비스 시작: sudo systemctl start containerd.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[crispin@lima-linux crispin]$ sudo systemctl daemon-reload
[crispin@lima-linux crispin]$ sudo systemctl enable containerd.service
Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /usr/local/lib/systemd/system/containerd.service.
[crispin@lima-linux crispin]$ sudo systemctl start containerd.service
[crispin@lima-linux crispin]$ sudo systemctl status containerd.service
● containerd.service - containerd container runtime
     Loaded: loaded (/usr/local/lib/systemd/system/containerd.service; enabled; preset: disabled)
     Active: active (running) since Sun 2025-06-01 18:32:59 KST; 4min 23s ago
       Docs: https://containerd.io
   Main PID: 15871 (containerd)
      Tasks: 9
     Memory: 14.0M
        CPU: 441ms
     CGroup: /system.slice/containerd.service
             └─15871 /usr/local/bin/containerd
# ...
  • 상태와 서비스가 활성화된 모습을 볼 수 있다.

CRI(container runtime interface) 활성화

  1. cri 설정 확인 활성화
    • 활성화 명령어: sudo sh -c 'containerd config default > /etc/containerd/config.toml && sed -i "s/ SystemdCgroup = false/ SystemdCgroup = true/" /etc/containerd/config.toml'
    • 설정 확인 명령어: cat /etc/containerd/config.toml
1
2
[crispin@lima-linux crispin]$ cat /etc/containerd/config.toml | grep SystemdCgroup
            SystemdCgroup = true

Kubeadm 설치

  1. repo 설정 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# permissive 모드로 SELinux 설정(효과적으로 비활성화)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet
  • 위 명령어를 통해 repo 를 설정 하는 경우
1
2
3
4
Errors during downloading metadata for repository 'kubernetes':
  - Status code: 404 for https://packages.cloud.google.com/yum/repos/kubernetes-el7-aarch64/repodata/repomd.xml (IP: xxx.xxx.xx.xxx)
Error: Failed to download metadata for repo 'kubernetes': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried
Failed to enable unit: Unit file kubelet.service does not exist.
  • 해당 에러가 발생 한다. 에러가 발생하는 원인은 Google Cloud의 기존 Kubernetes 패키지 저장소가 deprecated되어서 발생하는 문제로 패키지 저장소의 링크를 변경해주면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 기존 저장소 파일 제거
sudo rm -f /etc/yum.repos.d/kubernetes.repo

# 2. 새로운 저장소 추가
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/{version}/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/{version}/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

# 3. permissive 모드로 SELinux 설정(효과적으로 비활성화)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

# 4. 패키지 설치
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

# 5. kubelet 서비스 활성화
sudo systemctl enable --now kubelet
  • version 에 설치하고 싶은 k8s 버전을 기입하면 해당 버전으로 설치 할 수 있다.
  • 해당 포스팅에서는 v1.30 버전을 설치
  1. repo 설정 추가 확인
1
2
3
4
5
6
7
[crispin@lima-linux crispin]$ yum repolist enabled
repo id                     repo name
appstream                   Rocky Linux 9 - AppStream
baseos                      Rocky Linux 9 - BaseOS  
docker-ce-stable            Docker CE Stable - aarch64
extras                      Rocky Linux 9 - Extras
kubernetes                  Kubernetes
  • Kubernetes 가 추가되어 있는걸 확인
  1. SELinux 설정 확인
    • 설정 확인 명령어: cat /etc/selinux/config | grep SELINUX && sestatus
1
2
3
4
5
6
7
8
9
10
11
12
13
[crispin@lima-linux crispin]$ cat /etc/selinux/config | grep SELINUX && sestatus
SELINUX=permissive # 해당 설정 확인
SELINUXTYPE=targeted
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   permissive # 해당 설정 확인
Mode from config file:          permissive # 해당 설정 확인
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actual (secure)
Max kernel policy version:      33
  1. kubelet, kubeadm, kubectl 패키지 설치 확인
    • kubeadm 설치 확인 명령어: kubeadm version
1
2
[crispin@lima-linux crispin]$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"30", GitVersion:"v1.30.13", GitCommit:"50af91c466658b6a33d123fae8a487db1630971c", GitTreeState:"clean", BuildDate:"2025-05-15T09:55:10Z", GoVersion:"go1.23.8", Compiler:"gc", Platform:"linux/arm64"}
  • kubelet 설지 확인 명령어: systemctl status kubelet
1
2
3
4
5
6
7
8
9
10
[crispin@lima-linux crispin]$ systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: activating (auto-restart) (Result: exit-code) since Sun 2025-06-01 19:20:51 KST; 8s ago
       Docs: https://kubernetes.io/docs/
    Process: 18604 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=1/FAILURE)
   Main PID: 18604 (code=exited, status=1/FAILURE)
        CPU: 61ms
  • kubectl 설지 확인 명령어: kubectl version
1
2
3
4
[crispin@lima-linux crispin]$ kubectl version
Client Version: v1.30.13
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
The connection to the server localhost:8080 was refused - did you specify the right host or port?
  • 패키지 설정 확인 시 kubelet 이 지속적으로 재 실행 되는 부분이 확인 될 수 있는데 이건 kubeadm 이 아직 init 되지 않았기 때문에 발생하는 문제로 kubeadm init 이후 클러스터를 생성하면 해결된다.
  • kubectl 에서 보이는 refused 이후 kubectl 에 추가적인 설정을 해주면 해결된다.
  • 위 두가지 부분에 대해서는 아래에서 다룰 예정이다.

Kubeadm 으로 클러스터 생성

  1. pod network 세팅
    • 네트워크 인터페이스 확인 명령어: ip route show && ip addr show
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
default via xxx.xxx.xxx.1 dev eth0 proto dhcp src {ip} metric 100  
xxx.xxx.xxx.0/24 dev eth0 proto kernel scope link src xxx.xxx.xxx.xxx metric 100  

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000  
    link/loopback xx:xx:xx:xx:xx:xx brd xx:xx:xx:xx:xx:xx  
    inet 127.0.0.1/8 scope host lo  
       valid_lft forever preferred_lft forever  
    inet6 ::1/128 scope host  
       valid_lft forever preferred_lft forever  

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000  
    link/ether xx:xx:xx:xx:xx:xx brd xx:xx:xx:xx:xx:xx  
    altname enxxxxxx  
    inet xxx.xxx.xxx.xxx/24 brd xxx.xxx.xxx.255 scope global dynamic noprefixroute eth0  
       valid_lft 3121sec preferred_lft 3121sec  
    inet6 xxxx:xxxx:xxxx::xxxx/64 scope link  
       valid_lft forever preferred_lft forever  
  • {ip} 블록에 있는 ip 주소 확인
  1. 클러스터 초기화
    • 클러스터 초기화 명령어: kubeadm init --pod-network-cidr={cidr} --apiserver-advertise-address {ip}
    • cidr 은 사용하고자 하는 CNI 에 대한 기본 값을 사용해도 되고 별도로 설정해줘도 된다.
    • 해당 포스팅에서는 Flannel 를 사용할 예정이며, Flannelcidr 기본값은 10.244.0.0/16 이다.
  2. 클러스터 상태 확인
    • 클러스터 상태 확인 명령어: kubectl get node
1
2
3
[crispin@lima-linux crispin]$ kubectl get node
E0601 20:04:33.891690   22662 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
The connection to the server localhost:8080 was refused - did you specify the right host or port?
  • 클러스터 확인 시 위와 같은 에러가 발생하게되면 추가 설정이 필요하다.
  • 설정 명령어
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
  • 해당 명령어를 사용해서 config 를 추가해주고 다시 명령어를 사용하면
1
2
3
[crispin@lima-linux crispin]$ kubectl get nodes
NAME         STATUS     ROLES           AGE     VERSION
lima-linux   NotReady   control-plane   2m48s   v1.30.13
  • 생성된 node 를 확인할 수 있다.
  • nodeNotReady 상태인 이유는 아직 CNI 플러그인이 설치되지 않았기 때문이며, 플러그인을 설치해주면 Read 상태로 변경된다.
  • CNI 플러그인 설치 명령어
1
2
3
4
5
6
7
[crispin@lima-linux crispin]$ kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg createdkubectl cluster-info dump | grep -m 1 cluster-cidr
daemonset.apps/kube-flannel-ds created
  • 설치하고 1분정도 시간이 지난 이후에 다시 kubectl get nodes 명령어를 사용하면 Ready 상태로 변경된다.
1
2
3
[crispin@lima-linux crispin]$ kubectl get nodes
NAME         STATUS   ROLES           AGE   VERSION
lima-linux   Ready    control-plane   99s   v1.30.13
  1. Master에 pod 를 생성 할 수 있도록 설정(Optional)
    • 설정 명령어: kubectl taint nodes {node_name} node-role.kubernetes.io/control-plane-
1
2
[crispin@lima-linux crispin]$ kubectl taint nodes lima-linux node-role.kubernetes.io/control-plane-
node/lima-linux untainted
  • 확인 명령어: kubectl describe nodes | grep Taints
1
2
[crispin@lima-linux crispin]$ kubectl describe nodes | grep Taints
Taints:             <none> # 해당 설정 확인

쿠버네티스 편의 기능 설치

  1. kubectl 자동 완성 기능 추가
1
2
3
source <(kubectl completion bash)
alias k=kubectl
complete -o default -F __start_kubectl k
  • 해당 명령어를 사용하면 k get pods 처럼 kubectlk 로 사용할 수 있고, 추가적으로 tap 을 통해 자동완성을 사용할 수 있다.
1
2
3
4
[crispin@lima-linux crispin]$ k get nodes
NAME         STATUS   ROLES           AGE   VERSION
lima-linux   Ready    control-plane   18m   v1.30.13
[crispin@lima-linux crispin]$ k get bash: _get_comp_words_by_ref: command not found
  • k 는 사용이 가능한데 자동완성을 위해 tap 을 눌렸을때 위 처럼 에러가 발생할 수 있는데 bash-completion 패키지가 설치되어 있지 않아 발생하는 문제로 해당 패키지를 설치하면 된다.
  • 패키지 설치 명령어: sudo yum install -y bash-completion
1
2
sudo yum install -y bash-completion # 명령어 설치
source /etc/profile.d/bash_completion.sh # 새로고침
  • 해당 패키지 설치 이후 새로고침을 하면 자동완성을 사용할 수 있게 된다.

💡 마무리

현업에서 kubernetes 를 지금도 사용하고 있고, 자주 활용하고 있는데 직접 linuxkubernetes 를 설치한 경험은 처음이라 흥미로운 경험이였다. 매번 클라우드에서 제공되는 서비스를 통해서 사용하거나 이미 회사의 온프레미스 서버에 설치 되어 있는 kubernetes 를 사용하기만 했는데 직접 설치하고 사용해보니 생각보다 설치 과정이 쉽지 많은 않게 느껴졌다.

강의를 참고하고, 발생하는 에러는 검색을 하면서 진행했는데, 강의에서 안내해주는 tool 을 사용한것도 아니고 아키텍처도 다르다 보니 생각보다 오래걸리기는 했는데 설치하고 나서 pod 를 직접 띄우고 조회하면서 제대로 동작하는 모습을 보며 매우 뿌듯함을 느꼈다.


🔖 REFERENCE

This post is licensed under CC BY 4.0 by the author.