[홈랩 구축기] 4️⃣ - Kubernetes 설치 및 구축

developowl·2026년 2월 6일
post-thumbnail

[홈랩 구축기] 3️⃣ - Network편(간단) 를 마지막으로 라즈베리파이 홈랩의 기초적인 모든 작업을 완료했습니다. 홈랩(현질)의 시작이었던 쿠버네티스 실습 환경을 위해 이번에는 쿠버네티스 설치 및 구축을 해보았습니다.


1. OS 환경 최적화

1-1. Swap Off (스왑 비활성화)

📌 예측 불가능한 성능 저하 요소를 제거하여 안정성을 확보

  • K8s는 노드의 자원이 얼마나 남았는지 1KB 단위로 정확히 계산해서 Pod를 배치한다. 하지만 램이 부족할 때 디스크를 빌려 쓰는 ‘스왑’ 이 켜져 있으면 자원 계산이 꼬이고 성능이 급격히 떨어진다.
# 즉시 비활성화
sudo swapoff -a

# 재부팅 시에도 비활성화 (fstab에서 swap 라인 주석 처리)
sudo vi /etc/fstab
	# 없는 경우도 있음

# (라즈베리파이만 해당) 스왑 관리 서비스 제거
sudo apt-get remove --purge dphys-swapfile zraㅡ-config -y
  • 확인 (Swap 행의 Total이 0B 이어야 함)

1-2. Cgroup Memory 활성화 (cmdline.txt)

📌 컨테이너별 자원 제한(Limit) 기능을 커널 레벨에서 활성화

  • 컨테이너는 ‘격리된 프로세스’이다. 리눅스 커널의 Cgroup(Control Groups) 기능이 이 컨테이너가 메모리를 얼마나 쓸지 제한한다. 라즈베리파이는 기본적으로 이 기능이 꺼져 있으므로 수동으로 켜준 것.
sudo vi /boot/firmware/cmdline.txt

# 파일 끝에 아래 내용 추가 (중요: 한 줄로 작성!!)
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

2. 네트워크 통로 개척 (Kernel Networking)

📌 노드 간, 그리고 컨테이너 간의 복잡한 통신을 리눅스 커널이 처리할 수 있도록 설정을 변경하는 과정

2-1. 노드 간 이름 해석 설정

  • IP 대신 node01 같은 호스트네임으로 상호 통신하기 위함
sudo vi /etc/hosts

[IP address] [hostname]
[IP address] [hostname]
[IP address] [hostname]
# (Example) 192.1.1.1 node01

2-2. 커널 모듈 로드 및 IP Forwarding

  • 가상 브릿지 네트워크에서도 방화벽 규칙을 적용하고, 패킷을 다른 곳으로 전달(Routing) 하기 위함
  • → L2(Data Link Layer) 트래픽을 L3(Network Layer)의 방화벽 규칙으로 제어하기 위함
# 커널 모듈 설정
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 네트워크 파라미터 설정
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

# 설정 적용
sudo sysctl --system
  • 확인 (성공 기준: 두 값 모두 =1 로 나와야 함)
sysctl net.bridge.bridge-nf-call-iptables net.ipv4.ip_forward

3. 컨테이너 런타임(Conatainerd) 설치

📌 쿠버네티스의 표준 컨테이너 실행 엔진 (CRI) 구축

3-1. 패키지 설치

sudo apt-get update
sudo apt-get install -y containerd

3-2. 기본 설정 생성 및 수정

  • containerd 가 쿠버네티스의 자원 관리 방식(Systemd)과 호환되도록 설정을 변경해야 한다.
# 기본 설정 파일 저장 폴더 생성
sudo mkdir -p /etc/containerd

# 기본 설정값 추출하여 파일 생성
containerd config default | sudo tee /etc/containerd/config.toml

# [중요!!!] SystemdCgroup 설정을 true로 변경
# 쿠버네티스 노드의 안정적인 자원 제한(Cgroup)을 위해 반드시 필요합니다.
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

3-3. 엔진 가동 및 확인

sudo systemctl restart containerd
sudo systemctl enable containerd

# 확인: active (running)이 떠야 함
systemctl is-active containerd

# 확인: 결과가 true여야 함
grep "SystemdCgroup" /etc/containerd/config.toml

4. 쿠버네티스 설치(Kubeadm, Kubelet, Kubectl)

4-1. 공식 Repository 등록

# 필수 도구 설치
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

# 구글 클라우드 GPG 키 다운로드
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 쿠버네티스 저장소 추가
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update

4-2. 패키지 설치 및 버전 고정

  • 시스템 업데이트 시 쿠버네티스 버전이 의도치 않게 올라가 클러스터가 깨지는 것을 방지
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

4-3. ⚠️ 마스터 노드 초기화

⚠️ Control Plane 을 만드는 작업이기에 마스터 노드에만 작업을 해야 합니다.

sudo kubeadm init \
  --pod-network-cidr=[파드 네트워크 대역] \
  --apiserver-advertise-address=[마스터 노드 실제 IP]

sudo kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=192.168.55.21
  • conntrack 미설치 에러 발생

