Kubernetes入門　ローカル開発環境構築　

昨今Kubernetesが便利で流行っているということで今更ながら触ってみることにしました。
こちらに自分用のメモを兼ねて書きます。


ネットの記事は、AWSやGCPで利用することが前提になっているものが多く、
初見なのもありローカルの開発環境を作り、色々遊びながら理解を深めていきます。


### Kubernetesとは
Kubernetesの[公式ドキュメント](https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/)によると
Kubernetesは「コンテナを管理する基盤ツール」です。

使うと何が嬉しいかと言いますと、アプリケーションの開発・管理が楽で安全になります。

例えば、Kubernetesの基本機能として、デプロイ、拡張、負荷分散、ログ記録、監視などがあります。

また、アプリケーションの運用で頭を悩ませる問題として、高負荷などで異常が起きた時、スケールアウトしたり、フェールオーバーする必要があります。

VMを使う構成では、結局のところ管理はそのVM単位になってしまい、スケールアウト・フェールオーバーの設定もVM単位でしか行なえません。
Kubernetesを使うと、コンテナ単位つまりアプリケーション単位で管理することができ（実際にはVMを使っていて、アプリケーション単位で管理しているように扱える感じらしい）、スケールアウト・フェールオーバーもアプリケーション単位で設定することができます。

これは便利ですね。

### ゴール
今回の目指すゴールは2つ
・kubernetesの理解を深める
・ローカルの開発環境を作る
です。

