Creating a Local Kubernetes Development Environment - Installing and Using minikube

Creating a local development environment and running an application

This time, the goal is to run a web application container on local Kubernetes.

For reference, this article focuses on installation on macOS. The method may differ depending on your environment.

Installing and using Minikube

This time, use Minikube, a tool that makes it easy to run Kubernetes in a local environment. With this tool, you can create a single-node Kubernetes cluster.
For how to use Minikube, refer to the official documentation.

Preparation before installation

Install Docker

Before installing minikube, it is strongly recommended to install and use Docker.

Install kubectl

kubectl is a CLI tool used to communicate with a Kubernetes cluster and check the status of various objects or perform CRUD operations.
It is needed after installing minikube to work with the Kubernetes cluster.

Here, install it on macOS using Homebrew.

brew install kubectl

For other systems, proceed while referring to the official documentation.

Install Minikube on macOS

Here, install it with 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%

... middle omitted ...

==> 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

Using Minikube

Start a Minikube cluster

Check whether installation succeeded with the following command that starts a Kubernetes cluster.

You can start it by specifying a Kubernetes version as follows.

minikube start --kubernetes-version [version to start]

If you do not specify a version, the new version starts.

minikube start
% minikube start
😄  Darwin 12.5.1 (arm64) 의 minikube v1.26.1
🆕  이제 1.24.3 버전의 쿠버네티스를 사용할 수 있습니다. 업그레이드를 원하신다면 다음과 같이 지정하세요: --kubernetes-version=v1.24.3
✨  기존 프로필에 기반하여 docker 드라이버를 사용하는 중
👍  minikube 클러스터의 minikube 컨트롤 플레인 노드를 시작하는 중
🚜  베이스 이미지를 다운받는 중 ...

... middle omitted ...

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

Check after starting the Minikube cluster

Minikube downloads and runs a Docker image, creates a Kubernetes cluster, and completes the ~/.kube/config file configuration for connecting with kubectl. Let’s look at each item.

The Docker image downloaded when minikube starts can be checked as follows.

% docker images
REPOSITORY                    TAG       IMAGE ID       CREATED        SIZE
gcr.io/k8s-minikube/kicbase   v0.0.33   f7ba2bce4549   5 weeks ago    1.06GB

You can confirm that the minikube container was started from the downloaded Docker image and a Kubernetes cluster was created.

% 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

A config file containing information for connecting Kubernetes Cluster and kubectl has been created.

% cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority: /Users/user/.minikube/ca.crt
    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

Check Minikube cluster status

The command to check the cluster status is as follows.

minikube status
% minikube status
minikube
type: Control Plane
host: Running
kubelet: Stopped
apiserver: Stopped
kubeconfig: Configured

Pause and resume a Minikube cluster

The command to pause a Kubernetes cluster is as follows.

minikube pause

After pausing, access to the cluster through kubectl and additional commands time out and cannot be used.
However, already deployed applications are not affected and continue running.

To resume the cluster from the paused state, use the following command.

minikube unpause

Stop a Minikube cluster

minikube stop
% minikube stop
✋  Stopping node "minikube"  ...
🛑  Powering off "minikube" via SSH ...
🛑  1 node stopped.

Delete a Minikube cluster

minikube delete

The command to initialize and delete everything is as follows.

% minikube delete --all
🔥  docker 의 "minikube" 를 삭제하는 중 ...
🔥  /Users/user/.minikube/machines/minikube 제거 중 ...
💀  "minikube" 클러스터 관련 정보가 모두 삭제되었습니다
🔥  모든 프로필이 성공적으로 삭제되었습니다

Configure and start a web server with Kubernetes

Now that minikube is installed, create a Kubernetes environment and run a container.

For the web server, use echo-server, which returns a simple response suitable for Minikube.

Create a minikube cluster

Start minikube and create a cluster. If it is already running, you do not need to start it again.

minikube start

Check the running state of the Docker container.

% 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

You can confirm that the minikube container is running.

Create a deployment using kubectl

Next, create a Kubernetes Deployment with kubectl. By creating this Kubernetes Deployment object, the application can be run. It can be written as a YAML file. This itself is not exactly a service, but the Deployment app for creating Pods.

% kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10
deployment.apps/hello-minikube created

If you are using an M1 MacBook, use echoserver-arm:1.8 instead of echoserver:1.10.

kubectl create deploy hello-minikube --image=k8s.gcr.io/echoserver-arm:1.8

Expose the created hello-minikube Deployment as a service. This seems almost equivalent to the actual app.

% kubectl expose deployment hello-minikube --type=NodePort --port=8080
service/hello-minikube exposed

Check the container deployed to the Pod

At this point, check the Docker container status.

% 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

There is no separate container named hello-minikube; it appears to run on top of the minikube container. Presumably, the single Kubernetes node, Pods, and Deployment were created inside this minikube container.

Check whether a Pod was created.

% kubectl get pod
NAME                              READY   STATUS    RESTARTS   AGE
hello-minikube-5d44b6b577-l99jz   1/1     Running   0          4m59s

The STATUS is Running, so it is running. Also, 1/1 shows that there is one Pod.

Check service operation

The service URL can be checked with the following command.

% minikube service hello-minikube --url
http://127.0.0.1:54612

If you check it in a browser, you can confirm that the application is running.

echoserver

Delete

The following is the deletion procedure.

Delete the service with the following command.

% kubectl delete services hello-minikube
service "hello-minikube" deleted

Delete the hello-minikube Deployment with the following command.

% kubectl delete deployment hello-minikube
deployment.apps "hello-minikube" deleted

Appendix: looking inside the container

The official-document tutorial for creating a local development environment ends around here, but let’s look inside the container.

Enter minikube with the following command.

% docker exec -itu 0 minikube /bin/bash
root@minikube:/#

After entering the container, go to the root directory and run ll to see what is there.

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*
... omitted ...
drwxr-xr-x  14 root root 4096 Sep  7 06:33 var/
root@minikube:/#

Check processes with the top command.

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

    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

   ... omitted ...

The console output shows that kubelet and kube-apiserver processes are running near the top.

kube-apiserver provides an API that accepts operations from developers, and kubelet exists as an agent on each node, in this case a single node, and ensures Pod execution.
There are many processes written as containerd*, showing that several containers are running.

Now list the running Docker containers again with 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
... omitted ...
root@minikube:/#

This was the first time checking containers running inside a container, and it showed that containers using the echoserver image were running.

As a hypothesis, looking at NAMES, there are containers with the string POD, so Pods seem to be represented as containers.
There also appears to be a kube-proxy container, which seems to operate as a proxy for Services.

This is all for this time. Next time, we will look at Kubernetes architecture and how it behaves while changing settings.

References