Computer Science/k8s

kubeadm을 통한 kubernetes(1.27) EC2에 설치하기

imygnam 2023. 7. 31. 21:36

1. ec2 사양 정하기

2. 컨테이너 런타임 설치 ( containerd )

   2-1. containerd 설치

   2-2. systemd 설정

   2-3. runc 설치

   2-4. CNI 설치

3. cgroup 드라이버 구성

4. iptables 설정

5. kubeadm 설치

6. Control Plane Node 생성

7. Addon 설치

8. Worker Node 생성 및 연동


공식 문서를 보고 따라서 설치해보자.

https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

 

kubeadm 설치하기

이 페이지에서는 kubeadm 툴박스 설치 방법을 보여준다. 이 설치 프로세스를 수행한 후 kubeadm으로 클러스터를 만드는 방법에 대한 자세한 내용은 kubeadm으로 클러스터 생성하기 페이지를 참고한다.

kubernetes.io

1. ec2 사양 정하기

시작하기 전에를 보면 알 수 있듯이 2GB 이상의 램, 2코어 이상의 CPU가 필요하다고 나와있다.

이를 충족하는 가장 저렴한 ec2는 t3.small 이기에 해당 인스턴스로 진행하였다.

또한 특정 포트들의 개방, 스왑 메모리의 비활성화를 요구하는데 기본적으로 t3.small ec2는 스왑 메모리가 활성화 되어있지 않았다.

혹시 모르니 아래의 명령어로 확인해보자.

free -h

Swap 메모리 total이 0B로 활성화 되어있지 않는 것을 볼 수 있다.

사용 하는 특정 포트들에 대한 정보는 여기에 있다.

https://kubernetes.io/ko/docs/reference/networking/ports-and-protocols/

 

포트와 프로토콜

물리적 네트워크 방화벽이 있는 온프레미스 데이터 센터 또는 퍼블릭 클라우드의 가상 네트워크와 같이 네트워크 경계가 엄격한 환경에서 쿠버네티스를 실행할 때, 쿠버네티스 구성 요소에서

kubernetes.io

 

컨트롤 플레인 노드의 포트

프로토콜 방향 포트 범위 용도 사용 주체
TCP 인바운드 6443 쿠버네티스 API 서버 전부
TCP 인바운드 2379-2380 etcd 서버 클라이언트 API kube-apiserver, etcd
TCP 인바운드 10250 Kubelet API Self, 컨트롤 플레인
TCP 인바운드 10259 kube-scheduler Self
TCP 인바운드 10257 kube-controller-manager Self

쿠버네티스 컨트롤 플레인 컴포넌트(Control Plane components) 에 해당하는 쿠버네티스 API 서버, etcd 서버, kube-scheduler, kube-controller-manager 이렇게 4가지의 포트와 함께 kubelet API 포트를 사용한다. 여기서 쿠버네티스 API 서버 포트인 6443 포트는 열어주어야 워커노드와 통신이 가능하다.

 

워커 노드의 포트

프로토콜 방향 포트 범위 용도 사용 주체
TCP 인바운드 10250 쿠버네티스 API Self, 컨트롤 플레인
TCP 인바운드 30000-32767 NodePort 서비스 전부

워커노드는 kubelet 을 통해 플레인 노드와 통신하는데 해당 포트인 10250를 열어주어야 한다.

 

2. 컨테이너 런타임 설치 ( containerd )

https://github.com/containerd/containerd/blob/main/docs/getting-started.md

위 공식 문서를 보고 따라 진행했다.

 

2-1. containerd 설치

https://containerd.io/downloads/

 

containerd – containerd downloads

To install the binaries for containerd version 1.7.2 (latest), click on the Binaries (.tar.gz) button for that version in the Releases table below. That will copy the tarball URL to your clipboard. Use wget to download the tarball and untar it. The table b

containerd.io

wget https://github.com/containerd/containerd/releases/download/v1.7.2/containerd-1.7.2-linux-amd64.tar.gz

다운 받은 zip 파일을 /usr/local에 풀어준다.

sudo tar Cxzvf /usr/local containerd-1.7.2-linux-amd64.tar.gz

2-2. systemd 설정

containerd.service를 다운해서 /lib/systemd/system/containerd.service에 두라고 한다.

containerd.service 는 https://raw.githubusercontent.com/containerd/containerd/main/containerd.service 이곳에 존재한다.

sudo mkdir -p /usr/local/lib/systemd/system/ && sudo wget -P /usr/local/lib/systemd/system/ https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

아래와 같이 문구가 나와야 정상이다.

Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /usr/local/lib/systemd/system/containerd.service.

2-3. runc 설치

https://github.com/opencontainers/runc/releases

 

Releases · opencontainers/runc

