サーバーレス気になる人間
はじめまして。サーバーレスが気になって夜も6時間しか眠れないサーバーレス気になる人間「ながの」と申します。
転職してきて8ヶ月、今までやったことがない事を多くやらせてもらって刺激的な毎日を過ごしています。
が、せっかくのアドベントカレンダーなので、仕事でもやったことないことに触れていこうと思い、題材にKnativeを選択しました。よろしければ、ご一緒にKnativeの知識を深めていきましょう。
なぜKnativeか?
なぜKnativeの知識を深めたいのか?これには明確な理由があります。
それはKubernetes
を学びたいからです。
えっ?だったらKubernetes勉強すればいいんじゃない?
はい。確かにそうなんです。が、今からKubernetesを勉強します!って言うのも出遅れた感が出すぎてしまって恥ずかしいですよね、、、加えて公私ともにKubernetes使うシチュエーションに出会っていないので、なかなか勉強する気持ちがわかないんですよね、、、
そこでKnativeです。(Knativeであれば、今更感はまだそこまでないですよね??)
それにKnativeは何やらKubernetes上でサーバーレスな仕組みを構築できる、なんていう代物のようです。そうなんです!Kubernetes上にサーバーレスな仕組み
なので、Knativeを学ぶためにはKubernetesも知らないといけないんですよね。
そうなってくると、Knativeを触ってみればKubernetesもサーバーレスも理解できる!一石二鳥です。(とか思ったのが誤りで、Knativeも難しれば、Kubernetesも難しいという末路が待っていたことに、このときの私は気付きようもなかった、、、)
ということで私はKnativeを選択したというわけです。
まずはKnativeの知識を仕入れる
そもそもKnativeってなに?ってことになるかと思いますので、確認していきましょう。
参考にさせていただいたのは以下。全部メルペイの杉田さん(About Me – DoorLog)のものです。
-
Knativeの歩き方 KubernetesからServerlessを訪ねて 第2版 #技術書典 - カエルと空 - BOOTH
-
Knativeソースコードリーディング入門 Knativeで学ぶKubernetesのカスタムリソースとカスタムコントローラ - BOOTH
私のKnativeの知識の120%は杉田さんのアウトプットからできています。
で、結局Knativeとは何なのか?
最初は単純にKnativeってAWS LambdaのようなFaaSをAWS以外でも構築するためのOSSでしょって思ってました。
ところが色々と調べていくうちにそれだけではない、ということが分かりました。
誤解を恐れずに言えば、Kubernetesを使って実現しようとしたことをさらに効率よく実現するためのオプション的なものがKnativeである
と私は理解しました。
ではKubernetesを使って実現しようとしたこととはなんでしょうか?
これは私のようなKubernetes未経験者でも、ちょっとKubernetesを気にしてセミナーに通っているような人であれば、セミナーでよく耳にするアレです。こんな事ができるからKubernetesって凄いんだよって紹介されているアレです。
- コンテナを使ったマイクロサービス
- ブルーグリーンデプロイメント
- カナリアリリース
- オートスケール
- ゼロスケール
Kubernetesでは上記なようなことが実現できるようになる、とはよく言われることですよね。
でもどうやら上記のようなことをKubernetesだけで実現するとなると結構大変な部分もあるようなんです。
私なんて最初はKubernetesを使うだけで上記に列挙したようなCloudNativeなことがすぐにできちゃんだろうな、すごいなあって思っていたのですが、Kubernetesが抽象化したのはインフラ部分のようで、Kubernetes上で作られたサービス(インフラより上層にあるサービス)が、CICDを行い、ブルーグリーンデプロイメントを実現したり、負荷が高まった時にオートスケールしたり、はたまたアクセスがない時はリソース節約のためにゼロスケールしたり、というようなことは割と手間をかけて実現しないといけなかったという事実があるようです。
そこで、せっかくKubernetesでインフラを抽象化して、インフラの細かくて面倒なことは気にしなくても、いい感じのリソースを利用できるようになったのだから、そこから先(インフラより上層のサービス)もいい感じに抽象化して、深いことを考えずにCloudNativeらしいことをしたいよね、ってことで出てきたのがKnativeだということらしいんです!!(諸説ありますが、私の理解です)
なので、杉田さんの本にも以下のように記載されています
Knativeはつぎのような、コンテナアプリケーションを開発する上で必ずとおるが難しい課題を解決します
- コンテナの迅速なデプロイ
- ソースコードからURLをアクセスできるアプリケーションへ
- ブルー/グリーンデプロイを伴うルーティングとトラフィック管理
- オートスケーリングと需要に基づくワークロードのサイズ設定
- 実行中のサービスをイベントエコシステムに結び付ける
ということで、少しずつKnativeの実態がどんなものなのか分かってきましたね。
ひとまずKnativeを動かす
では、ひとまずKnativeを動かす環境をつくりましょう。
参考にさせて頂いたのは、こちらも杉田さんがServerlessDays Tokyo 2019で実施していたワークショップです。
今回は「クラスタの構築」と「各コンポーネントの理解」のServingのみだけですが試してみます。
GCPを利用
KubernetesはGKEで作成します。(さっそくKubernetesの勉強になってますね)やり方はワークショップ通りで私は問題なく進めることができました。
build-your-own-platform-with-knative/step0.md
軽く補足すると(補足なので基本はワークショップの通り進めてくださいね)
-
GCPでプロジェクトを作成
-
Google Cloud Shellを起動
-
以下の3つの環境変数をセット
-
GCPプロジェクトIDをセット
-
GKEとGCRを有効化
-
Kubernetesクラスタの作成
Kubernetesクラスタの作成コマンドはこんな感じです。
gcloud beta container clusters create $CLUSTER_NAME \
--addons=HorizontalPodAutoscaling,HttpLoadBalancing,Istio \
--machine-type=n1-standard-2 \
--cluster-version=latest --zone=$CLUSTER_ZONE \
--enable-stackdriver-kubernetes --enable-ip-alias \
--enable-autoscaling --min-nodes=1 --max-nodes=5 \
--enable-autorepair \
--scopes cloud-platform
確認します
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-knative-default-pool-743e9df0-8bg4 Ready <none> 5m54s v1.14.8-gke.17
gke-knative-default-pool-743e9df0-mbk3 Ready <none> 5m53s v1.14.8-gke.17
gke-knative-default-pool-743e9df0-z9bm Ready <none> 5m53s v1.14.8-gke.17
おお!簡単にできました。Kubernetesクラスタがあっという間にできちゃいました。
次にここにKnativeをインストールしていきます。
$ kubectl apply --selector knative.dev/crd-install=true \
--filename https://github.com/knative/serving/releases/download/v0.9.0/serving.yaml \
--filename https://github.com/knative/eventing/releases/download/v0.9.0/release.yaml \
--filename https://github.com/knative/serving/releases/download/v0.9.0/monitoring.yaml
むむ。--selector knative.dev/crd-install=true
の意味はなんでしょうか?これはKnativeをKubernetes上で利用するためにカスタムリソースとして事前に登録しているコマンドのようです。Kubernetesはこんな感じでいろんなカスタムをすることで機能を追加していくんですね。
そして事前準備が完了したので、実際にKnativeのリソースを作ります。
$ kubectl apply --filename https://github.com/knative/serving/releases/download/v0.9.0/serving.yaml \
--filename https://github.com/knative/eventing/releases/download/v0.9.0/release.yaml \
--filename https://github.com/knative/serving/releases/download/v0.9.0/monitoring.yaml
確認しましょう。おお、全部うごいてます!!
$ kubectl get pods --namespace knative-serving
NAME READY STATUS RESTARTS AGE
activator-68d9f95cd-qx4jk 2/2 Running 3 3m59s
autoscaler-5655c9fcfd-mp74z 2/2 Running 1 3m58s
autoscaler-hpa-8668fc6f68-97krf 1/1 Running 0 3m59s
controller-5b77c5596c-85hr2 1/1 Running 0 3m57s
networking-istio-6d7d44d879-f78mb 1/1 Running 0 3m56s
webhook-75b4fc9999-m62gq 1/1 Running 0 3m56s
$ kubectl get pods --namespace knative-eventing
NAME READY STATUS RESTARTS AGE
eventing-controller-db9b58855-v69nz 1/1 Running 0 4m21s
eventing-webhook-595c6b4fd8-gj2qh 1/1 Running 0 4m20s
imc-controller-7b9b7f9f66-4p78h 1/1 Running 0 4m19s
imc-dispatcher-775c96b5b5-rwzvl 1/1 Running 0 4m19s
sources-controller-78655cd9f9-dzvkn 1/1 Running 0 4m21s
$ kubectl get pods --namespace knative-monitoring
NAME READY STATUS RESTARTS AGE
elasticsearch-logging-0 1/1 Running 0 4m44s
elasticsearch-logging-1 1/1 Running 0 3m33s
fluentd-ds-fdcgj 1/1 Running 0 4m43s
fluentd-ds-nkqjf 1/1 Running 0 4m43s
fluentd-ds-wczz5 1/1 Running 0 4m43s
grafana-85c86fb7b9-tndgp 1/1 Running 0 4m39s
kibana-logging-7cb6b64bff-wdjp8 1/1 Running 0 4m43s
kube-state-metrics-56f68467c9-t864j 4/4 Running 0 3m24s
node-exporter-k6drr 2/2 Running 0 4m40s
node-exporter-qlh4q 2/2 Running 0 4m40s
node-exporter-txv9k 2/2 Running 0 4m40s
prometheus-system-0 1/1 Running 0 4m37s
prometheus-system-1 1/1 Running 0 4m37s
これでKubernetesクラスタとKnativeのインストールが完了です。次にワークショップの「各コンポーネントの理解」の中の「Serving」を試しみましょう。
Serving
ここからワークショップ的にはbuild-your-own-platform-with-knative/step1.mdに入っていきます。
で、そもそもServingとは?ってことですが、Knativeの3大要素のうちの1つです。
- Serving
- Evneting
- Build(これはTektonとして独立したのでKnativeから外れた?)
そのうちのServing
の役割とは以下のようなものらしいです。
オートスケールアウト・イン、トラフィックコントロール、バージョン管理などです。Servingは4つのコンポーネントから構成されます。
・Configuration: 最新の設定
・Revision: コードと設定の履歴
・Route: Revisionへのルーティング
・Service: RouteとConfigurationから構成されるサービス全体
うーん。なんとなくしか分からない、、、って感じなので、実際にServingを動かしてみましょう。
以下のようにserving.yaml
を作成します。
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: "gcr.io/knative-samples/helloworld-go"
env:
- name: "TARGET"
value: "Knative serving"
そして実行します。
$ kubectl apply -f service.yaml
確認します
$ kubectl get ksvc,configuration,route
NAME URL LATESTCREATED LATESTREADY READY REASON
service.serving.knative.dev/helloworld http://helloworld.default.example.com helloworld-w89zj helloworld-w89zj True
NAME LATESTCREATED LATESTREADY READY REASON
configuration.serving.knative.dev/helloworld helloworld-w89zj helloworld-w89zj True
NAME URL READY REASON
route.serving.knative.dev/helloworld http://helloworld.default.example.com True
これでKnativeのServingのコンポーネントであるservice,configuration,route
ができたってことですね。下の図の赤枠で囲んだものができたものです。
参照元:https://github.com/knative/docs/tree/master/docs/serving
で、これで何ができるようになったの?ってなりますよね。なので、以下の確認をしていきます。
# IPアドレスの取得
$ export IP_ADDRESS=$(kubectl get svc istio-ingressgateway --namespace istio-system --output 'jsonpath={.status.loadBalancer.ingress[0].ip}')
# curlでリクエスト
$ curl -H "Host: helloworld.default.example.com" http://$IP_ADDRESS
Hello Knative serving!
Hello Knative serving!
が無事に出力されました。
これの何が凄いの??
無事にHello Knative serving!
が出力されましたが、これの何が凄いのでしょうか?
まず最初に上記の15行くらいのyamlを実行しただけでKnativeが動くようになったということが挙げられます。
そして2つ目にKnativeのオブジェクトだけでなく、組み込みのKubernetesオブジェクトまで動いている
というのが凄い点です。KnativeがKubernetes上にサーバーレスな仕組みを構築するものなので、当然といえば当然ですが、Kubernetesを意識することなくKubernetesのメリットを利用できるというのは凄いことなのではないでしょうか。
では、どんなKubernetesオブジェクトができているのか確認してみましょう。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
helloworld-t75c2-deployment-54755c9bb5-tf6vl 2/2 Running 0 42s
$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
helloworld-t75c2-deployment-54755c9bb5 1 1 1 21m
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
helloworld-t75c2-deployment 1/1 1 1 21m
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
helloworld ExternalName <none> cluster-local-gateway.istio-system.svc.cluster.local <none> 20m
helloworld-t75c2 ClusterIP 10.0.0.176 <none> 80/TCP 21m
helloworld-t75c2-6l49j ClusterIP 10.0.13.34 <none> 80/TCP,8022/TCP 21m
helloworld-t75c2-metrics ClusterIP 10.0.2.146 <none> 9090/TCP,9091/TCP 21m
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 45m
おおー。確かにKubernetesのオブジェクトが動いています。15行くらいのyamlを実行しただけなのに色々と動いてますね。
実はKubernetesの組み込みオブジェクトだけでこれと同じことをしようとすると結構な手間らしいんです。
本当にそうなの?
と疑問に思ってくればしめたものです!本当に手間がかかるかの確認のために、KubernetesのPod,ReplicaSet,Deplyment,ingress
などを調べて実際に動かしてみればいいのですから。こうしてKubernetesについて色々と知る必要がでてきました。
自分なりに少し調べてみた感じですと、まずKubernetesクラスタ内にコンテナをたてる部分、そしてそのコンテナに外部からアクセスする部分、それらを作成するだけでも15行以上のyamlを書く必要があるということです。そこにさらに外部からアクセスができるようになっている状況が15行のyamlで作成できてしまうというのは、凄いことなのかなと思っています。
まとめ
いかがだったでしょうか?
KnativeをきっかけにしてKubernetesに興味を持とうという主旨は伝わりましたでしょうか。個人的にはこのやり方は割といいんじゃないかと思っています。それにKnativeのワークショップが充実しているので、そこを紐解いていけばKubernetesについても詳しくなれる!そんな気がしています。
今回はServingだけにしか触れていない(というか勉強できていない)ので、これからKnativeの他の部分についても触れていくことで、Kubernetesの勉強のきっかけを多く作って、Kubernetesの理解を深めていきたいと思います。