最強のServerlessプラットフォーム？ Knativeを動かしてみるぞい

[Google Cloud Nextで発表されたばかりのKnative](https://cloud.google.com/knative/)を動かしてみました。

[最強のServerlessプラットフォーム？ Knative登場](http://jaco.udcp.info/entry/2018/07/25/043415)

## GKE環境を用意する

Knativeを動かすにはk8s環境が必要ですので、今回はGKEに環境を用意します。なおk8s本体とKubectlは1.10以上が必要です。

KnativeはIstioなども含むリッチな仕組みのため、それなりのリソースを要求します。なのでやや大きめのインスタンスで立ち上げていますが、節約したい方はmachine-typeやnodeの数を編集してください。

```sh
export CLUSTER_NAME=knative
export CLUSTER_ZONE=asia-northeast1-a

gcloud container clusters create $CLUSTER_NAME \
  --zone=$CLUSTER_ZONE \
  --cluster-version=latest \
  --machine-type=n1-standard-4 \
  --enable-autoscaling --min-nodes=1 --max-nodes=5 \
  --enable-autorepair \
  --scopes=service-control,service-management,compute-rw,storage-ro,cloud-platform,logging-write,monitoring-write,pubsub,datastore \
  --num-nodes=3
```

k8s立ち上がったらget-credentials

```
gcloud container clusters get-credentials knative
```

カレントユーザーにcluster-adminをつけます。

```
kubectl create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$(gcloud config get-value core/account)
```

kubectlを使って、Istioをセットアップします

```
kubectl apply -f https://storage.googleapis.com/knative-releases/serving/latest/istio.yaml
```

defaultネームスペースにラベル設定
```
kubectl label namespace default istio-injection=enabled
```

Istioの諸々がRunningになっているか確認

```
kubectl get pods -n istio-system

NAME                                       READY     STATUS    RESTARTS   AGE
istio-citadel-7bdc7775c7-lktlt             1/1       Running   0          59s
istio-egressgateway-795fc9b47-tcp76        1/1       Running   0          1m
istio-ingress-84659cf44c-2gmlw             1/1       Running   0          1m
istio-ingressgateway-7d89dbf85f-qjpg5      1/1       Running   0          1m
istio-pilot-66f4dd866c-lr7zw               1/2       Running   0          1m
istio-policy-76c8896799-74m52              2/2       Running   0          1m
istio-sidecar-injector-645c89bc64-gz5vb    1/1       Running   0          59s
istio-statsd-prom-bridge-949999c4c-p97lv   1/1       Running   0          1m
istio-telemetry-6554768879-pmkqq           2/2       Running   0          1m
```

## Knativeコンポーネントをセットアップ

Knative Servingをセットアップします

```
kubectl apply -f https://storage.googleapis.com/knative-releases/serving/latest/release.yaml
```

Runningになっているか確認してみましょう

```sh
kubectl get pods -n knative-serving

NAME                          READY     STATUS    RESTARTS   AGE
activator-6bb6f6755f-l4ks8    2/2       Running   0          30s
controller-79cbd84cfb-n6l6h   1/1       Running   0          29s
webhook-7c884f4554-h7tx5      1/1       Running   0          29s
```
 
なんとこれだけでKnativeのセットアップは終わりです。それでは、実際に何かデプロイしてみましょうか。

## サンプルアプリのデプロイ

service.yamlを作成し、以下の内容を記述してください。

```yaml
apiVersion: serving.knative.dev/v1alpha1 # Current version of Knative
kind: Service
metadata:
  name: helloworld-go # The name of the app
  namespace: default # The namespace the app will use
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: gcr.io/knative-samples/helloworld-go # The URL to the image of the app
            env:
            - name: TARGET # The environment variable printed out by the sample app
              value: "Go Sample v1"
```

このサンプルアプリは、環境変数 TARGETの中身を表示するアプリケーションです。このyamlの例の場合、 "Go Sample v1" という文字を表示します。

保存した後、kubectl applyします

```sh
kubectl apply -f service.yaml

> service "helloworld-go" created
```

作成されたリソースをみてみます

```
kubectl get all

NAME                                    AGE
deploy/helloworld-go-00001-deployment   10s

NAME                                          AGE
rs/helloworld-go-00001-deployment-d47886fcb   10s

NAME                   AGE
routes/helloworld-go   10s

NAME                AGE
svc/helloworld-go   10s

NAME                           AGE
configurations/helloworld-go   10s

NAME                            AGE
revisions/helloworld-go-00001   10s

NAME                                                READY     STATUS    RESTARTS   AGE
po/helloworld-go-00001-deployment-d47886fcb-c97kx   3/3       Running   0          10s

NAME                              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
svc/helloworld-go                 ClusterIP   10.63.246.221   <none>        80/TCP         10s
svc/helloworld-go-00001-service   NodePort    10.63.252.252   <none>        80:30048/TCP   10s
svc/kubernetes                    ClusterIP   10.63.240.1     <none>        443/TCP        12h
```

なんかsvc/helloworld-go以外にもいっぱい作られてますね！


### 作成したアプリへのアクセス

istio-system namespaceを見てみると、knative-ingressgatewayというものが作られていることが分かります。

このknative-ingressgatewayが、アプリケーションへのルーティングを担うコンポーネントになります。

```
kubectl get svc knative-ingressgateway -n istio-system

NAME                     TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                                      AGE
knative-ingressgateway   LoadBalancer   10.23.247.74   35.203.155.229   80:32380/TCP,443:32390/TCP,32400:32400/TCP   2d
```

以下のコマンドでknative-ingressgatewayのEXTERNAL-IPを取得しておきます

```
export IP_ADDRESS=$(kubectl get svc knative-ingressgateway -n istio-system -o 'jsonpath={.status.loadBalancer.ingress[].ip}')
```

次に、以下のコマンドで、services.serving.knative.devを取得します

```
kubectl get services.serving.knative.dev helloworld-go  -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain

NAME            DOMAIN
helloworld-go   helloworld-go.default.example.com
```

DOMAINというところに、今回のアプリ向けのドメインが記されています。 knative-ingressgatewayはリクエストを見て、このドメインへのアクセスであれば作成されたアプリケーションへのルーティングを行うという動きをします。

とはいえexample.comは例示用ドメインなので、今回はcurlでホストヘッダを指定することで動きを見てみます。

```
curl -H "Host: helloworld-go.default.example.com" http://${IP_ADDRESS}

Hello World: Go Sample v1!
```

ほら、期待した文字列が表示されていますよね？

## まとめ

ということで、Knativeは簡単にセットアップできるよという話を紹介されていただきました。

ただ、ぶっちゃけ今回のサンプルアプリでは、Knativeの何がいいのか分からないですよね？　うん、僕も分かりません。

そもそもServerlessって言ってたのにどこにもServerless要素ないやん、こんなん素のKubernetesと変わらんやん！　ってツッコみたくなるかと思いますが、徐々に解説していきますのでもう少しお待ちください。

Knativeはさまざまな方法で利用が出来るプラットフォームです。なので、1記事ではとてもとても紹介しきれないのです。

今回は、KnativeはServerless Platformでありながらも、従来のようなアプリケーションも動かすことができる　という点を理解して頂ければよいかなと思います。

次回は、Buildpackを利用したアプリケーションのデプロイについて解説する予定です。

## (参考)お片付け

k8sをお片付けするには以下のコマンドで削除します

```
gcloud container clusters delete $CLUSTER_NAME --zone $CLUSTER_ZONE
```