CentOS7 kubespray で kubernetes(1.9) cluster を作る - その1 -



# Overview

kubernetes のインストールにはKops, kubeadm など様々なツールがありますが
単に`yum install kubeadm`だけ叩けばよい、ような物でない。

私はAnsible使いなので、この手の類いをコマンド一発、みたいなことを試みるならば
`kubespray` を使うのが良さそう。ということでkubesprayを使った環境作りの記録を残します。

既にQiitaにも先人の知恵があり、こちらなどがそうなのですが
1年以上前の記事と言うことで大分勝手が変わっている様子。

https://qiita.com/albatross/items/7f472a973d0c04041a4d

ちなみに私もインストール環境は vSpere ESXiの上にCentOS（ただし、7.4） を入れてインストール環境を用意しました。

# Scope of Work

1. kubesprayを使ったkubernetes のインストール
2.  kube-dashboard の表示
3.  後片付け


# インストール環境

| ホスト名 | IPアドレス | 別名 | 役割 |
|:---:|:---:|:---:|:---:|
|k8master01.localdomain|192.168.240.175|k8master01| Master + Node + Etcd |
|k8master02.localdomain|192.168.240.169|k8master02| Master + Node + Etcd |
|k8node01.localdomain|192.168.240.160|k8node01| Node + Etcd |
|k8node02.localdomain|192.168.240.168|k8node02| Node |
|kargo.localdomain|192.168.240.185|N/A| kubespray 実行ホスト |

IPアドレスが連番では無いのは、用意した環境でIPアドレスが連番では無かったから。

# 基本方針

- ベースの手順はこちら
 - https://kubernetes.io/docs/getting-started-guides/kubespray/
- kubespray-cli は使わない
 - ここを見るとよくわかるが、要するにansible を叩いている。
 - https://github.com/kubespray/kubespray-cli
 - というか、no longer maintain って書いてあった・・・・。

# 1. kubesprayを使ったkubernetes のインストール

## Install host構築

下記、基本パッケージインストールと、python3(4)のインストールは
拙速のansible playbookを使うと一通りそろえるようになっている。
特にswap offは罠なので忘れるとインストールできないので注意が必要。
なお、まだREADMEもろくに書いていないがhostsファイルに対象が書いてあるので
そちらについては適宜修正のこと。

- https://github.com/ainamori/ansible-kubespray-prepare　

### 基本パッケージインストール

ansible をインストールすると jinja2は依存関係を解決してインストールされるとは思うが
CentOS7 の Jinja2 は 2.9より古いため、そのままではkubesprayのインストール段階でコケてしまう。
従ってここはpipでjinja2の最新を入れ直す。

```
# yum install -y epel-release
# yum install -y ansible git gcc python-pip python-devel python-netaddr libffi-devel openssl-devel
# pip install pip --upgrade
# pip install jinja2
```

### python3 系のインストール

https://github.com/kubernetes-incubator/kubespray/blob/master/docs/getting-started.md#starting-custom-deployment

直接、ansible のInventoryファイルを理解した上で、編集できるのであれば不要だが、inventory generatorを使うのであれば
python3が必要なので、こちらを入れておく。

```
# yum install python34
```

### kubespray の取得

自分向けに編集するならば以下を元に、編集しupstreamを取り込めるようにするとよい、とあるが
pushすると公開されちゃうから、込み入った情報は書くな！ともある他、一度作成したplaybookをupstramから
更にアップデート取得することはあまり考えられないので、単純にcheckoutとする。
https://github.com/kubernetes-incubator/kubespray/blob/master/docs/integration.md

```
 # git https://github.com/kubernetes-incubator/kubespray.git
```

### inventory ファイルの編集

先ほどのIPアドレスに合わせてinventoryファイルを修正する。
直接編集してもよいが、自分用のinventoryを作るときは copy して my_inventoryを作れ、とあるので
そこはおとなしく従う。

```
 # cd kubespray-cli
 # cp -r inventory my_inventory
 # vi my_inventory/inventory.cfg
```

inventory.cfg

```
[all]
k8master01       ansible_host=192.168.240.169 ip=192.168.240.169
k8master02       ansible_host=192.168.240.175 ip=192.168.240.175
k8node01         ansible_host=192.168.240.160 ip=192.168.240.160
k8node02         ansible_host=192.168.240.168 ip=192.168.240.168

[kube-master]
k8master01
k8master02

[kube-node]
k8master01
k8master02
k8node01
k8node02

[etcd]
k8master01
k8master02
k8node01

[k8s-cluster:children]
kube-node
kube-master

[calico-rr]

[vault]
k8master01
k8master02
k8node01

[all:vars]
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_pass=ssh_password
ansible_sudo_pass=root_password
```

