Knativeワークショップに参加したあとKnative on kindを構築してみた #serverlessdays #serverlessfukuoka

ServerlessDays Fukuoka 2019にワークショップから本編、懇親会まで参加して楽しんできました!

fukuoka.serverlessdays.io

本編ではサーバレスな最新事例から新しく追加されたエコシステムまでキャッチアップできました。Amazon RDS Proxyとか「埋めてきたなー」という印象。

また、我々が運用しているコンテナランタイムやクラスタも負けてないぞと思って、いろんなタイミングで話してた気がします。主に懇親会で。

で、ServerlessDays Fukuoka 2019の個人的な一番の目当ては前日のワークショップでした。

Knativeで作るDIY FaaS

私が参加したのは "Knativeで作るDIY FaaS" で、Kubernetesクラスタ(GKE)上にKnativeを使ってFaaS環境をつくるというものです。

ワークショップのリポジトリはこちら

github.com

参加前から、かなり濃いだろうと予想していて、「1日がかりのワークショップだろうなー」と勝手に思っていたら午後から開始でした。まさかの濃縮。

実はこのワークショップはServerlessDays Tokyo 2019でも開催されたらしくワークショップとしては v1.1.0 とマイナーバージョンが上がっていました。ただの再演ではないわけですね。

講師の @toshi0607 さんのエントリからもわかるように考え抜かれた内容で、インプットの多い数時間でした。

印象的だったのがワークショップの内容が「ワークショップで持ち帰ってほしいところがはっきりしていること」「それ以外は限りなく時間がかからないようにしていること」です。

その分エンジニアにありがちな「このコマンドは何?」と気にはなったのですが、ドキュメントはあるし参考リンクはあるしで、「それはあとで」なんとかなるようになっていました。

短時間で綺麗に完結させているワークショップだと思いました。参加して良かった!

Knative on kind

というわけで、復習タイムというかやりたくなったのが「ローカルにKnative環境を構築する」です。

Kubernetesクラスタには使ってみたかった kind を選択。Knative on kindです。

最初は何も考えずに kubectl apply をしまくった結果ローカル環境のリソースが足りずクラスタを壊してたりしたのですが、落ち着いてドキュメント読むなどをしてなんとかサンプルアプリが動くところまで行くことができました。

最終的にうまくいった手順の記録です。

必要なツールをインストール

helmはv2を使うので helm@2 を指定します

$ brew install kind kubernetes-cli helm@2

kindでKubernetesクラスタを作成

control-planeとworkerの1つづつNodeを作成します。

# kind-config.yaml
kind: Cluster
apiVersion: kind.sigs.k8s.io/v1alpha3
nodes:
- role: control-plane
- role: worker
$ export K8S_VERSION=v1.16.3
$ kind create cluster --name knative --image kindest/node:${K8S_VERSION} --config kind-config.yaml
Creating cluster "knative" ...
 ✓ Ensuring node image (kindest/node:v1.16.3) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining worker nodes 🚜
Set kubectl context to "kind-knative"
You can now use your cluster with:

kubectl cluster-info --context kind-knative

Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
$ kubectl config use-context kind-knative
$ kubectl config current-context
kind-knative
$ kubectl cluster-info --context kind-knative
Kubernetes master is running at https://127.0.0.1:61330
KubeDNS is running at https://127.0.0.1:61330/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

MetalLBをインストール

Istioの istio-ingressgatewayService type:LoadBalancer を必要とするのですが、パブリッククラウドではないので Service type:LoadBalancer が標準では用意されていません。そのため MetalLB をインストールしてService type:LoadBalancer を用意します。

# metallb-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.240-192.168.1.250
$ export METALLB_VERSION=v0.8.3
$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/${METALLB_VERSION}/manifests/metallb.yaml
$ kubectl apply -f metallb-config.yaml

Istioをインストール

Knativeが利用するIngress/GatewayとしてIstioをインストールします。

ただ、フルパッケージを入れるとホスト(Macbook)のリソースが厳しいので、Knativeのドキュメントを参考に最低限をインストールします。

