kubernetes on OpenStack Queens

**OpenStack Queens** 上にVM3つ立ててk8sの確認。
**kubeadm**（実施時β）で構築。

> 後で、kuberenetes-dashboard導入時に外からのWebUI表示が上手くいかなかったので外側のネットワークはブリッジ接続にした。（「考察」参考）

![2018-05-05 10-39-19.jpg](https://qiita-image-store.s3.amazonaws.com/0/75458/20c4f6fa-a3ae-382d-8392-0a4792e37015.jpeg)

#環境

* インスタンス情報
  * CPU x 2
  * Memory 2GB
  * Disk 20GB

#準備

* インスタンスを3つたてる（少ないので適当に手動）
* Ubuntu 16.04 を利用
* kubernetes v1.10.2
* ローカルのDNS Server（192.168.0.2）に登録

# kubeadm 等インストール

雑だが、Ansible Playbookによりざっと作る。

* Ansible (OpenStack Host)：192.168.0.3
* Master x1：192.168.0.60
* Worker Node x2：192.168.0.61,192.168.0.61

https://github.com/tksarah/k8s_ansible/blob/master/setup_k8s.yml

```yaml
clientVersion:
  buildDate: 2018-04-27T09:22:21Z
  compiler: gc
  gitCommit: 81753b10df112992bf51bbc2c2f85208aad78335
  gitTreeState: clean
  gitVersion: v1.10.2
  goVersion: go1.9.3
  major: "1"
  minor: "10"
  platform: linux/amd64
serverVersion:
  buildDate: 2018-04-27T09:10:24Z
  compiler: gc
  gitCommit: 81753b10df112992bf51bbc2c2f85208aad78335
  gitTreeState: clean
  gitVersion: v1.10.2
  goVersion: go1.9.3
  major: "1"
  minor: "10"
  platform: linux/amd64
```


## インストール後の確認補足
https://kubernetes.io/docs/setup/independent/install-kubeadm/

**Configure cgroup driver used by kubelet on Master Node**

kubelet により使われる --cgroup-driver を合わせる。
> Ubuntu はデフォルトで cgroupfs , Fedora/CentOS/RHELは systemd


# クラスタ・セットアップ

https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/

## Master

Pod内ネットワークは**Flannel**を使う。

```shell-session
# kubeadm init --pod-network-cidr=10.244.0.0/16
```

kubectlをrootでないユーザで実行するための環境セットアップ。

```shell-session
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
```
> この時点では kube-dns は Pennding

Podネットワークを構成

```shell-session
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
```
> この後、Master が Readyに

```shell-session
$ kubectl -n kube-system get pod
NAME                                      READY     STATUS    RESTARTS   AGE
etcd-master-1.tk.net                      1/1       Running   0          2m
kube-apiserver-master-1.tk.net            1/1       Running   1          3m
kube-controller-manager-master-1.tk.net   1/1       Running   0          3m
kube-dns-86f4d74b45-wjdqq                 3/3       Running   0          2m
kube-flannel-ds-sl5n4                     1/1       Running   0          1m
kube-proxy-d4945                          1/1       Running   0          2m
```

## Node 
Worker Nodeを追加（追加するノード上、rootで）

```shell-session
# kubeadm join 192.168.0.60:6443 --token gw2eln.tp133sqp4c5mudqj --discovery-token-ca-cert-hash sha256:2a16400b56be121cb6f67301344b40b97ad7a267c92dc46f562ba5bdb8dd84ea
```

> トークン期限が切れたら、 ```kubeadm token create``` で作る

```shell-session
NAME              STATUS    ROLES     AGE       VERSION
master-1.tk.net   Ready     master    6m        v1.10.2
node-1.tk.net     Ready     <none>    36s       v1.10.2
node-2.tk.net     Ready     <none>    22s       v1.10.2
```

# クラスタセットアップ後補足

デフォルトだとMasterにはApp Podがスケジュールされない。もししたいのであれば、以下のコマンドを実行

```shell-session
$ kubectl taint nodes --all node-role.kubernetes.io/master-
```

> * デフォルトで Worker Node が全滅した場合には Master に寄った
> * taint はPodのノードスケジューリングをコントロール

# .kube/config

コンテキストを更新（ここではNamespaceだけの違い）

```shell-session
$ kubectl config set-context devel --cluster=kubernetes --user=kubernetes-admin --namespace=devel
$ kubectl config set-context guestbook --cluster=kubernetes --user=kubernetes-admin --namespace=guestbook
```

```yaml:.kube/config
contexts:
- context:
    cluster: kubernetes
    namespace: devel
    user: kubernetes-admin
  name: devel
- context:
    cluster: kubernetes
    namespace: guestbook
    user: kubernetes-admin
  name: guestbook
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: devel
```

# ダッシュボード

https://github.com/kubernetes/dashboard/

1. ダッシュボードのマニフェスト apply
2. クライアント証明書を作ってブラウザにインポートしブラウザ再起動
3. ダッシュボード用secretを作成
4. WebUIに確認

```shell-session
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
secret "kubernetes-dashboard-certs" configured
serviceaccount "kubernetes-dashboard" created
role.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
deployment.apps "kubernetes-dashboard" created
service "kubernetes-dashboard" created
```

```shell-session
$ grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crt
$ grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key
$ openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client"
```

```shell-session
$ kubectl create secret generic kubernetes-dashboard-certs --from-file=./kubecfg.crt -n kube-system
```

https://192.168.0.60:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

アクセスコントロールついては、下記を参照しプロダクションではNGだが、とりあえず「Admin privileges」を適用。画面上は「Skip」で。

https://github.com/kubernetes/dashboard/wiki/Access-control

```yaml:dashboard-admin.yml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  labels:
    k8s-app: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system
```

```shell-session
$ kubectl create -f dashboard-admin.yml
clusterrolebinding.rbac.authorization.k8s.io "kubernetes-dashboard" created
```

#考察
## kubernetes-dashboardのWebUIが表示できなかった件

インスタンスをPrivate Networkの配下に置き、External NetworkからはFloating IPアドレス経由でアクセスしていた場合、
k8sクラスタ外、且つOpenStackのExternal NetworkからK8sのDashbardにはアクセスできなかった。
ブラウザ上は以下のようなタイムアウト。これはDashboardの問題ではなく、ネットワーク上の問題。

```shell-session
Error: 'dial tcp 10.233.65.9:8443: getsockopt: connection timed out'
Trying to reach: 'http://10.233.65.9:8443/'
```
OpenStack は1ノードで構成されているためトラブルシュートのため、
External Networkへフラット接続するようにブリッジにしてやり直したら、アクセスできるようになった。

# Snippet
## Tear down

構成しなおす時など、クラスタから解除と登録情報削除。

Masterにて、

```shell-session
$ kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
$ kubectl delete node <node name>
```

削除されたNodeにて、（root）

```shell-session
# kubeadm reset
```