홈서버 4대로 쿠버네티스(Kubernetes, K8s) 구축하기

2025. 12. 1. 15:38·Infra/DevOps

마참내!!!!

길고 길었다이!!!

11월 중간에 급한 일도 있었고 조금 밀리고 실패도 많이 하다가 정말 긴 시간 끝에 완성했다!

홈서버 4대로 쿠버네티스 구축하기! 바로 가보자

 

ps. [25.12.02] 쿠버네티스 에러 포스팅을 정리하면서 필수인데 누락됐던 내용을 초반 부분에 추가했다


1. 사전 정리할 내용

- 아래는 이 포스팅에서 미리 알아야 이해하기 쉬운 내용들을 간단히 정리해뒀다


1) 노드는 서버를 의미한다

- 메인 노드 = 컨트롤 타워인 메인 서버

- 서브 노드 = worker에 해당하는 연결된 서브 서버

- 서버 구성은 분산 구조 구축했을 때의 기존의 홈서버 4대 그대로 사용했다

https://ratatou2.tistory.com/286

 

서버 부하 테스트 해보기 (feat. K6 스트레스 테스트 & 분산 구조 튜닝)

자 일해라 토끼같은 서버들아지난 분산 포스팅에 이어 오늘은 부하 테스트를 진행해볼 예정이다https://ratatou2.tistory.com/285 홈서버 4대로 분산 시스템 구축 해보기 (feat. 생각보다 겁나 쉬움!)분산

ratatou2.tistory.com


2) 쿠버네티스 쓰니까 Docker가 안됩니다

- 정상입니다!

- 이유를 한줄요약하면, 쿱네에서 컨테이너를 공식적으로 다루는 것은 'containerd'이기 때문이다

- containerd는 도커 내부의 컨테이너를 실행하는 엔진이다

- 즉, 쿠버네티스는 컨테이너를 도커가 아닌 '도커 알맹이'로 관리하는 것!!

- 쿠버네티스를 설치하면서 containerd가 기본 런타임이 되어버린 것이니 Docker가 안되는 것은 당연하다


2. 필수 사전 작업

- 미리 작업해야하는게 있다! 빼먹지 말자

- 참고로 아래 내용들은 모든 노드에서 진행하면 된다!


1) 모든 노드의 시간 동기화(NTP)

- 쿠버네티스는 토큰 검증, 인증서 만료, kubelet 통신 등 시간이 다르면 안되는게 많아서 미리 통일 시켜줘야한다

- 물론 우분투에도 기본적으로 systemd-timesyncd라는게 있긴 하다

- 다만, chrony가 훨씬 안정적인 NTP 동기화 제공해서 이것을 썼다

sudo apt install -y chrony
sudo timedatectl set-timezone Asia/Seoul
sudo systemctl enable --now chrony
chronyc sources

2) Swap 비활성화

- 이건 말 그대로 메모리 스왑에 관련된 옵션이다

- 메모리 스왑은 메모리가 부족하거나 메모리 확보가 필요할 때 발생한다

- 쿱네는 모든 리소스를 자기가 관리하는데, OS가 알아서 메모리 스왑을 하면? 메모리가 더 있는 줄 알게된다

- 당연히 램보단 성능 떨어지는 저장소를 램처럼 쓰니까 전체적인 성능 저하가 있을 수 있으므로 비활!

sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab

3) 방화벽/필수 포트 개방

- 내가 띄운 앱서버, 쿱네 등등 필요한 포트가 있는데 닫혀있으면 에러 잘 뱉는다

- 근데 이건 각자 개발 환경마다 달라서 미리 어디를 열어두세요는 좀 어렵다

- 그래도 추천 드리면 6443(내가 띄운 앱서버 여기로 잡힘), 2379(etcd), 4789, 8285 정도?

- 내부통신을 열어둬야 노드간 양방향 통신이 가능하니까 통신관련 포트는 열어두자 (control 서버 & worker 서버)

sudo ufw allow 10250/tcp   # Kubelet API
sudo ufw allow 30000:32767/tcp  # NodePort Service 범위
sudo ufw allow 4789/udp    # Flannel VXLAN
sudo ufw allow 8285/udp    # Flannel host-gw (선택)