# istio-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
 name: istio-system
 labels:
   istio-injection: disabled
$ export ISTIO_VERSION=1.4.2
$ curl -L https://istio.io/downloadIstio | sh -
$ for i in istio-${ISTIO_VERSION}/install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i; done
$ kubectl apply -f istio-namespace.yaml
$ helm template --namespace=istio-system \
  --set prometheus.enabled=false \
  --set mixer.enabled=false \
  --set mixer.policy.enabled=false \
  --set mixer.telemetry.enabled=false \
  --set pilot.sidecar=false \
  --set pilot.resources.requests.memory=128Mi \
  --set galley.enabled=false \
  --set global.useMCP=false \
  --set security.enabled=false \
  --set global.disablePolicyChecks=true \
  --set sidecarInjectorWebhook.enabled=false \
  --set global.proxy.autoInject=disabled \
  --set global.omitSidecarInjectorConfigMap=true \
  --set gateways.istio-ingressgateway.autoscaleMin=1 \
  --set gateways.istio-ingressgateway.autoscaleMax=2 \
  --set pilot.traceSampling=100 \
  istio-${ISTIO_VERSION}/install/kubernetes/helm/istio \
  > ./istio-lean.yaml
$ kubectl apply -f istio-lean.yaml
$ kubectl get pods -n istio-system
NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-6b699467f5-bxzjs   1/1     Running   0          42s
istio-pilot-7957c5468f-q67zl            1/1     Running   0          42s
$ kubectl get svc -n istio-system
NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)
        AGE
istio-ingressgateway   LoadBalancer   10.99.44.136    192.168.1.240   15020:30715/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31512/TCP,15030:30136/TCP,15031:30290/TCP,15032:31941/TCP,15443:31026/TCP   45s
istio-pilot            ClusterIP      10.100.11.226   <none>          15010/TCP,15011/TCP,8080/TCP,15014/TCP
        45s

Knative (Serving) をインストール

Knative (Serving) をインストールします

$ kubectl apply --filename https://github.com/knative/serving/releases/download/v0.11.0/serving.yaml
$ kubectl get pods -n knative-serving
NAME                                READY   STATUS    RESTARTS   AGE
activator-7db6679666-rm724          1/1     Running   0          41s
autoscaler-ffc9f79b4-nkd6n          1/1     Running   0          41s
autoscaler-hpa-5994dfdb67-j9vnv     1/1     Running   0          41s
controller-6797f99458-86vnl         1/1     Running   0          40s
networking-istio-85484dc749-qdcnh   1/1     Running   0          39s
webhook-6f97457cbf-wbzwq            1/1     Running   0          39s

Deploy app

Knativeのドキュメントにあるサンプルアプリをデプロイしてみます。

apiVersion: serving.knative.dev/v1 # Current version of Knative
kind: Service
metadata:
  name: helloworld-go # The name of the app
  namespace: default # The namespace the app will use
spec:
  template:
    spec:
      containers:
        - 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"
$ kubectl apply -f service.yaml
$ kubectl get ksvc helloworld-go
NAME            URL                                        LATESTCREATED         LATESTREADY           READY   REASON
helloworld-go   http://helloworld-go.default.example.com   helloworld-go-k2c9b   helloworld-go-k2c9b   True

ポートフォワーディング

istio-ingressgateway とホストをポートフォワーディングで繋げます。

$ kubectl port-forward svc/istio-ingressgateway -n istio-system 8880:80

Hello World

curlで叩くとリクエスト契機でアプリが立ち上がってレスポンスを返します。

$ curl -H "Host: helloworld-go.default.example.com" http://127.0.0.1:8880
Hello Go Sample v1!

今回もコードでまとめています

PostgreSQLの運用練習と同じように今回も動くコードでまとめています。

github.com

ServerlessDays Fukuoka 2019楽しかった!

運営の皆さん、発表者/ワークショップ講師の皆さん、ありがとうございましたー!