🫠

minikubeでKubernetesの基礎から学ぶ

2024/02/13に公開

概要

こんにちは🙌
業務にあたり、Kubernetesを迅速に学ぶ必要があるため、まずは、Kubernetes公式ドキュメントで用意されているチュートリアルに沿っての学習を進めることにしました。

進めるにあたっての個人的に集めたTips等も載せていきます。

チュートリアルは、以下ページとなります。
Kubernetes Documentation/Tutorials

目的

自身のアウトプットをメインの目的としています。
また、同じような箇所で詰まった方の助けになったらと書き記します。

環境

PC MacBook Pro 2023
チップ Apple M2 Pro
メモリ 32GB
OS macOS Ventura13.4

mikube実行ためのシステム要件

  • 2 CPUs or more
  • 2GB of free memory
  • 20GB of free disk space
  • Internet connection
  • Container or virtual machine manager, such as: Docker, QEMU, Hyperkit, Hyper-V, KVM, Parallels, Podman, VirtualBox, or VMware Fusion/Workstation

※ インストール方法は、次のリンクに記載があります。
minikube start

minikubeのバージョンを確認しておきます。

$ minikube version
minikube version: v1.32.0

Create Cluster(クラスターの作成)

まずはサンプルアプリケーションを動かす方法となります。

Deploymentの作成

  1. minikubeのクラスターを起動していきます。
$ minikube start
😄  Darwin 13.4 (arm64) 上の minikube v1.32.0
✨  既存のプロファイルを元に、docker ドライバーを使用します
👍  minikube クラスター中のコントロールプレーンの minikube ノードを起動しています
🚜  ベースイメージを取得しています...
🏃  実行中の docker 「minikube」 container を更新しています...
🐳  Docker 24.0.7 で Kubernetes v1.28.3 を準備しています...
🔎  Kubernetes コンポーネントを検証しています...
  1. ダッシュボードを開いてみます。
    ダッシュボードでは、コンテナ化されたアプリケーションをKubernetesクラスターにデプロイしたり、クラスタ内のリソースを視覚的に確認、管理することができます。
$ minikube dashboard
🤔  ダッシュボードの状態を検証しています...
🚀  プロキシーを起動しています...
🤔  プロキシーの状態を検証しています...
🎉  デフォルトブラウザーで http://127.0.0.1:51024/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ を開いています...

  1. Podを管理するためのDeloymentを作成します。
    Podでは、指定したコンテナイメージが実行されます。
    Deploymentを作成したことによって、Podの状態を監視し、Podのコンテナが停止した時には、台数を維持するように再起動するような動きとなります。
$ kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port=8080
deployment.apps/hello-node created
  1. Deployment、Podを確認します。
$ kubectl get deployments
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
hello-node   1/1     1            1           15s
$ kubectl get pods
NAME                         READY   STATUS    RESTARTS   AGE
hello-node-ccf4b9788-kdnkr   1/1     Running   0          30s

Serviceの作成

  1. Serviceを作成します。
    デフォルトの状態だと、PodはKubernetesクラスター内部からのみのアクセスが可能な状態となっています。
    コンテナにアクセスするためには、ServiceとしてPodを公開する必要があります。
$ kubectl expose deployment hello-node --type=LoadBalancer --port=8080
service/hello-node exposed
  1. サービスにアクセスするためのURLを取得して、ブラウザで開きます。
$ minikube service hello-node
|-----------|------------|-------------|---------------------------|
| NAMESPACE |    NAME    | TARGET PORT |            URL            |
|-----------|------------|-------------|---------------------------|
| default   | hello-node |        8080 | http://192.168.49.2:31814 |
|-----------|------------|-------------|---------------------------|
🏃  hello-node サービス用のトンネルを起動しています。
|-----------|------------|-------------|------------------------|
| NAMESPACE |    NAME    | TARGET PORT |          URL           |
|-----------|------------|-------------|------------------------|
| default   | hello-node |             | http://127.0.0.1:51862 |
|-----------|------------|-------------|------------------------|
🎉  デフォルトブラウザーで default/hello-node サービスを開いています...
❗  Docker ドライバーを darwin 上で使用しているため、実行するにはターミナルを開く必要があります。

アクセスした時刻を表示するような画面が表示されるかと思います。

アドオンの有効化

  1. metrics-serverのアドオンを有効化してみます。
    メトリクスサーバは、クラスター内のリソース使用状況データを取得するために利用されます。