ssh　はあらかじめキーを登録し、ログインできるようにしておく。
ansible playbook を見るとわかるが become が入っているので root　化は必須。
rootログインで入ってしまってもよいが、 sudo を仕込む方が本来は正しいと思う。
最後の4行はその辺りのおまじない。

## kubenetes インストール

環境ファイルのIPアドレス修正が終わったら以下を実行するのみ。

```
 # ansible-playbook -i my_inventory/inventory.cfg cluster.yaml -v
```

以下のように全て通ればOK。

```
PLAY RECAP **********************************************************************************************************************************************************************************
k8master01                 : ok=349  changed=111  unreachable=0    failed=0   
k8master02                 : ok=307  changed=105  unreachable=0    failed=0   
k8node01                   : ok=269  changed=85   unreachable=0    failed=0   
k8node02                   : ok=226  changed=65   unreachable=0    failed=0   
localhost                  : ok=2    changed=0    unreachable=0    failed=0   

Tuesday 30 January 2018  06:24:09 +0900 (0:00:00.035)       0:59:00.958 ******* 
=============================================================================== 
download : container_download | Download containers if pull is required or told to always pull (all nodes) ------------------------------------------------------------------------ 1034.29s
download : container_download | Download containers if pull is required or told to always pull (all nodes) ------------------------------------------------------------------------- 484.70s
download : container_download | Download containers if pull is required or told to always pull (all nodes) ------------------------------------------------------------------------- 262.40s
kubernetes/preinstall : Update package management cache (YUM) ---------------------------------------------------------------------------------------------------------------------- 228.95s
docker : ensure docker packages are installed -------------------------------------------------------------------------------------------------------------------------------------- 151.51s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 99.80s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 96.86s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 73.80s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 67.56s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 65.78s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 65.08s
download : container_download | Download containers if pull is required or told to always pull (all nodes) -------------------------------------------------------------------------- 56.23s
kubernetes/preinstall : Install packages requirements ------------------------------------------------------------------------------------------------------------------------------- 56.05s
etcd : Configure | Join member(s) to cluster one at a time -------------------------------------------------------------------------------------------------------------------------- 20.34s
etcd : Configure | Join member(s) to cluster one at a time -------------------------------------------------------------------------------------------------------------------------- 20.32s
kubernetes/secrets : Check certs | check if a cert already exists on node ----------------------------------------------------------------------------------------------------------- 18.30s
kubernetes/master : Master | wait for the apiserver to be running ------------------------------------------------------------------------------------------------------------------- 14.32s
kubernetes/node : install | Copy kubelet from hyperkube container ------------------------------------------------------------------------------------------------------------------- 12.19s
etcd : reload etcd ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 11.25s
docker : Docker | pause while Docker restarts --------------------------------------------------------------------------------------------------------------------------------------- 10.40s

```

## kubernetes インストール後


### kubernetes 環境の確認

セットアップが完了すると kubectl コマンドで様々な事ができる
まずは、状況の確認。

```
 # ssh k8master01
```

- Version の確認

```
# kubectl version
Client Version: version.Info{Major:"", Minor:"", GitVersion:"v1.9.0+coreos.0", GitCommit:"1b69a2a6c01194421b0aa17747a8c1a81738a8dd", GitTreeState:"clean", BuildDate:"2017-12-19T02:52:15Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"", Minor:"", GitVersion:"v1.9.0+coreos.0", GitCommit:"1b69a2a6c01194421b0aa17747a8c1a81738a8dd", GitTreeState:"clean", BuildDate:"2017-12-19T02:52:15Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
```

- Cluster info

