본문 바로가기
Kubernetes

kubeadm으로 Kubernetes 구축하기 on AWS EC2 (Containerd, Calico, RHEL8/RHEL9)

by study4me 2024. 11. 23.
반응형

본 게시글에서는 kubeadm / Containerd / Calico를 사용하여 구축을 진행한다.
구축 환경은 인터넷이 가능한 환경이며, 서버 간 적절한 방화벽이 오픈되어 있다고 가정한다.
별도 Private Repository를 사용하지 않는다.
공식 문서를 기반으로 구축을 진행한다.

root 계정으로 명령어를 수행한다.

테스트 환경은 AWS EC2에서 진행하였으며, 단일 서브넷에 2개의 인스턴스를 생성했다.


Kubernetes Cluster 구축 전 체크 사항

1. Kubernetes Cluster 구축 시 어떤 배포도구를 사용할 것인지?

kubeadm / kOps / Kubespray

 

2. 어떤 Container Runtime은 어떤 것을 사용할 것인지?

Containerd / CRI-O / Docker Engin / Mirantis

 

3. 어떤 CNI를 사용할 것인지?

CNI : Container Network Interface
Calico / Flannel / Weave / Canal

 

4. Kubernetes Version과 다른 서비스들 간 호환성 체크

Kubernetes에서 Container Runtime으로 Cotainerd를 사용할 예정으로 Containerd 공식 문서에서 호환성을 체크한다.

Containerd는 Runc를 내부적으로 사용한다. yum install 같은 패키지 설치 명령어로 containerd를 설치할 때는 자동으로 Runc를 설치해 주지만, Containerd 설치파일을 다운로드하여 압출을 푸는 방식으로 설치할 경우에는 Runc를 별도로 설치해줘야 한다. 따라서 Containerd와 Runc 간 버전 호환성을 체크해야 한다. Containerd 공식 Github에서는 Runc 버전을 명시해 둔다.

Kubernetes에서 CNI로 Calico를 사용할 예정으로 Calico 공식 문서에서 호환성을 체크한다.

Kubernetes를 구축할 때 kubeadm init 명령어를 사용할 예정이고, kubeadm init을 사용하면 kube-system에서 사용할 컨테이너 이미지를 자동으로 Pull 받아서 구축을 시작한다. 추후 Containerd의 Config 파일에서 pause라는 이름의 컨테이너 이미지 버전을 수정해야 하기 때문에 사용하는 컨테이너 이미지 버전을 체크해 둔다.

Containerd(for Kubernetes)
  - https://containerd.io/releases/#kubernetes-support
Runc(for Containerd)
   - https://github.com/containerd/containerd/blob/v2.0.0/docs/RUNC.md
   - https://github.com/containerd/containerd/blob/v2.0.0/script/setup/runc-version
Calio(for Kubernetes)
   - https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements#kubernetes-requirements
Kubernets Each Manifest
   - Kubernetes-버전에-따른-kube-system-이미지-버전-찾는-법 

 

5. 구축 환경이 인터넷이 가능한 환경인지?

구축환경이 인터넷이 가능한지 폐쇄망인지에 따라 설치 방법이 다르다.

 

6. Kubernets를 위한 최소 사양 체크

2 GiB or more of RAM per machine--any less leaves little room for your apps.At least 2 CPUs on the machine that you use as a control-plane node.
 - https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#before-you-begin

 

7. 서버 기본 셋팅이 되었는지?

서버 시간 설정, yum update, System Archtectur 확인

# Datetime setting
ls /usr/share/zoneinfo/Asia | grep Seoul
sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
date

# Package List Update
yum update -y
dnf update -y

# Check System Architecture
uname -m

Kubernetes Cluster 구축

작성일 기준 최신 버전으로 설치하였기 때문에 작성한 링크는 최신 버전 링크이며,

추후 이 글을 읽는 사람이 링크를 클릭했을 때 아래 버전의 문서가 아닐 수 있다.

Master Node에서는 0번 ~ 12번까지 수행

Worker Node에서는 0번 ~ 9번까지 그리고 13번 수행

