You are currently viewing 로컬 Kubernetes 클러스터 구성 도구 비교

로컬 Kubernetes 클러스터 구성 도구 비교

Intro


쿠버네티스 환경에서의 공부/개발 테스트 시 로컬 클러스터가 필요하다. 학습 목적의 클러스터가 필요할 수도 있고, 개발한 어플리케이션을 실제 운영/개발 환경에 배포하기 이전에 Manifest 단에서 잘 배포가 되는지 확인이 필요할 수 있기 때문이다.


이러한 로컬 Kubernetes 클러스터 도구에 대해서, 수많은 구성도구가 존재하며 모두 다 자기가 최선의 선택이다/많은 기능을 제공한다고 이야기를 한다. 하지만 선택받는것은 그 중 하나일 것이다.


본 글에서는 다양한 클러스터 도구를 간단히 설치하면서 테스트해보고, 각 도구별로 장점은 무엇인지/다른 도구 대비 단점은 무엇인지를 확인해보고자한다.


주요 Kubernetes 클러스터 구성 도구

본글에서 확인해 볼 주요 구성 도구는 다음과 같다.

  • UTM, Docker Desktop, Orbstack, Minikube, Kind

각 도구별로 여러가지 기준으로 나누어 볼 수 있다. 설치와 구성에 앞서 먼저 각 도구의 특징을 정리하면 아래와 같다.

  • VM 기반, 수동 구축
    • UTM
  • 컨테이너 기반, 자동 구축
    • 맥북(localhost)에 바로 붙을 수 있음
      • Docker Desktop
      • Orbstack
    • 맥북(localhost)에 붙기 위해 별도의 설정 필요
      • Minikube
      • Kind
      • K3s

  • 다수의 클러스터/노드 생성 여부
    • 단일 클러스터만 생성 가능
      • Docker Desktop
      • Orbstack
    • 다수 클러스터 생성 가능
      • Multi ControlPlane/Worker 구성 가능
        • UTM
        • Kind
        • K3s
      • Single ControlPlane / Multi Worker
        • Minikube

  • 생성 속도/시스템 부하
    • 낮음
      • Orbstack
      • Kind
    • 낮지 않음
      • Minikube
      • K3s
      • Docker Desktop
      • UTM


그 외에도 CNI지원/구성파일제공/등 여러가지 기준으로도 나누어 볼 수 있을 것이다.

UTM 소개와 구축 방법


UTM은 ARM기반 맥북(M1,…)에서 가상 머신을 생성할 수 있도록 도와주는 오픈소스 프로그램이다. ARM 기반 맥북 환경에서 가상머신을 구동하기 위해서는 도구가 제한적이다. VirtualBox는 지원되지않으며, VMware의 경우 VMware Fusion과 같은 도구를 사용할수 있긴하나 개인사용자 무료 플랜의 경우에도 별도 라이센스키 입력등 절차가 번거롭다.


UTM을 사용하면 오픈소스의 이점을 살려 간단히 생성과 구축을 할 수 있다. UTM을 사용한 구축기는 다른 M1맥북에서 Rocky리눅스에 UTM으로 HA Kubernetes 클러스터 구축하기 를 참고바란다. 해당글에서 HA설정부분(keepalived/haproxy)부분을 제외하고 수행하면 된다.


UTM을 사용하여 별도의 Linux VM을 구성할 수 있다. 생성된 VM들을 사욯해 노드 설정(sysconfig/CRI 등)을 수행한 뒤 kubeadm 또는 kube-spray와 같은 도구를 사용하여 클러스터 구성을 마칠 수 있다.


장점)

  • Node 설정 학습 가능
    후술할 도구들은 설치과정이 추상화되어 버튼딸깍/몇줄의 명령어로 클러스터 생성과 구축이 자동화되어 제공된다. UTM 기반 가상머신 클러스터 구성시 노드 생성, config설정, 클러스터 생성 전과정을 수행할 수 있다.

단점)

  • 그외 모든것