```
 # kubectl cluster-info
Kubernetes master is running at https://192.168.240.169:6443
KubeDNS is running at https://192.168.240.169:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
```
[kubernetes の tutorial[(https://kubernetes.io/docs/tutorials/kubernetes-basics/cluster-interactive/)
 を実行すると dashborad, grafana そして influxdb が動いていたりするので、kubespray の default は最小限で動作しているようだ


- get node(s)

```
 # kubectl get nodes

NAME         STATUS    ROLES         AGE       VERSION
k8master01   Ready     master,node   56m       v1.9.0+coreos.0
k8master02   Ready     master,node   56m       v1.9.0+coreos.0
k8node01     Ready     node          56m       v1.9.0+coreos.0
k8node02     Ready     node          56m       v1.9.0+coreos.0
```
get node でも　get nodes でも動作するようだ。

- get namespace

```
 # kubectl get namespaces

NAME          STATUS    AGE
default       Active    57m
kube-public   Active    57m
kube-system   Active    57m
```

- get pods all-namespaces

```
 # kubectl get pods --all-namespaces

NAMESPACE     NAME                                    READY     STATUS    RESTARTS   AGE
kube-system   kube-apiserver-k8master01               1/1       Running   0          56m
kube-system   kube-apiserver-k8master02               1/1       Running   0          56m
kube-system   kube-controller-manager-k8master01      1/1       Running   0          57m
kube-system   kube-controller-manager-k8master02      1/1       Running   0          57m
kube-system   kube-dns-6444ff8d8b-qdksn               3/3       Running   0          55m
kube-system   kube-dns-6444ff8d8b-xfhtp               3/3       Running   0          55m
kube-system   kube-flannel-4kf8n                      2/2       Running   0          56m
kube-system   kube-flannel-cfzjc                      2/2       Running   0          56m
kube-system   kube-flannel-gf584                      2/2       Running   0          56m
kube-system   kube-flannel-wk7cd                      2/2       Running   0          56m
kube-system   kube-proxy-k8master01                   1/1       Running   0          56m
kube-system   kube-proxy-k8master02                   1/1       Running   0          56m
kube-system   kube-proxy-k8node01                     1/1       Running   0          56m
kube-system   kube-proxy-k8node02                     1/1       Running   0          56m
kube-system   kube-scheduler-k8master01               1/1       Running   0          57m
kube-system   kube-scheduler-k8master02               1/1       Running   0          57m
kube-system   kubedns-autoscaler-58d9fbcbf6-lmm8c     1/1       Running   0          55m
kube-system   kubernetes-dashboard-75c5ff6844-wnnjv   1/1       Running   0          55m
kube-system   nginx-proxy-k8node01                    1/1       Running   0          56m
kube-system   nginx-proxy-k8node02                    1/1       Running   0          56m
```

### テストサービスの作成

master ホストにログインし、実際にpodを建ててみる。
幸い、ちょうど良いサンプルが公開されているので sock-shopを使ってやってみる。

- Create namespace
 - 後述のyamlを見るとわかるがnamespace指定があるので事前にnamespaceを作っておく
 
```
 # kubectl create namespace sock-shop
　# $ kubectl get namespace
NAME          STATUS    AGE
default       Active    1h
kube-public   Active    1h
kube-system   Active    1h
sock-shop     Active    4s
```

- service pod の作成

```
 # kubectl create -f "https://github.com/microservices-demo/microservices-demo/blob/master/deploy/kubernetes/complete-demo.yaml?raw=true"
deployment "carts-db" created
service "carts-db" created
deployment "carts" created
service "carts" created
deployment "catalogue-db" created
service "catalogue-db" created
deployment "catalogue" created
service "catalogue" created
deployment "front-end" created
service "front-end" created
deployment "orders-db" created
service "orders-db" created
deployment "orders" created
service "orders" created
deployment "payment" created
service "payment" created
deployment "queue-master" created
service "queue-master" created
deployment "rabbitmq" created
service "rabbitmq" created
deployment "shipping" created
service "shipping" created
deployment "user-db" created
service "user-db" created
deployment "user" created
```

- 進捗確認

```
 # kubectl get pod --namespace=sock-shop                                                                                                                                  
NAME                            READY     STATUS              RESTARTS   AGE
carts-74f4558cb8-d75ps          0/1       ContainerCreating   0          1m
carts-db-7fcddfbc79-6mk2z       0/1       ContainerCreating   0          1m
catalogue-676d4b9f7c-qzjpf      0/1       ContainerCreating   0          1m
catalogue-db-5c67cdc8cd-tqgtc   0/1       ContainerCreating   0          1m
front-end-977bfd86-6g49s        0/1       ContainerCreating   0          1m
orders-787bf5b89f-wdpvb         0/1       ContainerCreating   0          59s
orders-db-775655b675-jmm4l      0/1       ContainerCreating   0          59s
payment-75f75b467f-js97s        0/1       ContainerCreating   0          59s
queue-master-5c86964795-4pnn8   0/1       ContainerCreating   0          59s
rabbitmq-96d887875-vvx78        0/1       ContainerCreating   0          59s
shipping-5bd69fb4cc-tzw2f       0/1       ContainerCreating   0          59s
user-5bd9b9c468-jqs6s           0/1       ContainerCreating   0          59s
user-db-5f9d89bbbb-xz7s5        0/1       ContainerCreating   0          59s
```
これはまだ作成中。 STATUS が　全て Running になるまで待つ。

```
 # kubectl get pod --namespace=sock-shop
NAME                            READY     STATUS    RESTARTS   AGE
carts-74f4558cb8-d75ps          1/1       Running   0          20m
carts-db-7fcddfbc79-6mk2z       1/1       Running   0          20m
catalogue-676d4b9f7c-qzjpf      1/1       Running   0          20m
catalogue-db-5c67cdc8cd-tqgtc   1/1       Running   0          20m
front-end-977bfd86-6g49s        1/1       Running   0          20m
orders-787bf5b89f-wdpvb         1/1       Running   0          20m
orders-db-775655b675-jmm4l      1/1       Running   0          20m
payment-75f75b467f-js97s        1/1       Running   0          20m
queue-master-5c86964795-4pnn8   1/1       Running   0          20m
rabbitmq-96d887875-vvx78        1/1       Running   0          20m
shipping-5bd69fb4cc-tzw2f       1/1       Running   0          20m
user-5bd9b9c468-jqs6s           1/1       Running   0          20m
user-db-5f9d89bbbb-xz7s5        1/1       Running   0          20m
```
こうなったらOK。


- フロントエンドのIPアドレス確認

```
　# kubectl describe service front-end -n sock-shop                                                                                                                        
Name:                     front-end
Namespace:                sock-shop
Labels:                   name=front-end
Annotations:              <none>
Selector:                 name=front-end
Type:                     NodePort
IP:                       10.233.33.80
Port:                     <unset>  80/TCP
TargetPort:               8079/TCP
NodePort:                 <unset>  30001/TCP
Endpoints:                10.233.111.195:8079
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
```
- これでどのポートが公開されているのかがわかる。
 - NodePort -- 30001 がそれ
 
従って以下へアクセスすれば、sock-shopのデモが動いているのが確認できる。

 http://192.168.240.175:30001

# 2. kube-dashboard の表示

## kube-dashboard 状態確認

kubespray をインストールするとdashboardもインストールされる。
とはいえ、下記の通り内部にしかListenしていないのでそのままではアクセスできない。

```
 # kubectl -n kube-system get service kubernetes-dashboard
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes-dashboard   ClusterIP   10.233.24.184   <none>        443/TCP   19h
```

## kube proxy の起動

kubernetes の状況を確認するツールとして Dashboard がある。
インストールされた時点で利用は可能でアクセスもできるのだが、
以下のような画面になり利用できない。

https://192.168.240.175:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login

![kubernetes-dashboad-6443.png](https://qiita-image-store.s3.amazonaws.com/0/82979/fbb4c892-2e83-a1bd-e138-cecfd2ef63f9.png)


API経由で表示しているだけなので、dashboardアクセスとは異なる様子。
従って proxy を起動して dashboard そのものを表示してやる。
下のコマンドよりは上のコマンドの方がよさそう。
accept-hosts でドメインやIPアドレスが指定できるならば細かく書いてやる方が良い。

```
 # kubectl proxy --address 0.0.0.0 --accept-hosts '.*'
  OR
 # kubectl proxy --address 0.0.0.0  --disable-filter=true
```

これで以下のURLを叩くとdash boardを見ることができる。

http://192.168.240.175:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login

![kubernetes-dashboard-02.png](https://qiita-image-store.s3.amazonaws.com/0/82979/b2590bd3-9fdf-3e2e-6e15-645f8a470198.png)


ちなみに accept-hosts や disable-filter を書けないと
アクセスはできてもやはり auth fail として何も表示されない。

![kubernetes-dashboard-01.png](https://qiita-image-store.s3.amazonaws.com/0/82979/037bf035-4ade-7bfb-bc41-3b1578430691.png)


## フルコントロールの付与

ただし、これでもまた権限不足で情報表示ができないため、以下の設定を入れてあけてやる。

```
 # kubectl create -f dashboard-admin.yaml
```

dashboard-admin.yaml は、以下の通り 公式ドキュメントをコピペして作る。
https://github.com/kubernetes/dashboard/wiki/Access-control#bearer-token

```
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
```

これを叩いてやるとログインの最初に出る以下の場所で SKIP としても
全ての情報が表示されるようになる。

![kubernetes-dashboard-03.png](https://qiita-image-store.s3.amazonaws.com/0/82979/409b253d-d349-cc62-7649-3d5cbbc8c1ff.png)

 
# 3. 後片付け

## kubenetes master / node の削除

とりあえず一通り動いたと言うことで、環境の削除。
なぜならばサービスホストのIPアドレス空間など、インストール時に設定しておかなければ
後から修正できないような項目があるため。

```
 # ansible-playbook -i my_inventory/inventory.cfg reset.yaml -v
```

# ハマりどころ

- ansible がホストの環境パラメータを持ってしまう
 - /tmp/<hostname> として gather_info が記録されている。
   これがあると、ホストの収集情報が更新されず、パラメータ不良を直しても幾度となくコケることになる。
   retryの際には必ず、消してからやり直しましょう。

# 続き

今回はあくまで、インストールだけを主眼に置いているため
これさえやれば動く。というところしか書いていない。

Dashboardへのアクセス制御も極めてずさんなため、
次回以降で、細かくパラメータを見ていくことにする。

- [CentOS7 kubespray で kubernetes cluster を作る - dashboard -](https://qiita.com/ainamori/items/292f5a2848c5ed409088)
- [CentOS7 kubespray で kubernetes cluster を作る - deploy application -](https://qiita.com/ainamori/items/8e4208940162677c51f2)