- 아래 표는 구성 요소에 따른 포트 번호를 정리해둔 표니까 참고하시길

구성요소 포트번호 프로토콜 방향 설명
kube-apiserver 6443 TCP Inbound 클러스터 API 요청
etcd server 2379–2380 TCP Inbound etcd 데이터 저장
kube-scheduler 10251 TCP Local 스케줄러
kube-controller-manager 10252 TCP Local 컨트롤러
kubelet 10250 TCP Control → Node Pod 관리
NodePort Services 30000–32767 TCP 외부 → Node 외부 서비스
Flannel VXLAN 4789 UDP Node ↔ Node Pod 네트워크
Flannel host-gw 8285 UDP Node ↔ Node 대체 네트워크 모드

4) 브릿지 네트워크 커널 설정 (br_netfilter + sysctl)

- 쿠버네티스 CNI 사용 시 커널에서 브릿지 트래픽이 iptables를 거쳐야 한다

- 즉 iptables에 미리 세팅을 안해두면 트래픽이 차단될 수 있음

sudo modprobe br_netfilter
sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system

5) containerd 기본 설정 생성

- 나는 Ubuntu + kubeadm 환경이었다

- 이 환경에서는 containerd를 설치하면 default config가 없음

- 그래서 아래 명령어로 미리 default 만들어둬야 함

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

- 그리고 파일 편집하기

sudo vim /etc/containerd/config.toml

- 아래 내용 true로 바꿔주기

- kubelet과 containerd가 같은 방식(systemd)로 자원 관리하도록 맞춰주는 과정이다

# Before
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  # SystemdCgroup = false

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

- containerd 재시작

sudo systemctl restart containerd
sudo systemctl restart kubelet

3. 쿠버네티스 설치하기


1) 새로운 키 & 리포 추가

- 여기까지는 메인, 서브 노드 모두에서 실행해야한다 

- 쿠버네티스가 설치가 되어있어야 연결할 수 있기 때문이다

sudo apt update
sudo apt install -y curl apt-transport-https ca-certificates 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

2) 라우팅 기능 켜기

- 쿠버네티스도 결국 서버간의 '통신'이 필요하기 때문에 라우팅 기능을 켜둬야했었다

- 이 명령어는 모든 노드(서버)에서 실행한다

sudo sysctl -w net.ipv4.ip_forward=1

3) 실행

- 이거는 메인 노드에서만 실행하면 된다

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

4) 쿱네에 root 권한 주기

mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

5) 네트워크 플러그인 설치하기

- 그러고나면 네트워크 플러그인 설치하면 됐음

- 이건 메인 노드에서만 실행하면 된다

- 나머지 서브 노드엔 메인 노드가 알아서 세팅해준다

- 가장 편하고 많이 쓴다는 flannel 썼다

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

6) 서브 노드 연결하기

- 여기까지 진행하면 아래처럼 코드가 뜬다 이것들을 서브 노드에 붙여넣어 sudo 붙여 실행하면 된다

- 메인의 쿠버네티스에 연결하는 과정으로 이것이 마무리되면 정말로 worker 노드가 된다

# 예시
sudo kubeadm join 192.168.0.201:6443 --token ign2mp.k3afmzdtrtjwvs3e \
        --discovery-token-ca-cert-hash sha256:804369d46362266526d6d328d4f35ce843bd4369353b0d5a860229f8eff4f12b

- 실행하면 아래처럼 좔좔좔 뜬다

- 연결이 잘 됐는지는 아래 명령어로 메인 노드에서 확인하면 된다

kubectl get nodes

- 연결이 잘 됐다면 아래처럼 뜬다

NAME           STATUS   ROLES           AGE   VERSION
macmini-main   Ready    control-plane   5m    v1.31.0
n100-node      Ready    <none>          2m    v1.31.0
lg-node        Ready    <none>          2m    v1.31.0
samsung-node   Ready    <none>          2m    v1.31.0

