Kubernetesをレストランに例える (後半: minikubeとkubectlのハンズオン）

## 記事の目標

- はじめに用語の説明をする
- 用語の説明はざっくりと三行でまとめる。
- 後半minikubeを試すコマンド中心の記事になる。
- minikubeを試しているところではあんまり例えとか使って説明しない

## 前提知識

- Dockerは使ったことある
- ネットワークの基礎知識あり
- Webサーバに関するちょっとした知識あり

## コンテナ化とは

アプリケーションがどんな環境でも動くように、
アプリケーションをその依存関係ごと、「コンテナ」に入れること。

## Kubernetesとは

あなたはコンテナをたくさん作ってしまった。
するとそれぞれコンテナは動いているか、またそれぞれコンテナが何をしているかのチェックが大変になった。
Kubernetesはそのためのツールである。


### クラスタとは

Kubernetesにおける（基本的に）一番大きな単位。
今後の説明のために「レストラン」に例える。


### Podとは

KubernetesのPodは一つまたは複数のコンテナのグループである。
一つのPodは一つのアプリケーション、になることが多い。
コンテナという「部品」をつなぎ合わせて「ホールスタッフ・ロボA」として機能させる的なイメージ。

### Serviceとは

Podにアクセスするためのアドレスを提供すること。
「テーブルAはここ」と決めてお客さんを座らせる。


### Nodeとは

二種類あり、Worker　NodeとControl Plainがある。
ノード一つは一つの（物理・仮想)マシンに対応する。

### Worker Nodeとは

Podが動作するサーバ。Podが必要とするものを備えていないといけない。
ホールスタッフロボたちが働く一つの「ホール」的なもの。
複数あることもある。

### Control Plain(旧称: Master Nodeとは)

Podが入れない場所。Podに指示を出す。
例えば「ホールロボットA」は今後から「ホールD」に移動な
的な指示を出す、本部のようなもの。複数あることもある。

### Deployment

Pod、コンテナのスケーリング・更新・修復をどのようにするかを決めること。
Podの管理に関する広い意味があるので単に「ホールロボットAをホールAに置く」
だけでなく、「ホールBはスタッフ３人、ホールCは…」的な指定も、デプロイメントのうち。

### 改めてクラスタとは

複数の「ホール」と複数の「本部」からなる、一つのレストラン。


## minikubeとは

https://minikube.sigs.k8s.io/docs/start/

Kubernetes学習用のクラスタを作ってくれる。
Local Kubernetes　= Nodeはひとつ　である。
ホールも本部も全部ローカルで動くレストランみたいなことである。

### この後の注意点 

筆者の環境がMacだったのでそれ以外のことは触れない。
またほぼ公式のチュートリアル通りにminikubeを触るだけの記事となっています。



## この後の目標

- ローカルに開発用Kubernetesクラスターをデプロイ
- そのKubernetesクラスターにアプリをデプロイ
- アプリのログを取る方法の確認
- コンテナの方に直接アクセスする方法

## 参考URL(英語)

https://minikube.sigs.k8s.io/docs/tutorials/kubernetes_101/module1/

### Homebrewでインストールできる

```
brew install minikube
```

### バージョン確認

```
minikube version 

minikube version: v1.31.2
```

### クラスターを作る

```
minicube start
```

これだけでクラスタができてしまう。簡単である！

### kubectlとは

クラスターとやりとりする方法としてkubectlというコマンドラインツールがある。


### クラスターの情報を確認する

```
kubectl cluster-info
```

これだけである。

![スクリーンショット 2023-08-22 16.03.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305333/7ad86764-3d99-492f-f7be-f8a98d8329ff.png)

control planeは`https://127.0.0.1:62761`とある。
(通信方法)：//(アドレス):(ポート)である。

```
kubectl get nodes
```

このコマンドを打つと、確かにnodeがひとつしかなくそれがminikubeという名前であることが確認できるはず。
STATUSはreadyとなっており、アプリケーションをデプロイしても良い状態になっているはず。

### kubectlとは(2)

```
kubectl version
```
これを打つと、
Client　versionとServer versionの二つが表示されるはずである。

Clientの方は、kubectlのツール自体のバージョンを示している。
Serverの方は、クラスタを起動しているときに表示されるクラスタのバージョン。

### デプロイメントを作成する

kubectlでアプリのコンテナの元となるイメージの場所を指定する。今回はDocker Hubでホストされているイメージを使う。
```
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
```
実行すると、アプリがデプロイされる。「デプロイ」はこのようなことを含む。

