본 문서는 Ubuntu 24.04 환경에서 K3S 설치부터 워커 노드 구성, NFS StorageClass, MetalLB 및 Nginx Ingress 설정을 포함한 전체 과정을 다룹니다. 클러스터는 Master 노드 1개, Worker 노드 3개로 구축합니다. K3S는 Rancher Labs에서 개발한 경량 Kubernetes 배포판으로, 단일 바이너리로 배포 가능한 Kubernetes입니다. 기존 Kubernetes보다 메모리와 CPU 사용량이 낮아 리소스가 제한된 환경(예: IoT, 엣지 컴퓨팅, 개발 환경)에서 효율적으로 작동하며, 표준 Kubernetes API를 지원하므로 기존 도구와 호환됩니다. K3S는 개발, 테스트, 그리고 소규모 프로덕션 환경에서 널리 사용되며, 내장된 보안 기능과 쉬운 설치로 운영 환경에서도 채택되고 있습니다.
1. 사전 준비 (모든 노드 공통)
Kubernetes 환경을 위해 스왑(Swap) 메모리를 비활성화합니다.
# swap 비활성화
sudo swapoff -a
# fstab 수정 (재부팅 시에도 유지)
# /etc/fstab 파일 내 /swap.img 행을 주석(#) 처리합니다.
sudo sed -i '/swap/s/^/#/' /etc/fstab
2. K3S 클러스터 설치 및 노드 구성
2.1 Master Node 구성
기본 Ingress인 Traefik을 제외하고 클러스터를 초기화합니다.
# master node 설치
sudo curl -sfL https://get.k3s.io | sh -s - server \
--cluster-init \
--disable=traefik \
--disable=servicelb \
--flannel-backend=vxlan
# master node에서 토큰 조회 (복사하여 워커 노드 조인 시 사용)
sudo cat /var/lib/rancher/k3s/server/node-token
# 예: K10ea6ad1b45...::server:7604d858...
2.2 Worker Node 조인
각 워커 노드(3개)에서 아래 명령어를 실행합니다. (IP와 TOKEN을 환경에 맞게 수정)
sudo curl -sfL https://get.k3s.io | K3S_URL=https://192.168.0.106:6443 \
K3S_TOKEN="<MASTER_NODE_TOKEN>" sh -
2.3 Kubeconfig 및 프로필 설정 (Master)
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER:$USER ~/.kube/config
# 환경 변수 및 자동 완성 적용
echo 'export KUBECONFIG=~/.kube/config' >> ~/.bashrc
source <(kubectl completion bash)
2.4 Master Node 스케줄링 제외
마스터 노드에 일반 워크로드가 배포되지 않도록 설정합니다.
kubectl taint nodes master01 node-role.kubernetes.io/control-plane=:NoSchedule
설정이 완료되었는지 확인합니다:
kubectl describe node master01 | grep Taints
출력 예시:
Taints: node-role.kubernetes.io/control-plane:NoSchedule
2.5 클러스터 상태 확인
Kubeconfig 설정이 완료되면 클러스터 상태를 확인합니다:
# 클러스터 정보 확인
kubectl cluster-info
출력 예시:
Kubernetes control plane is running at https://192.168.0.106:6443
CoreDNS is running at https://192.168.0.106:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://192.168.0.106:6443/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
# 노드 상태 확인 (Master 1개, Worker 3개)
kubectl get nodes
출력 예시:
NAME STATUS ROLES AGE VERSION
master01 Ready control-plane,etcd 44h v1.34.4+k3s1
worker01 Ready 23h v1.34.4+k3s1
worker02 Ready 23h v1.34.4+k3s1
worker03 Ready 22h v1.34.4+k3s1
3. NFS 서버 설치
3.1 NFS 클라이언트 설치 (모든 노드)
sudo apt-get update && sudo apt-get install -y nfs-common
3.2 Helm 리포지토리 추가
NFS 서버 및 프로비저너를 위한 Helm 리포지토리를 추가합니다:
helm repo add nfs-ganesha-server-and-external-provisioner https://kubernetes-sigs.github.io/nfs-ganesha-server-and-external-provisioner/
helm repo update
3.3 NFS 서버 설치
NFS 서버를 Helm을 사용하여 설치합니다 (persistence 비활성화, 기본 StorageClass로 설정하지 않음):
NFS v4 프로토콜 기반으로 storageClass를 클래스를 구성하도록 values.yaml을 작성합니다.
cat > nfs-v4-values.yaml <<'EOF'
# 기존 설정 유지
persistence:
enabled: true
storageClass: local-path
size: 50Gi
storageClass:
name: nfs
defaultClass: true
# NFS v4.1로 변경 (핵심!)
mountOptions:
- nfsvers=4.1
- hard
- timeo=600
- retrans=2
- rsize=1048576
- wsize=1048576
- noatime
- nodiratime
nodeSelector:
node-role.kubernetes.io/control-plane: "true"
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
EOF
Helm Chart로 NFS Server와 StorageClass를 설치합니다.
helm install nfs-server nfs-ganesha-server-and-external-provisioner/nfs-server-provisioner \
--namespace kube-system \
-f nfs-v4-values.yaml
기본 StorageClass를 ’local-path’에서 ’nfs’로 변경합니다:
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
4. MetalLB 설정
Helm을 사용하여 MetalLB를 metallb-system 네임스페이스에 설치하고 IP Pool을 구성합니다.
helm repo add metallb https://metallb.github.io/metallb
helm repo update
helm install metallb metallb/metallb \
--version 0.14.9 \
--namespace metallb-system \
--create-namespace
# MetalLB 리소스 배포
kubectl apply -f - <<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ip-pool
namespace: metallb-system
spec:
addresses:
- 192.168.0.220-192.168.0.230
autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2-network
namespace: metallb-system
spec:
ipAddressPools:
- ip-pool
EOF
5. Nginx Ingress 설정
Helm을 사용하여 Nginx Ingress를 설치합니다.
rm -rf kustomize/base/helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm pull ingress-nginx/ingress-nginx \
--version 4.14.1 \
--untar \
--destination kustomize/base/helm
# Nginx Ingress 설치
helm install ingress-nginx ingress-nginx/ingress-nginx \
--version 4.14.1 \
--namespace ingress-nginx \
--create-namespace \
--values nginx-values.yaml
values.yaml 파일을 다음과 같이 구성합니다:
cat > nginx-values.yaml <<EOF
fullnameOverride: ingress-nginx
controller:
replicaCount: 1
progressDeadlineSeconds: 600
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-target-type: ip
resources:
requests:
cpu: 100m
memory: 90Mi
admissionWebhooks:
enabled: true
certManager:
enabled: false
clusterIssuer: "selfsigned-issuer"
config:
allow-snippet-annotations: "true"
annotations-risk-level: "Critical"
ingressClass: nginx
ingressClassResource:
name: nginx
enabled: true
default: true # default
extraArgs:
watch-ingress-without-class: "true"
EOF
6. Ingress 리소스 배포 예제
Nginx Ingress가 설치된 후, Ingress 리소스를 만들어 서비스를 외부에 노출합니다.
6.1 테스트 애플리케이션 배포
먼저, 테스트할 애플리케이션을 배포합니다.
# Nginx 애플리케이션 배포
kubectl create deployment nginx-test --image=nginx
kubectl expose deployment nginx-test --port=80 --type=LoadBalancer
# 배포 확인
kubectl get pods
kubectl get svc
6.2 Ingress 리소스 생성 및 배포
Ingress 리소스를 생성하여 외부에서 서비스에 접근할 수 있도록 합니다.
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: test.cnapcloud.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-test
port:
number: 80
EOF
Ingress가 정상적으로 생성되었는지 확인합니다:
kubectl get ingress
6.3 Nginx Ingress LoadBalancer IP 확인 및 호스트 등록
Nginx Ingress의 LoadBalancer IP를 확인하고, 로컬 호스트 파일에 등록하여 접속합니다.
# Nginx Ingress 서비스의 EXTERNAL-IP 확인
kubectl get svc -n ingress-nginx
# 예: EXTERNAL-IP가 192.168.0.221이라고 가정
# 로컬 호스트 파일에 등록 (관리자 권한 필요)
echo "192.168.0.221 test.example.com" | sudo tee -a /etc/hosts
6.4 접속 테스트
웹 브라우저나 curl을 사용하여 Ingress를 통해 서비스에 접속합니다.
# curl로 테스트
curl http://test.example.com
# 또는 웹 브라우저에서 http://test.example.com 접속
7. 최종 상태 확인
# 노드 상태 확인 (Master 1개, Worker 3개)
kubectl get nodes
# 모든 파드 상태 확인
kubectl get pods -A
# StorageClass 확인
kubectl get sc
# Ingress 확인
kubectl get ingress
8. 결론
이 가이드를 통해 Ubuntu 24.04 환경에서 K3S를 활용한 경량 Kubernetes 클러스터를 성공적으로 구축하고, NFS 스토리지, MetalLB 로드 밸런서, Nginx Ingress를 설정하는 방법을 배웠습니다. K3S는 리소스 제약이 있는 환경에서도 효율적으로 작동하는 경량 Kubernetes 배포판으로, 개발 및 테스트 환경에 이상적입니다.
구축된 클러스터의 주요 컴포넌트 요약
- K3S 클러스터: Master 1개, Worker 3개로 구성된 고가용성 클러스터
- NFS StorageClass: 영구 스토리지를 위한 NFS 서버 및 프로비저너
- MetalLB: LoadBalancer 타입 서비스를 위한 IP 주소 할당
- Nginx Ingress: 외부 트래픽을 클러스터 내부 서비스로 라우팅
K3S의 장점
- 경량성: 단일 바이너리로 배포 가능, 메모리와 CPU 사용량이 낮음
- 쉬운 설치: 복잡한 구성 없이 빠르게 클러스터 구축 가능
- 호환성: 표준 Kubernetes API 지원으로 기존 도구와 통합 용이
- 보안: 내장된 보안 기능으로 안전한 운영 환경 제공
추가 권장사항
- 모니터링: Prometheus와 Grafana를 추가하여 클러스터 상태 모니터링
- 보안 강화: RBAC, 네트워크 정책, 그리고 정기적인 업데이트 적용
- 백업: etcd 데이터와 중요 구성의 정기 백업
- 확장성: 필요에 따라 노드 추가 또는 고급 기능(예: cert-manager) 통합
이 가이드를 따라 구축한 클러스터는 개발, 테스트, 그리고 소규모 프로덕션 환경에 적합합니다. Kubernetes 생태계를 탐구하는 첫 걸음으로 활용하시길 바랍니다. 추가 질문이나 개선사항이 있으시면 언제든지 문의해 주세요!