➊ はじめに
Kubernetes?クバァ~...?なんて読むんだ?読めない………😓
呼び方分からないし、なんか内容も難しそうだし、見てみないフリをしていましたが、周りでは使っている人もチラホラ。分からないから逃げるではなく、ここは勇気を出して、一歩進んでみます!このハンズオンが終わることには、Kubernetesの呼び方も分かるようになっているでしょう😁
それでは、「クバァ~...?という人のためのハンズオン」初めましょう!
➋ クバァ~...?
クバァ~🤔❓の基本について、簡単に調査していきたいと思います。
(1) Kubernetesとは
⬢ 呼び名
Kubernetesは、クバネティス、クバネテス、クーべネティスなど呼び方がいくつかあるようです。私は、「クバネティス
」と呼ぶことにしました(どうでも良いですね)。Kubernetesは、ギリシャ語で航海長、または水先案内人を意味するようです。
⬢ 何をするもの?
Kubernetesの役割は、簡単に言うとコンテナ化したアプリケーションのデプロイ、スケーリング等の管理を行うものです。ここまで分かると、きちんと意図したネーミングだということが分かります。ちなみに「K8s
」と略されることもあります。
(2) 今回やるもの
更に知識を高めるために、Kubernetesをハンズオンしながらお勉強していきたいと思います。まずは、ローカル環境でKubernetesを動かすための「Minikube
」というツールがあるので、それを使って超初心者から初心者への階段を上りたいと思います。
➌ お勉強
「Minikube
」やる前に、覚える必要がある用語が色々あります。まずは、こちらを簡単に勉強していきましょう。以下の表は、かいつまんで記載しました。
⬢ 全体概要
用語 | 概要 |
---|---|
Kubernetes(K8s) | 呼び方は、クバネティス。コンテナ化したアプリケーションのデプロイ、スケーリング等の管理を行うもの。Googleが作っています。 |
Kubernetes Cluster | Control PlaneとNodesの集合体。 |
Control Plane | Podの指定レプリカ数の制御(Podのレプリカ数3で実行中、レプリカの1つダウンしレプリカ数が2になった場合、Podを1つ起動しレプリカ数を3に保ちます)など、クラスターイベントの検出および応答、スケジューリングなどを行います。 |
Node | 基本的にノードは1つのVMまたは物理的なマシンです。Nodeは、Podや、Podを制御するためのkubelet、ネットワークプロキシを行うkube-proxy、 Docker等を動作させるコンテナランタイムなども含んでいます。 |
Pod | 1つまたは複数のコンテナのグループであり、ストレージやネットワークの共有リソースを持ち、コンテナの実行方法に関する仕様(レプリカ数などの規定)を持っています。 |
Deployment | Deploymentは、Podの作成とレプリカ数の宣言を提供します。 |
Service | Podをクラスター内部および外部からアクセスできるように制御するネットワークサービスです。 |
⬢ 全体図
⬢ ノード図
引用:ノード図において、分かりやすかったのでKubenetesドキュメントの図を引用させて頂きました。
➍ Minikubeインストール
今回実施する環境は、win10、Docker Desktop、WSL2(Ubuntu)で実行します。
同じ様な環境で実施する場合は、こちらの記事をご参考にセットアップしてください。
(1) dockerの準備
Kubernetesは、Dockerだけでなく複数のコンテナランタイムをサポートしていますが、今回はDockerで実施します。
⬢ dockerが使える状態か確認
$ docker version
Client: Docker Engine - Community
Cloud integration: v1.0.20
Version: 20.10.10
API version: 1.41
Go version: go1.16.9
Git commit: b485636
Built: Mon Oct 25 07:43:23 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.10
API version: 1.41 (minimum version 1.12)
Go version: go1.16.9
Git commit: e2f740d
Built: Mon Oct 25 07:41:30 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.11
GitCommit: 5b46e404f6b9f661a205e28d59c982d3634148f8
runc:
Version: 1.0.2
GitCommit: v1.0.2-0-g52b36a2
docker-init:
Version: 0.19.0
GitCommit: de40ad0
⬢ dockerグループ所属
dockerコマンドをsudoしなくて良いように、ユーザをdockerグループに所属させます。
# docker GRP作成
$ sudo groupadd docker
# docker GRPにユーザ追加 (popcornはユーザ名です)
$ sudo usermod -aG docker popcorn
# docker GRP反映
$ sudo newgrp docker
使用ユーザが、dockerグループに所属できているか、確認しておきましょう。
$ cat /etc/group | grep docker
docker:x:1001:root,popcorn
(2) Minikubeインストール
詳細はこちら👉 https://minikube.sigs.k8s.io/docs/start/
⬢ Minikubeダウンロード
# ダウンロード
$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
⬢ Minikubeインストール
# インストール
$ sudo install minikube-linux-amd64 /usr/local/bin/minikube
⬢ Minikubeインストール確認
きちんとインストールできたか、確認してみましょう。
ClientとServerのバージョンが表示されれば、きちんとインストールできています。
# バージョン情報表示
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.5", GitCommit:"aea7bbadd2fc0cd689de94a54e5b7b758869d691", GitTreeState:"clean", BuildDate:"2021-09-15T21:10:45Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:35:25Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
(3) Minikube起動確認
⬢ Minikube起動
初回起動時は、minikubeのDockerイメージを自動でダウンロードしにいきます。
# Minikube起動
$ minikube start --driver=docker
😄 minikube v1.24.0 on Ubuntu 20.04
✨ Using the docker driver based on user configuration
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
💾 Downloading Kubernetes v1.22.3 preload ...
> preloaded-images-k8s-v13-v1...: 501.73 MiB / 501.73 MiB 100.00% 6.53 MiB
> gcr.io/k8s-minikube/kicbase: 355.78 MiB / 355.78 MiB 100.00% 4.29 MiB
🔥 Creating docker container (CPUs=2, Memory=2200MB) ...
🐳 Preparing Kubernetes v1.22.3 on Docker 20.10.8 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔎 Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
2回目以降は、立ち上げるだけになります。
# Minikube起動
$ minikube start
😄 minikube v1.24.0 on Ubuntu 20.04
✨ Using the docker driver based on existing profile
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
🔄 Restarting existing docker container for "minikube" ...
🐳 Preparing Kubernetes v1.22.3 on Docker 20.10.8 ...
🔎 Verifying Kubernetes components...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
⬢ Minikubeステータス確認
Minikubeがきちんと起動できているか、ステータスを確認します。
# Minikubeステータス確認
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
➎ Podを動作させよう
今回起動させるPod(コンテナ)は、以下の「mnister
」という自作Dockerイメージにします。
ポート5000番で待ち受けるwebアプリサーバです。
このDockerイメージをDeploymentすることにより、Podを作成します。
Kubernetesの Deployment はPodの状態を確認し、Podのコンテナが停止した場合には再起動します。DeploymentはPodの作成やスケールを管理するために推奨される方法です。
※引用:Kubenetesドキュメント
(1) Worker Node
⬢ Worker Nodeを追加
Podを動かすworkerノードを追加します。
$ minikube node add --worker
😄 Adding node m02 to cluster minikube
❗ Cluster was created without any CNI, adding a node to it might cause broken networking.
👍 Starting worker node minikube-m02 in cluster minikube
🚜 Pulling base image ...
🔥 Creating docker container (CPUs=2, Memory=2200MB) ...
🐳 Preparing Kubernetes v1.22.3 on Docker 20.10.8 ...
🔎 Verifying Kubernetes components...
🏄 Successfully added m02 to minikube!
⬢ 追加したNodeを確認
「minikube-m02
」ノードが追加されていますね。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane,master 21d v1.22.3
minikube-m02 Ready <none> 94m v1.22.3
⬢ Nodeのラベルを確認
workerの方に「kubernetes.io/hostname=minikube-m02
」というユニークなラベルがあることを確認しておきます。これは、次の手順で、どのNodeでPodを起動するか指定する際に使用します。
$ kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
minikube Ready control-plane,master 21d v1.22.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=minikube,kubernetes.io/os=linux,minikube.k8s.io/commit=76b94fb3c4e8ac5062daf70d60cf03ddcc0a741b,minikube.k8s.io/name=minikube,minikube.k8s.io/updated_at=2021_11_16T11_07_01_0700,minikube.k8s.io/version=v1.24.0,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
minikube-m02 Ready <none> 93m v1.22.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=minikube-m02,kubernetes.io/os=linux
(2) レシピ(yaml)を作成
Deploymentの設定ファイルであるレシピ(yaml)を作成します。
「spec
」以降は、コンテナの設定を記載します。「nodeSelector
」の箇所には、先程調べたラベルを指定します。これでworkerノードでPodが動作するようになります。
# -------------------------------------------------------------------------------------------
# Deployment
# -------------------------------------------------------------------------------------------apiVersion: apps/v1
kind: Deployment # 種別はDeployment
metadata:
name: mnister # mnisterという名前のDeploymentが作成
spec:
selector:
matchLabels:
app: mnister # Podテンプレートにて定義されたラベル(app: mnister)を選択
replicas: 1 # 1つのレプリカPodを作成
template:
# ---- ここからPodTemplate ----
metadata:
labels:
app: mnister # app: mnisterというラベルを付与
spec:
containers:
- name: mnister # Podがmnisterという名前で
image: poodlemaster/img-mnister:latesta # Docker Hubにあるimg-mnisterの最新バージョンのコンテナを動作させる
ports:
- containerPort: 5000 # containerPortは5000番
nodeSelector:
kubernetes.io/hostname: minikube-m02 # minikube-m02というラベルがついたNodeで動作させる
# ---- ここまでPodTemplate ----
(3) Pod作成
Deploymentを作成すると、その内容に従いPodが起動されます。
⬢ Deploymentの作成
先程の設定ファイルから、Deploymentを作成します。
$ kubectl apply -f mnister.yaml
deployment.apps/mnister created
Deploymentが作成されたことを確認します。
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
mnister 0/1 1 0 58s
「mnister
」が、立ち上がるまで待ちましょう。(AVAILABLE 0→1)
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
mnister 1/1 1 1 97s
⬢ Podの確認
Deploymentを作成すると、その内容に従いPodが起動されます。今回は、「mnister-79597cf8c9-phdq6
」という名のPodが、作成されたことを確認しておきましょう。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mnister-79597cf8c9-phdq6 1/1 Running 0 76m
PodがNode「minikube-m02
」で実行されているのを確認します。
$ kubectl describe pods
Name: mnister-79597cf8c9-phdq6
Namespace: default
Priority: 0
Node: minikube-m02/192.168.49.3
Start Time: Tue, 07 Dec 2021 17:28:15 +0900
Labels: app=mnister
pod-template-hash=64ff478f7d
Annotations: <none>
Status: Running
IP: 172.17.0.2
IPs:
IP: 172.17.0.2
Controlled By: ReplicaSet/mnister-64ff478f7d
Containers:
mnister:
Container ID: docker://2bf64e2cfefaccffd8c9844dd490eb5933ba9d18c61f8c4027f3d2480d67cf97
Image: poodlemaster/img-mnister:latest
Image ID: docker-pullable://poodlemaster/img-mnister@sha256:0f2c26e4910f2fb8e571106ddc1ed094625a3e867bfbe69cf7200d75757a83ec
Port: 5000/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 07 Dec 2021 17:28:18 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-z8mgm (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-z8mgm:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: kubernetes.io/hostname=minikube-m02
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: <none>
⬢ レプリカ動作の確認
レプリカ(replicas: 1)が正しく動作するか確認してみます。
今は「mnister-79597cf8c9-phdq6
」のPodが動いています。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mnister-79597cf8c9-phdq6 1/1 Running 0 2m10s
「mnister-79597cf8c9-phdq6
」のPodを削除します。
$ kubectl delete pod mnister-79597cf8c9-phdq6
pod "mnister-79597cf8c9-phdq6" deleted
「mnister-79597cf8c9-phdq6
」のPodを削除後、Podの状態を確認すると「mnister-64ff478f7d-4v58k
」という新たなPodが、自動的に1つ起動され運転中になりました。これで、レプリカが正しく動作していることが分かりました。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mnister-64ff478f7d-4v58k 0/1 ContainerCreating 0 3s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mnister-64ff478f7d-4v58k 1/1 Running 0 2m48s
※Podを消してもレプリカ設定数に戻そうとするので、Podを起動させたくない場合は、Deploymentを削除する必要があります。
⬢ Serviceの作成
mnisterをport5000番で公開するようにServiceの作成を行います。
$ kubectl expose deploy/mnister --port=5000
Serviceにmnisterが、追加されたことを確認します。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21d
mnister ClusterIP 10.103.65.68 <none> 5000/TCP 99m
⬢ おまけ
DeploymentとServiceをまとめて記載することもできます。その場合レシピ(yaml)は、以下のようになります。
# -------------------------------------------------------------------------------------------
# Deployment
# -------------------------------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment # 種別はDeployment
metadata:
name: mnister # mnisterという名前のDeploymentが作成
spec:
selector:
matchLabels:
app: mnister # Podテンプレートにて定義されたラベル(app: mnister)を選択
replicas: 3 # 3つのレプリカPodを作成
template:
# ---- ここからPodTemplate ----
metadata:
labels:
app: mnister # app: mnisterというラベルを付与
spec:
containers:
- name: mnister # Podがmnisterという名前で
image: poodlemaster/img-mnister:latest # Docker Hubにあるmnisterの最新バージョンのコンテナを動作させる
ports:
- containerPort: 5000 # containerPortは5000番
nodeSelector:
kubernetes.io/hostname: minikube-m02 # minikube-m02というラベルがついたNodeで動作させる
# ---- ここまでPodTemplate ----
---
# -------------------------------------------------------------------------------------------
# Service
# -------------------------------------------------------------------------------------------
apiVersion: v1
kind: Service # 種別はService
metadata:
name: mnister # mnisterという名前のServiceが作成
spec:
ports:
- port: 5000 # Port5000を外部へ公開
selector:
app: mnister # ラベル(app: mnister)のあるPodへ転送
レシピ(yaml)の適応方法は以下の通りです。「kubectl apply
」コマンドの応答メッセージは、新規作成の場合はcreated、設定変更した場合はconfigured、設定変更が無い場合はunchangedとなります。
$ kubectl apply -f mnister_deploy_svc.yaml
deployment.apps/mnister created
service/mnister created
(3) port-forward開始
⬢ port-forward
「localhostの5050番」へ届いたパケットを「Podの5000番」へ転送するように設定します。「kubectl port-forward」のあとに、Pod名、Deployment名、Service名などを指定できます。
$ kubectl port-forward deployment.apps/mnister 5050:5000
Forwarding from 127.0.0.1:5050 -> 5000
Forwarding from [::1]:5050 -> 5000
(4) ブラウザアクセス
⬢ ブラウザアクセス
この状態で、ブラウザから以下のURLへアクセスします。
⬢ アクセス結果
➏ ダッシュボード
Minikubeは、dashboard機能も持っています。
⬢ ダッシュボード起動
$ minikube dashboard
🤔 Verifying dashboard health ...
🚀 Launching proxy ...
🤔 Verifying proxy health ...
🎉 Opening http://127.0.0.1:34009/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...
👉 http://127.0.0.1:34009/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
⬢ ダッシュボード表示
「👉」で示されたURLへアクセスします。
⬢ アクセス結果
➐ Podへログインする
無理に入ることはないです(必須手順ではないです)が、Podの中で処理をしたい場合は、こちらのコマンドで入れます。
⬢ Podのリストを表示
Podのリストを表示します。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mnister-64ff478f7d-w29hf 1/1 Running 0 84m
⬢ Podの中に入る
Pod名「mnister-64ff478f7d-w29hf
」を指定してアクセスします。
$ kubectl exec --stdin --tty mnister-64ff478f7d-w29hf -- /bin/bash
(base) root@mnister-64ff478f7d-w29hf:/bg# ls
__pycache__ colab_mnist.hdf5 server.py static templates
➑ リソースの削除
グチャグチャに遊んだらキレイに消す手順も確認しておきましょう。
整理しますと、追加したのは、Deployment、Serviceに「
mnister
」を追加しました。また、「minikube-m02
」というWorker Nodeを1つ追加しました。これらを削除したいと思います。
⬢ Deploymentの削除
Deploymentに追加した「mnister
」を削除します。
$ kubectl delete deploy mnister
deployment.apps "mnister" deleted
⬢ Serviceの削除
Serviceに追加した「mnister
」を削除します。
$ kubectl delete svc mnister
service "mnister" deleted
⬢ Nodeの削除
今回追加した「minikube-m02
」ノードを削除します。
$ minikube node delete minikube-m02
🔥 Deleting node minikube-m02 from cluster minikube
✋ Stopping node "minikube-m02" ...
🛑 Powering off "minikube-m02" via SSH ...
🔥 Deleting "minikube-m02" in docker ...
💀 Node minikube-m02 was successfully deleted.
⬢ 削除できたか確認
nodes, pods, deployments, servicesを表示して確認する。(no, po, deploy, svcはそれぞれの省略形です)
$ kubectl get no,po,deploy,svc --all-namespaces
NAME STATUS ROLES AGE VERSION
node/minikube Ready control-plane,master 21d v1.22.3
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-78fcd69978-b4n2v 1/1 Running 8 (5h37m ago) 21d
kube-system pod/etcd-minikube 1/1 Running 8 (5h37m ago) 21d
kube-system pod/kindnet-4zc4b 1/1 Running 0 139m
kube-system pod/kube-apiserver-minikube 1/1 Running 9 (5h37m ago) 21d
kube-system pod/kube-controller-manager-minikube 1/1 Running 8 (5h37m ago) 21d
kube-system pod/kube-proxy-gm527 1/1 Running 8 (5h37m ago) 21d
kube-system pod/kube-scheduler-minikube 1/1 Running 8 (5h37m ago) 21d
kube-system pod/storage-provisioner 1/1 Running 17 (5h24m ago) 21d
kubernetes-dashboard pod/dashboard-metrics-scraper-5594458c94-f2f9c 1/1 Running 4 (5h37m ago) 20d
kubernetes-dashboard pod/kubernetes-dashboard-654cf69797-rk879 1/1 Running 7 (5h24m ago) 20d
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 1/1 1 1 21d
kubernetes-dashboard deployment.apps/dashboard-metrics-scraper 1/1 1 1 20d
kubernetes-dashboard deployment.apps/kubernetes-dashboard 1/1 1 1 20d
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 21d
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 21d
kubernetes-dashboard service/dashboard-metrics-scraper ClusterIP 10.102.195.221 <none> 8000/TCP 20d
kubernetes-dashboard service/kubernetes-dashboard ClusterIP 10.107.185.79 <none> 80/TCP 20d
➒ Minikubeの停止と削除
(1) Minikubeの停止
Minikubeクラスターを停止します。
$ minikube stop
✋ Stopping node "minikube" ...
🛑 Powering off "minikube" via SSH ...
🛑 1 node stopped.
(2) Minikubeの削除
Minikubeクラスターを削除します。これをやると追加したNodeもDeploymentもServiceも全て無くなります。一気に初期化したい場合は、これがオススメです。
$ minikube delete
🔥 Deleting "minikube" in docker ...
🔥 Deleting container "minikube" ...
🔥 Deleting container "minikube-m02" ...
🔥 Removing /home/popcorn/.minikube/machines/minikube ...
🔥 Removing /home/popcorn/.minikube/machines/minikube-m02 ...
💀 Removed all traces of the "minikube" cluster.
➓ 以上
ここまでやれば「Kubernetesってなぁに?」と聞かれたときに、「クバァ...ええと、クバネティスはね………」と答えることができるはずです。これで超初心者から初心者へ一段階段を登ったはずです。しかし、DockerからKubernetesへ勉強をスライドしてきましたが、一気に難しくなりましたね。頭から煙がでそうです。我慢ならないので、今日はもう寝て、明日以降勉強することとします😪
お疲れ様でした😊