Docker for Windows で kubernetes（2）


[Docker for Windows で Kubernetes（1）](https://qiita.com/tksarah/items/ba51f1120d5d7ac0435f)の続き。

**e-Learning OSSの「Irohaboard」**のmanifestを作ってみる。
今回は、以下のような要件にする。

* Irohaboard (Web,PHP）側はスケール可能
* DBはデータベースが１つだが永続的にデータを保持

ざっくりステップ

1. Irohaboard の各Dockerイメージを作成
2. 各種マニフェスト作成
3. デプロイ

ソースは[ここ](https://github.com/tksarah/irohaboard.git)。

# Dockerイメージ作成

* Irohaboard 本体用（Apache , PHP）
* Irohaboard データベース用（MySQL/Mariadb）

Irohaboard の仕様に合わせてデプロイ、**「http://＜your url＞/install」**にアクセスしてセットアップを行った後に利用開始できるところまでイメージを作る。

## Irohaboard 本体用イメージ

マニフェストに合わせて調整した部分。

**セッション情報はデータベースに格納**

* テーブルとしてセッションテーブルは作成済みとなるので、向きだけ変える
* デフォルトは'php'であり、php.iniに定義されている保存方式をとる

```php:Config/core.php
	Configure::write('Session', array(
		'defaults' => 'database'
	));
```

**database.php の設定**
予め設定する必要があるファイルであるが、ほとんどは固定よさそうだったので問題なかったので、以下のみをチューナブルにした。

* MySQL のホスト情報・・・これはマニフェストのサービスリソースから参照させる
* MySQL root パスワード（デフォルト：root）
* テンプレートファイルを作って、ビルド時に値を埋め込む（entrykit利用）

```php:Config/database.php.tmpl
class DATABASE_CONFIG {

	public $default = array(
		'datasource' => 'Database/Mysql',
		'persistent' => true,
		'host' => '{{ var "MYSQL_HOST" }}',
		'login' => 'root',
		'password' => '{{ var "MYSQL_ROOT_PASSWORD" | default "root" }}',
		'database' => 'irohaboard',
		'prefix' => 'ib_',
		'encoding' => 'utf8'
	);
}
```

> Dockerfile でビルド時にテンプレートを使ってコンフィグファイルを作れる「entrykit」を使っているので上記のようなファイルを作っている。

## Irohaboard データベース用イメージ

Irohaboardでは初めにデータベースを作っておく必要がある。

MySQLのコンテナ（ https://hub.docker.com/_/mysql/ ）ではイニシャルで指定したデータベースを作ってくれる機能があるが、デフォルトだと推奨文字コードのUTF-8で作られないので、 **/docker-entrypoint-initdb.d**　にSQLファイルを置くパターンにした。

```sql:inidb.sql
create database irohaboard default character set utf8
```

```dockerfile:Dockerfile
FROM mysql:5.7
LABEL maintainer="hoge@example.com"
WORKDIR /tmp
COPY initdb.sql /docker-entrypoint-initdb.d/
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
```

> docker-entrypoint.sh を編集する、パターンもあるが元の仕組みをイレギュラーに変更するのが気に入らなかった。

# Manifest 作成
Docker for Windows（SingleNode）としての注意点が少しあったので、補足。

## PV のパス指定
Irohaboard のデータベース用の領域に**PersistentVolumes（PV）**を使う事にする。Volumeプラグインとして**hostPath**使うが、この時のパスの指定は下記のようにした。

```
path: /host_mnt/c/Users/<user name>/.docker/Volumes/mysql-pv
```

この時、Docker for Windows では**C：**がシェアドライブとして設定する必要がある。シェアされていない場合、PVを作らず**PersistentVolumeClaims**により要求すると、Windows側でポップアップが上がり**C：**ドライブの共有を求められる。

> 中身をハックしていないけども、manifest （kubernetes）で指定する際には/host_mntにC:がマウントされている
> Windows Subsystem for Linux では /mnt/c にマウントされているので、紛らわしい・・・

## Ingress

L7のHTTPルーティングには**NGINX Ingress Controller**を使う。

https://kubernetes.github.io/ingress-nginx/deploy/

```powershell
PS> kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
PS> kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/cloud-generic.yaml

PS> kubectl -n ingress-nginx get service,pod
NAME                           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/default-http-backend   ClusterIP      10.100.83.10    <none>        80/TCP                       1d
service/ingress-nginx          LoadBalancer   10.99.108.131   localhost     80:30580/TCP,443:32007/TCP   1d

NAME                                           READY     STATUS    RESTARTS   AGE
pod/default-http-backend-7c5bc89cc9-7t2kd      1/1       Running   2          1d
pod/nginx-ingress-controller-5b6864749-ttqnc   1/1       Running   2          1d
```

Ingress を定義したマニフェストを作る際、

https://kubernetes.io/docs/concepts/services-networking/ingress/#the-ingress-resource

名前ベースのバーチャルホスティング想定時、``- host``に使うアドレスとして、Docker for Windowsの**ホスト上からアクセスするため**のちょうど良いのがある。実は、Docker for Windowsインストール時に **hosts** がアップデートされている。（WSLから/etc/hostsファイルで参照できる）

```text
# This file is automatically generated by WSL based on the Windows hosts file:
# %WINDIR%\System32\drivers\etc\hosts. Modifications to this file will be overwritten.
127.0.0.1       localhost
127.0.1.1       DESKTOP-QVCDBPV.localdomain     DESKTOP-QVCDBPV
192.168.0.18    host.docker.internal
192.168.0.18    gateway.docker.internal
```

見ての通り、「host.docker.internal」と「gateway.docker.internal」があり、これがホストの内部につながるネットワークインタフェースとして形成されてる。これを指定することで、Ingressのテストで利用できる。

```yaml:ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: irohaboard
  namespace: irohaboard
spec:
  rules:
  - host: gateway.docker.internal
    http:
      paths:
      - path: /
        backend:
          serviceName: irohaboard-service
          servicePort: 80
```

## Secret 
Secretは使わなくてもよかったが、MySQLのパスワードのところだけ利用した。

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: iroha-db-secrets
  namespace: irohaboard
type: Opaque
data:
  mysqlrootpassword: cm9vdA==
```

つづく、、、