직접적으로 노드를 테스트할 수 있다 외의 장점은 없다. VM 노드 기반이기에 컨테이너 노드 기반의 아래 도구들 보다 무겁다. 또한 별도의 자동화도구/스크립트의 도움을 받지 않는다면 수동 구축이라는 부분은 실 사용시 단점이다. UTM에서는 자체적인 VM 스냅샷등의 기능이 없어 다수 클러스터 테스트시 어려움이 존재한다.(구축 완료된 머신들을 복제해놓는식으로 우회하려면 가능은함)



Docker Desktop 소개와 구축 방법

https://docs.docker.com/desktop/install/mac-install/

Docker Desktop은 Linux 이외의 환경에서 Docker의 설치와 실행을 위해 필요한 프로그램이다. 기본적으로 Docker Engine은 Linux 환경에서 작동하기 때문에 Linux가 아닌 MacOS, Windows 환경에선 별도의 Overlay 환경이 필요하다. Docker Desktop이 Linux 제외환 환경에서 Docker 실행을 위한 별도 환경을 제공한다.

클러스터 생성


위의 공식문서의 설치 절차에 따라 Docker Desktop 설치를 마무리한다. 이후 Docker Desktop UI에서 Settings > Kubernetes > Enable Kubernetes > Apply & Restart를 선택하면 kubernetes 구성이 마무리된다.


구성 이후 kubectl get node -o wide 명령어를 통해 호스트 머신을 control-plane 및 worker node를 겸하는 단일 노드 기반으로 생성된것을 알 수 있다. docker network inspect --format='{{json .Containers}}' host | jq . 명령어를 통해 호스트 머신의 host network를 통해 구성요소 Pod들이 연결되어있는 것을 볼 수 있으며, 위의 구성 설정에서 Show system containers (advanced) 옵션을 활성화하고 재시작하면 docker ps 명령어를 통해 생성된 구성요소 pod(etcd, api-server, etc.)를 확인할 수 있다.

접근 테스트

접근 테스트를 위해 간단히 nginx pod를 생성한 뒤, LoadBalancer 타입의 Service 를 생성하고, 응답의 헤더값을 출력하면 다음과 같이 200을 확인할 수 있다.

# nginx pod 생성 및 대기
kubectl run nginx --image nginx
sleep 5

# 생성된 nginx pod를 호스트머신의 8010 포트로 노출
kubectl expose pod nginx --port=8010 --target-port=80 --name=lb-service --type=LoadBalancer

# 생성된 service의 EXTERNAL-IP가 localhost임을 확인
kubectl get service

# curl 요청의 헤더값만 출력
curl -I localhost:8010

장점)

  • 간편한 구성

위의 한장의 이미지로 정리할 수 있을 정도로, 생성이 간편하다.

  • localhost와 네트워크를 공유하여 바로 연결 될 수 있음

위의 설정처럼, host network를 통해 바로 연결되어있어 클러스터 외부 연결시 LoadBalancer 유형의 Service를 생성하면 바로 붙을 수 있다.


단점)

  • 자세한 설정 불가

버튼 몇개로 생성할 수 있는것은 장점이나, 별도로 추가적인 설정을 적용하기는 어렵다. ex) 만약 추가적인 node를 생성하고싶다면? 컨테이너 런타임(CRI)를 변경하고 싶다면? upstream 대신 다른 버전의 클러스터를 생성하고 싶다면?

  • 다수 클러스터 생성 불가

클러스터간 통신 테스트 또는 버전이 다른 클러스터를 다수 생성해서 어플리케이션이 잘 배포되는지 확인해야한다면 적절한 도구가 아니다.

  • 시스템 리소스 소모 큼

정확한 테스트를 위해 다른 프로세스 종료등 최적화를 한것은 아니지만, 기본적인 클러스터만 생성하고 IDLE 상태임에도 다음과 같은 리소스를 가져간다. 추후 테스트 어플리케이션 등이 생성되면 소요량은 더 늘어날 것이다.


Orbstack

https://docs.orbstack.dev/install

