K8s 기초 #2 로컬 환경 — minikube / kind / Docker Desktop k8s

10 분 소요

#1 쿠버네티스란에서 control plane과 worker로 나뉜 클러스터의 큰 그림을 봤습니다. 이번 글에서는 로컬에서 K8s 클러스터를 띄우는 세 가지 방법인 minikube, kind, Docker Desktop이 내장한 K8s를 비교하고, kubectl을 설치해 kind로 첫 클러스터를 띄운 뒤 노드와 시스템 파드를 확인하는 흐름을 다루겠습니다.

이번 시리즈는 K8s 기초 7편입니다.

이번 글의 끝에서는 **로컬 클러스터 한 대 + 그 클러스터를 들여다볼 수 있는 kubectl**까지 준비합니다. 그 상태가 #3부터의 출발점입니다.

로컬 K8s 세 가지 길 #

세 도구는 모두 “로컬에 K8s 클러스터를 한 대 띄운다"는 같은 일을 하지만, 동작 방식과 장단점이 조금씩 다릅니다.

도구동작 방식멀티 노드시작 시간추천 대상
Docker Desktop k8sDocker Desktop 내부의 VM 위에서 단일 노드 K8s 실행X (단일 노드)보통macOS,Windows에서 이미 Docker Desktop을 쓰는 사용자
minikubeVM 또는 컨테이너 드라이버 중 선택해 클러스터 실행O (옵션)보통애드온(ingress, dashboard 등)을 풍부하게 쓰고 싶을 때
kind도커 컨테이너 한 대 한 대를 K8s 노드로 사용O빠름가볍게, 또는 멀티 노드를 YAML로 정의하고 싶을 때 / CI

조금 더 풀어 설명하면 이렇습니다.

Docker Desktop k8s는 macOS와 Windows에서 가장 손이 덜 가는 길입니다. Docker Desktop을 이미 쓰고 있다면 설정 메뉴의 Kubernetes 탭에서 체크 한 번이면 클러스터가 뜨고, kubectl의 컨텍스트도 자동으로 docker-desktop으로 잡힙니다. 단점은 macOS,Windows 한정이고(리눅스용 Docker Desktop도 같은 옵션을 제공하지만 환경마다 사정이 다릅니다), 어차피 Docker Desktop이 띄운 VM 안에서 도는 K8s라 메모리,CPU를 꽤 사용합니다.

minikube는 로컬 K8s 도구 중 가장 오래된 축에 속합니다. 환경에 따라 docker / hyperkit / kvm / virtualbox 등 여러 드라이버 중 하나가 자동 선택되거나 사용자가 골라 쓸 수 있습니다. 가장 큰 장점은 **애드온(addon)**이 풍부하다는 점입니다. ingress, metrics-server, dashboard, registry 같은 흔히 필요한 부가 기능을 명령 한 줄로 켤 수 있습니다.

kind는 이름이 곧 동작 설명입니다 — Kubernetes IN Docker. 도커 컨테이너 한 대를 K8s 노드로 사용하는 방식이라, VM을 따로 띄우는 minikube/Docker Desktop보다 가볍고 빠릅니다. 멀티 노드 클러스터를 짧은 YAML로 정의할 수 있어 control plane과 worker를 분리한 환경을 흉내내기 좋고, 그래서 K8s 자체 CI에서도 사용됩니다.

어떤 걸 고를까 #

이미 macOS,Windows에서 Docker Desktop을 쓰고 있다면 처음에는 Docker Desktop k8s가 가장 편합니다. 체크 박스 한 번에 클러스터가 뜨고, 평소 쓰던 도커 환경과 자연스럽게 묶입니다. 리눅스 사용자거나, 멀티 노드 환경을 흉내내 보고 싶거나, 클러스터를 자주 만들고 지우고 싶다면 kind가 잘 맞습니다. 애드온을 한 줄 명령으로 끄고 켜며 이것저것 시험해 보고 싶다면 minikube도 좋은 선택입니다.

이 시리즈의 본문에서는 kind를 메인 길로 깔고 갑니다. 가볍고 빠르며, 명령어 한두 줄로 클러스터를 만들고 지울 수 있어 학습용으로 적합하기 때문입니다. 다만 어떤 걸 고르든 #3부터의 kubectl 명령은 동일합니다. 클러스터를 띄우는 방법만 다를 뿐, 그 위에서 다루는 K8s 리소스는 같습니다. 그러니 자기 환경에 맞는 걸 고르고 따라오면 됩니다.

