dockerマネジメントツール：痛くないKubernetesメモ帳

# 経緯
dockerを導入してからその便利さがますます実感する。本当にコンテナさまさましか思えないほどだった。ですが、コンテナ数がweb service stackとともに増加しつつ、管理上も複雑になる。
加えて肝心なデータ解析ファームの**GPUリソース**の利用状況は理想とは言切れない。
~~目当てはGPUスケジュール機能でした。~~

# 始めよう
## システム配置
- ubuntu 16.04
- docker 1.13.1また17.09
- nvidiaグラフィックカードとドライバ

## Kubernetesを設置
Kubernetesという名前は少々長いので、幸い開発コミュニティが**k8s**というあだ名を呼び始めた。下記もk8sを書きします。
オフィシャル[ドキュメント](https://kubernetes.io/docs/setup/independent/install-kubeadm/)に記載されている手順をおすすめします。

### kubeadmとkubeletとkubectlをインストール
dockerがインストール済みという前提として、ホストにkubeadm、kubeletとkubectlをインストールする。

```shell-session:pre-install.sh
apt-get update && apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
```
## クラスタを作る
![cluster_pod.png](https://qiita-image-store.s3.amazonaws.com/0/211063/d4f03c54-9bb3-7101-9d68-abf98426e0d8.png)

k8sで構築されたクラスタ、コンテナの管理はポッド(POD)という単位で行われる。一つのポッドに一個以上のコンテナが含まれる。
k8sを通ってポッドをクラスタ内のノードへ投げることで、ロードバランシングを容易にすることができます。


### Masterノードを設置
クラスタを立ち上げるの第一歩はMasterノードを決めます。ノードのリソース利用状態監視やコンテナ管理はすべてMasterノード上で行います。

```console
$ kubeadm init
```
### ネットワークポッドを設置
このステップはすごく重要で、間違えばクラスタは色々な問題が発生する可能性があります。
ドキュメントでは幾つの[ネットワークアドオン](https://kubernetes.io/docs/concepts/cluster-administration/addons/)を紹介されますが、ここは[Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/)を使います。
アドオンと言いますが、実際はコンテナ化され、一連のポッドになりました。

```console
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
```

大半は以上のコマンドをbashに入力して、設置が完了です、が
バーチャルマシンやフィジカルマシンの接続環境によって、そう上手くいかないと思います。
だからポッド定義ファイルをダウンロードして、必要の部分を編集し、またネットワークポッドを設定するのは得策。
[Weave Netポッド定義ファイル](https://github.com/weaveworks/weave/releases)をダウンロード
`$ Curl -O -L https://cloud.weave.works/k8s/v1.7/net`
例：プライベートIPアドレスを編集する

```yaml:net.yaml
...
containers:
        - name: weave
          env:
            - name: IPALLOC_RANGE
              value: 10.0.0.0/16
...
```
編集完了の定義ファイルをクラスタに適用する。

```console
$ kubectl apply -f net.yaml
```

さて、次はWorkerノードをMasterノードに登録します。

### GPU機能を有効にする
Workerノードに搭載されたGPUを利用できるのために、Workerノードに相応の設定は必要です。
`nano /etc/systemd/system/kubelet.service.d/10-kubeadm.conf`
設定ファイルを開けると、中身はこんな感じ。
![gpu_feature.png](https://qiita-image-store.s3.amazonaws.com/0/211063/c8af96ce-d95e-9b8f-5cf3-7088f318e9e9.png)

```control:10-kubeadm.conf
...
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS --feature-gates="Accelerators=true [...]"
...

```
設定完了後、serviceを再起動します。

```console:restart-kubelet.sh
systemctl daemon-reload
systemctl restart kubelet
```
### - ホストは一台だけ
広義的にホスト一台だけでもクラスタを構築できます。あるいはMasterノード自身もWorkerノードとして働くことです。

```console
$ kubectl taint nodes --all node-role.kubernetes.io/master-
```
### - ホストは二台以上の場合
一般的にクラスタはMasterノードとWorkerノードに分かれている。Workerノードから登録するには、Masterノード設置完了のメッセージの中にいる下記のようなコマンドを入力する。

```console
$ kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>
```

## インストール後の手順
ここまでは多分気付いたと思う、上記のコマンドは**sudo**がないです。k8sのインストールからクラスタ設置まで、全部**root**権限です。
実はクラスタを設置する際にsudo権限だけでいい。root権限はすごいですが、しかし気付かない内にどこのファイルが消された状況もある。
だから、なるべくroot権限使用しなくていい。
ここでsudo権限があるアカウントをk8sにアクセスの権限を付与する。

```console:post-install.sh
cp /etc/kubernetes/admin.conf $HOME/
chown $(id -u):$(id -g) $HOME/admin.conf
echo "export KUBECONFIG=$HOME/admin.conf" >> ~/.bashrc
echo "source <(kubectl completion bash)" >> ~/.bashrc
```

# まとめ
k8sを利用することで、複数ホストにおけるコンテナ管理は楽になりますでしょう。
しかしホスト数が少ない場合は、k8s本来の目的、データセンターのような規模でコンテナ管理の機能は多分実感がないと思います。
まだ突然k8sに突っ込んって、すぐに壁にぶち当たるの可能性もある。だから状況によって、適切なツールを利用するこそがオーケストラ。
下記のは同じくdockerコンテナマネジメントツール、どちらもコンテナのままで配置することができます。
[portainer](https://portainer.io/) ([github](https://github.com/portainer/portainer))
[rancher](http://rancher.com/rancher/) ([github](https://github.com/rancher/rancher))

参考資料
- [Kubernetesオフィシャルドキュメント](https://kubernetes.io/docs/setup/independent/install-kubeadm/)