- 특히 메인 노드는 아래처럼 control-plane이라고 뜨는 것을 볼 수 있음

NotReady 뜨면 문제가 있다는 것이다..


4. 쿠버네티스 초기화(리셋)하기

- 엄청 꼬였을 때, 뭐가 잘 안될 땐 역시 삭제하고 하나씩 다시하는게 나았다

- 이건 그냥 메인, 서브 노드 모두에 해주면 된다


1) 전부 리셋(삭제) 하기

sudo kubeadm reset -f

2) 잔여 파일 삭제

sudo systemctl stop kubelet
sudo systemctl stop containerd
sudo rm -rf /etc/cni/net.d
sudo rm -rf /etc/kubernetes
sudo rm -rf /var/lib/cni
sudo rm -rf /var/lib/kubelet
sudo rm -rf /var/lib/etcd
sudo rm -rf ~/.kube
sudo systemctl restart containerd

5. 테스트 앱 빌드하기

- 앞서 미리 말했듯이 쿠버네티스는 컨테이너를 containered로 관리한다

- 즉, 도커를 쓰지 못하니 빌드를 할 때도 다른 방법이 필요하다는 것이다

- 아무튼 쿠버네티스 환경에서 앱 빌드할 땐 nerdctl이란 도커 호환툴을 써야한다

https://github.com/containerd/nerdctl

 

GitHub - containerd/nerdctl: contaiNERD CTL - Docker-compatible CLI for containerd, with support for Compose, Rootless, eStargz,

contaiNERD CTL - Docker-compatible CLI for containerd, with support for Compose, Rootless, eStargz, OCIcrypt, IPFS, ... - containerd/nerdctl

github.com


1) nerdctl, git에서 다운 받기

- 아직 리눅스에서 배포하지 않아서 git에서 다운받아 써야했다

# (1) 최신 릴리스 버전 확인 및 다운로드
VERSION=$(curl -s https://api.github.com/repos/containerd/nerdctl/releases/latest | grep tag_name | cut -d '"' -f 4)
wget https://github.com/containerd/nerdctl/releases/download/${VERSION}/nerdctl-${VERSION#v}-linux-amd64.tar.gz

# (2) 압축 해제 및 설치
sudo tar -C /usr/local/bin -xzf nerdctl-${VERSION#v}-linux-amd64.tar.gz

# (3) 설치 확인
nerdctl --version

2) buildctl 설치

- nerdctl 설치하면 끝인줄 알았는데 하나 더 필요하다고 해서 진행함

# (1) 최신 BuildKit 다운로드 (v 포함)
VERSION=$(curl -s https://api.github.com/repos/moby/buildkit/releases/latest | grep tag_name | cut -d '"' -f 4)
wget https://github.com/moby/buildkit/releases/download/${VERSION}/buildkit-${VERSION}.linux-amd64.tar.gz

# (2) 압축 해제 후 설치
sudo tar -C /usr/local -xzf buildkit-${VERSION}.linux-amd64.tar.gz

# (3) 로그 디렉토리 권한 확인 및 생성
sudo mkdir -p /var/log
sudo touch /var/log/buildkitd.log
sudo chmod 666 /var/log/buildkitd.log

# (4) 백그라운드 실행 (이제 권한 문제 없음)
sudo nohup /usr/local/bin/buildkitd >> /var/log/buildkitd.log 2>&1 &

# (5) 설치 확인
ps aux | grep buildkitd

3) 앱 파일 빌드하기

- 앱 파일들이 있는 곳에 가서 아래 명령어로 빌드하면 된다

sudo nerdctl build -t myapp:latest .

- 그러고나면 이미지 리스트에서 확인할 수 있다

nerdctl images

- 재밌는게 일반 빌드와 달리 nerdctl로 빌드하면 디렉토리에 빌드 파일로 남지 않는다

- 바로 컨테이너 이미지에 자동으로 올라가는데 Docker나 nerdctl은 일반 빌드가 아닌 '컨테이너 빌드' 시스템이라서 그렇다고 한다


6. 앱 빌드 배포하기

- 보통 배포 전에 이미지 빌드한 것을 레지스트리 등록한다

- 메인에 등록해두면 서브에서 땡겨 쓸 수 있는 편리한 구조


1) 로컬 레지스트리에 앱 이미지 업로드하기