📌 conntrack 란?

  • Connection Tracking
  • conntrack 는 리눅스 커널의 네트워크 서브시스템인 Netfilter 프레임워크 내에서 작동하는 모듈
  • 패킷의 흐름을 추적하여 네트워크 연결의 상태(State)를 관리
    • 수많은 네트워크 패킷 중 이 패킷이 ‘새로운 대화의 시작’인지, 아니면 ‘이미 대화 중인 관계의 일부’인지를 추적하는 역할

(conntrack를 설치하고 다시 진행해보겠습니다.)

# conntrack 설치
sudo apt-get install -y conntrack

# 실패한 초기화 기록 정리
sudo kubeadm reset -f

# 다시 초기화 실행
sudo kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=192.168.55.21
  • 여러 로그와 함께 Your Kubernetes control-plane has initialized successfully! 성공 문구가 나온 것을 보니 Control Plane 이 성공적으로 설치된 것 같습니다.

5. 마스터 노드 관리 설정 및 네트워크(CNI) 배포

  • 지금 상태에서는 kubectl 명령어를 쳐도 권한 에러가 날 수 있음..

📌 CNI(Container Network Interface)란?

  • 컨테이너 간의 네트워킹을 제어하기 위해 쿠버네티스와 같은 컨테이너 오케스트레이터와 네트워크 플러그인(Flannel, Calico 등) 사이의 통신 규약을 정의한 표준 인터페이스(API)
  • 컨테이너의 네트워크 네임스페이스를 생성하고, 가상 인터페이스를 연결하며, IP를 할당하는 일련의 과정을 자동화하는 표준 프로토콜

5-1. kubectl 권한 설정 (⚠️ master에서 실행)

  • 일반 사용자(admin) 계정에서 쿠버네티스를 조작할 수 있도록 설정 파일(kubeconfig)을 복사하기
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

5-2. Pod 네트워크(Flannel) 설치 (⚠️ master에서 실행)

  • 쿠버네티스 노드와 Pod 들이 서로 통신할 수 있게 해주는 CNI 를 설치해야함.
  • 앞서 4-3 마스터 노드 초기화 단계에서 설정한 10.244.0.0/16 대역과 가장 잘 맞는 Flannel 을 설치
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

6. 워커 노드 합류 (node01, node02에서 실행)

  • 이제 워커 노드(제 기준 node01, 02 입니다) 터미널로 이동해서, 아까 kubeadm init 결과물로 나왔던 join 명령어를 입력하는 단계
# 워커 노드에서 실행!!
sudo kubeadm join [마스터_노드_IP]:6443 \
  --token [임시_비밀번호] \
  --discovery-token-ca-cert-hash sha256:[서버_인증_해시값]

# 토큰값
sudo kubeadm join 192.168.55.21:6443 \
	--token mkxxx.xxxxxxxxxx \
	--discovery-token-ca-cert-hash sha256:99090xxxxxxxxxxxxxxxxxxxxxxxxxx

7. 클러스터 상태 최종 확인 (master에서 실행)

  • 워커 노드에서 join 이 완료되었다면, 다시 master 노드로 돌아와서 노드들이 잘 연결되었는지 확인
kubectl get nodes


잠깐!

🤔 “무아지경으로 쿠버네티스 설치와 연결을 했는데, 언제 연결이 되었으며 마스터 노드에 연결되기 전의 워커 노드를 가로챌 수 없을까?”

→ 마스터와 워커는 kudeadm join 명령어를 실행하는 순간 TLS Bootstrapping 이라는 과정을 통해 서로를 인식하고 비밀 통로를 만든다.

1. 언제 서로를 인식하나요? (연결 타이밍)

node02 에서 join 명령어를 입력했을 때, 내부에서는 다음과 같은 일이 일어난다.

  • Discovery : 워커 노드가 --token 을 들고 마스터 노드의 IP로 찾아감. 이때 마스터 노드는 토큰을 확인하며 워커 노드를 일단 신뢰한다.

  • Handshake : 마스터 노드는 워커 노드에게 해당 워커만 사용할 수 있는 Certificate 를 제안하고, 워커 노드는 자신의 정보를 담은 인증 요청서(CSR) 를 마스터 노드에게 보낸다.

  • 비밀 통로 개설 : 마스터 노드의 api-server 가 이 요청을 승인하면, 워커 노드에 고유한 인증서가 발급됨. 이때부터 두 노드는 gRPC 기반의 암호화된 통신을 시작하며 서로를 클러스터의 일원으로 정식 인식한다.

2. 중간에 가로챌 수 있나요? (제가 한다는건 아니고) - MITM 공격 가능성

  • MITM(Man-In-The-Middle) 중간 가로채기를 방지하기 위해 쿠버네티스는 두 가지 방어를 한다.
  1. CA 해시값 (--discovery-token-ca-cert-hash)
    • join 뒤에 붙였던 아주 긴 sha256:… 해시값은 마스터 노드의 신분이 진짜인지 확인하는 값
    • 해시값이 일치하지 않으면 연결이 바로 차단됨
  2. 단기 토큰 (--token)
    • 이 토큰은 기본적으로 24시간만 유효하다.
    • 한 번 노드 합류에 사용되고 나면, 나중에 해커가 이 토큰을 알아내더라도 이미 시간이 지났거나 인증서 체계가 잡힌 뒤라 침투하기 어렵다.
  3. 현업에서는 Private Network, Firewall 설정, 인증서 자동 갱신 등의 방법으로 보안을 강화한다고 합니다.
profile
Don’t get mad at the computer.

0개의 댓글