kubectl 설치 #

클러스터를 어디에 띄우든, 그 클러스터와 대화하는 클라이언트는 공통으로 kubectl 입니다. K8s 컨트롤 플레인의 API 서버(kube-apiserver)에 HTTP로 명령을 보내는 CLI입니다.

macOS — Homebrew #

kubectl 설치 (macOS)
brew install kubectl

Windows — winget 또는 Chocolatey #

kubectl 설치 (Windows)
winget install -e --id Kubernetes.kubectl
# 또는
choco install kubernetes-cli

Linux — 공식 바이너리 #

kubectl 설치 (Linux)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

배포판에 따라 패키지 매니저(apt, dnf 등)로도 설치할 수 있지만, K8s는 클라이언트와 서버 버전의 호환 범위를 맞춰 두는 편이 안전합니다. 정확한 설치 절차가 필요하면 kubernetes.io의 설치 안내를 참고하세요.

설치가 끝나면 클라이언트 버전을 확인합니다.

설치 확인
kubectl version --client
출력 예시
Client Version: v1.30.x
Kustomize Version: v5.x.x

이 시점에는 아직 클러스터가 없으므로 서버 버전은 잡히지 않습니다. 클러스터를 띄우면 그다음에 표시됩니다.

kind로 첫 클러스터 띄우기 #

이번 글의 메인 길입니다. 먼저 kind 자체를 설치합니다.

kind 설치 (macOS)
brew install kind
kind 설치 (Windows)
winget install -e --id Kubernetes.kind
# 또는
choco install kind
kind 설치 (Linux)
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x kind
sudo mv kind /usr/local/bin/

kind는 도커 데몬을 사용합니다. Docker Desktop 또는 도커 엔진이 먼저 실행 중이어야 합니다.

이제 클러스터를 하나 만듭니다. 단일 노드라면 명령 한 줄이면 끝입니다.

클러스터 생성
kind create cluster
출력 예시
Creating cluster "kind" ...
 - Ensuring node image (kindest/node:v1.30.x) - 
 - Preparing nodes - 
 - Writing configuration - 
 - Starting control-plane - 
 - Installing CNI - 
 - Installing StorageClass - 
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

마지막 줄이 핵심입니다. kubectl의 컨텍스트가 자동으로 kind-kind로 잡힙니다. 이제 kubectl 명령은 이 클러스터로 향합니다.

kind는 어떻게 동작하는가 #

kind는 도커 컨테이너 한 대를 K8s 노드로 사용한다고 했습니다. 정말 그런지 도커 쪽에서 확인할 수 있습니다.

kind가 띄운 컨테이너 보기
docker ps
출력 예시
CONTAINER ID   IMAGE                  COMMAND                  PORTS                       NAMES
abc123def456   kindest/node:v1.30.x   "/usr/local/bin/entr…"   127.0.0.1:xxxxx->6443/tcp   kind-control-plane

kindest/node 이미지로 만들어진 컨테이너 한 대가 떠 있고, 그 안에서 control plane과 worker가 같이 동작합니다. 호스트의 임의 포트가 컨테이너의 6443(K8s API 서버 기본 포트)으로 매핑되어 있습니다. kubectl은 이 포트로 명령을 보냅니다.

첫 명령 — 노드와 시스템 파드 둘러보기 #

클러스터가 떴으니, #1에서 이름만 나왔던 컴포넌트들이 실제로 떠 있는 모습을 확인해 봅시다.

노드 목록
kubectl get nodes
출력 예시
NAME                 STATUS   ROLES           AGE   VERSION
kind-control-plane   Ready    control-plane   45s   v1.30.x

단일 노드 클러스터라 한 줄만 보입니다. 이 노드 한 대가 control plane 역할도 하고 동시에 워크로드도 받는 형태입니다(로컬 환경의 흔한 구성).

다음으로 모든 네임스페이스의 파드를 봅니다. K8s 컴포넌트는 클러스터 위에 파드 형태로 떠 있는 경우가 많기 때문입니다.

