Kubernetesのローカル版minikubeを使ってみる

# Kubernetesのローカル版minikubeを使ってみる

MacOSを使って実装してみます。
基本的に http://kubernetes.io/docs/tutorials/ にそって確認。

## インストール

- kubectlのインストール
    - `curl -Lo kubectl http://storage.googleapis.com/kubernetes-release/release/v1.5.1/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/`
- minikubeのインストール
    - `curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.14.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/`

## completionの適用

CLIで作業をおこなうので、zsh等で自動補完を適応しておくと便利

```bash
$ source <(kubectl completion zsh)
```

## クラスタの作成

まず、minikubeクラスタを立ち上げる。

`minikube start`

実行してみると、kubectl上でクラスタが作成されていることが確認出来る

```bash
# kubectlのバージョン確認
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.1", GitCommit:"82450d03cb057bab0950214ef122b67c83fb11df", GitTreeState:"clean", BuildDate:"2016-12-14T00:57:05Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.1", GitCommit:"82450d03cb057bab0950214ef122b67c83fb11df", GitTreeState:"clean", BuildDate:"1970-01-01T00:00:00Z", GoVersion:"go1.7.1", Compiler:"gc", Platform:"linux/amd64"}

# kubectlのクラスタ状況
$ kubectl cluster-info
Kubernetes master is running at https://localhost:8443
KubeDNS is running at https://localhost:8443/api/v1/proxy/namespaces/kube-system/services/kube-dns
kubernetes-dashboard is running at https://localhost:8443/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

# kubectlのノード状態
$ kubectl get nodes
NAME       STATUS    AGE
minikube   Ready     6m
```

## コンテナのデプロイ

クラスタが作成された状態であれば、containerizedされたアプリケーションをデプロイできるようになる。

`kubectl run <デプロイ名> --image=<DockerImage名> --port=<ポート番号>`

デプロイ一覧は下記で確認可能

```bash
$ kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy       1         1         1            0           1m
```

これでデプロイはできたが、このままだとクラスタ内のみからのアクセスだけ許可されている状態となるのでexposeする必要がある

```bash
$ kubectl proxy

# 別タブで下記を実行
$ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
$ echo $POD_NAME
fpm-443137322-c4h5j
$ curl http://localhost:8001/api/v1/proxy/namespaces/default/
pods/$POD_NAME/
# 実行結果の表示
```

## Pod

これでkubernetesでいうPodというものが作成される。Podはいくつかのコンテナの集まりであり、一つのサービスとして複数のコンテナを集めるときに使えるもの。

例えばLaravelでのnginx + fpm + Mysqlみたいな感じで一つのPodにまとめる

逆にIPを別にしたい場合は違うPodにするのがいい。

## Node

そしてそれをまとめているのがNodeと呼ばれる。Node内での通信は`Kubelet`というもので通信されている。アプリケーションはDockerなどのcontainer runtimeによって動く

## 実行

コンテナ内でコマンドを直接実行する場合は`kubectl exec -it <Pod名> bash`で実行できる

## Service

Podの塊で、なにかしらの機能を実現するものをServiceと呼ぶ。LoadBalancingやNodePort(NAT)の実現で使う。
minikubeではLBの指定は今のところ出来ない模様。`--type`オプションで指定する

minikubeではデフォルトで`kubernetes`というサービスが作成されている

```bash
$ kubectl get service
NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   10.0.0.1     <none>        443/TCP   1d
```

NodePortでサービスを作成する場合は`kubectl expose <リソースタイプ> <リソース名> --type="NodePort" --port <ポート番号>`
※ チュートリアルでは `<リソースタイプ>/<リソース名>`とスペースではなくスラッシュで指定しているようだが、現在のcliだとコマンド補完ができなくなっているみたい

```bash
$ kubectl describe service fpm2 
Name:                   fpm2
Namespace:              default
Labels:                 run=fpm2
Selector:               run=fpm2
Type:                   NodePort
IP:                     10.0.0.179
Port:                   <unset> 8080/TCP
NodePort:               <unset> 31147/TCP
Endpoints:
Session Affinity:       None
No events.
```

作成されているのが確認できる

### Label

ServiceにはLabelを作成でき、Serviceに所属するコンテナに名前をつけられる

上記のコマンドで実行すると、自動的に`run=<デプロイ名>`でラベルが作成されている。

```bash
$ kubectl get deployment -o go-template='{{range .items}}{{.metadata.labels}}{{end}}{{"\n"}}'
map[run:fpm2]
```

`kubectl get` や `kubectl describe`などで`-l`コマンドでラベル名を指定してあげることで、そのラベルの該当処理を行うことができる
ラベルの更新は`kubectl label pod <Pod名> app=1`のような形で更新できる。

### Serviceの削除

`kubectl delete service -l <label名>`で削除できる。service自体は削除されているが、Pod自体は削除されていないので、直接Podに対してコマンドを打つと正常に実行できる

## Scale

ScaleupするとPodがふえ、ScaleDownするとPodが減る。それに応じてNodeのスケジューリングも更新される。
Kubernetesはautoscaleも対応している。

ScaleUpもScaleDownもコマンドは簡単で`kubectl scale deployment <deploy名> --replicas=<レプリカ数>`で指定したレプリカ数に増減することができる

## アップデート

ローリングアップデートに対応しているので、複数のPodに対して、downtime無しでアップデートを行うことができる
スケーリングと同様、Serviceは実行可能なPodのみに対してロードバランシングを行う

アップデートは下記をサポートしている

- containerイメージのアップデートにより、新しい環境へアップデート
- ロールバック
- CI, CDをdowntimeゼロで実行

実行は`kubectl set image deployment <デプロイ名> <コンテナ名>=<イメージの名前>:<イメージのバージョン>`で指定する
実行後ロールバックしたい場合は`kubectl rollout undo deployment <デプロイ名>` ステータスは`kubectl rollout status deployment <デプロイ名>`で確認