$ minikube addons enable metrics-server
💡  metrics-server is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
    ▪ registry.k8s.io/metrics-server/metrics-server:v0.6.4 イメージを使用しています
🌟  'metrics-server' アドオンが有効です
$ kubectl get pod,svc -n kube-system
NAME                                   READY   STATUS    RESTARTS      AGE
pod/metrics-server-7c66d45ddc-6dbdz    1/1     Running   0             2m59s
NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                  AGE
service/metrics-server   ClusterIP   10.101.235.248   <none>        443/TCP                  2m59s

これで、Create Cluster(クラスターの作成)が終わりました。

Deploy an App(アプリケーションのデプロイ)

アプリケーションをKubernetesにデプロイする方法となります。

  • Deploymentとは
    前のチュートリアルCreate Clusterの中でもDeploymentについて書きましたが、コンテナ化されたアプリケーションのインスタンスをKubernetes上に作成し、ノードで実行するようにスケジュールされることとなります。
    Deploymentは、それらのインスタンスを監視し、ホストしているノードが停止、削除された場合に、クラスター内の別ノードのインスタンスと置き換えるような動作(セルフヒーリング)となります。
  1. デプロイメントの作成をします。
$ kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
deployment.apps/kubernetes-bootcamp created
$ kubectl get pod
NAME                                  READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-f95c5b745-zxh9m   1/1     Running   0          31s
$ kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   40s
  1. Kubernetesクラスタ内へアクセスするためにproxyを使用します。
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
$ curl http://localhost:8001/version
{
  "major": "1",
  "minor": "28",
  "gitVersion": "v1.28.3",
  "gitCommit": "a8a1abc25cad87333840cd7d54be2efaf31a3177",
  "gitTreeState": "clean",
  "buildDate": "2023-10-18T11:33:18Z",
  "goVersion": "go1.20.10",
  "compiler": "gc",
  "platform": "linux/arm64"
}%

これで、Deoloy an App(アプリケーションのデプロイ)が完了です。

Explorer Your App(アプリケーションの探索)

デプロイしたアプリケーションとその環境の情報を取得していきます。

  1. podの情報を取得してみます。
$ kubectl get pods
NAME                                  READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-f95c5b745-b6gtz   1/1     Running   0          12s
$ kubectl describe pods
Name:             kubernetes-bootcamp-f95c5b745-b6gtz
Namespace:        default
Priority:         0
Service Account:  default
Node:             minikube/192.168.49.2
Start Time:       xxxxxxxxx
Labels:           app=kubernetes-bootcamp
                  pod-template-hash=f95c5b745
Annotations:      <none>
Status:           Running
IP:               10.244.0.4
.....
  1. アプリケーションへアクセスします。
    ここでもクラスタ内へのアクセスが必要になるため、kubectl proxyから実行していきます。
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
# POD_NAME環境変数を設定します。
$ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
# アプリケーションにアクセスしてみます。
$ curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-f95c5b745-b6gtz | v=1
.....
  1. コンテナログを確認します。
$ kubectl logs "$POD_NAME"
Kubernetes Bootcamp App Started At: xxxxxxxx | Running On:  kubernetes-bootcamp-f95c5b745-b6gtz

Running On: kubernetes-bootcamp-f95c5b745-b6gtz | Total Requests: 1 | App Uptime: 62.79 seconds | Log Time: xxxxxxxx
  1. コンテナでコマンドを実行します。
$ kubectl exec "$POD_NAME" -- env
<設定されている環境変数が表示されます。>
# bashのセッションを開始します。
$ kubectl exec -ti $POD_NAME -- bash
root@kubernetes-bootcamp-f95c5b745-b6gtz:/# cat server.js
var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;
.....

アプリケーションの情報を取得、コンテナに入ってコマンドが実行できることまで確認ができました。

Expose Your App(アプリケーションの公開)

ここではServiceを使って、アプリケーションの公開をしていきます。
Serviceはラベルとセレクタを使って、Podを照合するような動作をします。

  1. 新しいサービスを作り、exposeコマンドで公開をします。
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
$ kubectl get services
NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1        <none>        443/TCP          10m
kubernetes-bootcamp   NodePort    10.106.214.150   <none>        8080:30852/TCP   4s # これが新しく作られたサービス
  1. どのポートで公開されているのか確認します。
