Kubernetes 로컬 개발 환경 만들기 - minikube 설치 및 사용
로컬 개발 환경 만들기, 어플리케이션 동작시키기
이번에는 웹 어플리케이션의 컨테이너를 로컬 Kubernetes에 세우는 것을 목표로 한다.
참고로, 여기서는 macOS 중심으로 설치를 진행하였다. 환경이 달라 방법이 다를 수 있으니 참고 바란다.
Minikube 설치 및 사용
이번에는 Minikube라는 로컬 환경에서 Kubernetes를 쉽게 실행할 수 있는 도구를 사용한다. 이 도구를 사용하면 단일 노드 Kubernetes 클러스터를 만들 수 있다.
Minikube의 사용법은 공식 문서를 참고하면 된다.
설치 전 사전 준비
docker 설치
minikube 설치 전에 Docker를 반드시 설치하여 사용하는 것이 좋다.
kubectl 설치
kubectl은 Kubernetes의 Cluster와 통신하여 다양한 Object들의 상태 확인 또는 CRUD 작업 등을 위해 사용되는 CLI 도구이다.
minikube 설치를 하고 Kubernetes Cluster와의 작업을 위해 필요하다.
여기서는 macOS에서 Homebrew를 사용하여 설치할 것이다.
brew install kubectl
다른 시스템에서는 공식 문서를 참고하면서 진행한다.
Minikube macOS에 설치
여기에서는 Homebrew를 사용해서 설치를 진행한다.
brew install minikube
% brew install minikube
Running `brew update --auto-update`...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
agg echidna kalign libplacebo shaderc
c gator kubesess licenseplist taplo
distrobox hof libff popeye vineyard
You have 3 outdated formulae installed.
You can upgrade them with brew upgrade
or list them with brew outdated.
==> Downloading https://ghcr.io/v2/homebrew/core/kubernetes-cli/manifests/1.25.0
######################################################################## 100.0%
... 중간 생략 ...
==> Summary
🍺 /opt/homebrew/Cellar/minikube/1.26.1: 9 files, 70.6MB
==> Running `brew cleanup minikube`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Caveats
==> minikube
zsh completions have been installed to:
/opt/homebrew/share/zsh/site-functions
Minikube 사용하기
Minikube cluster 시작
설치가 성공했는지 아래의 Kubernetes 클러스터를 시작하는 명령으로 확인하면 된다.
아래와 같이 쿠버네티스 버전을 입력해서 기동하는 방법이 있다.
minikube start --kubernetes-version [기동하려는 버전]
아래와 같이 지정하지 않으면 신규 버전이 기동된다.
minikube start
% minikube start
😄 Darwin 12.5.1 (arm64) 의 minikube v1.26.1
🆕 이제 1.24.3 버전의 쿠버네티스를 사용할 수 있습니다. 업그레이드를 원하신다면 다음과 같이 지정하세요: --kubernetes-version=v1.24.3
✨ 기존 프로필에 기반하여 docker 드라이버를 사용하는 중
👍 minikube 클러스터의 minikube 컨트롤 플레인 노드를 시작하는 중
🚜 베이스 이미지를 다운받는 중 ...
> gcr.io/k8s-minikube/kicbase: 0 B [______________________] ?% ? p/s 1m11s
🔥 Creating docker container (CPUs=2, Memory=4000MB) ...
> kubectl.sha1: 41 B / 41 B [---------------------------] 100.00% ? p/s 0s
> kubeadm.sha1: 41 B / 41 B [---------------------------] 100.00% ? p/s 0s
> kubelet.sha1: 41 B / 41 B [---------------------------] 100.00% ? p/s 0s
> kubectl: 42.64 MiB / 42.64 MiB [--------------] 100.00% 4.04 MiB p/s 11s
> kubeadm: 40.36 MiB / 40.36 MiB [--------------] 100.00% 2.69 MiB p/s 15s
> kubelet: 111.81 MiB / 111.81 MiB [------------] 100.00% 6.37 MiB p/s 18s
▪ 인증서 및 키를 생성하는 중 ...
▪ 컨트롤 플레인이 부팅...
💢 initialization failed, will try again: wait: /bin/bash -c "sudo env PATH="/var/lib/minikube/binaries/v1.16.1:$PATH" kubeadm init --config /var/tmp/minikube/kubeadm.yaml --ignore-preflight-errors=DirAvailable--etc-kubernetes-manifests,DirAvailable--var-lib-minikube,DirAvailable--var-lib-minikube-etcd,FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml,FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml,FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml,FileAvailable--etc-kubernetes-manifests-etcd.yaml,Port-10250,Swap,SystemVerification,FileContent--proc-sys-net-bridge-bridge-nf-call-iptables": Process exited with status 1
stdout:
[init] Using Kubernetes version: v1.16.1
[preflight] Running pre-flight checks
... 중간 생략 ...
stderr:
[WARNING Swap]: running with swap on is not supported. Please disable swap
[WARNING SystemVerification]: this Docker version is not on the list of validated versions: 20.10.17. Latest validated version: 18.09
[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher
💡 권장: Check output of 'journalctl -xeu kubelet', try passing --extra-config=kubelet.cgroup-driver=systemd to minikube start
🍿 관련 이슈: https://github.com/kubernetes/minikube/issues/4172
Minikube cluster 시작 후에 확인
minikube는 Docker image를 다운받고 실행하여, Kubernetes Cluster를 생성하고, kubectl
과의 연결을 위해 ~/.kube/config
파일 설정까지 완료해 준다.
하나씩 살펴보도록 하자.
minikube 시작 시 download 되는 docker image는 아래와 같이 확인 할 수 있다.
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gcr.io/k8s-minikube/kicbase v0.0.33 f7ba2bce4549 5 weeks ago 1.06GB
다운받은 docker image로 minikube container를 실행하여 kubernetes cluster 생성된 것을 확인 할수 잇다.
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d9391f64eba5 gcr.io/k8s-minikube/kicbase:v0.0.33 "/usr/local/bin/entr..." About an hour ago Up About an hour 0.0.0.0:49463->22/tcp, 0.0.0.0:49464->2376/tcp, 0.0.0.0:49466->5000/tcp, 0.0.0.0:49467->8443/tcp, 0.0.0.0:49465->32443/tcp minikube
Kubernetes Cluster와 Kubectl의 연결을 위한 정보가 담긴 config 파일 생성되었다.
% cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority: /Users/user/.minikube/ca.crt
extensions:
- extension:
last-update: Wed, 07 Sep 2022 11:56:39 KST
provider: minikube.sigs.k8s.io
version: v1.26.1
name: cluster_info
server: https://127.0.0.1:50472
name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
user:
client-certificate: /Users/user/.minikube/profiles/minikube/client.crt
client-key: /Users/user/.minikube/profiles/minikube/client.key
Minikube cluster 상태 확인
클러스터에 상태 확인하는 명령어는 아래와 같다.
minikube status
% minikube status
minikube
type: Control Plane
host: Running
kubelet: Stopped
apiserver: Stopped
kubeconfig: Configured
Minikube cluster 일시정지/재가동
kubernetes cluster를 일시정지하는 명령어는 아래와 같다.
minikube pause
일시정지 후에는 kubectl을 통한 Cluster의 접근이나 추가적인 명령어는 timeout이 발생하며 사용이 불가능하다.
단, 이미 배포된 application에는 영향을 미치지 않기 때문에 계속 동작한다.
일시정지 상태에서 다시 Cluster를 재가동 하고자 할때는 아래와 같은 명령어를 사용한다.
minikube unpause
Minikube cluster 종료
minikube stop
% minikube stop
✋ Stopping node "minikube" ...
🛑 Powering off "minikube" via SSH ...
🛑 1 node stopped.
Minikube cluster 삭제
minikube delete
모든 내용 삭제하는 초기화 명령은 아래와 같다.
% minikube delete --all
🔥 docker 의 "minikube" 를 삭제하는 중 ...
🔥 /Users/user/.minikube/machines/minikube 제거 중 ...
💀 "minikube" 클러스터 관련 정보가 모두 삭제되었습니다
🔥 모든 프로필이 성공적으로 삭제되었습니다
Kubernetes로 웹 서버 설정하여 기동하기
minikube를 설치하였으니, Kubernetes 환경을 만들고 컨테이너를 실행해 보도록 하자.
웹 서버는 Minikube에 해당하는 간단한 응답만 반환하는 echo-server를 사용하도록 하겠다.
minikube 클러스터 생성
그럼 minikube를 기동하여 클러스터를 생성한다. 이미 기동이 되어 있다면 다시 기동하지 않아도 된다.
minikube start
이때 도커 컨테이너의 기동되어 상태를 확인 한다.
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
39b6898f6256 gcr.io/k8s-minikube/kicbase:v0.0.33 "/usr/local/bin/entr..." About a minute ago Up About a minute 0.0.0.0:51435->22/tcp, 0.0.0.0:51436->2376/tcp, 0.0.0.0:51438->5000/tcp, 0.0.0.0:51439->8443/tcp, 0.0.0.0:51437->32443/tcp minikube
minikube의 컨테이너가 동작하고 있는 것을 확인 할 수 있다.
kubectl 사용하여 생성 배포
다음 kubectl에서 Kubernetes Deployment라는 것을 만든다. 이 Kubernetes Deployment 객체를 작성하는 것으로 어플리케이션을 실행할 수 있게 되었다. 이것은 YAML 파일로 작성할 수 있다. 이것 자체는 서비스라고 하는 것보다, Pod를 만들기 위한 Deployment의 앱인 것이다.
% kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10
deployment.apps/hello-minikube created
혹시, M1 맥북이라면 “echoserver:1.10"가 아닌 “echoserver-arm:1.8"를 사용해야 한다.
kubectl create deploy hello-minikube --image=k8s.gcr.io/echoserver-arm:1.8
생성된 hello-minikube Deployment를 사용하여 서비스로 노출시킨다. 여기가 실제 앱과 거의 동등한 것 같습니다.
% kubectl expose deployment hello-minikube --type=NodePort --port=8080
service/hello-minikube exposed
Pod에 배포된 생성 컨테이너 확인
이 시점에서 docker 컨테이너의 작동 상태를 확인해 보자.
% docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
24733d0fd443 gcr.io/k8s-minikube/kicbase:v0.0.33 "/usr/local/bin/entr..." 5 minutes ago Up 5 minutes 0.0.0.0:54248->22/tcp, 0.0.0.0:54249->2376/tcp, 0.0.0.0:54251->5000/tcp, 0.0.0.0:54247->8443/tcp, 0.0.0.0:54250->32443/tcp minikube
분명히 hello-minikube라는 컨테이너는 별도로 움직이지 않았으며, minikube의 컨테이너 위에 동작하는거 같다. 아마도 이 minikube 컨테이너 자체에 kubernetes의 단일 노드와 Pod, Deployment가 만들어진 것 같다.
그럼 Pod에 생겼는지 확인한다.
% kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-minikube-5d44b6b577-l99jz 1/1 Running 0 4m59s
STATUS가 Running이 되어 있고, 기동하고 있는 것을 확인할 수 있다. 또 “1/1"이라는 것으로 부터 Pod의 수는 1개라는 것도 알 수 있다.
서비스 동작 확인
서비스 URL은 아래와 같이 명령어로 확인 할 수 있다.
% minikube service hello-minikube --url
http://127.0.0.1:54612
브라우저에서 확인해 보면, 어플리케이션이 실행 중인 것을 확인할 수 있다.
삭제
다음은 삭제 절차이다.
서비스 삭제는 아래와 같은 명령어로 진행한다.
% kubectl delete services hello-minikube
service "hello-minikube" deleted
hello-minikube Deployment 삭제는 아래와 같은 명령어로 진행한다.
% kubectl delete deployment hello-minikube
deployment.apps "hello-minikube" deleted
부록: 컨테이너 안을 들여다 보기
공식 문서에 있던 로컬 개발 환경을 만드는 튜토리얼은 이 정도로 끝이지만, 컨테이너 안을 들여다 보려고 한다.
아래 명령으로 minikube에 들어가 본다.
% docker exec -itu 0 minikube /bin/bash
root@minikube:/#
컨테이너에 들어가면 루트 디렉터리에 들어가서 뭐가 있는지, 루트 디렉터리에서 ll
명령어를 실행해 보자.
root@minikube:/# ll
total 80
drwxr-xr-x 1 root root 4096 Sep 7 06:33 ./
drwxr-xr-x 1 root root 4096 Sep 7 06:33 ../
-rwxr-xr-x 1 root root 0 Sep 7 06:33 .dockerenv*
-rw-r--r-- 1 root root 1093 Jul 29 17:41 Release.key
lrwxrwxrwx 1 root root 7 May 31 15:55 bin -> usr/bin/
drwxr-xr-x 2 root root 4096 Apr 15 2020 boot/
drwxr-xr-x 2 root root 4096 Sep 7 06:33 data/
drwxr-xr-x 9 root root 2820 Sep 7 06:33 dev/
-rw-r--r-- 1 root root 3817 Jul 29 17:36 docker.key
drwxr-xr-x 1 root root 4096 Sep 7 06:33 etc/
drwxr-xr-x 1 root root 4096 Jul 29 17:43 home/
-rw-r--r-- 1 root root 96 Jul 29 17:43 kic.txt
drwxr-xr-x 1 root root 4096 Sep 7 06:33 kind/
lrwxrwxrwx 1 root root 7 May 31 15:55 lib -> usr/lib/
drwxr-xr-x 2 root root 4096 May 31 15:55 media/
drwxr-xr-x 2 root root 4096 May 31 15:55 mnt/
drwxr-xr-x 1 root root 4096 Sep 7 06:33 opt/
dr-xr-xr-x 231 root root 0 Sep 7 06:33 proc/
drwx------ 1 root root 4096 Sep 7 06:33 root/
drwxr-xr-x 13 root root 360 Sep 7 06:33 run/
lrwxrwxrwx 1 root root 8 May 31 15:55 sbin -> usr/sbin/
drwxr-xr-x 2 root root 4096 May 31 15:55 srv/
dr-xr-xr-x 13 root root 0 Sep 7 06:33 sys/
drwxrwxrwt 5 root root 140 Sep 7 06:33 tmp/
drwxr-xr-x 1 root root 4096 Jul 29 17:37 usr/
drwxr-xr-x 14 root root 4096 Sep 7 06:33 var/
root@minikube:/#
top
명령어로 프로세스도 확인해 보자.
root@minikube:/# top
top - 07:23:51 up 18:40, 0 users, load average: 0.69, 0.44, 0.37
Tasks: 38 total, 1 running, 37 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.5 us, 2.7 sy, 0.0 ni, 94.6 id, 0.1 wa, 0.0 hi, 0.1 si, 0.0 st
MiB Mem : 7851.4 total, 1617.5 free, 972.4 used, 5261.4 buff/cache
MiB Swap: 1024.0 total, 1024.0 free, 0.0 used. 6346.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1855 root 20 0 1998680 100428 64300 S 7.6 1.2 3:17.60 kubelet
1675 root 20 0 1171496 360280 72324 S 7.3 4.5 5:20.97 kube-apiserver
588 root 20 0 2028192 91008 44340 S 5.3 1.1 1:24.24 dockerd
106 root 20 0 1565148 57832 31212 S 3.7 0.7 1:02.06 containerd
760 root 20 0 740472 40728 24740 S 3.7 0.5 1:13.45 cri-dockerd
1615 root 20 0 815700 99604 61428 S 3.7 1.2 2:37.76 kube-controller
1662 root 20 0 10.7g 50516 20972 S 3.3 0.6 2:20.11 etcd
1669 root 20 0 751044 47684 34416 S 1.0 0.6 0:21.92 kube-scheduler
1586 root 20 0 712636 10432 7852 S 0.7 0.1 0:02.20 containerd-shim
1549 root 20 0 712636 9956 7340 S 0.3 0.1 0:02.04 containerd-shim
1583 root 20 0 712380 10312 7596 S 0.3 0.1 0:02.08 containerd-shim
1634 root 20 0 712380 10328 7404 S 0.3 0.1 0:02.10 containerd-shim
2162 root 20 0 712636 10304 7532 S 0.3 0.1 0:03.02 containerd-shim
2182 root 20 0 750988 44096 32876 S 0.3 0.5 0:15.10 coredns
... 이하 생략 ...
콘솔 내용을 보면 상위에 kubelet
과 kube-apiserver
의 프로세스가 실행되고 있다.
kube-apiserver
는 개발자로부터의 작업을 수락하는 API를 제공하며, kubelet
은 에이전트로 각 노드(이번에는 단일 노드)에 있으며, Pod 실행을 보장한다.
containered*
로 작성된 많은 프로세스가 있는데, 여러 컨테이너가 올라가 있음을 알 수 있다.
이제 또 docker ps
명령어로 실행되고 있느 도커 컨테이너 목록 조회해 보자.
root@minikube:/# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
20094df9033f ba04bb24b957 "/storage-provisioner" 59 minutes ago Up 59 minutes k8s_storage-provisioner_storage-provisioner_kube-system_514497a4-deaf-4755-a600-73f796f6be9e_1
a9368295b1f7 7a75aeb869dc "/usr/local/bin/kube..." 59 minutes ago Up 59 minutes k8s_kube-proxy_kube-proxy-52hmm_kube-system_d0ed4ddc-0ccc-4f06-aeb9-cc18d5184e77_0
9b1f9ed7a6c1 k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_kube-proxy-52hmm_kube-system_d0ed4ddc-0ccc-4f06-aeb9-cc18d5184e77_0
a7bd350916bd k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_storage-provisioner_kube-system_514497a4-deaf-4755-a600-73f796f6be9e_0
d96748e31b07 edaa71f2aee8 "/coredns -conf /etc..." 59 minutes ago Up 59 minutes k8s_coredns_coredns-6d4b75cb6d-8kr7r_kube-system_9c240144-c6cc-4d22-984b-3ea3c0756ea2_0
15ad9748eb82 k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_coredns-6d4b75cb6d-8kr7r_kube-system_9c240144-c6cc-4d22-984b-3ea3c0756ea2_0
8ffe4e9bf3b5 531fdfc5fea6 "kube-apiserver --ad..." 59 minutes ago Up 59 minutes k8s_kube-apiserver_kube-apiserver-minikube_kube-system_af8a252bb89a737e9c95199d01283487_0
ff7b78b958a0 8f1507b1a173 "kube-scheduler --au..." 59 minutes ago Up 59 minutes k8s_kube-scheduler_kube-scheduler-minikube_kube-system_2e95d5efbc70e877d20097c03ba4ff89_0
d7366714e112 a9a710bb96df "etcd --advertise-cl..." 59 minutes ago Up 59 minutes k8s_etcd_etcd-minikube_kube-system_906edd533192a4db2396a938662a5271_0
2beb89ca5127 f98535efcd55 "kube-controller-man..." 59 minutes ago Up 59 minutes k8s_kube-controller-manager_kube-controller-manager-minikube_kube-system_76444121a189d8a30add20fb32ab6d4e_0
24a244ecac48 k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_etcd-minikube_kube-system_906edd533192a4db2396a938662a5271_0
5ee0a82c5478 k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_kube-controller-manager-minikube_kube-system_76444121a189d8a30add20fb32ab6d4e_0
bea7e607e058 k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_kube-apiserver-minikube_kube-system_af8a252bb89a737e9c95199d01283487_0
c126a82b0d93 k8s.gcr.io/pause:3.6 "/pause" 59 minutes ago Up 59 minutes k8s_POD_kube-scheduler-minikube_kube-system_2e95d5efbc70e877d20097c03ba4ff89_0
root@minikube:/#
컨테이너 내에서 컨테이너의 가동을 처음해 봤는데, 이것으로 echoserver의 이미지를 사용한 컨테이너가 움직이고 있는 것을 알았다.
가설이지만 NAMES
를 보면, POD
라는 문자가 쓰여 있는 컨테이너가 있고, Pod를 컨테이너로 표현하고 있는 것으로 생각된다.
kube-proxy
의 컨테이너도 있는 것 같고, 이 녀석이 Service의 프록시로서 움직이고 있는 것 같다.
이번은 여기까지 이지만, 다음번은 좀 더 Kubernetes의 아키텍처와 설정을 바꾸어 가면서 어떻게 동작하는지 보도록 하겠다.