公式ドキュメントには、ブラウザ上でコマンドを叩いて動かす[チュートリアル](https://kubernetes.io/ja/docs/tutorials/)があります。
ただ、今回はローカルのマシンに実際にKubernetes環境を作るところを目標にやっていきたいと思います。

### 0.アーキテクチャの理解
公式サイトにわかりやすい図がなかったので、図だけ[wikipedia](https://ja.wikipedia.org/wiki/Kubernetes)からお借りしました。
![Kubernetes.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/ab09b9fd-4a15-711f-863a-9e5e13126944.png)
引用：Kubernetes　Kubernetesのアーキテクチャ図　https://ja.wikipedia.org/wiki/Kubernetes

Kubernetesをデプロイするとクラスターが展開されます。
このKubernetesクラスターは、コンテナ化されたアプリケーションを実行するノード（Node）と呼ばれるワーカーマシンの集合です。アプリケーションのコンポーネントはPodと呼ばれ、図のように、このPodがノードに1つ以上の含まれ、展開されています。ノードの制御は、kubeletと呼ばれるエージェントで行われ、ノードへのアクセスはkube-proxyと呼ばれるプロキシを介して行われます。

コントロールプレーンと呼ばれるコンポーネントは、クラスターを制御する機能を持ちます。

以下は公式ドキュメントに書かれた詳細な説明です。

#### コントロールプレーンコンポーネント
##### kube-apiserver
・Kubernetes APIを外部に提供する
・Kubernetesコントロールプレーンのフロントエンド
##### etcd
・一貫性、高可用性を持ったキーバリューストアで、Kubernetesの全てのクラスター情報の保存場所
#### kube-scheduler
・Podにノードが割り当てられているか確認し、割り当てを行う
#### kube-controller-manager
・通知やPodの数を監視する複数のコントローラープロセスを実行する
#### cloud-controller-manager
・基盤であるクラウドプロバイダーと対話するコントローラーを実行する
### ノードコンポーネント
#### kubelet
・クラスター内の各ノードで実行されるエージェント。各コンテナがPodで実行されていることを保証
#### kube-proxy
・クラスター内の各nodeで動作しているネットワークプロキシ
### コンテナランタイム
・コンテナの実行を担当する

### 1.ローカルの開発環境を作る、アプリを動かす
今回は、WebアプリのコンテナをローカルのKubernetes上に立てることを目指します。
[こちら](https://kubernetes.io/ja/docs/setup/learning-environment/minikube/)を参考に進めます。

#### Minikubeのインストール
今回、Minikubeと呼ばれるローカル環境でKubernetesを簡単に実行するためのツールを使います。このツールではシングルノードのKubernetesクラスターを作ることができます。
Minikubeの使い方は[こちら](https://kubernetes.io/docs/setup/learning-environment/minikube/#specifying-the-vm-driver)

※私のローカル開発環境はUbuntu18.04です。

##### kubectlのインストール
まず、kubectlのインストールですが、こちらは[ドキュメント](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/#install-kubectl-on-linux)通りにさらっとインストールできました。
##### ハイパーバイザーのインストール
私は以前VirtualBoxをインストールしていたので、こちらは特に作業なしでした。
必要な方は[こちら](https://www.virtualbox.org/wiki/Downloads)から
##### Minikubeのインストール
今回はバイナリをダウンロードして、指定の場所に置きインストールしました。

```shell
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
  && chmod +x minikube

$ sudo mkdir -p /usr/local/bin/

$ sudo install minikube /usr/local/bin/
```

##### インストール確認
インストールが成功したかを下記のKubernetesクラスターを起動するコマンドで確認します。

```shell_session

$ minikube start --kubernetes-version {起動するバージョン}

※指定なしの場合は最新のバージョンが起動されます。
$ minikube start

```

実行例：
![ku.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/0d8b629d-703a-8b7e-ff22-6d7a3b4c343c.png)

kubernetes起動後

ステータス確認

```shell
$ minikube status
```

停止

```shell
$ minikube stop
```

削除

```shell
$ minikube delete
```

また、この時点でdockerイメージとdockerボリューム見てみますと、

dockerイメージ

```shell
$ docker images

REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
gcr.io/k8s-minikube/kicbase    v0.0.12-snapshot3   25ac91b9c8d7        5 weeks ago         952MB
```

dockerボリューム

```shell
$ docker volume ls

DRIVER              VOLUME NAME
local               minikube
```

Minikubeのイメージとボリュームができていました。

#### Webサーバをkubernetesで立てる
Minikubeのインストールができたので、kubernetes環境を作り、コンテナの稼働をさせます。
WebサーバはMinikubeに対応している単純な応答だけを返すecho-serverを使います。

次に、Minikubeを起動して、クラスターを作成します。

```shell
$ minikube start
```

この時、dockerコンテナの稼働状況は

```shell
$ docker ps

CONTAINER ID        IMAGE                                           COMMAND                  CREATED             STATUS              PORTS                                                                                                      NAMES
7f144c151a63        gcr.io/k8s-minikube/kicbase:v0.0.12-snapshot3   "/usr/local/bin/entr…"   20 hours ago        Up 22 minutes       127.0.0.1:32779->22/tcp, 127.0.0.1:32778->2376/tcp, 127.0.0.1:32777->5000/tcp, 127.0.0.1:32776->8443/tcp   minikube
```

minikubeのコンテナが動いています。

次にkubectlでKubernetes Deploymentというものを作ります。このKubernetes Deploymentオブジェクトを作成することでアプリケーションを実行できるようになるようです。こちらはYAMLファイルで記述ができます。これ自体はサービスというより、Podを作るためのDeploymentのアプリのようです。

```shell
$ kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10

deployment.apps/hello-minikube created
```

できたhello-minikube Deploymentを使い、サービスとして公開します。こちらが実際のアプリとほぼ等価のようです。

```
$ kubectl expose deployment hello-minikube --type=NodePort --port=8080

service/hello-minikube exposed
```

この時点でdockerコンテナの稼働状況は

```
$ docker ps

CONTAINER ID        IMAGE                                           COMMAND                  CREATED             STATUS              PORTS                                                                                                      NAMES
7f144c151a63        gcr.io/k8s-minikube/kicbase:v0.0.12-snapshot3   "/usr/local/bin/entr…"   20 hours ago        Up 40 minutes       127.0.0.1:32779->22/tcp, 127.0.0.1:32778->2376/tcp, 127.0.0.1:32777->5000/tcp, 127.0.0.1:32776->8443/tcp   minikube
```

どうやらhello-minikubeというコンテナは別に動いておらず、minikubeのコンテナ上で動いているものと思われます。おそらく、このminikubeコンテナ自体にkubernetesのシングルノードやPod、Deploymentが作られていると思われます。

Podができているかを確認します。

```
$ kubectl get pod

NAME                              READY   STATUS    RESTARTS   AGE
hello-minikube-5d9b964bfb-vcznp   1/1     Running   0          24m
```

statusがRunningになっており、稼働していることが確認できました。また1/1ということからPodの数は1つだとわかります。

ServiceのURLは

```shell
$ minikube service hello-minikube --url

http://172.17.0.2:31199
```

で確認できます。アクセスすると
![ku1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275351/b5891691-89de-dc3d-ca96-9b6f633fc2fd.png)

アプリが立ち上がっていることが確認できました。
通常より設定する分が少なくさっとできました。
ただ、本来は色々と設定が必要であると思われ、現時点では試せた程度のものと思われます。

以下は削除の手順です。
Serviceの削除は

```shell
$ kubectl delete services hello-minikube

service "hello-minikube" deleted
```

hello-minikube Deploymentの削除は

```shell
$ kubectl delete deployment hello-minikube

deployment.extensions "hello-minikube" deleted
```

### 2.コンテナを覗く
公式ドキュメントにあったローカル開発環境を作るチュートリアルはこのくらいで終わりですが、
せっかくなので、コンテナ内を覗こうかと思います。

```shell
$ docker exec -itu 0 minikube /bin/bash
```

上のコマンドでminikube内に入ります。コンテナに入るとrootディレクトリに入ったので、少し探索します。
rootディレクトリでll

```shell
root@minikube:/# ll
total 64
drwxr-xr-x  81 root root 4096 Oct  3 15:55 ./
drwxr-xr-x  81 root root 4096 Oct  3 15:55 ../
-rwxr-xr-x   1 root root    0 Oct  3 15:54 .dockerenv*
-rw-r--r--   1 root root 1094 Aug 25 22:55 Release.key
-rw-r--r--   1 root root 2543 Aug 25 22:55 afbjorklund-public.key.asc
lrwxrwxrwx   1 root root    7 Apr 23 11:06 bin -> usr/bin/
drwxr-xr-x   2 root root 4096 Apr 15 11:09 boot/
drwxr-xr-x   2 root root 4096 Oct  3 15:54 data/
drwxr-xr-x  17 root root 4260 Oct  4 11:11 dev/
drwxr-xr-x  97 root root 4096 Oct  4 11:11 etc/
drwxr-xr-x   5 root root 4096 Oct  3 15:54 home/
-rw-r--r--   1 root root    0 Aug 25 22:55 kic.txt
drwxr-xr-x   2 root root 4096 Oct  3 15:54 kind/
lrwxrwxrwx   1 root root    7 Apr 23 11:06 lib -> usr/lib/
lrwxrwxrwx   1 root root    9 Apr 23 11:06 lib32 -> usr/lib32/
lrwxrwxrwx   1 root root    9 Apr 23 11:06 lib64 -> usr/lib64/
lrwxrwxrwx   1 root root   10 Apr 23 11:06 libx32 -> usr/libx32/
drwxr-xr-x   2 root root 4096 Apr 23 11:06 media/
drwxr-xr-x   2 root root 4096 Apr 23 11:06 mnt/
drwxr-xr-x   5 root root 4096 Oct  3 15:54 opt/
dr-xr-xr-x 385 root root    0 Oct  4 11:11 proc/
drwx------   3 root root 4096 Oct  3 15:55 root/
drwxr-xr-x  10 root root  300 Oct  4 11:11 run/
lrwxrwxrwx   1 root root    8 Apr 23 11:06 sbin -> usr/sbin/
drwxr-xr-x   2 root root 4096 Apr 23 11:06 srv/
dr-xr-xr-x  13 root root    0 Oct  4 11:11 sys/
drwxrwxrwt   5 root root  180 Oct  4 11:11 tmp/
drwxr-xr-x  45 root root 4096 Oct  3 15:55 usr/
drwxr-xr-x  14 root root 4096 Oct  3 15:54 var/
```

topでプロセスを見る

```shell
$ top

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                                     
    789 root      20   0 2144664 112188  63072 S  10.7   0.7   4:18.88 kubelet                                                                                                                                     
   1946 root      20   0 1096140 334648  67804 S   8.0   2.0   4:42.40 kube-apiserver                                                                                                                              
   1971 root      20   0   10.1g  59396  20936 S   3.3   0.4   1:34.37 etcd                                                                                                                                        
    155 root      20   0 2484692 112980  48532 S   3.0   0.7   1:32.43 dockerd                                                                                                                                     
   1926 root      20   0  812076 102952  58672 S   2.7   0.6   1:42.38 kube-controller                                                                                                                             
    144 root      20   0 1414636  52844  24364 S   0.7   0.3   0:11.42 containerd                                                                                                                                  
   1940 root      20   0  747680  51316  32688 S   0.7   0.3   0:18.26 kube-scheduler                                                                                                                              
   2692 root      20   0  748940  43908  31260 S   0.7   0.3   0:18.71 coredns                                                                                                                                     
    178 root      20   0 2742836  63612  24592 S   0.3   0.4   0:13.66 containerd                                                                                                                                  
      1 root      20   0   21768  11356   8332 S   0.0   0.1   0:00.75 systemd                                                                                                                                     
    131 root      19  -1   29056  11408  10068 S   0.0   0.1   0:00.66 systemd-journal                                                                                                                             
    149 root      20   0   12164   7276   6352 S   0.0   0.0   0:00.01 sshd                                                                                                                                        
   1445 root      20   0  110356   7744   3988 S   0.0   0.0   0:00.22 containerd-shim                                                                                            
```

見ると、kubeletやkube-apiserverのプロセスが立ち上がっています。
kube-apiserverで開発者からの操作を受け付けるAPIを提供しており、kubeletはエージェントとして各ノード（今回はシングルノード）にあり、Podの実行を保証します。containered*と書かれたプロセスが多数あり、いくつかのコンテナが立ち上がっていることがわかります。

```
$ docker ps

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS               NAMES
416c4ef429b6        k8s.gcr.io/echoserver   "/usr/local/bin/run.…"   About an hour ago   Up About an hour                        k8s_echoserver_hello-minikube-5d9b964bfb-vcznp_default_bed83287-6790-4b31-bfa7-73ca575f44c8_0
164da53f6764        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_hello-minikube-5d9b964bfb-vcznp_default_bed83287-6790-4b31-bfa7-73ca575f44c8_0
e9c6dc7cd409        bad58561c4be            "/storage-provisioner"   About an hour ago   Up About an hour                        k8s_storage-provisioner_storage-provisioner_kube-system_69b7aff7-ed52-450b-8886-7662e5166c22_2
4129a33df546        bfe3a36ebd25            "/coredns -conf /etc…"   About an hour ago   Up About an hour                        k8s_coredns_coredns-f9fd979d6-7hm4z_kube-system_d7f88807-7a1b-4a83-867b-6cc8d9d4557b_2
0754ca7dafae        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_storage-provisioner_kube-system_69b7aff7-ed52-450b-8886-7662e5166c22_2
9c1a1303176f        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_coredns-f9fd979d6-7hm4z_kube-system_d7f88807-7a1b-4a83-867b-6cc8d9d4557b_2
913319017cfc        d373dd5a8593            "/usr/local/bin/kube…"   About an hour ago   Up About an hour                        k8s_kube-proxy_kube-proxy-b7pnl_kube-system_f1dbeedd-0267-4d28-8d91-3a64ccad1f46_2
ae3deb3fc9c9        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_kube-proxy-b7pnl_kube-system_f1dbeedd-0267-4d28-8d91-3a64ccad1f46_2
655d493156ee        0369cf4303ff            "etcd --advertise-cl…"   About an hour ago   Up About an hour                        k8s_etcd_etcd-minikube_kube-system_5bf47183fef419a3373296d9f180a0b9_2
d1e86d25a77f        2f32d66b884f            "kube-scheduler --au…"   About an hour ago   Up About an hour                        k8s_kube-scheduler_kube-scheduler-minikube_kube-system_ff7d12f9e4f14e202a85a7c5534a3129_2
72e006e2b202        607331163122            "kube-apiserver --ad…"   About an hour ago   Up About an hour                        k8s_kube-apiserver_kube-apiserver-minikube_kube-system_4d8688f08be9c141bacb3bd9e87b9ae5_2
0ec70066cfe6        8603821e1a7a            "kube-controller-man…"   About an hour ago   Up About an hour                        k8s_kube-controller-manager_kube-controller-manager-minikube_kube-system_dcc127c185c80a61d90d8e659e768641_2
2d9e3f653304        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_kube-controller-manager-minikube_kube-system_dcc127c185c80a61d90d8e659e768641_2
aec1dd9a5f44        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_kube-scheduler-minikube_kube-system_ff7d12f9e4f14e202a85a7c5534a3129_2
29837fb95080        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_kube-apiserver-minikube_kube-system_4d8688f08be9c141bacb3bd9e87b9ae5_2
8be268ad2daa        k8s.gcr.io/pause:3.2    "/pause"                 About an hour ago   Up About an hour                        k8s_POD_etcd-minikube_kube-system_5bf47183fef419a3373296d9f180a0b9_2
```

コンテナ内でのコンテナの稼働を初めて見ましたが、これを見ると、
echoserverのイメージを使ったコンテナが動いていることがわかりました。仮説はあっていたようです。
よく見るとPODという文字が書かれているコンテナがあり、Podをコンテナで表現しているのかな？と思いました。
kube-proxyのコンテナもあるようで、こいつがServiceのプロキシとして動いているものと思われます。


今回はここまでにしますが、
次回はもう少しKubernetesのアーキテクチャ周りの勉強と、設定を変えてどんな挙動をするのか見たいと思います。


### 参考

[公式](https://kubernetes.io/ja/)

[Wikipedia](https://ja.wikipedia.org/wiki/Kubernetes)

[独学Kubernetes　コンテナ開発の基本を最速で理解する](https://qiita.com/Brutus/items/d19af6b9c55de93663f6)
・すごくわかりやすかったです。