본문 바로가기
사이드 프로젝트

[CI/CD 프로젝트] K8S - kubeadm으로 Kubernetes Cluster 구축하기

by 간장공장공차장 2024. 11. 19.
반응형

쿠버네티스란?

쿠버네티스는 Container Orchestration 개념으로, 많은 컨테이너를 쉽게 관리할 수 있도록 도와주는 도구이다.

쿠버네티스의 동작 원리는, kubectl 을 통해 control plane에 있는 etcd에 desired state를 입력하고, 다양한 컴포넌트를 통해 container를 배포한다. 이런 동작 원리로, self healing과 같은 특징이 생기게 된다.

이 외에도,

  • Service에 대한 load balancing : 원래는 우리는 서비스를 호출하기 위해 사용하고 있는 ip와 포트를 알아야한다. 쿠버네티스는 서비스들을 label로 관리하여 서비스를 호출 하였을 때 해당 label이 붙어있는 pod로 트래픽을 분산해준다.
  • Storage 관리 : K8S는 스토리지를 명시하여 자동으로 mount될 수 있도록 할 수 있도록 한다.
  • Update 지원 : K8S 의 Deployment 오브젝트는 RollingUpdate와 Recreate를 지원한다.
  • Secret, Config 관리 : Secret 과 ConfigMap 을 통해 민감한 정보 및 환경 변수를 선언적으로 관리할 수 있다.
  • 확장 : K8S는 HPA, KEDA와 같은 오브젝트를 통해 특정 조건에서 수평적인 확장을 지원한다.

클러스터 아키텍처

출처) http://kubernetes.io/

각 Cluster 의 컴포넌트의 역할은 아래와 같다.

Control Plane

주로 Kubernetes 시스템과 관련된 컨테이너가 올라온다. 관리를 위해 taint가 설정되어, 일반 pod는 할당되지 않는다.

  • kube-apiserver : kubectl을 통해서 kubernetesAPI를 호출 받는다.
kubectl run nginx --image=nginx:latest ## kube-apiserver를 통해서 API 호출
  • etcd : kube-apiserver에서, client에 전달받은 desired state를 입력받는다. key-value형식의 저장소이다. 모든 상태가 저장되기 때문에 etcd를 통해 백업을 진행한다.
  • kube-scheduler : pod를 배포할 때 어떤 노드에 배정할지 스케줄링 결정을 위해 리소스 요구 사항, 제약 조건, 선호도 등을 고려한다.
  • kube-controller-manager : 컨트롤러는 특정 리소스(예: Pods, Nodes, Services 등)에 대한 상태를 모니터링하고, 필요한 경우 변경 작업을 수행하여 원하는 상태를 유지합니다.

Worker Node

  • kubelet : 각 노드에서 실행되는 컨테이너를 확인한다.
  • kube-proxy : node의 pod간 네트워크를 담당한다.

실습

(Control Plane, Worker Node 모두) 이전 실습 상태

2024.11.19 - [사이드 프로젝트] - K8S - Containerd 내부 구조 이해

(Control Plane, Worker Node 모두) kubeadm, kubelet, kubectl 설치

  • SELinux 비활성화
    컨테이너가 호스트 파일 시스템에 액세스할 수 있도록 SELinux를 비활성화한다.
sudo setenforce 0
  • Kubernetes repository 추가

기존 document에 있는 google 패키지 저장소는 만료되었으므로, 아래의 저장소로 다운 받으면 된다.
참고 : https://v1-28.docs.kubernetes.io/docs/tasks/administer-cluster/kubeadm/change-package-repository/

기존 docs 에 나와있는 리포지토리로 다운 받게 되면 아래와 같은 404에러를 보게된다.

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
  • kubelet, kubeadm, kubectl 설치

이때 버전이 일치 하지 않을 경우 문제가 발생할 수 있기 때문에 확인을 진행한다. ( 자동으로 맞춰주지 않음)

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
kubeadm version
kubectl version --client
kubelet --version

아래와 같이 모두 v1.27 로 버전이 설치된 것을 볼 수 있다.

(Control Plane만)Control Plane 설정

  • init 설정 값
    • cgroup설정 : cgroup은 cgroupfs와 systemd 두 가지가 있다. systemd가 이미 init system일 경우 cgroupfs를 사용하게 되면 불안정도가 높아지므로, systemd가 init system일 경우 아래와 같이 cgroupDriver를 명시한다.
    • Calico와 K8S의 네트워크 대역을 일치 시키기 위해 podSubnet을 VPC 대역과 일치시킨다.
    • containerRuntime을 containerd로 명시하여 초기화한다.
# kubeadm-config.yaml

apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
---
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.27.16
networking:
  podSubnet: "192.168.0.0/16"  # calico 기본 대역
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd

sudo kubeadm init --config kubeadm-config.yaml
## 향후 모든 버전에서 systemd 로 설정

정상적으로 init이 되면, 아래와 같이 성공적으로 설치가 되었음을 알 수 있다.

일반 user에서 사용을 위한 설정과, cluster를 위한 join 명령어가 안내된다. 이 join 명령어를 클립보드에 복사해 두는 것을 추천한다.

  • kubeadm은 Network Interface의 default gateway의 usable IP를 찾는다.
ip route show # Look for a line starting with "default via"
  • kubectl 이 현재 유저에서 수행될 수 있도록 설정
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

수행하지 않고, 바로 사용 할 시 root 유저라도 사용이 불가능하다.

  • Calico 설치 : 다음 문서를 통해서 설치 후 이후 절차를 진행한다.

(Worker Node만) Cluster binding

설치 완료되었을 때 안내되었던 명령어를 붙여넣으면 된다. 추가로, cri를 명시해서 초기화시켜주는 옵션을 추가하였다.

kubeadm join <master-node-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash> --cri-socket=/var/run/containerd/containerd.sock

정상적으로 설치가 완료되었다.

control node에서 정상적으로 바인딩 된 모습을 볼 수 있다.

kubectl get nodes

  • Node에 대한 cgroup 설정하기 (건너뛰기)
kubectl edit cm kubelet-config -n kube-system

cgroupDriver: systemd

Node 에서 변경하기
kubectl drain <node-name> --ignore-daemonsets

systemctl stop kubelet
systemctl stop containerd

# /var/lib/kubelet/config.yaml
cgroupDriver: systemd

systemctl start containerd
systemctl start kubelet
ㅁkubectl uncordon <node-name>
  • alias 설정
vi ~/.bashrc

alias k='kubectl'
alias kg='kubectl get'
alias kc='kubectl create'
alias kd='kubectl delete'
alias klogs='kubectl logs'

Kubeadm 삭제 후 다시 깔기 위한 명령어

❈ Cluster 설정이 잘못되어 init한 설정을 취소하고, 다시 설치할 때 두 가지 모두 수행되어야 한다.

  1. kubeadm reset
  2. rm $HOME/.kube/config

Troubleshooting

  • Pod에서 인터넷으로 나가지 못하는 문제

  • core-dns 로그 확인

  • ec2-user가 kubernetesAPI 사용할 수 있도록 권한 변경
mkdir .kube
cp ~/.kube/config /home/ec2-user/.kube/config
chown ec2-user:ec2-user /home/ec2-user/.kube/config
  • 일반 사용자로 명령어 수행 확인

참고로, ec2-user에서 alias를 사용하려면 /home/ec2-user/.bashrc 에 다시 추가를 진행한다.

  • 기존 생성하였던 리소스 모두 삭제 후 apply
반응형