minikubeでKubernetesの基礎から学ぶ
概要
こんにちは🙌
業務にあたり、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の作成
- 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 コンポーネントを検証しています...
- ダッシュボードを開いてみます。
ダッシュボードでは、コンテナ化されたアプリケーションをKubernetesクラスターにデプロイしたり、クラスタ内のリソースを視覚的に確認、管理することができます。
$ minikube dashboard
🤔 ダッシュボードの状態を検証しています...
🚀 プロキシーを起動しています...
🤔 プロキシーの状態を検証しています...
🎉 デフォルトブラウザーで http://127.0.0.1:51024/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ を開いています...
- 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
- 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の作成
- Serviceを作成します。
デフォルトの状態だと、PodはKubernetesクラスター内部からのみのアクセスが可能な状態となっています。
コンテナにアクセスするためには、ServiceとしてPodを公開する必要があります。
$ kubectl expose deployment hello-node --type=LoadBalancer --port=8080
service/hello-node exposed
- サービスにアクセスするための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 上で使用しているため、実行するにはターミナルを開く必要があります。
アクセスした時刻を表示するような画面が表示されるかと思います。
アドオンの有効化
-
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は、それらのインスタンスを監視し、ホストしているノードが停止、削除された場合に、クラスター内の別ノードのインスタンスと置き換えるような動作(セルフヒーリング)となります。
- デプロイメントの作成をします。
$ 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
- 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(アプリケーションの探索)
デプロイしたアプリケーションとその環境の情報を取得していきます。
- 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
.....
- アプリケーションへアクセスします。
ここでもクラスタ内へのアクセスが必要になるため、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
.....
- コンテナログを確認します。
$ 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
- コンテナでコマンドを実行します。
$ 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を照合するような動作をします。
- 新しいサービスを作り、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 # これが新しく作られたサービス
- どのポートで公開されているのか確認します。
$ kubectl describe services/kubernetes-bootcamp
.....
NodePort: <unset> 30852/TCP
.....
# NodePort が公開されたポートとなります。
- アクセスしてみます。
$ 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にアクセスしに行きます。これでアクセスすることができました。
- ラベルを使っていきます。
ラベルは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
.....
- Serviceを削除します。
$ kubectl delete service -l app=kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
これで、Expose Your App Publicly(アプリケーションの公開)が完了となります。
Scale Your App(アプリケーションのスケーリング)
ここでは、複数インスタンスでアプリケーションを起動させていきます。
また、複数インスタンスにトラフィックを分散するためのロードバランサも使ってみます。
- レプリカ数を確認します。
Deploymentを作成した時点で、ReplicaSetも作成がされています。
ReplicaSetとは、稼働させたいPodのレプリカ数を維持管理するためのオブジェクトとなっています。
ここまで進めた状態であれば、レプリカ数の値は全て1になっています。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
kubernetes-bootcamp-f95c5b745 1 1 1 40m
- アプリケーションをスケールします。
$ 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をスケールすることができました。
- ロードバランサを試してみます。
サービスを削除している場合、再度作成しておきます。
$ 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のみにトラフィックを送信します。
- アプリケーションのスケールダウンをします。
$ 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をアップデートすることができます。
- 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
- 更新を確認します。
# 環境変数を設定します。
$ 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
- アップデートのロールバックをします。
# 新しいイメージで更新を試みます。
$ 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