HelloMinikubeでk8sのお勉強

#Kubernetesはじめました
世間的には結構前から話題になっていますが、仕事でこれから少しKubernetesをさわることになるため、ただいま必死こいて勉強中です。自宅でもKubernetesを勉強したいですが、なんせ使っているMacBookAirが弱小なので・・・お手軽だと噂の**Minikube**を試してみました。

勉強するにあたり、以下の本を数日前に購入し、サラーっと最後まで読みましたが、
Kubernetesってカバー範囲が広いし、ほんと奥が深いのね・・・。

<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4295004804/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4295004804&linkCode=as2&tag=fukumasa08-22&linkId=1f890552662e63b149594b887dc3cf74"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4295004804&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=fukumasa08-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=fukumasa08-22&l=am2&o=9&a=4295004804" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />


#Minikubeとは？
WindowsやMacなど手元のマシン上に**ローカルKubernetes**を簡単に構築・実行することが出来るツールです。手軽な反面、Kubernetesの一部機能が使えないなどの制約があります。
MinikubeはVMにMasterとNodeを立てるので、VirtualBoxやHyper-Vなどのハイパーバイザーが必要になります。


#my環境
- MacBook Air (13-inch, Mid 2012)
 - OS : macOS Catalina(10.15)
 - プロセッサ : 1.8 GHz デュアルコアIntel Core i5
 - メモリ : 4 GB 1600 MHz DDR3
 - ディスク : 128GB (外部ストレージ : 1TB)

|ツール  |バージョン  |
|---|---|
|VirtualBox  |6.0.12 r133076 (Qt5.6.3)  |
|Kubernetes  |v1.16.0  |
|Docker  |18.09.9 |
|Minikube  |v1.4.0 on Darwin 10.15 |
|kubectl (Client)  |v1.10.3 → v1.16.0|
|kubectl (Server)  |v1.16.0|


絵にすると多分こんな感じだと思います。
![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206972/cfeea227-0415-1f70-1e6b-325f060919d8.png)


Kubernetesでは、コンテナ（Pod）が稼働する**Node**と、コンテナのスケジューリングなどKubernetesを管理する**Master**はそれぞれ別ノード（サーバ）で動かしますが、Minikubeでは1つのVM内に両方が稼働しています。