Orbstack은 MacOS에서 컨테이너와 리눅스 머신을 가동하기 위한 빠르고 가벼운 도구이다. Docker Desktop을 완벽히 대체할 수 있다고 소개 되어있다. OrbStack vs Docker
Desktop

클러스터 생성


Mac 환경에서 brew로 간단히 설치할 수 있고, orb 명령어로 간단히 클러스터를 시작할 수 있다.

# orbstack 설치
brew install orbstack

# Kubernetes 클러스터 시작
orb start k8s

접근 테스트

Docker Desktop의 경우 LocalHost 대역은 192.168.~ 대역 / Pod 대역은 10.~ 대역을 가져갔던것과 달리 Orbstack은 Cluster 대역 또한 192.168.194.0/25 대역을 동일하게 가져가기 때문에, 별도의 External IP를 위해 Service를 추가하지 않아도 ClusterIP를 통해 통신이 가능하다. 물론 External IP를 통한 통신도 가능하다.

# cluster cidr 범위 확인
kubectl cluster-info dump | grep cluster-cidr
# --cluster-cidr\",\"192.168.194.0/25

# nginx pod 생성
kubectl run nginx --image nginx
sleep 5

# 생성된 nginx pod를 호스트머신의 8010 포트로 노출
kubectl expose pod nginx --port=8010 --target-port=80 --name=lb-service --type=LoadBalancer

# nginx pod로 요청 보내기
curl -I $(kubectl get pod nginx -o jsonpath='{.status.podIP}')

# service의 clusterIP/EXTERNAL IP로 요청 보내보기
curl -I $(kubectl get svc lb-service -o jsonpath='{.spec.clusterIP}'):8010
curl -I $(kubectl get svc lb-service -o jsonpath='{.status.loadBalancer.ingress[].ip}'):8010

# 수동으로 해보기: pod IP / service IP 확인 후 curl -I 뒤 직접입력 (port:8010 유의)
kubectl get pod -o wide 
kubectl get svc -o wide
# 

장점)

  • 가벼움

위의 Docker Desktop 과 비교했을 때 IDLE 상태에서 소모량은 다음과 같았다.

뭔가 큰차이가 안나보이긴 하는데;; 쓰다보면 리소스 차이가 발생할것이다ㅠㅠ

  • 간편한 Network

접근 테스트를위해 별도 External IP를 할당받지않아도, Cluster IP를 통해 바로 통신이 가능하다

단점)

  • 빈약한 orb 명령어 지원

딱 주어진것만 사용하기엔 아쉬울 것이 없으나, 아직 초기라서 그런가.. 무언가를 설정하려고 한다면 부족한것이 많았다.

orb외에 CLI로 제어하려면 orbctl을 사용하여야 한다. 하지만 명령어외에, 추가적인 flag 등을 찾아보고자하면 텅비어있는 help페이지를 자주 마주하게된다


Minikube 소개와 구축 방법

https://minikube.sigs.k8s.io/docs/start/

Minikube는 Kubernetes 공식 문서에서도 소개 된, 로컬 환경에서 쿠버네티스 클러스터를 사용하기 위한 도구이다. 사용자 지정한 버전의 Kubernetes 클러스터를 생성, CRI/CNI 변경등을 수행할 수 있다. 주로 명령어(CLI)를 사용하여 클러스터를 제거하고 파라미터를 통해 추가 addon 들을 쉽게 구성하고 제어할 수 있다.

클러스터 생성


Mac 환경에서 brew로 간단히 설치할 수 있고, minikube 명령어를 통해 클러스터 생성, 중지, 변경, 삭제등의 제어가 가능하다. 설명과 조금 더 대중적인 환경을 위해 orbstack을 종료하고 docker desktop 환경에서 진행한다.

# Minikube 설치
brew install minikube

# Kubernetes 클러스터 시작
minikube start

이때 생성된 클러스터는 미니큐브의 profile 단위로 관리 된다. 이를 통해 다른 버전의 클러스터를 생성하고 context/profile 전환을 통해 멀티 클러스터 테스트가 가능하다