0. 사용할 버전 셋팅

호환성을 고려하여 버전은 아래와 같이 구성한다.

export kube_ver_minor='1.31'
export kube_ver_micro='1.31.3'
export coredns_ver_micro='1.11.1'
export pause_ver_minor='3.9'
export etcd_ver_micro='3.5.15-0'
export containerd_ver_micro='2.0.0'
export runc_ver_micro='1.2.1'
export calico_ver_micro='3.29.1'

1. /etc/hosts 파일 셋팅

vi /etc/hosts

MasterNode_IP MasterNode_Hostname
WorkerNode_IP WorkerNode_Hostname

# 예시
# 10.0.1.10 master01
# 10.0.1.11 worker01
# 10.0.1.12 worker02

2. Swap Off

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#swap-configuration
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab

3. Firewall Disable

각 서버 간 방화벽을 오픈해야 한다.

필요한 포트를 오픈해도 되지만 여기서는 그냥 모두 오픈해 주기로 한다.

특정 포트만 오픈하려면 공식 문서를 참고한다.

https://kubernetes.io/docs/reference/networking/ports-and-protocols/
systemctl stop firewalld
systemctl disable firewalld

4. SELinux Permissive Mode

kubeadm, kubelet, kubectl 설치를 위해서 SELinux Mode를 Permissive로 변경해야 한다.
순서를 앞쪽으로 뺀 이유는 해당 설정을 적용하지 않으면 Contained 설치 과정에서 systemctl enable --now containerd 명령어가 정상 실행되지 않기 때문이다.

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

5. Enable IPv4 packet forwarding

https://kubernetes.io/docs/setup/production-environment/container-runtimes/#prerequisite-ipv4-forwarding-optional
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

# Apply sysctl params without reboot
sudo sysctl --system

# Verify that net.ipv4.ip_forward is set to 1
sysctl net.ipv4.ip_forward

6. Install Containerd

Cgroup 관련해서는 다음과 같이 이해했다.

Cgroup Driver라는 것이 있는데 cgroupfs, systemd 두 종류가 있다.

Kubernetes v1.22 이후부터는 기본값으로 kubelet에서 systemd를 사용하도록 구성되어 있다.

kubelet과 Container Runtime은 같은 Cgroup Driver를 사용해야 한다.

공식 문서에서는 systemd를 사용하는 것을 권장하는 느낌이다.

[Containerd 설치]
 - https://github.com/containerd/containerd/blob/main/docs/getting-started.md#option-2-from-apt-get-or-dnf
 - https://docs.docker.com/engine/install/centos/
[Containerd Config.toml]
 - https://github.com/containerd/containerd/blob/main/docs/getting-started.md#customizing-containerd
[Containerd Config.toml - SystemdCgroup 관련]
 - https://github.com/containerd/containerd/blob/main/docs/cri/config.md#cgroup-driver
[Containerd Config.toml - Sandbox image 관련]
 - https://kubernetes.io/docs/setup/production-environment/container-runtimes/#override-pause-image-containerd

 

따라서 kubelet에서 기본값을 systemd를 사용하니까

Containerd(Container Runtime)의 구성파일을 수정하여 Containerd도 systemd를 사용하도록 설정하도록 한다.

Note:Starting with v1.22 and later, when creating a cluster with kubeadm, if the user does not set the cgroupDriver field under KubeletConfiguration, kubeadm defaults it to systemd.
If you configure systemd as the cgroup driver for the kubelet, you must also configure systemd as the cgroup driver for the container runtime. Refer to the documentation for your container runtime for instructions.
 - https://kubernetes.io/docs/setup/production-environment/container-runtimes/#systemd-cgroup-driver

 

Containerd의 Config 파일을 수정하면 restart를 해줘야 반영된다.

# Containerd 설치
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install -y containerd.io-${containerd_ver_micro}
systemctl daemon-reload
systemctl enable --now containerd

# Containerd config 파일 Default로 생성
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml


# --------------------------------------------------------------------------
# Containerd config 파일 수정
vi /etc/containerd/config.toml

