K8s 기초 #2 로컬 환경 — minikube / kind / Docker Desktop k8s
#1 쿠버네티스란에서 control plane과 worker로 나뉜 클러스터의 큰 그림을 봤습니다. 이번 글에서는 로컬에서 K8s 클러스터를 띄우는 세 가지 방법인 minikube, kind, Docker Desktop이 내장한 K8s를 비교하고, kubectl을 설치해 kind로 첫 클러스터를 띄운 뒤 노드와 시스템 파드를 확인하는 흐름을 다루겠습니다.
이번 시리즈는 K8s 기초 7편입니다.
- #1 쿠버네티스란 — 왜 컨테이너 오케스트레이터가 필요한가
- #2 로컬 환경 — minikube / kind / Docker Desktop k8s ← 이번 글
- #3 kubectl과 첫 Pod
- #4 Deployment / ReplicaSet
- #5 Service — ClusterIP / NodePort / LoadBalancer
- #6 ConfigMap / Secret
- #7 Namespace와 라벨
이번 글의 끝에서는 **로컬 클러스터 한 대 + 그 클러스터를 들여다볼 수 있는 kubectl**까지 준비합니다. 그 상태가 #3부터의 출발점입니다.
로컬 K8s 세 가지 길 #
세 도구는 모두 “로컬에 K8s 클러스터를 한 대 띄운다"는 같은 일을 하지만, 동작 방식과 장단점이 조금씩 다릅니다.
| 도구 | 동작 방식 | 멀티 노드 | 시작 시간 | 추천 대상 |
|---|---|---|---|---|
| Docker Desktop k8s | Docker Desktop 내부의 VM 위에서 단일 노드 K8s 실행 | X (단일 노드) | 보통 | macOS,Windows에서 이미 Docker Desktop을 쓰는 사용자 |
| minikube | VM 또는 컨테이너 드라이버 중 선택해 클러스터 실행 | 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 #
brew install kubectlWindows — winget 또는 Chocolatey #
winget install -e --id Kubernetes.kubectl
# 또는
choco install kubernetes-cliLinux — 공식 바이너리 #
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 --clientClient Version: v1.30.x
Kustomize Version: v5.x.x이 시점에는 아직 클러스터가 없으므로 서버 버전은 잡히지 않습니다. 클러스터를 띄우면 그다음에 표시됩니다.
kind로 첫 클러스터 띄우기 #
이번 글의 메인 길입니다. 먼저 kind 자체를 설치합니다.
brew install kindwinget install -e --id Kubernetes.kind
# 또는
choco install kindcurl -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 clusterCreating 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 노드로 사용한다고 했습니다. 정말 그런지 도커 쪽에서 확인할 수 있습니다.
docker psCONTAINER ID IMAGE COMMAND PORTS NAMES
abc123def456 kindest/node:v1.30.x "/usr/local/bin/entr…" 127.0.0.1:xxxxx->6443/tcp kind-control-planekindest/node 이미지로 만들어진 컨테이너 한 대가 떠 있고, 그 안에서 control plane과 worker가 같이 동작합니다. 호스트의 임의 포트가 컨테이너의 6443(K8s API 서버 기본 포트)으로 매핑되어 있습니다. kubectl은 이 포트로 명령을 보냅니다.
첫 명령 — 노드와 시스템 파드 둘러보기 #
클러스터가 떴으니, #1에서 이름만 나왔던 컴포넌트들이 실제로 떠 있는 모습을 확인해 봅시다.
kubectl get nodesNAME STATUS ROLES AGE VERSION
kind-control-plane Ready control-plane 45s v1.30.x단일 노드 클러스터라 한 줄만 보입니다. 이 노드 한 대가 control plane 역할도 하고 동시에 워크로드도 받는 형태입니다(로컬 환경의 흔한 구성).
다음으로 모든 네임스페이스의 파드를 봅니다. K8s 컴포넌트는 클러스터 위에 파드 형태로 떠 있는 경우가 많기 때문입니다.
kubectl get pods -ANAMESPACE 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-infoKubernetes 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-contextsCURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kind-kind kind-kind kind-kind kubectl config current-contextkind-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 버전에 따라 조금씩 다르지만, 대체로 다음과 같습니다.
- Docker Desktop 실행 → Settings(또는 Preferences)
- 왼쪽 메뉴에서 Kubernetes 탭
- Enable Kubernetes 체크 → Apply & Restart
처음 활성화할 때는 K8s 컴포넌트 이미지를 받아오느라 몇 분 걸립니다. 끝나면 kubectl의 컨텍스트가 자동으로 추가됩니다.
kubectl config use-context docker-desktop
kubectl get nodesNAME STATUS ROLES AGE VERSION
docker-desktop Ready control-plane 2m v1.30.x이후의 kubectl 명령은 kind와 완전히 동일합니다.
minikube로 띄울 경우 #
minikube도 비슷합니다. 먼저 minikube CLI를 설치한 뒤(공식 안내: minikube.sigs.k8s.io), 클러스터를 시작합니다.
minikube start드라이버를 명시적으로 고르고 싶다면 --driver 옵션을 줍니다. 기본 드라이버는 환경에 따라 docker / hyperkit / kvm 등으로 자동 선택됩니다.
minikube start --driver=dockerminikube가 뜨면 컨텍스트가 minikube로 잡힙니다.
kubectl config use-context minikube
kubectl get nodesminikube의 매력 중 하나인 애드온은 minikube addons 명령으로 다룹니다. 예를 들어 ingress 컨트롤러를 켜려면 이렇게 합니다.
minikube addons enable ingress정리,치우기 #
학습이 끝났거나 클러스터를 새로 만들고 싶을 때, 깔끔하게 치우는 방법도 알아 두면 좋습니다.
kind
kind delete cluster이름을 따로 준 적이 없으면 기본 이름(kind)의 클러스터가 지워집니다. 여러 클러스터를 동시에 운영했다면 --name으로 지정하세요.
Docker Desktop k8s
설정의 Kubernetes 탭에서 Disable Kubernetes를 체크하면 됩니다. 또는 같은 화면의 Reset Kubernetes Cluster 버튼으로 초기화할 수도 있습니다.
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의 진짜 시작입니다.