$ kubectl describe services/kubernetes-bootcamp
.....
NodePort:                 <unset>  30852/TCP
.....
# NodePort が公開されたポートとなります。
  1. アクセスしてみます。
$ export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"
NODE_PORT=30852
$ curl http://"$(minikube ip):$NODE_PORT"
# 試してみた結果、私の環境では、アクセスできませんでした。
# チュートリアル上では、`minikube service kubernetes-bootcamp --url`となっていますが、--urlを付けないほうが結果から動きが分かりやすかったので、オプションは外しています。
$ minikube service kubernetes-bootcamp
|-----------|---------------------|-------------|---------------------------|
| NAMESPACE |        NAME         | TARGET PORT |            URL            |
|-----------|---------------------|-------------|---------------------------|
| default   | kubernetes-bootcamp |        8080 | http://192.168.49.2:30852 |
|-----------|---------------------|-------------|---------------------------|
🏃  kubernetes-bootcamp サービス用のトンネルを起動しています。
|-----------|---------------------|-------------|------------------------|
| NAMESPACE |        NAME         | TARGET PORT |          URL           |
|-----------|---------------------|-------------|------------------------|
| default   | kubernetes-bootcamp |             | http://127.0.0.1:56420 |
|-----------|---------------------|-------------|------------------------|
🎉  デフォルトブラウザーで default/kubernetes-bootcamp サービスを開いています...
❗  Docker ドライバーを darwin 上で使用しているため、実行するにはターミナルを開く必要があります。
# ブラウザが勝手に開いて、URLにアクセスしに行きます。これでアクセスすることができました。
  1. ラベルを使っていきます。
    ラベルはPodなどのオブジェクトに割り当てられたキーとバリューのペアのことです。
    ラベルを使うことによって、オブジェクトを識別し、グルーピングしたりすることができます。
# podの名前を環境変数`POD_NAME`に取得します。
$ export POD_NAME="$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')"
echo "Name of the Pod: $POD_NAME"
Name of the Pod: kubernetes-bootcamp-f95c5b745-b6gtz
# podに`version=v1`というラベルを付けます。
$ kubectl label pods "$POD_NAME" version=v1
pod/kubernetes-bootcamp-f95c5b745-b6gtz labeled
$ kubectl describe pods "$POD_NAME"
.....
Labels:           app=kubernetes-bootcamp
                  pod-template-hash=f95c5b745
                  version=v1
.....
  1. Serviceを削除します。
$ kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

これで、Expose Your App Publicly(アプリケーションの公開)が完了となります。

Scale Your App(アプリケーションのスケーリング)

ここでは、複数インスタンスでアプリケーションを起動させていきます。
また、複数インスタンスにトラフィックを分散するためのロードバランサも使ってみます。

  1. レプリカ数を確認します。
    Deploymentを作成した時点で、ReplicaSetも作成がされています。
    ReplicaSetとは、稼働させたいPodのレプリカ数を維持管理するためのオブジェクトとなっています。
    ここまで進めた状態であれば、レプリカ数の値は全て1になっています。
$ kubectl get rs
NAME                            DESIRED   CURRENT   READY   AGE
kubernetes-bootcamp-f95c5b745   1         1         1       40m
  1. アプリケーションをスケールします。
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   4/4     4            4           48m
$ kubectl get pods -o wide
NAME                                  READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-f95c5b745-b6gtz   1/1     Running   0          48m   10.244.0.4   minikube   <none>           <none>
kubernetes-bootcamp-f95c5b745-kwr9k   1/1     Running   0          18s     10.244.0.6   minikube   <none>           <none>
kubernetes-bootcamp-f95c5b745-vj5df   1/1     Running   0          18s     10.244.0.5   minikube   <none>           <none>
kubernetes-bootcamp-f95c5b745-w5lbq   1/1     Running   0          18s     10.244.0.7   minikube   <none>           <none>

kubectl scaleコマンドを使うことによって、簡単にPodをスケールすることができました。

  1. ロードバランサを試してみます。
    サービスを削除している場合、再度作成しておきます。
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
$ export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"
$ minikube service kubernetes-bootcamp --url
http://127.0.0.1:57072

$ curl http://127.0.0.1:57072
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-f95c5b745-kwr9k | v=1
$ curl http://127.0.0.1:57072
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-f95c5b745-b6gtz | v=1
$ curl http://127.0.0.1:57072
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-f95c5b745-w5lbq | v=1