# cat config.toml | grep version 명령어 반환 이 version = 3 일 경우
# [plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options] 하위의

# cat config.toml | grep version 명령어 반환 이 version = 2 일 경우
# [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] 하위의

# SystemdCgroup = false를 찾아서 아래와 같이 수정해주면됨
SystemdCgroup = true

# Overriding the sandbox (pause) image
# Kubernets Version에서 제시하는 pause image version으로 수정해주기
# sandbox_image = "registry.k8s.io/pause: 부분을 찾아서 아래와 같이 수정해주면됨
sandbox_image = "registry.k8s.io/pause:3.9"
# --------------------------------------------------------------------------

systemctl restart containerd
systemctl status containerd --no-pager

7. Kubernetes Repository 등록

Kubernets에서 제공하는 Repository를 사용할 수 있도록 등록해 준다.

설치하고자 하는 Kubernetes Version에 맞게 Repository URL을 설정해 준다.

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v${kube_ver_minor}/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v${kube_ver_minor}/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
더보기

공식문서를 한국어로 보면 안 되는 이유

아래 링크는 latest 버전(한국어) 임에도 불구하고 더 이상 사용하지 않는 Kubernetes Repository URL을 사용하라고 안내한다. 영어가 아닌 페이지는 최신 버전이 아닐 수 있기 때문에 꼭 영어 버전으로 보는 것이 좋다.

 

https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#kubeadm-kubelet-%EB%B0%8F-kubectl-%EC%84%A4%EC%B9%98

 

위 링크에 들어가면 아래와 같이 google cloud 링크를 알려주는데 더 이상 사용하지 않는다고 한다.

https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/change-package-repository/

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

8. Install kubeadm, kubelet, kubectl

설치되는 kubelet, kubeadm, kubectl은 Kubernetes Repository에서 지정한 Kubernetes Version을 따른다.

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-kubeadm-kubelet-and-kubectl
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
kubeadm version
kubelet --version
kubectl version
systemctl status kubelet --no-pager

9. Setting crictl Endpoint

crictl을 사용하기 위해서는 아래와 같이 endpoint 설정이 필요하다.

https://kubernetes.io/docs/tasks/debug/debug-cluster/crictl/#general-usage
https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md#usage
cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: true
EOF

10. kubeadm init

kubeadm init 명령어를 사용하여 Kubernetes Control Plane을 구축한다.

[옵션]

--pod-network-cidr : Pod Network 대역으로 필수로 넣어주자. 공식 문서에 명시된 Default 값이 없다.

--service-cidr : Kubernetes의 서비스 오브젝트를 위한 대역으로 기본값은 10.96.0.0/12이다.

--kubernetes-version : 설치할 Kubernetes 버전을 의미하며, 별도로 지정 안 하면 현재 기준 stable 버전으로 설치하는 것 같다.

 

Pod Network와 Service Network, Node의 IP 대역이랑 겹치면 안 된다.

Node, Container에서 접근해야 하는 네트워크 대역과도 겹치면 안 된다.

즉, Pod Network, Service Network, Node Network, 연동 대상 Network와 IP가 서로 겹치면 안 된다.

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#initializing-your-control-plane-node
https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/
export kube_pod_net='192.168.0.0/16'
export kube_svc_net='10.96.0.0/12'

kubeadm init --pod-network-cidr=${kube_pod_net} --service-cidr=${kube_svc_net} --kubernetes-version=v${kube_ver_micro} >> kubeadm_ini_output.txt

systemctl restart kubelet
systemctl status kubelet --no-pager

11. Kube Config

새로 생성한 Cluster를 대상으로 kubectl을 사용하려면 사용자의 홈디렉터리 하위에 .kube/config 가 필요하며

config 파일은 Master Server의 /etc/kubernets/admin.config를 복사한다.

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

12. Install Calico, Calicoctl

Calico를 설치할 때 사용하는 custom-resources.yaml은 pod network가 192.168.0.0/16인 것을 기준으로 작성되어 있다.

