Othl Tech#34 ハンズオン手順 Kubernetes/Rancher on さくらのクラウド

# 概要

[Othlo Tech](http://www.othlo.tech/) [#34](https://othlotech.connpass.com/event/91098/) 向けのハンズオン手順です。[Kubernetes](https://kubernetes.io/) でコンテナのオーケストレーション概念を把握するために、kubernetes 構築方法の理解と基本的なコマンド操作を行います。
![kube-othlo-handson.png](https://qiita-image-store.s3.amazonaws.com/0/13002/9ad9a236-1dde-fa02-9a61-b4bfd0c90561.png)

- Kubernetes クラスタを kubectl / kubeadm で構築する
- 作成したクラスタを [Rancher 2.0](https://rancher.com/) に取り込み監視できるようにする
- kubectl コマンドを操作する

以上の作業を[さくらのクラウド](https://cloud.sakura.ad.jp/)上の[VPCルータ](https://manual.sakura.ad.jp/cloud/network/vpc-router/index.html)配下のネットワーク上で構築します。

- Rancher 選定の理由…クラスタ状態やサービス等の状況を把握するためには、kubernetes の [Dashoboard UI](https://github.com/kubernetes/dashboard)よりも初期設定やユーザ権限に関する設定が簡単であり、学習に最適なため。
- VPCルータ on さくらのクラウド選定の理由…ローカル・ネットワーク上にKubernetesクラスタを構築したり、ネットワーク上のサービスをインターネット側へ公開するために、VPCルータのネットワーク・モデルが一般的な学内・社内・家庭内と共通する汎用性があり、Kubernetes学習のためのオーバーヘッドを減らすため。

# A. Kubernetes 環境構築編

## A1. VPCルータと仮想サーバの作成

### A1-1. さくらのクラウドにログイン

[コントロールパネル](https://secure.sakura.ad.jp/cloud/) https://secure.sakura.ad.jp/cloud/ にアクセスします。
画面右側 `さくらのクラウドユーザとしてログイン` へ配布済みのユーザ情報でログインします。

それから `さくらのクラウド IaaS`をクリックします。

### A1-2. 「VPCルータ」を作成

「VPCルータ」機能を使い、クラウド上に外から直接接続できないローカル・ネットワークを構築します。

1. メニューから `VPCルータ`->`追加` をクリック 
2. 「名前」は `myvpc`
3. `作成` をクリック

メニューから `マップ` をクリックすると、画面上にどのように表示されていますか。


### A1-3. 「スイッチ」を作成

VPCルータのネットワークは以下に複数の仮想サーバを置きます。

1. メニューから `ネットワーク`->`スイッチ`をクリック
2. `追加`をクリック
3. 「名前」に `192.168.0.0/24` を入力
4. `作成` をクリック

メニューから `マップ` をクリックすると、画面上にどのように表示されていますか。

### A1-4. VPCルータにスイッチを接続して起動

1. メニューから `アプライアンス` -> `VPCルータ`
2. 「VPCルータ一覧」で `myvpc` をダブルクリック（コピー中の表示の場合は、再読み込みボタンをクリック）
3. `インターフェース` タブをクリックし、「グローバル」にある「IPアドレス」をメモ（後で SSH やブラウザでの表示に使います）
4. 「プライベート１」にある `鉛筆アイコン` をクリックします
5. `既存スイッチを接続`： 「接続先スイッチ」を ``192.168.0.0/24`
6. 「IPアドレス」を `192.168.0.1`
7. 「プリフィックス」を `/24`
7. `更新` をクリック 
8. `反映` をクリック
9. `電源操作` -> `起動` を選び、VPC ルータを起動

メニューから `マップ` をクリックすると、画面上にどのように表示されていますか。

### A1-6. Kubernetes クラスタ用サーバの作成

ここでは4台の仮想マシンを作成します。いずれのサーバのeth0インターフェースを VPC ルータ配下の `192.168.0.0/24` スイッチに対して接続します。

- Kubernetes 用の仮想マシン3台 (192.168.0.21～23）
- Rancher用の仮想マシン1台（192.168.0.11）

1. メニューから `サーバ` -> `追加` をクリック
2. `CentOS 7.5` が選ばれたまま、「サーバプラン」`4GB / 2 仮想コア` を選択
3. 「接続先のネットワーク」を `スイッチ` にし、 `192.168.0.0/24` を選択
4. 「サーバの設定」で「IPアドレスの設定」を `固定IPアドレスの利用` を選択
5. 「IPアドレス」は `192.168.0.11`
6. 「ネットマスク」は `24`（デフォルト）
7. 「ゲートウェイ」は `192.168.0.1`（VPCルータ側）を入力
8. 「管理ユーザのパスワード」（英数字・記号混在が望ましい）を入力
9. 「ホスト名」は `rancher` と入力
10. `作成` をクリック
11. 「確認画面」で `作成` をクリックし `閉じる` をクリック
12. 手順5～11 を以下のIPアドレス・ホスト名で繰り返す。

- 192.168.0.21 - kube1
- 192.168.0.22 - kube2
- 192.168.0.23 - kube3

メニューから `マップ` をクリックすると、画面上にどのように表示されていますか。

## A3. Rancher セットアップ

Rancher用の「192.168.0.11」を作業用サーバとして使います。VPC ルータ以下のネットワークには直接ログインできません。リモートアクセス（PPTPまたはL2TP/IPsec）用のアカウントを作成するか、インターネット側から SSH 用のポートを NAT します。それから Rancher を動かすために Docker をセットアップします。

### A3-1. Rancher 用サーバに SSH ログイン

1. メニュー `アプライアンス` -> `VPCルータ` から `NAT` タブをクリックし、`追加` をクリック
2. プロトコル `TCP` 、「グローバル側ポート番号」`10022`、「プライベート側IPアドレス」`192.168.0.11`、「プライベート側IPアドレス」`22`を入力し、`追加`
3. `反映` をクリック
4. `ssh -l root <VPCルータのIP> -p 10022` を入力して rancher(192.168.0.11) にログイン

`traceroute www.sakura.ad.jp` や `ip route` コマンドを実行して、何か気づきますか？

### A3-2. Docker と Rancher のセットアップ

1. Docker(Docker Engine)をセットアップするため、以下のコマンドを実行します。

```
curl -fsSL get.docker.com -o get-docker.sh
sh ./get-docker.sh
systemctl enable docker && systemctl start docker
```

2.`docker version` を実行し、`Server:` 行が表示されるのを確認します。

```
# docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a
 Built:             Tue Aug 21 17:23:03 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.1-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       e68fc7a
  Built:            Tue Aug 21 17:25:29 2018
  OS/Arch:          linux/amd64
  Experimental:     false
```

4.Rancherのセットアップ

```
docker run -d --restart=unless-stopped \
-p 80:80 -p 443:443 \
rancher/rancher:latest
```

docker ps で確認：

```
[root@rancher ~]# docker ps
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS                                      NAMES
a935d58a1d39        rancher/rancher:latest   "entrypoint.sh"     3 seconds ago       Up 1 second         0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   condescending_meninsky
```

5.VPCルータでNAT設定を追加

`VPCルータ` -> `NAT` -> `追加`をクリックし

- プロトコル：TCP
- グローバル側：443
- プライベート側IPアドレス：192.168.0.11
- プライベート側ポート番号：443

`追加` -> `反映` をクリック。

### A3-3. Rancher 初期セットアップ

1. ブラウザで `https://<VPC-IP>/` にアクセス（ブラウザ側で SSL 証明書に関するセキュリティ例外の追加が必要）
2. `Set a specific password to use`（使用するパスワードを指定）をクリックし、「New Password」「Confirm Password」にパスワードを入力し、 `Continue` をクリック
3. 「Rancher Server URL」はそのまま `Save URL` をクリック

Rancher の管理画面が開くので、様々な操作をします。

表示言語を切り替えるには、右下にある `English` をクリックし、`日本語 (ja-jp)` をクリックします。

## A4. Kubernetes セットアップとクラスタ構築

Rancher(192.168.0.11)を経由して、kuberntesサーバにログインし、kubeletやkubeadmなど関連パッケージをセットアップします。

### A4-1. 初期セットアップ

kubenetes の CNI ( Container Network Interface) は Flannel を使います。

1.kube1(192.168.0.21)、kube2(192.168.0.22)、kube3(192.168.0.23)、の各サーバに SSH でログイン

2.セットアップ用のコマンドを実行します（リポジトリのセットアップ、パッケージのセットアップ、kubeletの起動）

```
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
```

3.swap を無効化します（kubeletが起動しません。なぜだか分かりますか？）

```
/sbin/swapoff -a
```

`free` コマンドを実行して、swap の無効化を確認します。

サーバを再起動する場合は、 `/etc/fstab` からも swap を有効にするエントリを削除しておきます。

4.作業を簡単にするため firewalld を停止します。

```
systemctl stop firewalld && systemctl disable firewalld
```

5.Docker をセットアップします。

```
curl -fsSL get.docker.com -o get-docker.sh
sh ./get-docker.sh
systemctl enable docker && systemctl start docker
```


6.kube1 のみクラスタ初期化コマンドを実行します。

```
kubeadm init --pod-network-cidr=10.244.0.0/16
```

しばらく待ちます。

正常に処理が終わると、次のような文字列が画面に出ます。

```
Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 192.168.0.21:6443 --token n5f3gr.c3enfuqrftc6tvqw --discovery-token-ca-cert-hash sha256:e0fff6e419121483a453a3cb886882dd9b9fb64ec3ac16a38b32c8c11704271b
```

7.kubectl 用の設定ファイルをコピーします。

```
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
```

8.`kubectl version` を実行します。

```
# kubectl version
Client Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.2", GitCommit:"bb9ffb1654d4a729bb4cec18ff088eacc153c239", GitTreeState:"clean", BuildDate:"2018-08-07T23:17:28Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.2", GitCommit:"bb9ffb1654d4a729bb4cec18ff088eacc153c239", GitTreeState:"clean", BuildDate:"2018-08-07T23:08:19Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
```

9.ノード一覧を表示します。

```
# kubectl get nodes
NAME      STATUS     ROLES     AGE       VERSION
kube1     NotReady   master    3m        v1.11.2
```

10.CoreDNS の Pod が起動していないのを確認します。どのような状態ですか？


```
# kubectl get pods --all-namespaces
NAMESPACE     NAME                            READY     STATUS    RESTARTS   AGE
kube-system   coredns-78fcdf6894-drjc4        0/1       Pending   0          4m
kube-system   coredns-78fcdf6894-xs7tm        0/1       Pending   0          4m
kube-system   etcd-kube1                      1/1       Running   0          3m
kube-system   kube-apiserver-kube1            1/1       Running   0          3m
kube-system   kube-controller-manager-kube1   1/1       Running   0          3m
kube-system   kube-proxy-mnqzt                1/1       Running   0          4m
kube-system   kube-scheduler-kube1            1/1       Running   0          3m
```

11.CNI の flannel をセットアップします。

```
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml
```

それから

```
kubectl get pods --all-namespaces
watch -n 1 !!
```

を実行して様子を見ます。どのような変化がありますか？

12.kube1(192.168.0.21)ではノード一覧を表示し続けます。

```
kubectl get nodes
watch -n 1 !!
```

13.kube2(192.168.0.22)、kube3(192.168.0.23)でノード追加用コマンドを実行します。

※先ほどkubeadm initコマンド実行時に表示された`kubeadm join`コマンドです。以下の通り実行してもトークンが違うため、正常にクラスタに対してノードが追加できません。

```
kubeadm join 192.168.0.21:6443 --token n5f3gr.c3enfuqrftc6tvqw --discovery-token-ca-cert-hash sha256:e0fff6e419121483a453a3cb886882dd9b9fb64ec3ac16a38b32c8c11704271b
```

この時、kube1 側の出力はどのようになっていますか？

以上で Kubernetes のセットアップは完了しました。

例：

- Example: Deploying PHP Guestbook application with Redis - Kubernetes
  - https://kubernetes.io/docs/tutorials/stateless-application/guestbook/

次のコマンドを実行して、Guestbook を起動します。



```
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-deployment.yaml
kubectl get pods
kubectl logs -f redis-master-<id>
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-service.yaml
kubectl get service
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-slave-service.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
kubectl get pods -l app=guestbook -l tier=frontend
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
kubectl get services 
```

このままでは VPC の中からしかアクセスできません。
インターネットからゲストブックをブラウザで開くにはどうしたらよろしいでしょうか。

## A5. Rancher に Kubernetes クラスタを取り込み(import)

1.Rancherの管理画面にアクセスします。

2.`Clusters` -> `Add Cluster` をクリックし、

3.`Import`をクリックしたあと、画面をスクロールし「Cluster Name」を`mykube`にします。

4.`Create` をクリック

5.実行結果の1行目をコピーし、 `[USER_ACCOUNT]` を `admin` に置き換えて `kube1` 上で実行します。

```
kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user admin
```

それから3行目をコピーして実行します

```例（※環境によってコマンドのトークンやIPアドレスが異なります）
curl --insecure -sfL https://<ip>/v3/import/rlxpgghqf5k6t2fq7hfr96cvg6tr7jfj5w4n8xsj8fccgc5xxwg2n4.yaml | kubectl apply -f -
```

6.Rancher UI上の画面で`Done`をクリックすると、クラスタ一覧ページに移動します。


`Pending` -> `Active` に切り替われば設定完了です。
しばらく画面を触って自由に操作します。

# B. アプリケーション実行編

## B1. RancherUIからWordPress を立ち上げる

1. `Global` -> `Default`
2. `Catalog Apps`
3. `Launch` -> `wordpress`
4. ユーザ名とパスワードの設定を必ずする
5. `Launch`

起動後はインターネットから接続するには？
スケールできますか？

ヒント：２つあるポートは http と https です

## B2. Kubernetes チュートリアルで学ぶ

- Tutorials - Kubernetes
  - https://kubernetes.io/docs/tutorials/