# Minikube k8s Cluster 생성
minikube start

# 다른 이름의, 1.26 버전의 클러스터 생성
minikube start -p test-1.26

# minikube profile 조회 및 default profile 변경
minikube profile list
minikube profile test-1.26
minikube profile list

접근 테스트

위와 동일하게, nginx 파드를 생성하고 외부로 노출하여 접근을 시도해 볼것이다.

# nginx pod 생성 및 대기
kubectl run nginx --image nginx
sleep 5

# 생성된 nginx pod를 호스트머신의 8010 포트로 노출
kubectl expose pod nginx --port=8010 --target-port=80 --name=lb-service --type=LoadBalancer

# 생성된 service의 EXTERNAL-IP가 localhost임을 확인
kubectl get service

# curl 요청의 헤더값만 출력
curl -I localhost:8010

바로 접근이 되지 않는 것을 확인할 수 있다. 위의 UTM, Docker Desktop, Orbstack과 달리 Minikube 부터는 호스트 머신과 별개의 네트워크 구조를 가지고 클러스터가 구성되기 때문이다. 따라서 Minikube의 서비스에 접근하기 위해서는 kubectl port-forward 또는 minikube service/tunnel 등의 명령어를 추가적으로 사용하여야 한다.

  1. minukube service/tunnel 방식

minikube service 명령을 통해 특정 k8s service 오브젝트를 로컬호스트와 매핑할 수 있다. 또는 minikube tunnel 명령을 통해 전체 클러스터를 매핑할 수 있다. 실행시 sudo 권한이 필요하며, 해당 terminal은 연결 상태로 두어야 한다.

minikube service 명령어를 사용하면 좌측상단의 터미널과같이

  • 8010 > 31840 으로 k8s service > container node로 한번 점프 한뒤
  • 31840 > 49581 으로 container node > host machine으로 두번 점프하는 것을 확인할 수 있다.

또한 >/dev/null 2>&1 & 을 실행 명령어뒤에 추가하여 Background로 보낼수 있다.

# 1. minikube service [ServiceName]
minikube service lb-service

# 2. minikube tunnel 
minikube tunnel

# minikube service 명령어 사용시 --url 옵션을 주어 브라우저 접속 대신 url만 생성할 수 있다.
minikube service lb-service --url

# 또는 >/dev/null 2>&1 &을 추가하여 background로 보낼수도 있다
minikube tunnel >/dev/null 2>&1 &


2. kubectl port-forward 방식

minikube에 의존하지않는 kubernetes native한 방식으로는 kubectl port-forward 명령어가 있다. 해당명령어를 통해 localhost <> service 오브젝트로의 포트로 전환할 수 있다.

여기서도 동일하게 >/dev/null 2>&1 & 를 붙여 백그라운드로 전환할 수 있다.

# port-forward host:svc
kubectl port-forward svc/lb-service 8010:8010

# 호스트의 다른 포트랑 연결하고자 한다면
kubectl port-forward svc/lb-service 10210:8010

장점)

  • 다양한 환경 구성 가능

minikube start page에서 볼 수 있는것처럼, 시작시 전달할 수 있는 다양한 옵션들이 있다. 이를 통해서 서로 다른 클러스터 버전/CRI/CNI 등의 환경을 갖는 클러스터 생성 및 전환이 가능하다.

또한 minikube ssh 등으로 생성된 컨테이너 기반 노드에 접근하여 구성값을 살펴 볼 수 있다.

  • 사용자 수 많음

추후 언급하겠지만, 컨테이너기반 도구 중에서 GitStar등 유명도가 높다. 이는 사용중 에러발생시 구글링 하기에도 용이할 듯 하다

단점)

  • 명령어로밖에 구성할 수 없음

CLI로 시작시 전달하는 parameter를 통해서만 구성 설정이 가능하다. 별도의 config 파일을 통한 생성등은 지원하지않으며 이것저것 덕지덕지 붙이다보면 실행명령어가 지저분해진다.

