Cloud/Kubernetes

[v1.21] Kubeadm + Containerd + Calico + NFS-Provisioner + Ingress-Nginx 설치

21.05.22 현재 최신 버전인 v1.21 기준으로 쿠버네티스 클러스터 세팅을 기록해두려고 한다.

 

구축환경

  • Hyper-V
    • Controlplane : 2CPU, 3GB MEM, 20GB STORAGE, Bridge Network
    • node01 : 2CPU, 4GB MEM, 15GB STORAGE, Bridge Network
    • node02 : 2CPU, 4GB MEM, 15GB STORAGE, Bridge Network
    • nfs : 1CPU, 1GB MEM, 110GB(10GB SSD + 100GB HDD) STORAGE, Bridge Network
  • OS
    • Ubuntu 20.04 LTS Server
  • Cluster
    • Kubernetes : Kubeadm
    • CRI : Containerd
    • Network Addon : Calico
    • NFS-Provisioner : nfs-subdir-external-provisioner
    • Ingress Controller : Nginx (external IPs)

설치하기 전에

Containerd

쿠버네티스 1.22버전부터 docker 지원이 종료된다고 하여 containerd를 설치하였다.

Ingress Controller

Network Addon으로 Calico를 사용할 경우, Ingress Controller로 MetalLB를 사용하면 BGP 이슈가 있었다. 그래서 Ingress Controller는 external IPs 방식으로 설치하였다.

NFS-Provisioner

기존 stable 헬름 차트에 있던 nfs-server-provisioner는 작년 말 차트 업데이트 지원이 중단되면서 최신 쿠버네티스 버전에 대한 업데이트가 끊겼다. 그래서 최신 버전에 대응하는 nfs-subdir-external-provisioner 차트를 사용하여 설치한다.

설치

Containerd

필수 구성요소 설치 및 구성

cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 필요한 sysctl 파라미터를 설정하면 재부팅 후에도 유지된다.
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

# 재부팅하지 않고 sysctl 파라미터 적용
sudo sysctl --system

containerd 설치

sudo apt-get update

sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo \
  "deb [arch=amd64 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-get update
sudo apt-get install containerd.io

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

sudo systemctl restart containerd

systemd cgroup driver 사용 설정

sudo vi /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    # 라인 추가
    SystemdCgroup = true
sudo systemctl restart containerd

Kubeadm

br_netfilter 모듈 로드

sudo modprobe br_netfilter

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

sudo sysctl --system

swap 삭제 및 비활성화

sudo swapoff -a
sudo rm /swap.img

sudo vi /etc/fstab
/swap.img       none    swap    sw      0       0 #라인 삭제

kubeadm, kubelet, kubectl 설치

sudo apt-get update
sudo apt-get 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

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-get update
# 노드에 kubectl이 필요하지 않으면 제외하고 설치
sudo apt-get install -y kubelet kubeadm kubectl
# 노드에 kubectl이 필요하지 않으면 제외하고 설정
sudo apt-mark hold kubelet kubeadm kubectl

Controlplane 초기화

# host가 192.168.10.0/24 대역을 사용중이기 때문에 172.16.0.0/16으로 변경하여 초기화
sudo kubeadm init --pod-network-cidr=172.16.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Node 참가

# Controlplane 초기화 후 출력되는 명령어 복사하여 사용
sudo kubeadm join 192.168.10.101:6443 --token 6005sj.z8snl36wrcpj6vkt \
        --discovery-token-ca-cert-hash sha256:787233795e6ab5c88e41f8557f83c16e40c8d1a5ab311ac162068e6f65e4d4c5

참고사항

kubernetes v1.21부터 KubeletConfiguration에 CgroupDriver를 systemd로 세팅하지 않아도, kubeadm init 명령어 사용 시 기본적으로 systemd로 설정됩니다.

만약 kubernetes v1.20 이하 버전을 설치하시는 분은 수동으로 설정이 필요합니다.

Calico

wget https://docs.projectcalico.org/manifests/calico.yaml
vi calico.yaml
# 주석 해제 후 192.168 -> 172.16으로 변경
- name: CALICO_IPV4POOL_CIDR
  value: "172.16.0.0/16"
kubectl apply -f calico.yaml

설치확인

kubectl get nodes

NFS-Provisioner

nfs server (nfs) 설치

sudo apt update
sudo apt upgrade

sudo fdisk /dev/sdb
n(ew)
Enter(Default)
Enter(Default)
Enter(Default)
Enter(Default)
w(rite)

sudo mkdir /mnt/k8s-nfs
sudo vi /etc/fstab
# /etc/fstab

# 부팅 시 /mnt/k8s-nfs 마운트 하도록 설정
/dev/sdb1 /mnt/k8s-nfs ext4 defaults 1 1
sudo mount -t ext4 /dev/sdb1 /mnt/k8s-nfs
sudo apt install nfs-kernel-server
sudo vi /etc/exports
/mnt/k8s-nfs 192.168.10.0/24(rw,sync,no_root_squash)
sudo systemctl restart nfs-kernel-server

nfs client (controlplane, node01, node02) 설치

sudo apt install nfs-common

helm 설치

wget https://get.helm.sh/helm-v3.6.0-rc.1-linux-amd64.tar.gz
tar -zxvf helm-v3.6.0-rc.1-linux-amd64.tar.gz
sudo mv linux-amd64/helm /usr/local/bin/

nfs-subdir-external-provisioner 설치

helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
# nfs 서버 IP와 PATH 입력
# 현재 설치되는 storage class를 default로 사용
helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --namespace nfs-provisioner --create-namespace \
    --set nfs.server=192.168.10.100 \
    --set nfs.path=/mnt/k8s-nfs \
    --set storageClass.defaultClass=true

Ingress-Nginx

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm pull ingress-nginx/ingress-nginx --untar

vi ingress-nginx/values.yaml
    ## List of IP addresses at which the controller services are available
    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips
    ##
    # kubectl get node -o wide 명령어로 cluster IP 확인 후 아래 채워넣기
    externalIPs: ["192.168.10.101","192.168.10.102","192.168.10.103"]
helm install ingress-nginx . -f values.yaml --namespace ingress-nginx --create-namespace