따라서 kubeadm init을 할 때, 192.168.0.0/16이 아닐 경우 custom-resources.yaml을 수정한 후 배포해야 한다.

아래 코드에서는 변경이 필요한지 체크한 후 자동으로 변경하도록 짜여있다.

https://docs.tigera.io/calico/latest/getting-started/kubernetes/quickstart https://docs.tigera.io/calico/latest/operations/calicoctl/install
# Install Calico
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v${calico_ver_micro}/manifests/tigera-operator.yaml
curl -LO https://raw.githubusercontent.com/projectcalico/calico/v${calico_ver_micro}/manifests/custom-resources.yaml

if [ "${kube_pod_net}" != "192.168.0.0/16" ]; then
  sed -i "s/cidr: 192\.168\.0\.0\/16/cidr: ${kube_pod_net//\//\\/}/g" ~/custom-resources.yaml
  cat ~/custom-resources.yaml |grep cidr
fi
kubectl create -f ~/custom-resources.yaml

sleep 30
kubectl get pods -n calico-system
kubectl get nodes -o wide


# Install Calicoctl
curl -L https://github.com/projectcalico/calico/releases/download/v${calico_ver_micro}/calicoctl-linux-amd64 -o calicoctl
chmod +x ./calicoctl
mv calicoctl /usr/local/bin

13. Worker Node Join

# Master Server에서 cat ~/kubeadm_ini_output.txt 명령어 수행 후 나오는 내용 중
# kubeadm join 부분을 복사해서 Worker Node에서 실행

kubeadm join master_node_ip:6443 --token xxxxxxxxxxxxxxxx \
        --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

번외.

AWS 환경에서 Calico를 사용한다면 다음 문서를 꼭 읽어보기를 바란다.

나는 단일 서브넷에 EC2를 생성하였기 때문에 Source/Destination Check를 중지 시켜줬다.

여러 AZ에 거쳐서 서브넷을 사용하고 있다면 뭔가 더 많은 설정을 해줘야하는 듯하다.

https://docs.tigera.io/calico/latest/reference/public-cloud/aws

 

Azure, GCP, IBM에서 테스트를 하고 있다면 다음 문서를 읽어보기를 바란다.

https://docs.tigera.io/calico/latest/reference/public-cloud/azure

https://docs.tigera.io/calico/latest/reference/public-cloud/gce

https://docs.tigera.io/calico/latest/reference/public-cloud/ibm

 


Advanced step

1. Containerd에서 사용하는 저장 공간을 OS 영역과 분리된 Disk로 변경해주기.

OS 영역과 다른 Disk를 사용하여 OS 영역의 Disk 공간이 부족해져 장애가 발생하는 상황을 방지하기 위함.

Containerd에서 사용하는 공간으로 다음 경로가 있다.

노란색으로 표시한 Path에 별도 디스크를 mount하거나 Containerd Config 파일을 수정하여 다른 경로로 변경할 수 있다.

Path Description config 위치
/var/lib/containerd Containerd의 영구 데이터 저장소
컨테이너 이미지, 스냅샷, 메타데이터 등이 저장된다.
Containerd가 재시작되더라도 컨테이너 상태를 복원할 수 있게해줌.
/etc/containerd/config.toml
/run/containerd Container 런타임 파일을 저장 /etc/containerd/config.toml
/var/run/containerd /var/run은 심볼릭 링크를 사용하여 /run을 가리키고 있음
(windows로 따지면 바로가기 폴더 같은 느낌)

ls -al /var |grep run
lrwxrwxrwx.  1 root root    6 Mar 27  2024 run -> ../run
 
/var/log/pods Pod의 로그 파일 저장 ???
/var/log/containers /var/log/containers 하위에 있는 로그 파일들은 /var/log/pods 하위의 파일들을 가리키고 있음
(바로가기 파일(?) 같은 느낌)
 

 

 


Kubernetes Cluster 구축 에러 및 시행착오

참고: https://study4me-it.tistory.com/entry/Kubernetes-%EB%AC%B8%EC%A0%9C%ED%95%B4%EA%B2%B0-%EB%AA%A8%EC%9D%8C

반응형