こんにちは、Red Hatソリューションアーキテクトの石川です。 今月の11月2日にアップストリームのKnativeがバージョン1.0としてリリースされました。 プロジェクトがスタートしたのが2018年とのことなので3年の月日を経て満を辞してのリリースだったかなと思います。
https://knative.dev/blog/articles/knative-1.0/
OpenShiftでもKnativeはOpenShift Serverlessというコンポーネントで提供されており、これを使うことでOpenShiftクラスタ上でサーバーレスのアプリケーションを動かすことが出来ます。
(Knative 1.0対応はまだしてないですが…)
今回の記事ではこのKnativeについてあらためてご紹介していきたいと思います。
ちなみに以前にも赤帽ブログでKnativeについて紹介している記事がありますのでそちらも併せてご参照下さい。
rheb.hatenablog.com rheb.hatenablog.com
Knativeの概要
Knativeはサーバーレスでのアプリケーション実行を可能とするOSSのプロジェクトであり、大きくKnative ServingとKnative Eventingという二つの要素で構成されています。
Knative Servingはサーバーレスアプリケーションを公開し、実行する部分を担っており、Knative Eventingは様々なイベント情報とKnative Servingを結びつけ、イベントドリブンなアプリケーション実行を行う役割を持っています。
ちなみに以前はKnative Buildというコンポーネントもあったのですが、そちらはKnativeからスピンアウトしてCIを行うTekton Projectとして独立しました。
一度に全てを説明すると長くなるため今回はこのKnative Servingに焦点を当ててご紹介しようと思います。
Knative Servingは何をしてくれるのか?
さてサーバーレスでのアプリケーション実行ということですがKnative Servingは実際には何をしているのでしょうか。
実はアプリケーションの実行自体は、KubernetesやOpenShiftで普通にアプリケーションを動かすのと同様にPod(コンテナ)で実行しています。
しかしKnative Servingの場合、アプリを実行していないときにこのPodは0までスケールインして完全に停止します。そしてアプリケーションのエンドポイントにアクセスがあったときに初めてPodを起動し、必要な処理を実施し、それが終わればまた停止するというサイクルを繰り返します。
つまり動いてない時はサーバーのリソースが不要(サーバーレス)ということですね。
またKnative Servingのもう一つの特徴として、スケールインだけではなくスケールアウトも出来るという点があります。アプリケーションに対する接続要求が増えれば必要な数だけ自動でPodの数を増やし処理を実行してくれます。
Knative Servingを使わない場合でもPodのスケールアウトは可能ですが、その場合HPA(Horizontal Pod Autoscaler)の設定が必要となるため、Knative Servingの方が楽に実装出来ると言えるでしょう。(HPAとスケールアウトの挙動は異なりますが。)
Knative Servingを使用するにはどうすれば良いのか?
Knative Servingを使用するにはKnativeの"Service"と呼ばれるカスタムリソースを作成する必要があります。
Kubernetesのデフォルトのリソースにもネットワーク機能を提供するServiceリソースがありますが、それとこのKnativeの"Service"は別物です。
これ以外にもKnativeにはまぎらわしい名前のリソースが多数存在するため、本記事上ではKnative/ServiceやDefault/Serviceなど区別を付け記述したいと思います。
Knative/Serviceが作成されると、OpenShiftのデフォルトのリソースとKnativeのカスタムリソースをクラスタ上に自動で作成します。
- デフォルトリソース
・Deployment:Podのデプロイ
・Default/Service:Podへのアクセス
・Default/Route:クラスタ外部へのアプリケーションの公開 - カスタムリソース
・Revision
・Configuration
・Knative/Route
実はこれ以外にも作成されるリソースはあるのですが、まずは一旦これらについて見ていきましょう。
1のデフォルトリソースについてはDeployment、Default/Service、Default/Routeの3種類となります。OpenShiftやKubernetesの経験がある方であれば、これらが作成されることでアプリケーションコンテナがクラスタにデプロイされ、外部公開されるイメージはなんとなく付くのではないでしょうか。 Knative/Serviceを一つ作成するだけでこれらのリソースは自動で作られるため、例えばKubernetesの仕組みに詳しくないアプリケーションの開発者であっても簡単にクラスタ上でアプリを動かすことが出来ます。
2のカスタムリソースについて、Knative Servingのドキュメントにはそれぞれの関係性を表す以下の図が載っています。
まずKnative/Serviceの情報を元にConfigurationとKnative/Routeという二つのリソースが作成されます。
Knative ServingにおいてデプロイするアプリのバージョンはRevisionという単位で管理されるのですが、ConfigurationがRevisionを作成するためのテンプレート情報を保持しており、それを元にRevisionが作成されます。作成されたRevisionはImmutable(後から変更不可)な性質を持ち、新しいバージョンのアプリがデプロイされると、過去のRevisionの更新を行うのではなく、新たな別のRevisionが作成されることとなります。
Knative/RouteはこれらRevisionに対するトラフィックの振り分け情報を保持しています。デフォルトでは最新のRevisionに100%のトラフィックが振り分けられますが、例えばA/Bテストやカナリアリリースを実施したい場合などに、以前のRevisionと最新のRevisionで9:1などの割合でトラフィックを振り分けることが可能になっています。
このように様々なカスタムリソースが存在していますが、Knative Servingを使用する場合、あくまでこれらは裏側の仕組みであり、利用者の目線では基本的にKnative/Serviceのみを意識すればよく、こちらに対して追加や変更を実施していくこととなります。
Knative/Serviceの作成方法
Knative/Serviceリソースを作成するには大きく以下の3つの方法が考えられます。それぞれ順番に見ていきましょう。
1. yamlを作成しapplyする
2. kn CLIを使用して作成する
3. OpenShiftコンソールから作成する
yamlを作成しapplyする
Knative/Serviceはカスタムリソースの一種であるため、デフォルトのリソースと同様にマニフェストファイルを作成し、それをapplyすることでクラスタにデプロイすることが出来ます。
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: helloworld-go namespace: default spec: template: spec: containers: - image: gcr.io/knative-samples/helloworld-go env: - name: TARGET value: "Go Sample v1"
apiVersion
がserving.knative.dev/v1
となっていることに注意しましょう。
このマニフェストでは実行するアプリケーションのコンテナイメージと変数を設定しています。
oc apply -f
にて準備したマニフェストを適用するとアプリケーションのエンドポイントが作成されます。そちらにアクセスすると変数で設定された値を含むレスポンスが確認することが出来ます。
curl http://helloworld-go-default.apps.mycluster4.bsf7.p1.openshiftapps.com Hello Go Sample v1!
レスポンス返却時にはコンテナが起動していますが、追加のリクエストが無ければ約90秒ほどで停止します。
oc get pod -w NAME READY STATUS RESTARTS AGE helloworld-go-00001-deployment-96bbf98f9-d4m4p 2/2 Running 0 14s helloworld-go-00001-deployment-96bbf98f9-d4m4p 2/2 Terminating 0 63s helloworld-go-00001-deployment-96bbf98f9-d4m4p 0/2 Terminating 0 94s helloworld-go-00001-deployment-96bbf98f9-d4m4p 0/2 Terminating 0 95s helloworld-go-00001-deployment-96bbf98f9-d4m4p 0/2 Terminating 0 95s
kn CLIを使用して作成する
KnativeにはknというCLIツールがあり、それを使うことでKnative/Serviceを作成することが出来ます。 CLIのインストール方法についてはKnativeのドキュメントをご参照下さい。
knを使ってyamlを書くパターンと同じ設定のKnative/Serviceを作成する場合は以下のコマンドとなります。
kn service create helloworld-go --env TARGET="Go Sample v1" --image gcr.io/knative-samples/helloworld-go
実行結果としては以下が返却され、最後の行でアプリケーションのエンドポイントが表示されているのが見えます。 (アクセス時の結果は一つ目のパターンと同じため割愛)
Creating service 'helloworld-go' in namespace 'default': 0.046s The Route is still working to reflect the latest desired specification. 0.049s Configuration "helloworld-go" is waiting for a Revision to become ready. 0.067s ... 4.996s ... 5.026s Ingress has not yet been reconciled. 5.117s Waiting for load balancer to be ready 5.298s Ready to serve. Service 'helloworld-go' created to latest revision 'helloworld-go-00001' is available at URL: http://helloworld-go-default.apps.mycluster4.bsf7.p1.openshiftapps.com
OpenShiftコンソールから作成する
これまでの方法はあらかじめアプリケーションのコンテナが準備されていることが前提となっていましたが、OpenShiftコンソールを使うとアプリのソースコードがあればKnative/Serviceを作成することが出来ます。
まずOpenShiftのDeveloperパースペクティブを開き、"+追加"をクリックします。 ここでGitリポジトリを選択し、次の画面に移ります。
デプロイするアプリケーションのソースコードが置かれたGitリポジトリのURLを入力すると、リソースタイプとしてServerlessデプロイメントを選択することが出来ます。このオプションはOpenShift ServerlessのOperatorをインストールしている時のみ表示されます。
Serverlessを選択しアプリケーションを作成すると、トポロジービューからKnative/Serviceが作成され、アクセスのためのエンドポイントが提供されていることが確認出来ます。
このようにOpenShiftコンソールを使うパターンではより簡単にサーバーレスのアプリケーションを実行することが出来ます。
まとめ
今回の記事ではKnative Servingの基礎的な内容についてご紹介させて頂きました。
サーバーレスというと敷居が高いと感じられる方もいらっしゃるかもしれませんが、実際にはわずかなステップで簡単にアプリケーションをデプロイすることが出来ます。
もし自分でも触ってみたいという方がいれば、learn.openshift.comにあるServerlessのコンテンツを無料で触ることも出来るため是非試してみて下さい!