Hyper.shのServerless kubernetes Pi を体験しました

[hyper.sh](http://hyper.sh/) といたら、VM（runV）でコンテナを実装しよりセキュリティの CaaS を提供するサービスで知られています。Docker と同じの操作で、リモートに Docker のコンテナを起動し、自分はなんのインフラの管理もしなくて、コストも低くて、すごく便利なサービスです。

この [hyper.sh](http://hyper.sh/) 最近、[Hyper は Serverless の Kubernetes サービス Pi をラウンチしました](https://blog.hyper.sh/introducing-pi-on-gcp.html)。どんなサービスなのか、興味深くて試してみました。

## Pi のクライアントをインストールする

まずはクライント（Pi）をインストールするが必要です。

Pi のソースが [GitHub](https://github.com/hyperhq/pi) にあがっていますので、自分がソースからビルドもできますし、[リリースページ](https://github.com/hyperhq/pi/releases) からビルド済みのバイナリをダンロードもできます。

Pi バイナリを `PATH` におけば、インストールは終わりとなります。

次にユーザの情報（認証情報）を設定しておきましょう。

```
$ pi config set-credentials myuser --access-key="xxx" --secret-key="yyy"
```

`access-key` と `secret-key` は https://console.hyper.sh/account/credential から確認してください。もしなれば、あたらしいのを作成してください。

そしたら一つのコマンドを実行しましょう（基本的に `kubectl` と同じの使い方）。

```
$ pi get services
No resources found.
```

Service のリソースがないため、何も返ってきませんでした。

## Wordpress サービスを立ち上がります

Pi は K8s の Pod、Service と Secret をサポートする以外に、Volume（今は GCP の Persistent Disk ）と FIP（外部からサービスをアクセスためのIPアドレス）もサポートしています。

ここに例として、Wordpress ＋ MySQL の環境を構築し、データの長期保存のために、それぞれに Volume を使ってデータを格納します。Wordpress から MySQL のアクセスは K8s のサービス（Service　Discovery）を利用して、外部から Wordpress をアクセスできるために、LoadBalance の Service を作成し、FIPを利用します。

具体の手順は下記となります。

## PDを作ります

[hyper.sh](http://hyper.sh/) は昔から Volume という概念がありまして、Pi にもそれを使えます。後ろに GCE の PD が使われています（ Pi 自体は今 GCE 上動いています）。

```
$ pi create volume mysql-data --size=10
volume/mysql-data

$ pi create volume wp-data --size=10
volume/wp-data

$ pi get volumes
NAME        ZONE               SIZE(GB)  CREATEDAT                  POD
mysql-data  gcp-us-central1-c  10        2018-05-26T07:04:14+00:00
wp-data     gcp-us-central1-c  10        2018-05-27T07:43:52+00:00
```

Wordpress と MySQL 用の PD　を一つずつを作成しました。

## FIP（Float IP）を作成します

```
$ pi create fip
fip/35.184.xxx.xxx

$ pi get fip
FIP             NAME  CREATEDAT                  SERVICES
35.184.xxx.xxx        2018-05-25T04:45:56+00:00
```

外部からはこの `35.184.xxx.xxx` という IP を利用し Wordpress サービスをアクセスできます。

## K8s の Secret を利用し MySQL のパスワードを設定します

`YOUR_REAL_MYSQL_PASSWORD` を自分のパスワードを書き換えてください。

```yaml
# mysql-secret.yaml
kind: Secret
apiVersion: v1
metadata:
  name: mysql-password
data:
  password: <YOUR_REAL_MYSQL_PASSWORD>
```


あとは Secret を作りましょう。

```shell
$ pi create -f mysql-secret.yaml
```

次は Wordpress の Service を見てみましょう。

## MySQL を立上ます

まずは MySQL の Pod です。

これも K8s のそのものが使えます。要注意のは PD（Volume）の使い方です。

Volume には必ず `flexVolume` を使わなければなりません、そして、Volume の Name を`options.volumeID` に設定することです。

```yaml
# mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  containers:
  - image: mariadb:10.3.6
    name: mysql
    args:
      - "--ignore-db-dir"
      - "lost+found"
    env:
      - name: MYSQL_ROOT_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysql-password
            key: password
    ports:
      - containerPort: 3306
        name: mysql
    resources:
      limits:
          memory: 1000Mi
      requests:
          memory: 1000Mi
    volumeMounts:
        # name must match the volume name below
      - name: mysql-data
        # mount path within the container
        mountPath: /var/lib/mysql
  volumes:
    - name: mysql-data
      flexVolume:
        options:
          # volumes from `pi get volumes`
          volumeID: mysql-data
```

MySQL は外部にサービスを提供することはないですから、クラスタ IP のないサービスを使えば十分だと思います。

```yaml
# mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
    - name: tcp-3306
      port: 3306
      protocol: TCP
      targetPort: 3306
```

あとは Pod と Service を作成すます。

```shell
$ pi create -f mysql-pod.yaml -f mysql-service.yaml
```

## Wordpress を立上ます

これも基本的に K8s の Service と同じです。気をつけなければならないの二箇所です。

* `type` を `LoadBalancer` に固定すること
* `loadBalancerIP` をほんものの `YOUR_REAL_FIP` を書き換えてください


```yaml
# wordpress-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  ports:
    - name: tcp-80
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: wordpress
  type: LoadBalancer
  loadBalancerIP: <YOUR_REAL_FIP>

```

Wordpress の Pod も Volume を利用しています（ Theme と Plugin などを格納するため）。

```yaml
# wordpress-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: wordpress
  labels:
    app: wordpress
spec:
  containers:
  - name: wordpress
    image: wordpress:4.9.5-apache
    env:
    - name: WORDPRESS_DB_HOST
      value: mysql
    - name: WORDPRESS_DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mysql-password
          key: password
    ports:
    - containerPort: 80
      name: wordpress
    volumeMounts:
      - name: wp-data
        mountPath: /var/www/html
  volumes:
    - name: wp-data
      flexVolume:
        options:
          # volumes from `pi get volumes`
          volumeID: wp-data
```

Wordpress の Pod と Service を作りましょう。

```shell
$ pi create -f wordpress-pod.yaml -f wordpress-service.yaml

```

全部のリソースをできているため、下記のコマンドを使って確認できます。

```shell
$ pi get pods
NAME        READY     STATUS    RESTARTS   AGE
mysql       1/1       Running   1          1d
wordpress   1/1       Running   1          1d

$ pi get services
NAME        TYPE           CLUSTER-IP      LOADBALANCER-IP   PORT(S)    AGE
mysql                      None            <unknown>         3306/TCP   1d
wordpress   LoadBalancer   10.97.136.zzz   35.184.xxx.yyy    80/TCP     1d

$ pi get secrets
NAME             TYPE      DATA      AGE
mysql-password             1         1d

```

問題がなければ、ブラウザに先作成した FIP をアクセスすれば、 Wordpress の初期化画面が表示されると思います。

## 終わりに

すべての K8s リソースをサポートしていないですが、基本の Pod と Service があれば、普通のHTTPサービス、CI/CD 処理など十分に利用できると思います。

一番魅力のは、K8s 風の使い方で、インフラの管理入らないというところです。

でも Deployment がいまだにサポートされていないため、Pod のライフサイクルを自部が管理しなければなりません、もし何らかの原因で Pod が落ちったら、自分が手動で回復させない限り、K8s（Pi）も何もしてくれないという点を覚悟しておきましょう。

Cloud Native というのは、ある意味から言うと、なんでも自分がやり通すことをやめ、できるだけ外部のサービスを利用することがおすすめでしょうか。

参考：

* [Pi on GitHub](https://github.com/hyperhq/pi)
* [クラスタ不要で柔軟な Docker ホスティングが行える Hyper.sh を試してみた](http://blog.shibayan.jp/entry/20170704/1499149762)
* [Moved from Arukas to hyper.sh](https://blog.lorentzca.me/moved-from-arukas-to-hyper-sh/)
* [TravisCIからHyper.shへDockerコンテナなアプリを継続的デプロイ](https://blog.hmatoba.net/Article/117)