-
kubeadm을 통한 kubernetes(1.27) EC2에 설치하기Computer Science/k8s 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/
1. ec2 사양 정하기
시작하기 전에를 보면 알 수 있듯이 2GB 이상의 램, 2코어 이상의 CPU가 필요하다고 나와있다.
이를 충족하는 가장 저렴한 ec2는 t3.small 이기에 해당 인스턴스로 진행하였다.
또한 특정 포트들의 개방, 스왑 메모리의 비활성화를 요구하는데 기본적으로 t3.small ec2는 스왑 메모리가 활성화 되어있지 않았다.
혹시 모르니 아래의 명령어로 확인해보자.
free -h
사용 하는 특정 포트들에 대한 정보는 여기에 있다.
https://kubernetes.io/ko/docs/reference/networking/ports-and-protocols/
컨트롤 플레인 노드의 포트
프로토콜 방향 포트 범위 용도 사용 주체 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/
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
자신의 아키텍처 맞는 파일을 다운해주자.
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
똑같이 내 OS와 아키텍처를 확인해서 다운로드를 해준다.
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/
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/
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/
링크를 들어가보면 Addons의 종류가 여러가지가 있는데 이를 비교한 사이트가 있다.
위에서 확인했듯이 현재로서는 Calico가 범용적으로 좋은 성능을 보여준다. 하여 Calico로 설치하도록 하겠다.
Caclico 설치의 요구사항이 있는지 우선 확인을 해보았더니 현재로서는 추가 Port를 열어주어야 하는 것 이외에는 없다.
https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements
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
이곳에서 확인 할 수 있듯이 현재로서는 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
'Computer Science > k8s' 카테고리의 다른 글
EFS를 pv, pvc로 k8s 환경에서 사용하기 ( NFS ) (0) 2023.08.15 GitHub Action, ECR 과 ArgoCD를 이용하여 CI/CD 구축하기 ( k8s ) (0) 2023.08.15 k8s 설치 방식 종류 (0) 2023.07.28 k8s Secret 적용 및 Containers 에서 사용하기 (0) 2023.06.30 Pod - readiness, liveness, startup probe (0) 2023.03.26