Knative でサーバーレス
今日は OpenShift 上に Knative な環境を構築して、サーバーレスアプリケーションをデプロイしてみたいと思います。
今回利用した OpenShift のバージョンは 4.3 となっています。
おしながき
以下のとおりとなっています。途中で起動された Pod が 0 までスケールダウンするところ見てみましょう。
- OpenShift に Serverless Operator のインストールと Knative Serving のインストール
- サーバーレスアプリケーションのデプロイ
- トラフィック分割
Serveless Operator のインストールと Knatvie Serving のインストール
手順1. OpenShift Web コンソールに管理者権限でログインします。
手順2. 左のメニューから「Operators」→「OperatorHub」の順にアクセスします。
手順3. 検索ボックスに「Serverless」を入れて、「OpenShift Serverless Operator」を選択します。
手順4.「Install」を選択します。
手順5.「Installation Mode」は「All namespaces on the cluster (default)」、「Update Channel」は「4.3」、「Approval Strategy」は「Automatic」にし「Subscribe」を選択します。
手順7.「default」プロジェクトの「Installed Operator」の画面に遷移しますが、しばらく待つと「default」プロジェクトにもインストールされます。
ここからは oc コマンドを使用します。
手順8. 管理者権限で oc login を実行します。
$ oc login https://xxxxxxxx -u <user> -p <password>
手順9. knative-serving ネームスペースを作成します。
$ oc create namespace knative-serving
namespace/knative-serving created
手順10. 以下の内容を記載した serving.yaml ファイルを用意します。
apiVersion: operator.knative.dev/v1alpha1
kind: KnativeServing
metadata:
name: knative-serving
namespace: knative-serving
手順11. oc apply コマンドを実行します。
$ oc apply -f ./serving.yaml
knativeserving.operator.knative.dev/knative-serving created
手順12. インストールの状態を確認します。Ready=True になるまで待ちましょう。
$ oc get knativeserving.operator.knative.dev/knative-serving -n knative-serving --template='{{range .status.conditions}}{{printf "%s=%s\n" .type .status}}{{end}}'
DependenciesInstalled=True
DeploymentsAvailable=True
InstallSucceeded=True
Ready=True
手順13. Pod の状態は以下の通りとなります。
$ oc get pods -n knative-serving
NAME READY STATUS RESTARTS AGE
activator-7db4dc788c-6xvdv 1/1 Running 0 2m43s
activator-7db4dc788c-j96h2 1/1 Running 0 2m58s
autoscaler-659dc48d89-x2897 1/1 Running 0 2m57s
autoscaler-hpa-57fdfbb45c-fkdbm 1/1 Running 0 2m47s
autoscaler-hpa-57fdfbb45c-jnjqq 1/1 Running 0 2m47s
controller-dc7886b47-5pt4v 1/1 Running 0 2m41s
controller-dc7886b47-pll4k 1/1 Running 0 2m52s
kn-cli-downloads-7558874f44-w7rfs 1/1 Running 0 3m3s
webhook-7d9644cb4-4lqnk 1/1 Running 0 2m55s
おまけ: OpenShift のコンソールから「Knative Serving」が有効になっているのを確認してみましょう。プロジェクトを「knative-serving」に変更して、「Operators」→「Installed Operators」→「Knative Serving」をみてみると、Serverless Operator をインストール直後にはなかった kantive-serving が作成されているのを確認できます。oc コマンドからではなく、本ページから Web UI でも作成可能です。
これで Serverless Operator のインストールは完了です。
サーバーレスアプリケーションのデプロイ
今回使用するアプリケーションはこちらになります。Quarkus フレームワークを利用しています。
HTTP リクエストを受け取って、「Hi Greeting」というメッセージを返却するだけの簡単なアプリケーションです。必要に応じてソースコードを眺めてみましょう。
Knative Serving を利用するアプリケーションは Pod がアイドルになると、0までスケールダウンし、リクエストイベントが発生すると Pod が起動されます。通常の Java アプリケーションだと起動のたびに Java の BootStrap 処理が走るため、サーバーレスには向いていませんが、Quarkus を利用すると 使い慣れた Java 言語で Linux ネイティブなバイナリアプリケーションを生成することができこうした問題を解決できます。
Linux バイナリで生成したコンテナイメージは Quay に格納されています。
手順13. 一般ユーザーで oc login します。
手順14. knative-test プロジェクトを作成します。
$ oc new-project knative-test
Now using project "knative-test" on server "https://api.cluster-xxxxxxxxx:6443".You can add applications to this project with the 'new-app' command. For example, try: oc new-app django-psql-exampleto build a new example application in Python. Or use kubectl to deploy a simple Kubernetes application: kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node
手順15. 以下の service.yaml を用意します。
既に作成済みのコンテナイメージを指定しています。Quarkus の Liveness Probe や Readiness Probe についてはこちらを参照ください。
kind が Service になっている点に注意してください。
手順16. oc apply コマンドでデプロイします。
$ oc apply -f ./service.yaml
service.serving.knative.dev/greeter created
手順17. Knative Serving の Route をチェックします。
$ oc get rt
NAME URL READY REASON
greeter http://greeter-knative-test.apps.xxxxxxxx True
OpenShift のコンソール上では、左メニューの「Serverless」→「Routes」から確認することができます。
手順18. 上記の URL に Web ブラウザでアクセスします。
上記のように「Hi greeter => ‘xxxxxxxxx’: 1」と表示されたら成功です。
手順19. しばらく環境を放置します。
手順20. Pod が 0 までスケールダウンされていることを確認します。
$ oc get pods
No resources found in knative-test namespace.
OpenShift のコンソールから「Developer」→「Topology」を確認して、Pod が存在しないことも確認しておきます。
手順21. 再度ブラウザから URL にアクセスして、Pod が起動するか確認します。
これで Serverless アプリケーションのデプロイは完了です。
トラフィック分割
事前に OpenShift のコンソール右上から ? →「Command Line Tools」の順にアクセスし、自身の環境にあった kn コマンドをダウンロードしておきます。
oc コマンドは引き続き一般ユーザーで実行します。
手順22. 新しいリビジョンのサービスを定義します。今回はソースコードには手を加えず、環境変数を読み込むように YAML ファイルを変更します。以下の service2.yaml を用意しましょう。
手順23. oc apply し、新しいバージョンのサービスを適用します。
$ oc apply -f ./service2.yaml
service.serving.knative.dev/greeter configured
手順24. URL をブラウザで開き、メッセージが 「Hi」から「Namaste」に変わっていることを確認します。
この Namaste は YAML ファイルに新たに環境変数 MESSAGE_PREFIX を設定したことによりアプリケーションが default の Hi から環境変数を適用したために動作が変わっています。
env:
- name: MESSAGE_PREFIX
value: Namaste
手順25. リビジョンを確認します。
$ oc get revision
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON
greeter-mk286 greeter greeter-mk286 2 True
greeter-shxmk greeter greeter-shxmk 1 True
Hi を返す GENERATION 1 と Namaste を返す GENERATION 2 が存在することが確認できます。
手順26. kn コマンドでもリビジョンを確認します。
$ kn revision list
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON
greeter-mk286 greeter 100% 2 9m44s 3 OK / 4 True
greeter-shxmk greeter 1 19m 3 OK / 4 True
上記により、環境変数を適用したアプリケーションにトラフィックが100% 流れることが確認できます。
手順27. kn コマンドを使用して、GENERATION 1 と GENERATION 2 へトラフィックが 50% ずつ流れるよう変更します。
$ kn service update greeter --traffic @latest=50 --traffic greeter-shxmk=50
Updating Service 'greeter' in namespace 'knative-test': 0.390s Ingress has not yet been reconciled.
0.493s Ready to serve.Service 'greeter' with latest revision 'greeter-mk286' (unchanged) is available at URL:http://greeter-knative-test.apps.xxxxxxxxx
トポロジは以下のようになります。
手順28. 以下のコマンドを実行して10回連続で curl コマンドを実行します。
$ for i in {1..10}; do curl http://greeter-knative-test.apps.cluster-tokyo-6d19.tokyo-6d19.example.opentlc.com; done
Hi greeter => '9861675f8845' : 1
Hi greeter => '9861675f8845' : 2
Hi greeter => '9861675f8845' : 3
Hi greeter => '9861675f8845' : 4
Namaste greeter => '9861675f8845' : 1
Namaste greeter => '9861675f8845' : 2
Hi greeter => '9861675f8845' : 5
Namaste greeter => '9861675f8845' : 3
Namaste greeter => '9861675f8845' : 4
Hi greeter => '9861675f8845' : 6
完全に50% とは行きませんでしたが、ほぼ半分ずつトラフィックが別れたことが確認できました。
今回は以上になります。