それぞれのノードは複数のコンポーネントから構成されており、VM内ではそれらがDockerコンテナとして稼働しています。コンポーネント詳細については[公式ドキュメント](https://kubernetes.io/ja/docs/concepts/overview/components/)などを参考にして見てください。


#Hello Minikubeやってみた
[Hello Minikube](https://kubernetes.io/ja/docs/tutorials/hello-minikube/)をベースにMinikubeと戯れてみました。


##0. 事前準備
- Homebrewをアップデート

```
$ brew update
```

- VirtualBoxをインストール

```
$ brew cask install virtualbox
```

##1. Minikubeをインストール

```
$ brew cask install minikube
```

##2. Minikubeを起動

```
$ minikube start --vm-driver=virtualbox

😄  minikube v1.4.0 on Darwin 10.15
💡  Tip: Use 'minikube start -p <name>' to create a new cluster, or 'minikube delete' to delete this one.
🔄  Starting existing virtualbox VM for "minikube" ...
⌛  Waiting for the host to be provisioned ...
🐳  Preparing Kubernetes v1.16.0 on Docker 18.09.9 ...
💾  Downloading kubelet v1.16.0
💾  Downloading kubeadm v1.16.0
🔄  Relaunching Kubernetes using kubeadm ... 
⌛  Waiting for: apiserver proxy etcd scheduler controller dns
🏄  Done! kubectl is now configured to use "minikube"

```

VirtualBoxでminikubeというVMが作られました。

![スクリーンショット 2019-10-11 22.53.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206972/86d2c410-69b6-82d1-6b3d-1a8a9dcdec5a.png)


Kubernetesと同じ画面がMinikubeにもついています。
いわゆるdashboardというやつです。

```
$ minikube dashboard
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
🎉  Opening http://127.0.0.1:50668/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...
```

ブラウザが自動起動し画面が表示されました。まだ見方がさっぱりん...

![スクリーンショット 2019-10-11 23.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206972/a5baa6c3-71bb-8143-3c48-012bb7e3ae89.png)


##3. Developmentを作成
まずは、コンテナ（Development）を起動します。

```
$ kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node

error: no matches for kind "Deployment" in version "extensions/v1beta1"
```

ん・・・！？エラーになった。
extensions/v1beta1というバージョンにはDeploymentがないと言っている!?
めちゃくちゃググったけどそれっぽい情報が全然HITせず...

試しにkubectlのバージョンを調べてみる。

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:17:39Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:27:17Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}
```

クライアントのkubectlが古そうなので、バージョンアップしてみる。

```
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.16.0/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:36:53Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:27:17Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}
```

クライアントもサーバと同じv1.16.0になったので、改めてコマンドを実施してみる。

```
$ kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node
deployment.apps/hello-node created
```

おっ！今度は出来たっぽい！ （ここまでたどり着くのにかなりの時間を要してしまいました...）

```
$ kubectl get deployments
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
hello-node   1/1     1            1           27m
```

ダッシュボードで見ると、Deployment、Pod、ReplicaSetが作られています。

![スクリーンショット 2019-10-16 23.50.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206972/2d1822ee-a1e2-8142-9146-edbe69ed0b61.png)

Podというのがコンテナの実体で、ReplicaSetはPodの監視を行い指定されたレプリカ数になるように調整をしてくれます。さらに、DeploymentがReplicaSetを管理し、ローリングアップデートやロールバックを実現してくれます。

少しややこしいですが、、DeploymentがReplicaSetを管理し、ReplicaSetがPodを管理する３層の親子関係になっています。


##4. Serviceを作成
作成したコンテナへアクセスできるように、ネットワーク（Service）を作成します。

```
$ kubectl expose deployment hello-node --type=LoadBalancer --port=8080
service/hello-node exposed
```

出来たServiceを確認します。

```
$ kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node   LoadBalancer   10.110.214.34   <pending>     8080:30341/TCP   99s
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          5d
```

今回作成したLoadBalancerサービスは、Kubernetesクラスタ外のLoadBalancerに外部疎通性のある仮想IPを払い出しますが、クラスタが構築されているインフラがこの仕組みに対応している必要があります。

GCPやAWSなどのクラウドサービスでKubernetesを使うケースではほぼ対応していますが、今回のようにローカルで立ち上げるケースでは残念ながら対応していないことが多いので仮想IPは払い出されません。EXTERNAL-IPはずっと`<pending>`のままです。

LoadBalancerサービスを作成すると、同時に**ClusterIP**と**NodePort**も同時に作成されます。
ClusterIPというのは、コンテナ内からの通信に利用されるIPで、クラスタ内からしか接続できません。今回は「10.110.214.34」というIPが振り出されています。
NodePortは、外部からのアクセスを受け付けるために振り出されるポート番号で、今回は「30341」です。もしLoadBalancerサービスがうまく機能すれば、イメージ的にはクラスタ外のLoadBalancerからNodePort宛にバランシングされる感じです。



##5. 画面を表示
`minikube service`を使ってサービスを起動します。

```
$ minikube service hello-node
|-----------|------------|-------------|-----------------------------|
| NAMESPACE |    NAME    | TARGET PORT |             URL             |
|-----------|------------|-------------|-----------------------------|
| default   | hello-node |             | http://192.168.99.101:30341 |
|-----------|------------|-------------|-----------------------------|
🎉  Opening kubernetes service  default/hello-node in default browser...
```

![スクリーンショット 2019-10-17 0.03.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206972/dd009992-6682-38ea-f108-802e7c439675.png)

ブラウザが自動起動して「Hello World!」が表示されました。
URLの192.168.99.101:30341は「VMのアドレス:NodePort」です。

参考までに、MinikubeのVMからもClusterIPを使ってアクセスしてみます。
`minikube ssh`を使えばノードにssh接続出来ます。便利ですね。

```
$ minikube ssh
                         _             _            
            _         _ ( )           ( )           
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __  
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)

$ curl 10.110.214.34:8080
Hello World!
```

おぉ〜！ちゃんとアクセス出来ましたね。

ここまで構築した環境を図にまとめてみました。こんな感じかな。

![qiita投稿用 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206972/bb19328a-8fec-2e02-b45b-8bdcb8691f52.png)



##6. クリーンアップ
最後に作成したServiceとDeploymentを削除します。

```
$ kubectl delete service hello-node
service "hello-node" deleted
$ kubectl delete deployment hello-node
deployment.apps "hello-node" deleted
```

おしまい。


#最後に
なかなか自前の環境でKubernetesを動かすのは難しいので、手軽に触ってみるという意味でMinikubeは最適ですね。Hello Minikubeはサンプルとは言いながらも1つ1つが何をしているのか、どういう構成を構築しているのかを理解しようと思うと結構大変でした。KubernetesはDockerやる上でほぼデファクトなので、色んなコマンドを試しつつ引き続き勉強に励みたいと思います。


#おまけ
上記インストールしなくても、[Hello Minikube](https://kubernetes.io/ja/docs/tutorials/hello-minikube/)のサイトではWeb上でMinikubeを試せる[Katacoda](https://www.katacoda.com)というサービスも提供されているので、よりお手軽に試せるのでそちらもオススメです。ひと昔前と比べるとやる気さえあれば誰でも勉強しやすい環境になりましたよね。


# 参考リンク
- [Qiita : minikubeをMacにインストールする](https://qiita.com/Manjiii/items/88699c52f5ade2bf4b6f)
- [kubernetesチュートリアル : Hello Minikube](https://kubernetes.io/ja/docs/tutorials/hello-minikube/)
- [minkube Documentation](https://minikube.sigs.k8s.io/docs/)
- [Installing Kubernetes with Minikube](https://kubernetes.io/docs/setup/learning-environment/minikube/#quickstart)