リクエストごとに、異なるPodにアクセスしに行くことを確認ができました。
Serviceによって、内部的にトラフィックを複数のPodに対して分散させるような動きを確認することができたかと思います。Serviceは実行中のPodを継続的に監視して、使用可能なPodのみにトラフィックを送信します。

  1. アプリケーションのスケールダウンをします。
$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment.apps/kubernetes-bootcamp scaled
# Podの数を確認してみます。
$ kubectl get pods -o wide
NAME                                  READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-f95c5b745-b6gtz   1/1     Running   0          1h26m   10.244.0.4   minikube   <none>           <none>
kubernetes-bootcamp-f95c5b745-vj5df   1/1     Running   0          38m     10.244.0.5   minikube   <none>           <none>

これで、Scale Your App(アプリケーションのスケール)が完了となります。

Update Your App(アプリケーションのアップデート)

Kubernetesでは、アプリケーションのアップデートをローリングアップデートで行います。つまり、Podを段階的にアップデートしていくことで、ダウンタイムなしでDeploymentをアップデートすることができます。

  1. imageの更新をします。
    元々起動していた、2つのPodがTerminatingとなり、新たに2つのPodが起動してきています。
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2
deployment.apps/kubernetes-bootcamp image updated
$ kubectl get pods
NAME                                   READY   STATUS        RESTARTS   AGE
kubernetes-bootcamp-65df967b7f-8x8dm   1/1     Running       0          11s
kubernetes-bootcamp-65df967b7f-qt8zz   1/1     Running       0          16s
kubernetes-bootcamp-f95c5b745-b6gtz    1/1     Terminating   0          1h43m
kubernetes-bootcamp-f95c5b745-vj5df    1/1     Terminating   0          55m
  1. 更新を確認します。
# 環境変数を設定します。
$ export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo "NODE_PORT=$NODE_PORT"
NODE_PORT=30852
$ minikube service kubernetes-bootcamp --url
http://127.0.0.1:57699

# 先程までと違う結果が2つのPodから返ってきています。
$ curl http://127.0.0.1:57699
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-65df967b7f-8x8dm | v=2
$ curl http://127.0.0.1:57699
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-65df967b7f-qt8zz | v=2

# ロールアウトのステータスも確認してみます。
$ kubectl rollout status deployments/kubernetes-bootcamp
deployment "kubernetes-bootcamp" successfully rolled out
  1. アップデートのロールバックをします。
# 新しいイメージで更新を試みます。
$ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
deployment.apps/kubernetes-bootcamp image updated
# Podを確認してみます。
$ kubectl get pods
NAME                                   READY   STATUS         RESTARTS   AGE
kubernetes-bootcamp-65df967b7f-8x8dm   1/1     Running        0          9m19s
kubernetes-bootcamp-65df967b7f-qt8zz   1/1     Running        0          9m24s
kubernetes-bootcamp-7497bc6797-klwwr   0/1     ErrImagePull   0          13s

PodのSTATUSがエラーになっていますので、イメージを戻してみます。

$ kubectl rollout undo deployments/kubernetes-bootcamp
deployment.apps/kubernetes-bootcamp rolled back
$ kubectl get pods
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-65df967b7f-8x8dm   1/1     Running   0          13m
kubernetes-bootcamp-65df967b7f-qt8zz   1/1     Running   0          13m
$ kubectl describe pods
.....
Containers:
  kubernetes-bootcamp:
    Container ID:   docker://8a1137c04d9b4ad4d708d65962623b19aa89543378c86a1a6f4f9b890fda3464
    Image:          jocatalin/kubernetes-bootcamp:v2
.....

もともとのイメージであった、v2でコンテナが起動されていることを確認できました。
以上で、Update Your App(アプリケーションのアップデート)が完了となります。

おわりに

チュートリアルということで、入門としてKubernetesの最低限の仕組み、動き方、用語を知るのに非常に適した教材であったかと思います。
以前は、Katacodeを使ってウェブ上で試すことができたようですが、現時点では日本語版の埋め込みの対話型チュートリアルは使えないようになっています。
代わりとしてKillercodeといったサービスが出てきているようなので、次回はそれを使ってKubernetesともっと仲良くなれるように遊んでみます。

ありがとうございました🙌

Discussion