適切なノードを探し、アプリのインスタンスが実行されるようにする　=> 今回の場合一個しかないのでminikubeが選ばれる。
そこでアプリが実行されるよう「スケジュール」する
クラスタがもし新しいノードを作ったらそこにアプリのインスタンスを移せるよう設定する。

```
kubectl get deployment
```

実行すると確かにkubernetes-bootcampという名前のdeploymentが作成されているはず。


### Podの性質について

Podは他のPodからアクセスできるが、クラスターの外からはアクセスできない。
レストランを動かしている私たちのマシンの使うネットワークと、
レストラン内のネットワークは違うからである。

### kubuctlについて(3)

kubectlはproxyを作り、このPodたちが使っているネットワークに通信を転送できる。

```
echo -e "プロキシを起動しました。起動中は特に何も出力しないのでcontrol-Cで戻ろう。\n"; kubectl proxy
```
![スクリーンショット 2023-08-22 16.49.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305333/e30ad38c-9ddb-20fd-84e5-46d32e6efbac.png)


### APIを使う

先程のproxyを起動したままlocahost:8001にアクセスするとAPIにアクセスできる。
proxyのAPIから直接バージョンを問い合わせしてみるには以下のコマンドを試す。

```
curl http://localhost:8001/version
```
この結果で出る結果はJSONオブジェクトの形式で表示されるはず。
そのgitVersionというプロパティは、
先程の kubectl versionで表示されたServerのversionと一致しているはずである。

###　環境変数にPodの名前を記録する

```
export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
echo Name of the Pod: $POD_NAME
```
一行目はPOD_NAMEとして環境変数を作り、それにPodの名前を改行で仕切って入れている。
二行目を実行すると例えば以下のようになるはず。

```
Name of the Pod: hello-minikube-59d4768566-dvqtp
kubernetes-bootcamp-855d5cc575-5fld9
```

この記事に従っていると`Name of the Pod: kubernetes-bootcamp...`しか出ないと思われる。

:::note warn
ここで複数表示される人へ
今後のチュートリアルはPodがひとつしかないためにうまく行くものである。
$POD_NAMEの設定でkubernetes-bootcamp以外に起動しているPodがあった場合にうまくいかなくなるコマンド多数である
もしそのようなPodがあって無くても問題なければ

```
kubectl delete deployment kesitai-pod-name
```
しておき先程のPodの環境変数の登録をやり直した方が今後楽かも。
:::

### APIを通じたPodへのアクセス

```
curl http://localhost:8001/api/v1/namespaces/default/pods/$PODNAME
```

このようにすると

![スクリーンショット 2023-08-22 17.38.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305333/0571f0a6-6d2e-665c-e2f4-f043df6776cb.png)


自分の環境ではかなり長いレスポンスがあり、その中を探すと、確かに先程起動したpodのメタデータがある。
デプロイメントしたアプリを、このようなProxyを使わずアクセス可能にさせるにはどうしたら良いのだろう。

### アプリの設定を確認する

```
kubectl get pods
```
このようにすると動いているPodの一覧と、そのステータス、稼働時間などを確認できるはず。
ここでkubernetes-bootcamp...と始まるPodの名前をコピペする。

```
kubectl describe pod kubernetes-bootcamp-<nanka_iroiro>
```
このようにするとpodの情報が読みやすく表示される。
例えばIPや使われているポートや、Podの稼働状態などが出るはず。

### コンテナでコマンドを実行する

Podが実行されているときにexecで、コマンドを実行できる。
ここでアクセスしているのは"Pod"ではなく"Pod"を動かすためのコンテナ(今回はひとつ)である。

```
kubectl exec $POD_NAME -- env
```

このようにするとpodに設定されている環境変数の一覧を見ることができる。



### コンテナでbashのセッションを始める

```
kubectl exec -ti $POD_NAME -- bash
```

このようにすると、コンテナの名前と#というrootユーザ向けのプロンプトが表示されるはず。

```
cat server.js
```
実行すると、
http.createServerといった関数が見える。
またhandleRequestの中身を見ることで、どのようにレスポンスするかが定義されていることがわかる。

```
root@kubernetes-bootcamp-855d5cc575-5fld9:/# curl localhost:8080
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-855d5cc575-5fld9 | v=1
```

コンテナの内部で「ローカルホスト」を指定してcurlすることによって、レスポンスを確認できる。

今回はここまで。