ex) 컨트롤과 워커가 분리된 2개의 노드로 구성하고, cpu/mem 리밋을 설정하고, CRI는 Docker/CNI는 Calico를 사용하되 dashboard, metrics, ingress, storage등의 addon을 설정한 1.26 k8s cluster 생성하기

sudo minikube start -p nasir-minikube --output='text' --nodes 2 --cpus='2' --disk-size='20000mb' --container-runtime=docker --cni='calico' --addons=dashboard --addons=metrics-server --addons="ingress" --addons="ingress-dns" —addons=“storage-provisioner” --addons=“default-storage class” --kubernetes-version=v1.26.0 --force

  • 실질적인 멀티노드 클러스터 구성 불가

minikube node add 명령어를 통해 node의 추가가 가능하지만, 이는 worker 노드의 추가만이 가능하다.

      --control-plane       This flag is currently unsupported.

다수의 ControlPlane를 가진 HA 클러스터 구성 및 테스트는 불가능하다


Kind 소개와 구축 방법

https://kind.sigs.k8s.io/docs/user/quick-start/#installation

Kind는 Kubernetes IN Docker 의 약자로, Kubernetes 테스트를 위한 로컬 클러스터를 제공해준다. 과거에 공식문서에서는 kubeadm/kubespray/minikube 밖에 없었는데 언젠가 부터 kind 또한 추가 되었다. minikube와 유사하게 컨테이너 노드 기반 Kubernetes 클러스터 구축 도구이나, 구성파일을 사용하여 생성 및 공유가 간편 / 설정할 수 있는 옵션이 많다는 특징이 있다.

클러스터 생성

brew를 통해 간편히 설치할 수 있고, kind 명령어를 통해 환경을 제어할 수 있다.

# kind 설치
brew install kind

kind create cluster --name my-cluster 같은 명령어를 통해서 클러스터 제어가 가능하지만, config 파일을 통해 조금 더 세세한 설정이 가능하다. 문서의 Advanced 설정과 같이 별도의 config.yaml을 통해 HA설정, 호스트머신과의 포트매핑 등을 수행할 수 있다. 본글에서는 3개의 컨트롤, 2개의 워커로 HA설정이 되어있고 테스트할 8010과 80이 포트매핑 되어있는 클러스터를 생성할것이다

# kind.yaml로 저장한 뒤 kind create cluster --config=./kind.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 8010
    hostPort: 8010
    protocol: TCP
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
- role: worker
  extraPortMappings:
  - containerPort: 8010
    hostPort: 8010
    protocol: TCP
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP

접근 테스트

동일하게 nginx pod 배포 및 svc 생성 후 연결 테스트를 수행해보겠다.

# nginx pod 생성 및 대기
kubectl run nginx --image nginx
sleep 5

# 생성된 nginx pod를 호스트머신의 8010 포트로 노출
kubectl expose pod nginx --port=8010 --target-port=80 --name=lb-service --type=LoadBalancer

# 생성된 service의 EXTERNAL-IP가 localhost임을 확인
kubectl get service

# curl 요청의 헤더값만 출력
curl -I localhost:8010

아잇.. port mapping이 내가 생각했던 방식대로는 작동하지 않는듯하다. port-forward 같은 옵션으로 이해했는데 nodeport 옵션을 위한 설정인듯 하다

This can be useful if using NodePort services or daemonsets exposing host ports.

8010 대신 32000을 오픈한 클러스터를 생성한다

# kind-np.yaml로 저장한 뒤 kind create cluster --config=./kind-np.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 32000
    hostPort: 32000
    protocol: TCP
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
- role: worker
  extraPortMappings:
  - containerPort: 32000
    hostPort: 32000
    protocol: TCP
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP

NodePort 유형의 서비스를 생성한뒤, 포트를 32000으로 변경한다

# nginx pod 생성 및 대기
kubectl run nginx --image nginx
sleep 5

# 생성된 nginx pod에 대한 NodePort 유형의 svc 생성
kubectl expose pod nginx --port=80 --target-port=80 --name=np-service --type=NodePort