모든 네임스페이스의 파드
kubectl get pods -A
출력 예시
NAMESPACE            NAME                                         READY   STATUS    RESTARTS   AGE
kube-system          coredns-xxxxxxxxxx-aaaaa                     1/1     Running   0          1m
kube-system          coredns-xxxxxxxxxx-bbbbb                     1/1     Running   0          1m
kube-system          etcd-kind-control-plane                      1/1     Running   0          1m
kube-system          kindnet-xxxxx                                1/1     Running   0          1m
kube-system          kube-apiserver-kind-control-plane            1/1     Running   0          1m
kube-system          kube-controller-manager-kind-control-plane   1/1     Running   0          1m
kube-system          kube-proxy-xxxxx                             1/1     Running   0          1m
kube-system          kube-scheduler-kind-control-plane            1/1     Running   0          1m
local-path-storage   local-path-provisioner-xxxxxxxxxx-yyyyy      1/1     Running   0          1m

#1에서 이름만 들었던 컴포넌트들이 그대로 보입니다 — kube-apiserver, etcd, kube-scheduler, kube-controller-manager, kube-proxy, 그리고 클러스터 DNS인 coredns. 거기에 kind 특유의 네트워크 플러그인 kindnet과, 로컬 환경에서 PersistentVolume을 흉내내 주는 local-path-provisioner까지요.