CLI tool for spawning and running containers according to the OCI specification - opencontainers/runc

github.com

자신의 아키텍처 맞는 파일을 다운해주자.

Linux의 경우 아래 명령어로 확인이 가능하다.

uname -m

 

x86_64 가 나왔다. 이는 amd64로 https://github.com/opencontainers/runc/releases/download/v1.1.8/runc.amd64 이곳에서 설치가 가능하다.

wget https://github.com/opencontainers/runc/releases/download/v1.1.8/runc.amd64
sudo install -m 755 runc.amd64 /usr/local/sbin/runc

2-4. CNI 설치

https://github.com/containernetworking/plugins/releases

 

Releases · containernetworking/plugins

Some reference and example networking plugins, maintained by the CNI team. - containernetworking/plugins

github.com

똑같이 내 OS와 아키텍처를 확인해서 다운로드를 해준다.

https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz 

wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.3.0.tgz

3. cgroup 드라이버 구성

https://kubernetes.io/docs/setup/production-environment/container-runtimes/

 

Container Runtimes

Note: Dockershim has been removed from the Kubernetes project as of release 1.24. Read the Dockershim Removal FAQ for further details. You need to install a container runtime into each node in the cluster so that Pods can run there. This page outlines what

kubernetes.io

cgroupfs, systemd 둘 중 하나로 cgroup을 통일해야한다고 나와있다.

다만 systemd 가 init system이면 systemd를 사용하라고 나와있다. systemd가 Init system인지 확인하는 방법은 다음과 같은 명령어를 치면 알 수 있다.

ps -p 1 -o comm=

결과가 systemd로 나오면 systemd가 init system으로 존재한다.

1.22 version 이후로는 default가 systemd라고 하니 추가로 설정할 것은 없어보이며 여기서 중요한것은 containerd 설정이다.

config.toml을 생성하면서 수정까지 해주자.

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

위의 명령어로 생성 및 확인을 할 수 있다.

아래와 같이 SystemCgroup 부분을 true로 변경해주어야 한다.

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

간단하게 아래의 명령어로 진행하자.

sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

설정을 변경한 후 containerd를 재시작하면 된다.

sudo systemctl restart containerd

 

4. iptables 설정

bridged traffic의 경우 iptables를 우회 할 수 있기에 해당 설정을 진행해야한다.

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

sudo modprobe overlay
sudo modprobe br_netfilter

# sysctl params required by setup, params persist across reboots
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

# Apply sysctl params without reboot
sudo sysctl --system

확인하는 과정은 다음과 같다.

lsmod | grep br_netfilter
lsmod | grep overlay

존재한다면 잘 적용 된 것이다.

net.bridge.bridge-nf-call-iptables, net.bridge.bridge-nf-call-ip6tables, net.ipv4.ip_forward가 1로 설정되어있는지 확인하는 명령어는 다음과 같다.

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

전부 1로 나온다면 정상이다.

 

5. kubeadm 설치

내 ec2는 레드햇 기반 배포판이기에 아래의 명령어를 적용시켰다.

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

마지막 명령어를 입력시 아래와 같은 문구가 나왔다.

Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /usr/lib/systemd/system/kubelet.service.

좋다 이제 클러스터를 생성해보자.

 

6. Control Plane Node 생성

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

 

Creating a cluster with kubeadm

Using kubeadm, you can create a minimum viable Kubernetes cluster that conforms to best practices. In fact, you can use kubeadm to set up a cluster that will pass the Kubernetes Conformance tests. kubeadm also supports other cluster lifecycle functions, su

kubernetes.io

 

sudo kubeadm init

만약 외부 ip를 이용하여 cluster를 생성하고 싶다면 아래와 같이 진행하면된다.

sudo kubeadm init --apiserver-cert-extra-sans=<외부 IP> --control-plane-endpoint=<외부 IP>:6443
#sudo kubeadm init --apiserver-cert-extra-sans=0.0.0.0 --control-plane-endpoint=0.0.0.0:6443

 

그럼 아래와 같이 성공했다는 문구가 나온다.

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 10.0.0.7:6443 --token <###############> \
	--discovery-token-ca-cert-hash sha256:<##################>

나는 현재 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

이제 pod들이 잘 떠있는지 확인해보자.

[ec2-user@ip-10-0-0-7 ~]$ kubectl get pods -n kube-system
NAME                                                                  READY   STATUS    RESTARTS   AGE
coredns-5d78c9869d-2d8nz                                              0/1     Pending   0          5m46s
coredns-5d78c9869d-z6sr2                                              0/1     Pending   0          5m46s
etcd-ip-10-0-0-7.ap-northeast-2.compute.internal                      1/1     Running   0          5m50s
kube-apiserver-ip-10-0-0-7.ap-northeast-2.compute.internal            1/1     Running   0          5m50s
kube-controller-manager-ip-10-0-0-7.ap-northeast-2.compute.internal   1/1     Running   0          5m53s
kube-proxy-tj7kp                                                      1/1     Running   0          5m47s
kube-scheduler-ip-10-0-0-7.ap-northeast-2.compute.internal            1/1     Running   0          5m53s