# 생성된 NodePort svc의 포트번호를 32000으로 변경
kubectl patch svc np-service --type='json' -p='[{"op": "replace", "path": "/spec/ports/0/nodePort", "value":32000}]'


# curl 요청의 헤더값만 출력
curl -I localhost:32000


장점)

  • (진짜) 다양한 환경 구성 가능

Configuration 항목에서 볼 수 있듯이, Network, Node, Volume, Extra Ports, Lable등 다양한 항목을 필요에 따라 변경할 수 있다.

단점)

  • Network 직접 접근 불편함

PortMapping문구만 보고 minikube tunnel이 기본 적용된 상태로 생성될줄 알았는데 아니였음 이런


Outro

  • 다른 기준의 클러스터 선택 비교

사실 이 글은 k8s 클러스터 생성 도구를 고민하던 중, Minikube vs. k3d vs. kind vs. Getdeck 의 글을 읽고 시작하게 되었다. 해당 글로만 봐서는 kind가 minikube 보다 더 끌리기도 했었다.

  • 빠른 클러스터 구축 시간(minikube 생성29s, 삭제2.6s / kind 생성19s,삭제0.8s)
  • 적은 자원 소모량 (minikube 680MiB/ kind 581MB)
  • 진짜 멀티노드 클러스터 가능 (다수 마스터노드 가능/minikube의 마스터는1대만)
  • cli옵션 대신 config파일로 클러스터 시작 가능 (구성 공유에 용이)

그래서 kind가 최고일줄 알았는데 아니였네


도구들 vs 붙이기 간단히 살펴볼 수 있는 stackshare 에서 minikube vs Kind를 하면 다음과 같았다.

상황별 도구 선택

여러가지 도구를 살펴봤지만 최종적인 하나를 선택하기는 어려운듯 하다. 사용자의 사용 목적에 따라서 최적의 도구가 결정될 수 있을것이다.

  • 학습 목적
    • UTM
    • 가상 머신기반으로, 전체 클러스터의 생성과정을 수동으로 진행해 볼 수 있는 도구는 UTM이 유일하다.
  • 개발 테스트 목적
    • Docker Desktop
    • 클러스터 구성이나 기능보다는, 그 위의 k8s 리소스가 잘 생성되는지, 접근 테스트하기 간편한지 등에는 Docker Desktop이 간편하다
    • (조건부) Orbstack
    • service 생성도 필요없이 clusterIP를 통해 pod/svc 모두 붙을 수 있고 리소스 소모량이 적다. 다만 그 작동원리나 사용 사례가 아직은 많지 않다
  • 무난하게 따라가기
    • minikube
    • 설정 시간도 오래걸리고, 네트워킹도 복잡하지만 많이 사용되는것에는 이유가 있을것이다. 많은 사용자를 기반으로 에러시 구글링에도 용이할 듯 함


개인적으로는 다수 클러스터 생성 및 전환을 위해서 minikube를 선택 후 사용중이며 HA 테스트 필요시 UTM을 사용하였지만 구성이 번거로워 kind를 사용할까 고민중이다.


개인적으로는 node단에 설정할 수 있는 옵션들(taints/node affinity/topologySpreadConstraints)의 테스트를 위해 멀티 노드를 지원하고, 다수 클러스터 생성 및 전환이 가능하기 때문에 minikube를 주로 사용하였다. 그 외에 HA 테스트등 수동으로 구축 테스트가 필요한 경우 부분으로 UTM을 사용하기도 하였다.


이에 덧붙여 사용자 수가 많아 트러블 슈팅에도 용이할것같아 주변 개발자분들에게도 로컬 클러스터 구축시 minikube를 권했으나.. 지금은 다소 후회중이다. 멀티노드/클러스터전환 대신 YAML manifests에 오류는 없는지, 생성된 pod에 호출등의 검증용도로 사용되어 굳이 추가로 설치하고 네트워크설정이 필요한 minikube가 필요한지 싶다. 개발자들에게는 docker for desktop에 내장된 kubernetes를 권할걸

Leave a Reply