kube-system 네임스페이스는 K8s가 자기 운영을 위해 쓰는 파드들이 모이는 칸입니다. 우리가 앞으로 만들 앱은 default 네임스페이스(또는 직접 만든 네임스페이스, #7)로 갑니다.

마지막으로 클러스터 자체의 메타 정보를 확인합니다.

클러스터 정보
kubectl cluster-info
출력 예시
Kubernetes control plane is running at https://127.0.0.1:xxxxx
CoreDNS is running at https://127.0.0.1:xxxxx/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

이 출력의 첫 줄에 적힌 IP,포트가 바로 위에서 본 docker ps의 포트 매핑과 같은 곳입니다. 즉 kubectl은 호스트에서 도커가 노출해 준 포트를 통해 노드 컨테이너 안의 kube-apiserver와 대화하고 있습니다.

kubeconfig — kubectl이 어디로 명령을 보내는지 #

kubectl이 어떤 클러스터로 명령을 보낼지는 kubeconfig 파일이 정합니다. 기본 경로는 다음과 같습니다.

  • macOS / Linux — ~/.kube/config
  • Windows — %USERPROFILE%\.kube\config

이 파일에는 세 가지 정보가 들어 있습니다.

항목의미
clusters어떤 클러스터들이 있는지 (API 서버 주소, CA 인증서)
users그 클러스터에 어떤 자격 증명으로 접근하는지 (인증서, 토큰 등)
contexts“이 클러스터 + 이 사용자 + 이 네임스페이스"의 묶음. kubectl이 한 번에 하나의 컨텍스트를 사용

kind가 클러스터를 만들면서 kind-kind라는 컨텍스트를 자동으로 추가하고 현재 컨텍스트를 거기에 맞춰 둡니다. 직접 확인해 봅시다.

컨텍스트 보기
kubectl config get-contexts
출력 예시
CURRENT   NAME             CLUSTER          AUTHINFO         NAMESPACE
*         kind-kind        kind-kind        kind-kind        
현재 컨텍스트
kubectl config current-context
출력 예시
kind-kind

여러 클러스터를 동시에 다루게 되면(예: 로컬 kind, 회사 dev 클러스터, 회사 prod 클러스터) kubectl config get-contexts에 항목이 여러 개 나옵니다. 그중 하나를 골라 현재 컨텍스트로 바꿀 때 쓰는 명령이 use-context입니다.

컨텍스트 전환
kubectl config use-context kind-kind

회사 클러스터와 로컬을 오가며 작업할 때, 명령을 잘못된 클러스터에 보내지 않도록 컨텍스트를 항상 의식하는 습관이 중요합니다. 셸 프롬프트에 현재 컨텍스트를 띄워 주는 도구(kube-ps1, starship 등)도 많이 사용됩니다.

Docker Desktop k8s로 띄울 경우 #

Docker Desktop을 이미 쓰는 환경이라면 설정 메뉴에서 K8s를 켜는 것만으로 클러스터가 뜹니다. 정확한 메뉴 경로는 Docker Desktop 버전에 따라 조금씩 다르지만, 대체로 다음과 같습니다.

  1. Docker Desktop 실행 → Settings(또는 Preferences)
  2. 왼쪽 메뉴에서 Kubernetes
  3. Enable Kubernetes 체크 → Apply & Restart

처음 활성화할 때는 K8s 컴포넌트 이미지를 받아오느라 몇 분 걸립니다. 끝나면 kubectl의 컨텍스트가 자동으로 추가됩니다.

Docker Desktop k8s 컨텍스트로 전환
kubectl config use-context docker-desktop
kubectl get nodes
출력 예시
NAME             STATUS   ROLES           AGE   VERSION
docker-desktop   Ready    control-plane   2m    v1.30.x

이후의 kubectl 명령은 kind와 완전히 동일합니다.

minikube로 띄울 경우 #

minikube도 비슷합니다. 먼저 minikube CLI를 설치한 뒤(공식 안내: minikube.sigs.k8s.io), 클러스터를 시작합니다.

minikube 클러스터 시작
minikube start

드라이버를 명시적으로 고르고 싶다면 --driver 옵션을 줍니다. 기본 드라이버는 환경에 따라 docker / hyperkit / kvm 등으로 자동 선택됩니다.

드라이버를 명시한 시작
minikube start --driver=docker

minikube가 뜨면 컨텍스트가 minikube로 잡힙니다.

확인
kubectl config use-context minikube
kubectl get nodes

minikube의 매력 중 하나인 애드온은 minikube addons 명령으로 다룹니다. 예를 들어 ingress 컨트롤러를 켜려면 이렇게 합니다.

ingress 애드온
minikube addons enable ingress

정리,치우기 #

학습이 끝났거나 클러스터를 새로 만들고 싶을 때, 깔끔하게 치우는 방법도 알아 두면 좋습니다.

kind

kind 클러스터 삭제
kind delete cluster

이름을 따로 준 적이 없으면 기본 이름(kind)의 클러스터가 지워집니다. 여러 클러스터를 동시에 운영했다면 --name으로 지정하세요.

Docker Desktop k8s

설정의 Kubernetes 탭에서 Disable Kubernetes를 체크하면 됩니다. 또는 같은 화면의 Reset Kubernetes Cluster 버튼으로 초기화할 수도 있습니다.

minikube

minikube 정지/삭제
minikube stop      # 일시 정지 (다음에 다시 start가능)
minikube delete    # 완전히 삭제

로컬 클러스터는 언제든 지우고 다시 만들 수 있다는 가벼움이 큰 장점입니다. 무언가 꼬였다고 판단되면 깨끗이 지우고 다시 띄우는 편이 빠를 때가 많습니다.

정리 #

이번 글에서 잡은 흐름:

  • 로컬에 K8s를 띄우는 길은 셋입니다 — Docker Desktop k8s(체크 한 번, macOS,Windows), minikube(애드온이 풍부), kind(가볍고 빠름, 멀티 노드 지원).
  • 클러스터를 어디에 띄우든 클라이언트는 공통으로 **kubectl**입니다. 패키지 매니저나 공식 바이너리로 설치한 뒤 kubectl version --client로 확인합니다.
  • kind는 도커 컨테이너 한 대를 노드로 사용합니다. kind create cluster 한 줄로 단일 노드 클러스터가 뜨고, docker ps에서 kindest/node 컨테이너로 보입니다.
  • kubectl get nodes / kubectl get pods -A / kubectl cluster-info로 클러스터를 둘러보면 #1에서 이름만 들었던 kube-apiserver, etcd, coredns 등이 실제로 떠 있습니다.
  • kubeconfig(~/.kube/config)는 clusters / users / contexts 세 부분으로 구성되고, kubectl config use-context로 여러 클러스터 사이를 오갑니다.
  • 다 쓴 클러스터는 kind delete cluster / minikube delete / Docker Desktop의 Disable Kubernetes로 깔끔하게 지웁니다.

다음 — kubectl로 첫 Pod 띄우기 #

이번 글에서는 로컬 클러스터를 띄우는 방법과 kubectl을 연결하는 출발점을 잡았습니다. 다음 글에서는 이 클러스터에 첫 Pod를 띄우는 방법을 다루겠습니다.

#3 kubectl과 첫 Pod에서는 K8s의 최소 실행 단위인 Pod를 보겠습니다. kubectl run으로 명령형으로 띄우는 길과 YAML 매니페스트로 선언형으로 띄우는 길을 둘 다 보고, kubectl get / describe / logs / exec 같은 일상 명령으로 Pod를 들여다보는 흐름까지 정리하겠습니다. 거기서부터가 K8s의 진짜 시작입니다.

X