이번에 사내 Kubernetes(이하 쿠버네티스) 스터디를 주도하는 기회를 받았습니다. 실습 위주 스터디가 효율적이라 생각했고, 간단한 쿠버네티스 클러스터 성하는 것을 목표로 했습니다. minikube, k3s 등 간단하게 클러스터를 구축할 수 있는 도구들이 있지만, 표준적인 방법인 kubeadm을 통해 클러스터를 구축하는 것이 학습 및 현업에 좋다고 생각했습니다. 이에 해당 글에서는 kubeadm을 통해 쿠버네티스 클러스터를 구축하겠습니다.
1. Local repository 구성
dvd iso내 제공되는 기본 패키지들을 통해서 Local Repository를 구성합니다.
$ lsblk
$ fdisk -l
$ mkdir /iso
$ mkdir /mnt/cdrom
$ mount /dev/sr0 /mnt/cdrom
$ cp -rvf /mnt/cdrom/* /iso
$ umount /mnt/cdrom
local.repo를 설정합니다.
$ vi /etc/yum.repo.d/local.repo
---
[BaseOS]
name=BaseOS
baseurl=file:///iso/BaseOS
enabled=1
gpgcheck=0
[AppStream]
name=AppStream
baseurl=file:///iso/AppStream
enabled=1
gpgcheck=0
---
- repo를 확인합니다.
$ yum clean all
$ yum repolist
$ yum list
2. firewalld Disable/Stop
- 테스트를 위한 목적이라, 편의성을 위해 firewalld는 비활성화하겠습니다.
# firewalld
$ systemctl status firewalld
$ systemctl stop firewalld
$ systemctl disable firewalld
3. selinux 비활성화
- 테스트를 위한 목적이라, 편의성을 위해 selinux도 비활성화하겠습니다.
$ vi /etc/selinux/config
---
...
SELINUX=disabled # enforcing -> disabled 로 변경
...
---
- 확인
$ cat /etc/selinux/config | grep 'SELINUX=disabled'
4. swap 기능 비활성화
- 쿠버네티스 공식 문서는 swap 기능울 비활성화하는 것을 권장합니다. 이에, swap을 비활성화 하겠습니다.
$ swaopoff -a
# 영구 적용
$ sed -i '/swap/s/^/#/' /etc/fstab
# 확인
# swaopon --show
$ swapon -s
# swaop 영역 확인
$ free -h
5. network-scripts 설정
- RHEL 8.x 에서는
network-scripts, NetworkManager가 공존하며, 모두 사용 가능합니다. - 여기서는 Legacy한 방식인
network-scripts를 사용해서 네트워크를 설정하겠습니다.- 네트워크 인터페이스, IP 등 세부 설정은 상황에 맞게 변경합니다.
$ vi /etc/sysconfig/network-scripts/ifcfg-ens192
---
TYPE=Ethernet
#PROXY_METHOD=none
#BROWSER_ONLY=no
BOOTPROTO=static
#DEFROUTE=yes
#IPV4_FAILURE_FATAL=no
#IPV6INIT=yes
#IPV6_AUTOCONF=yes
#IPV6_DEFROUTE=yes
#IPV6_FAILURE_FATAL=no
NAME=ens192
DEVICE=ens192
ONBOOT=yes
IPADDR=192.168.0.75 # 실제 설정에 맞게 변경
NETMASK=255.255.255.0 # 실제 설정에 맞게 변경
GATEWAY=192.168.0.254 # 실제 설정에 맞게 변경
---
$ systemctl restart network
- 확인
$ ping -c 2 192.168.0.254
PING 192.168.0.254 (192.168.0.254) 56(84) bytes of data.
64 bytes from 192.168.0.254: icmp_seq=1 ttl=64 time=0.374 ms
64 bytes from 192.168.0.254: icmp_seq=2 ttl=64 time=0.351 ms
--- 192.168.0.254 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1049ms
rtt min/avg/max/mdev = 0.351/0.362/0.374/0.022 ms
7. hostname, /etc/hosts, /etc/resolv.conf 설정
hostnamectl set-hostname k8s-master01
exec bash
[root@k8s-master01 ~]
vi /etc/hosts
---
# 추가
192.168.0.70 k8s-master01
192.168.0.75 k8s-worker01
---
7-1. (인터넷 사용 가능 및 필요 시)(인터페이스 내 설정) DNS 서버 설정
$ cat /etc/sysconfig/network-scripts/ifcfg-ens192
---
TYPE=Ethernet
#PROXY_METHOD=none
#BROWSER_ONLY=no
BOOTPROTO=static
#DEFROUTE=yes
#IPV4_FAILURE_FATAL=no
#IPV6INIT=yes
#IPV6_AUTOCONF=yes
#IPV6_DEFROUTE=yes
#IPV6_FAILURE_FATAL=no
NAME=ens192
DEVICE=ens192
ONBOOT=yes
IPADDR=192.168.0.75
NETMASK=255.255.255.0
GATEWAY=192.168.0.254
DNS1=8.8.8.8 # 추가
---
7-2. /etc/resolv.conf 설정
- 추후,
kubeadm init으로 클러스터 생성 시,/etc/reslov.conf파일의 존재 여부를 점검합니다.
오류 방지를 위해 생성 및 설정합니다. - 폐쇄망 등의 환경이라 실제로 해당 DNS를 사용하지 않더라도, kubeadm에서는 파일의 존재여부를 점검합니다. 따라서, dummy nameserver를 지정하여 파일 존재를 보장해야 합니다.
$ vi /etc/resolv.conf
---
# 추가
nameserver 8.8.8.8
---
8. NTP 설치 및 시간 동기화
- 클러스터를 구성하는 노드별 시간이 동일 및 동기화 돼야 합니다. 이를 위해
chrony를 설치합니다. - RHEL 8.x 에서는
chrony가 기본 설치되지 않으므로, 직접 설치해줍니다. 패키지는dvd iso내 기본 제공 패키지로서 제공됩니다.
$ yum list | grep -i chrony
$ yum install -y chrony
$ systemctl status chronyd
$ systemctl start chronyd
$ systemctl enable chronyd
$ systemctl is-enabled chronyd
$ systemctl status chronyd
# NTP 확인
$ chronyc tracking
$ chronyc sources
9. containerd 설치 및 설정
9-1. 기존 docker 관련 패키지 삭제 (필수)
- 설치 과정에서 오류 발생 가능하므로, 기존에 설치된 pkg들을 삭제합니다.
dnf remove docker \\
docker-client \\
docker-client-latest \\
docker-common \\
docker-latest \\
docker-latest-logrotate \\
docker-logrotate \\
docker-engine \\
podman \\
runc
9-2. 패키지 다운로드 및 설치
- RHEL 8.4 version 기준
$ mkdir pkg-containerd
$ cd pkg-containerd
$ curl -fsSLO https://download.docker.com/linux/rhel/8/x86_64/stable/Packages/containerd.io-1.7.27-3.1.el8.x86_64.rpm
$ curl -fsSLO https://download.docker.com/linux/rhel/8/x86_64/stable/Packages/docker-buildx-plugin-0.23.0-1.el8.x86_64.rpm
$ curl -fsSLO https://download.docker.com/linux/rhel/8/x86_64/stable/Packages/docker-ce-28.1.1-1.el8.x86_64.rpm
$ curl -fsSLO https://download.docker.com/linux/rhel/8/x86_64/stable/Packages/docker-ce-cli-28.1.1-1.el8.x86_64.rpm
$ curl -fsSLO https://download.docker.com/linux/rhel/8/x86_64/stable/Packages/docker-ce-rootless-extras-28.1.1-1.el8.x86_64.rpm
$ curl -fsSLO https://download.docker.com/linux/rhel/8/x86_64/stable/Packages/docker-compose-plugin-2.35.1-1.el8.x86_64.rpm
# 확인
$ ls
containerd.io-1.7.27-3.1.el8.x86_64.rpm
docker-buildx-plugin-0.23.0-1.el8.x86_64.rpm
docker-ce-28.1.1-1.el8.x86_64.rpm
docker-ce-cli-28.1.1-1.el8.x86_64.rpm
docker-ce-rootless-extras-28.1.1-1.el8.x86_64.rpm
docker-compose-plugin-2.35.1-1.el8.x86_64.rpm
# 설치
$ yum install ./*
9-3. containerd 확인 및 start/enable
$ systemctl status docker
$ systemctl start docker
$ systemctl enable docker
$ systemctl status docker
$ systemctl status containerd
$ systemctl enable containerd
10. (Master Node) 클러스터 생성
$ kubeadm init --pod-network-cidr=192.168.158.0/24
- 성공 메세지
- 아래의 성공 메세지가 출력 안된다면, 오류 메세지를 읽고 트러블 슈팅이 필요합니다.
- 아래 join에 사용되는 키 값은 매번 달라지니, 참고만 하시길 바랍니다.
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
<https://kubernetes.io/docs/concepts/cluster-administration/addons/>
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.70:6443 --token gq2w9s.ebkkcq3um7926wwi \\
--discovery-token-ca-cert-hash sha256:149134142b21de6122e6f4552970422045d99227d494994c47614b58b7312db3
- config 설정
- 출력 결과에 나온대로 config 설정
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
- 출력 결과 중 다음의 내용은 추후 worker node를 클러스터에 join시킬 때 필요하므로,
따로 저장합니다.
$ kubeadm join 192.168.0.70:6443 --token <TOKEN> \\
--discovery-token-ca-cert-hash <HASH>
- 만약 저장하지 않고 넘어갔다면, 다음의 명령을 마스터 노드에서 실행함으로써 다시 얻을 수 있습니다. 기존 클러스터 노드의 운영에는 영향을 끼치지 않습니다.
$ kubeadm token create --print-join-command
11. (Master Node) 클러스터 확인
- 클러스터 확인 시,
STATUS가NotReady일텐데, CNI가 설치 및 설정이 안돼있기 때문입니다.
정상인 상황이니 다음으로 넘어갑니다.
$ kubectl get nodes
# 출력 결과
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane 3m53s v1.28.15
12. CNI 설치
- 다음 내용은 클러스터를 구성하려는 Master node와 Worker node를 join 시킨 후,
Master Node에서 수행해야 합니다. 즉, 다음과 같은 상태여야 합니다.
$ kubectl get nodes
# 출력 결과
NAME STATUS ROLES AGE VERSION
k8s-master01 NotReady control-plane 6m8s v1.28.15
k8s-worker01 NotReady <none> 4m11s v1.28.15
- 쿠버네티스 클러스터에서 구성 요소 간 통신을 가능하게 하는 CNI를 설치합니다.
- 여러 CNI가 존재하지만, 여기서는
Calico CNI로 구성하겠습니다. Calico CNI도 쿠버네티스 버전에 따라 호환되는 버전이 상이합니다.
반드시 공식 홈페이지에서 호환성을 확인 후, 적절한 버전으로 설치합니다.- 여기서는
Kubernetes v1.28을 호환하는calico v3.19로 구성하겠습니다.
12-1. calico manifest 다운
$ curl -fsSLO https://docs.projectcalico.org/archive/v3.19/manifests/calico.yaml
$ ls
calico.yaml # 출력 결과 (현재 위치에 calico.yaml 파일이 다운 받아집니다.)
12-2. calico.yaml 수정
- Pod CIDR를 기본값인
192.168.0.0/16로 사용하는 경우, 해당 절차를 생략하고 바로apply합니다. - 하지만, 여기서는
kubeadm init으로 클러스터 생성 시, Pod CIDR를192.168.158.0/24으로 설정 했습니다. 따라서,calico.yaml에서 다음의 내용을 수정해야 합니다.
$ vi calico.yaml
---
# /CALICO_IPV4POOL_CIDR 를 통해 패턴을 찾은 후, 주석 제거 후 변경
...
## 변경 전
# - name: CALICO_IPV4POOL_CIDR
# value: "192.168.0.0/16"
## 변경 후
- name: CALICO_IPV4POOL_CIDR
value: "192.168.158.0/24"
...
---
- 다음의 내용도 수정해야 합니다.
- Kubernetes 1.21 버전부터
policy/v1이 정식 API 버전으로 도입되어,
Kubernetes v1.25 버전부터policy/v1beta1API 버전의PodDisruptionBudget이 더 이상 제공되지 않기 때문입니다.
- Kubernetes 1.21 버전부터
$ vi calico.yaml
---
...
apiVersion: policy/v1 # 기존 v1beta1 을 수정
kind: PodDisruptionBudget
metadata:
name: calico-kube-controllers
namespace: kube-system
labels:
k8s-app: calico-kube-controllers
spec:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: calico-kube-controllers
...
---
12-3. calico.yaml 적용
$ kubectl apply -f calico.yaml'Kubernetes' 카테고리의 다른 글
| K8S Multi-Master Cluster | 쿠버네티스 멀티-마스터 클러스터링 (0) | 2025.11.08 |
|---|---|
| K8S Multi-Master Cluster | 멀티-마스터 클러스터를 위한 로드밸런서(Nginx) 구성 (0) | 2025.11.01 |
| Zero-to-K8S Cluster | 쿠버네티스 워커(데이터플레인) 노드 구축 (0) | 2025.10.25 |