coredns가 뜨지 않는 것을 확인할 수 있는데 이는 pod network add-on이 설치되지 않아서이다.

성공문구에도 나와있는데 자세히보면 pod network를 배포하라고 나와있다.

 

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/

7. Addon 설치

https://kubernetes.io/docs/concepts/cluster-administration/addons/

 

Installing Addons

Note: This section links to third party projects that provide functionality required by Kubernetes. The Kubernetes project authors aren't responsible for these projects, which are listed alphabetically. To add a project to this list, read the content guide

kubernetes.io

링크를 들어가보면 Addons의 종류가 여러가지가 있는데 이를 비교한 사이트가 있다.

https://itnext.io/benchmark-results-of-kubernetes-network-plugins-cni-over-10gbit-s-network-updated-august-2020-6e1b757b9e49

 

Benchmark results of Kubernetes network plugins (CNI) over 10Gbit/s network (Updated: August 2020)

This article is an update of my previous benchmark (2018 and 2019), now running Kubernetes 1.19 and Ubuntu 18.04 with CNI version…

itnext.io

위에서 확인했듯이 현재로서는 Calico가 범용적으로 좋은 성능을 보여준다. 하여 Calico로 설치하도록 하겠다.

Caclico 설치의 요구사항이 있는지 우선 확인을 해보았더니 현재로서는 추가 Port를 열어주어야 하는 것 이외에는 없다.

https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements

 

System requirements | Calico Documentation

Review requirements before installing Calico to ensure success.

docs.tigera.io

Calico Network requirements

프로토콜 방향 포트 범위 Configuration Host(s)
TCP 양방향 179 Calico networking (BGP) All
UDP 양방향 4789 Calico networking with VXLAN enabled All
TCP 인바운드 5473 Calico networking with Typha enabled Typha agent hosts
UDP 양방향 51820 Calico networking with IPv4 Wireguard enabled All
UDP 양방향 51821 Calico networking with IPv6 Wireguard enabled All
TCP 인바운드 443, 6443 All kube-apiserver-host
TCP 인바운드 2379 etcd datastore etcd hosts

여기서 179 포트는 플레인노드든 워커노드든 열어주어야한다. Calico 는 해당 포트로 동신을 하기 때문이다.

 

https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises

 

Install Calico networking and network policy for on-premises deployments | Calico Documentation

Install Calico networking and network policy for on-premises deployments.

docs.tigera.io

이곳에서 확인 할 수 있듯이 현재로서는 https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml 이 파일로 배포를 하면된다.

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

잠시 뒤에 다시한번 확인해보면 전부 정상으로 배포되었다.

[ec2-user@ip-10-0-0-7 ~]$ kubectl get pods -n kube-system
NAME                                                                    READY   STATUS    RESTARTS   AGE
calico-kube-controllers-85578c44bf-cxz4j                                1/1     Running   0          16m
calico-node-s9s7r                                                       1/1     Running   0          16m
coredns-5d78c9869d-2d8nz                                                1/1     Running   0          16m
coredns-5d78c9869d-z6sr2                                                1/1     Running   0          16m
etcd-ip-10-0-0-7.ap-northeast-2.compute.internal                        1/1     Running   0          17m
kube-apiserver-ip-10-0-0-7.ap-northeast-2.compute.internal              1/1     Running   0          17m
kube-controller-manager-ip-10-0-0-7.ap-northeast-2.compute.internal     1/1     Running   0          17m
kube-proxy-tj7kp                                                        1/1     Running   0          16m
kube-scheduler-ip-10-0-0-7.ap-northeast-2.compute.internal              1/1     Running   0          17m

 

8. Worker Node 생성 및 연동

Worker Node 또한 1~5까지의 설정은 동일하다. 다만 마지막이 Kube init 아닌 join을 해주어야한다.

성공했다는 문구에서 마지막을 보면 Join 명령어를 준다. 해당 명령어를 이용하면된다.

아래의 명령어는 처음 init 했을 때 성공했다는 문구에 있으니 그걸 복사해서 진행해야만 한다.

kubeadm join 10.0.0.7:6443 --token <###############> \
	--discovery-token-ca-cert-hash sha256:<##################>

만약 분실하였다면 아래의 명령어로 새로 발급받을수 있다.

kubeadm token create --print-join-command