Kubernetes 홈 서버 구축기 - (2)

이상윤·2026년 3월 27일

Kubernetes

목록 보기
2/6

저번 포스팅에서 VM 설치와 세팅, 그리고 Kubernetes 관련 패키지를 설치하였다.
이번 포스팅에서는 노드 설정과 함께 CNI를 설치해보자.

먼저 VM의 IP 포워딩 기능을 켜 줘야한다.
다음 명령어로 리눅스 설정 파일을 추가하자.

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

그러면 이제 마스터 노드가 될 VM을 초기화 해야한다.

sudo kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=<MASTER_IP>

먼저 kubeadm init 명령어는 많은 동작을 하지만, 중요한 몇 가지만 정리하고 넘어가자.
실제 전체 동작은 다음 공식 Document에서 확인할 수 있다.

  1. 사전 점검 및 환경 준비
    실제 설치에 들어가기 전, 시스템이 쿠버네티스를 실행할 수 있는 상태인지 확인하고 보안 통신을 위한 기반을 만든다. 여기엔 VM의 스펙 체크(CPU 2 core 이상, 메모리 2GB이상, 포트 점유 여부 등), 인증서 생성 등이 포함된다.

  2. 핵심 컴포넌트 구동
    쿠버네티스의 핵심 서비스들을 정적 포드 형태로 실행하기 위한 YAML파일을 /etc/kubernetes/manifests에 작성하며, 여기는 kube-apiserver, kube-controller-manager, kube-scheduler, etcd 등이 있다.
    이 경로에 파일이 생성되면, 해당 노드의 kubelet이 이를 감지하고 containerd를 통해 컨테이너로 실행시킨다.

  3. 노드 설정 및 토큰 발행
    현재 노드에 마스터임을 알리는 라벨과 Taint를 설정하여, 일반 사용자 포드가 마스터 노드에 배치되지 않도록 격리한다. 또한, 다른 워커 노드들이 클러스터에 join할 때 신원을 증명하기 위한 보안 토큰을 생성한다.

  4. 필수 애드온 설치
    클러스터 운영에 필요한 기본 서비스를 배포하며, 이는 CoreDNS와 kube-proxy 등이 있지만 필자는 CNI로 eBPF를 사용하는 cilium을 설치할 것이므로 생략한다. 이 이유는 밑에 따로 정리하겠다.

이제 init 명령어의 옵션으로 설정한 명령어들을 알아보자.

  1. --pod-network-cidr=10.244.0.0/16
    클러스터 내부에서 Pod들이 서로 통신하기 위해 가상의 IP 주소 대역을 미리 예약한다.

  2. --apiserver-advertise-address
    다른 노드들이 접속할 마스터 노드의 대표 IP 주소를 명시한다.

명령어를 실행하면 다음과 같이 초기화가 잘 실행된 것을 확인할 수 있다.

이 밑에는 join 명령어와 토큰값이 적혀 있을텐데, 이는 Worker Node에서 사용할 예정이다.
나와있는대로 3줄의 명령어를 입력하면 kubectl 명령어를 사용할 수 있다!

이젠 CNI를 설치해야 한다. 필자의 경우는 Cilium을 설치하지만, kube-proxy를 사용해도 되고, Cilico를 사용해도 되고, 다른걸 사용해도 된다.

cilium install --version 1.19.2 \
  --set kubeProxyReplacement=true \
  --set k8sServiceHost=<MASTER-IP> \
  --set k8sServicePort=6443 \
  --set operator.replicas=1

옵션은 굳이 설명 안해도 읽어보면 쉽게 알 수 있기에 넘어가겠다.

그럼 이제 cilium을 설치 했으니 kube-proxy를 제거한다. kube-proxy의 역할을 cilium이 할 수 있고, cilium이 서비스가 커진 상황에서도 효과적으로 동작하기 때문이다.
이는 kube-proxy가 IPtables를 사용하여 네트워크 트래픽을 제어하기 때문인데, IPtables는 기본적으로 선형 검색을 사용해 패킷이 들어오면 등록되어 있는 Rule을 전부 대조하여 패킷을 보낸다. 또한, Rule 업데이트 시에도 증분 업데이트가 불가능하기 때문에 Lock을 걸고 전체 Rule 리스트를 메모리로 가져와서 수정 후 커널에 덮어씌워야 하기 때문이다. 이러한 방식은 서비스 규모가 커질수록 서버에 부하가 커진다.
사실 학습용이라 크게 영향을 미치지는 않는다.

kubectl delete ds kube-proxy -n kube-system
kubectl delete cm kube-proxy -n kube-system

참고로 ds는 demonset, cm은 configmap을 의미한다.

이제 Worker VM으로 들어가서 아까 init 시에 나왔던 join 명령어를 입력해주면.. 다음과 같이 성공 문구가 뜬다! Warning은 kupe-proxy가 없어서 그런거니 넘어가자. 의도된 사항이다.

그리고 Master로 가서 kubectl get nodes를 입력하면 다음과 같이 노드가 정상적으로 표기되는 것을 볼 수 있다.

이제 다음 포스팅에서는 프로젝트 세팅을 하거나, 대충 설명하고 넘어갔던 네트워크 지식을 다룰 예정이다.

0개의 댓글