sudo nerdctl run -d -p 5001:5000 --restart=always --name registry registry:2
sudo nerdctl tag myapp:latest localhost:5001/myapp:latest
sudo nerdctl push localhost:5001/myapp:latest

- 그러고나면 뭔가 잔뜩 업로드하고 푸시하고 그런다

- 이제 각 서브 노드에서 배포하면 된다


2) 서브 노드에 배포하기

- 메인 노드에서 .yaml 파일이 하나 필요하다

- 아까 배포한 'myapp'이란 서비스를 어떻게 띄울 것인지에 대한 주문서(order) 같은 것이다

- 파일부터 생성

sudo vim myapp-deployment.yaml

- 파일 내용 기입

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: localhost:5001/myapp:latest
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 5000
  type: NodePort

- 위에 보면 replicas라는 옵션이 있는데 이게 pod를 몇개까지 띄울 것인지에 대한 명시다

- 아래 명령어를 통해 각 노드에 App 서버 pod를 띄울 수 있다

kubectl apply -f myapp-deployment.yaml

- 띄우고 나면 아래 명령어를 통해 띄워져 있는 pod들을 확인할 수 있음

kubectl get pods -A -o wide

replicas를 200까지 설정한 모습


번외

- 정말 많은 실패와 에러가 있었다..

- 그것들을 전부 여기에 적기엔 너무 많아서 따로 빼서 포스팅할 예정

- 튜닝 과정 및 테스트도 따로 포스팅할 것이다!

 

반응형

'Infra > DevOps' 카테고리의 다른 글

쿠버네티스(Kubernetes, K8s) 실험과 배운 것들에 대한 회고록  (0) 2025.12.06
쿠버네티스(Kubernetes, K8s) 구축 과정에 마주한 에러들  (0) 2025.12.03
Prometheus, Out of Bound 해결방법 (feat. 서버 시간 통일 & TSDB 초기화)  (0) 2025.11.28
Fail2Ban, 다시 iptables-nft 체제로 전환하기 (feat. 최최최종ver)  (0) 2025.11.24
Fail2Ban, nftables 체제로 완전 전환하기 (feat. 눈물겨운 이유와 Ubuntu 22.04)  (0) 2025.11.15
'Infra/DevOps' 카테고리의 다른 글
  • 쿠버네티스(Kubernetes, K8s) 실험과 배운 것들에 대한 회고록
  • 쿠버네티스(Kubernetes, K8s) 구축 과정에 마주한 에러들
  • Prometheus, Out of Bound 해결방법 (feat. 서버 시간 통일 & TSDB 초기화)
  • Fail2Ban, 다시 iptables-nft 체제로 전환하기 (feat. 최최최종ver)
Ratatou2
Ratatou2
온갖 정보들을 기록해두는 메모보드 블로그
  • Ratatou2
    nak-z
    · Ratatou2 ·
  • 전체
    오늘
    어제
  • 공지사항

    • 블로그 이전 진행 중 (24.11.25 ~)
    • 분류 전체보기 (303) N
      • OS (89) N
        • Linux (39)
        • Window (24)
        • Mac (21) N
        • Android (5)
      • Infra (83) N
        • DevOps (38) N
        • Docker (14)
        • Jenkins (9)
        • n8n (13)
        • Nextcloud (8)
        • Rasberry Pi (1)
      • Dev (17)
        • JAVA (7)
        • Python (1)
        • DB (3)
        • Vue (2)
        • AI (4)
        • Git (0)
      • Tools (10)
      • Study (69)
        • Algorithm (66)
        • CS (3)
      • Game (10)
        • Project Zomboid (9)
        • Don't Starve Together (1)
      • etc (24)
        • Temp (0)
      • 개발 외 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Ratatou2
홈서버 4대로 쿠버네티스(Kubernetes, K8s) 구축하기
상단으로

티스토리툴바