클러스터 생성 및 설정 (Kubeadm)
본질적으로 "Vanilla Kubernetes"는 광범위한 사용 사례에 적합한 쿠버네티스의 표준 버전을 의미하다. 이 버전은 쿠버네티스의 핵심 기능들을 모두 포함하고, 이번 데모에서는 한 물리 서버에, 가상 머신 3대를 사용하여 쿠버네티스 클러스터를 생성할 예정이다.
💡 현재 VMWare Workstation에서 실습 진행
- Master Node: 192.168.1.10
- Worker Node 1: 192.168.1.20
- Worker Node 2: 192.168.1.30
쿠버네티스 클러스터 설정 시 Swap Memory 비활성화를 권장 한다. Swap Memory는 하드 디스크를 이용하여 RAM을 보충하는 가상 메모리이지만, K8s는 많은 자원을 요구하므로 Swap Memory를 사용하면 성능 저하와 스케줄링 지연이 발생할 수 있다. 또한, Swap Memory는 리소스 관리에 문제를 야기할 수 있으므로 안정적이고 효율적인 성능을 위해 스왑 메모리를 비활성화해야 한다. 더 자세한 내용은 여기 블로그 링크 참고.
CentOS 7에서 K8s 클러스터
Docker Installation
시작 전, 이전 버전들을 삭제 한다
sudo dnf remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
yum-utils 설치와 로컬 yum repository (저장소) 지정
sudo dnf install -y yum-utils
sudo dnf-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
도커 최신 버전 설치
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
도커 서비스 시작
sudo systemctl start docker
도커 버전 확인
docker version
Kubernetes Installation
💡 Master Node과 Worker Node에서 동일 하게 작업
Swap Memory 비활성화
swapoff -a
daemon.json 파일 생성 후 cgroupdriver을 systemd로 설정
vi /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
daemon 재시작
systemctl daemon-reload
systemctl restart docker
쿠버네티스 로컬 저장소 지정 및 설치
vi /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
# 쿠버네티스 설치
dnf install -y kubelet-1.19.16-0.x86_64 kubectl-1.19.16-0.x86_64 kubeadm-1.19.16-0.x86_64
쿠버네티스 설치 완료 확인
rpm -qa | grep kube
쿠버네티스 클러스터 요소들 통신을 위해 방화벽 포트 추가
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=443/tcp
firewall-cmd --permanent --add-port=2376/tcp
firewall-cmd --permanent --add-port=2379/tcp
firewall-cmd --permanent --add-port=2380/tcp
firewall-cmd --permanent --add-port=6443/tcp
firewall-cmd --permanent --add-port=8472/udp
firewall-cmd --permanent --add-port=9099/tcp
firewall-cmd --permanent --add-port=10250/tcp
firewall-cmd --permanent --add-port=10251/tcp
firewall-cmd --permanent --add-port=10252/tcp
firewall-cmd --permanent --add-port=10254/tcp
firewall-cmd --permanent --add-port=10255/tcp
firewall-cmd --permanent --add-port=30000-32767/tcp
firewall-cmd --permanent --add-port=30000-32767/udp
firewall-cmd --permanent --add-masquerade
firewall-cmd --reload
💡마스터 노드에서만 진행
쿠버네티스 클러스터 생성
kubeadm init --apiserver-advertise-address=192.168.1.10 --pod-network-cidr=10.244.0.0/16
# K8s control plane 생성 완료 화면
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.1.10:6443 --token 172vji.r0u77jcmcnccm6no \
--discovery-token-ca-cert-hash sha256:72b9648c647f724ab52471847cb06c47b23097375f2e67633b745fc69db16e8d
kubectl 활성화 위해 admin.conf 복사 작업
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
네트워크 플러그인 다운로드 (Flannel)
[ CNI(Container Network Interface)는 컨테이너를 위한 네트워킹을 제어할 수 있는 플러그인을 만들기 위한 표준이라고 한다. 간단하게 설명 하면 CNI플러그인을 쿠버네티스 클러스터에 설치하여 서로 다른 노드에서 실행되는 컨테이너 간의 네트워킹을 할 수 있다 ]
더 자세한 내용은 링크 참고
curl -O -L https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kube-flannel.yml 파일 안에 --iface=(가상 인터페이스 이름) 지정
vi kube-flannel.yml
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens160
네트워크 플러그인 YAML 파일 적용 후 kubelet 재시작
kubectl apply -f kube-flannel.yml
systemctl restart kubelet
💡 Worker Node에서 작업
Master Node에서 받은 Discovery Token 값을 join 명령어로 통해 Master과 Worker 노드 묶기
kubeadm join 192.168.1.10:6443 --token 172vji.r0u77jcmcnccm6no \
--discovery-token-ca-cert-hash sha256:72b9648c647f724ab52471847cb06c47b23097375f2e67633b745fc69db16e8d
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 작업이 완료 후 마스터 노드에서 쿠버네티스 클러스터 확인
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 107m v1.19.16
node-1 Ready <none> 91s v1.19.16
node-2 Ready <none> 48s v1.19.16
Rocky Linux 9.1에서 K8s 클러스터
Docker Installation
업데이트 확인 및 업데이트 있으면 실행
sudo dnf check-update
sudo dnf update
도커 repository (저장소) 추가
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
도커 설치
sudo dnf install docker-ce docker-ce-cli containerd.io
도커 시작 및 확인
sudo systemctl start docker
sudo systemctl enable docker
sudo docker version
'sudo' 생략 하고 docker 만 쓰고 싶으면
sudo usermod -aG docker $(whoami)
Kubernetes Installation
💡 Master Node과 Worker Node에서 동일 하게 작업
Swap Memory 비활성화
sudo swapoff -a
daemon.json 파일 생성 후 cgroupdriver을 systemd로 설정
sudo vi /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
daemon 재시작
sudo systemctl daemon-reload
sudo systemctl restart docker
쿠버네티스 로컬 저장소 지정 및 설치
sudo vi /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
# 쿠버네티스 설치
sudo dnf -y kubelet-1.19.16-0.x86_64 kubectl-1.19.16-0.x86_64 kubeadm-1.19.16-0.x86_64
쿠버네티스 설치 완료 확인
sudo rpm -qa | grep kube
쿠버네티스 클러스터 요소들 통신을 위해 방화벽 포트 추가
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=2376/tcp
sudo firewall-cmd --permanent --add-port=2379/tcp
sudo firewall-cmd --permanent --add-port=2380/tcp
sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --permanent --add-port=8472/udp
sudo firewall-cmd --permanent --add-port=9099/tcp
sudo firewall-cmd --permanent --add-port=10250/tcp
sudo firewall-cmd --permanent --add-port=10251/tcp
sudo firewall-cmd --permanent --add-port=10252/tcp
sudo firewall-cmd --permanent --add-port=10254/tcp
sudo firewall-cmd --permanent --add-port=10255/tcp
sudo firewall-cmd --permanent --add-port=30000-32767/tcp
sudo firewall-cmd --permanent --add-port=30000-32767/udp
sudo firewall-cmd --permanent --add-masquerade
sudo firewall-cmd --reload
💡마스터 노드에서만 진행
슈퍼 유저 (root 계정)으로 전환
sudo su
쿠버네티스 클러스터 생성
kubeadm init --apiserver-advertise-address=192.168.1.10 --pod-network-cidr=10.244.0.0/16
# K8s control plane 생성 완료 화면
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:
sudo kubeadm join 192.168.1.10:6443 --token 1x7qb2.dww3u7mjsrq2hoxt --discovery-token-ca-cert-hash sha256:10a6803e9a45bb029af4ad3c1d0d894dfaee9980d2318c495739296daeffb9eb
kubectl 활성화를 위해 admin.conf 복사 작업 (꼭 root계정으로 해야됨!)
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
네트워크 플러그인 다운로드
curl -O -L https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
네트워크 플러그인 YAML 파일 적용 후 kubelet 재시작 (꼭 root계정으로 해야됨!)
kubectl apply -f kube-flannel.yml
systemctl restart kubelet
💡 Worker Node에서 작업
Master Node에서 받은 Discovery Token 값을 join 명령어로 통해 Master과 Worker 노드 묶기
sudo kubeadm join 192.168.1.10:6443 --token 1x7qb2.dww3u7mjsrq2hoxt \
--discovery-token-ca-cert-hash sha256:10a6803e9a45bb029af4ad3c1d0d894dfaee9980d2318c495739296daeffb9eb
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 작업이 완료 후 마스터 노드에서 쿠버네티스 클러스터 확인
sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 33m v1.19.16
worker-1 Ready <none> 91s v1.19.16
worker-2 Ready <none> 48s v1.19.16
Ubuntu 20.04.6에서 K8s 클러스터
Docker Installation
업데이트 확인 및 실행
sudo apt update
필수 패키지 설치
sudo apt install ca-certificates curl gnupg lsb-release
도커 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
도커 Repository 등록
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
도커 엔진 설치 및 확인
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
sudo docker version
sudo systemctl status docker
## 서버 재시작 시 docker 가 자동으로 시작되도록 설정 ##
sudo systemctl enable docker
Kubernetes Installation
💡 Master Node과 Worker Node에서 동일 하게 작업
Swap Memory 비활성화
sudo swapoff -a
노드간 통신을 위한 iptables에 브릿지 관련 설정 추가
sudo vi /etc/modules-load.d/k8s.conf
br_netfilter
sudo vi /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
# sysctl.conf 파일 맨 아래에도 동일 하게 두 줄 추가
sudo vi /etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
# sysctl 설정 파일들의 변동을 저장 하기 위해
sudo sysctl --system
sudo sysctl -p
daemon.json 파일 생성 후 cgroupdriver을 systemd로 설정
sudo vi /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
daemon 재시작
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl enable docker
apt 업데이트 및 ca 관련 패키지 다운로드 및 설
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
도커 gpg 및 소스 리스트 내용 추가 및 apt 업데이
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
kubeadm, kubelet 그리고 kubectl 설치 및 활성화
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl start kubelet && systemctl enable kubelet
💡마스터 노드에서만 진행
쿠버네티스 클러스터 생성을 위해 kubeadm init 실행
sudo kubeadm init --apiserver-advertise-address=192.168.1.10 --pod-network-cidr=10.244.0.0/16
# K8s control plane 생성 완료 화면
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.1.10:6443 --token mu72kx.sn06xzcg3lde7mha \
--discovery-token-ca-cert-hash sha256:d134654458b474c796667776ab8175adbc0e1dc4bc21a712a19a7bb405ee9273
kubectl 활성화를 위해 admin.conf 복사 작업
sudo mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
네트워크 플러그인 다운로드
curl -O -L https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
네트워크 플러그인 YAML 파일 적용 후 kubelet 재시작
kubectl apply -f kube-flannel.yml
sudo systemctl restart kubelet
💡 Worker Node에서 진행
Master Node에서 받은 Discovery Token 값을 join 명령어로 통해 Master과 Worker 노드 묶기
sudo kubeadm join 192.168.1.10:6443 --token mu72kx.sn06xzcg3lde7mha \
--discovery-token-ca-cert-hash sha256:d134654458b474c796667776ab8175adbc0e1dc4bc21a712a19a7bb405ee9273
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 작업이 완료 후 마스터 노드에서 쿠버네티스 클러스터 확인
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 33m v1.19.16
worker-1 Ready <none> 91s v1.19.16
worker-2 Ready <none> 48s v1.19.16
Error Troubleshooting
[ERROR CRI]: container runtime is not running [Issue Encountered]
이 문제는 사용되는 CRI가 Containerd인 경우 마스터 노드에서 kubeadm init 명령을 실행할 때 자주 발생한다. 대부분의 경우 config.toml 파일에 문제가 있다.
해결
# config.toml 파일을 삭제 한다
sudo rm /etc/containerd/config.toml
# containerd 서비스 재시작
sudo systemctl restart containerd
The connection to the server <IP 주소>:6443 was refused - did you specify the right host or port?
이 에러는 보통 API 서버가 실행 중이지 않거나 네트워킹 문제가 있는 경우 발생할 수 있다. 하지만 이 애러가 마스터 노드 재시작 후 발생 한다면 Swap 메모리 문제일 가능성이 높다. 그런 경우 리소스 제약 때문에 발생한 문제일 가능성이 있다. Swap이 활성화되어 있으면, 커널은 비활성화된 페이지를 디스크로 이동시킬 수 있으며, 이로 인해 API 요청과 같은 지연이 발생할 수 있다. 이러한 시스템 재시작 할때 매번 swap memory를 비활성화 해야 된다.
해결
/etc/fstab 설정 파일안에서 swap을 주석 처리 해준다
sudo vi /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda3 during curtin installation
/dev/disk/by-uuid/05bb7e29-bd2d-4ffb-86c6-8868e48548f4 / ext4 defaults 0 1
# /boot/efi was on /dev/sda2 during curtin installation
/dev/disk/by-uuid/ebbd40d6-5f57-4214-806f-8cf8e929b23d /boot/efi ext4 defaults 0 1
# /swap.img none swap sw 0 0