Knative でのルーティング
Knative は Kubernetes の機能を拡張するオープンソース・プラットフォームです。その目的は、最新のソース中心のコンテナー化されたサーバーレス・アプリケーションを作成できるようにすることにあります。 Knative は Istio を統合することで、簡単にワークロードをインターネットに公開して、モニタリング、制御できるようにしています。 このチュートリアルでは、Knative のトラフィック管理機能に焦点を当てます。
目標
このチュートリアルでは、次の方法を学びます。
- アプリケーションの新しいリビジョンをロールアウトする
- アプリケーションの前のリビジョンにロールバックする
前提条件
このチュートリアルでは読者が一連の Knative 入門ラボを完了し、 Knative の基本概念を理解していること、すでに IBM Cloud Kubernetes Service クラスターを作成し、Knative をインストールしていることを前提としています。 このチュートリアルを完了するには、クラスターが作成済みになっている必要があります。
以下の演習にまだ取り組んでいない場合は、このチュートリアルの手順を開始する前に完了してください。
- 開発者用ツールをインストールする (ibmcloud、kubectl、knctl)
- IBM Cloud 上に Kubernetes クラスターを作成する
- プライベート・コンテナー・レジストリーをセットアップする
- Knative と Istio をクラスター上にインストールする
サンプル・アプリケーションをデプロイする
Knative を使用するには次の 2 つの方法があります。
- 下位レベルの Knative リソース (ルート、構成など) を直接管理する
- 上位レベルの Knative サービス・リソースを管理して、基礎となる下位レベルのリソースは Knative に管理させる
このチュートリアルでは単純にするために、2 番目の方法を使用します。
このチュートリアルでサンプルとして使用する helloworld プログラムは、このサンプルを編集したものです。
サンプル・アプリケーションのリポジトリーを複製し、そこに含まれている yaml ファイルを使用できるようにします。
git clone github.com/IBM/knative-routing-tutorial
Knative 入門で、kaniko ビルド・テンプレートを使用して Dockerfile ファイルからコンテナー・イメージをビルドする方法を学びました。まだ kaniko ビルド・テンプレートをクラスターにインストールしていない場合は、次のコマンドを使ってインストールしてください。
kubectl apply --filename https://raw.githubusercontent.com/knative/build-templates/master/kaniko/kaniko.yaml
helloworld1.yaml ファイルを使用して、helloworld プログラムをデプロイします。このファイルの内容を確認しましょう。
apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: helloworld-go namespace: default spec: runLatest: configuration: build: apiVersion: build.knative.dev/v1alpha1 kind: Build spec: serviceAccountName: build-bot source: git: url: https://github.com/IBM/knative-routing-tutorial revision: master template: name: kaniko arguments: - name: IMAGE value: registry.ng.bluemix.net/<NAMESPACE>/helloworld-go:1 - name: DOCKERFILE value:/workspace/helloworld1/Dockerfile revisionTemplate: spec: serviceAccountName: build-bot container: image: registry.ng.bluemix.net/<NAMESPACE>/helloworld-go:1 env: - name: TARGET value: "Go Sample v1"
この yaml ファイルは、git リポジトリー内のソース・コードからアプリケーションをビルドして、ビルドしたコンテナー・イメージをプライベート・コンテナー・レジストリーにプッシュします。その上で、コンテナーをレジストリーからプルして実行します。
helloworld1.yaml ファイルを編集して、独自のコンテナー・レジストリーの名前空間を指すようにする必要があります。
のすべてのインスタンスを、Knative 入門で作成したコンテナー・レジストリーの名前空間で置き換えてください。この作業が完了したら、helloworld1.yaml ファイルをクラスターに適用します。 kubectl apply -f helloworld1.yaml
ビルド・プロセスが実行されてプログラムが動作可能な状態になるまでには、しばらく時間がかかる場合があります。 サービスを表示すると、進捗状況をモニタリングできます。
kubectl get ksvc helloworld-go
サービスが実行可能な状態になったことが出力に示されたら、手順を進めます。次のような出力が表示されるまで待ってください。
NAME DOMAIN LATESTCREATED LATESTREADY READY REASON helloworld-go helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud helloworld-go-00001 helloworld-go-00001 True
上記の出力から、サービスのホスト名が
helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
であることがわかります。サービスのホスト名の一般的な形式は、service-name.service-namespace.ingress-subdomain です。
service name と service-namespace は service yaml ファイルによって決定されます。この例の場合、yaml では名前空間を指定していないので、
default
名前空間が使用されています。ingress subdomain は、クラスターにアクセスするためのパブリック URL です。これは、クラスターに付けた名前とクラスターが位置する場所によって異なってきます。
サービスのホスト名がわかったので、helloworld アプリケーションに対して curl コマンドを実行できます。以下の curl コマンドに含まれるサービス名の部分は実際の名前で置き換えてください。
curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello Go Sample v1!
のようなレスポンス・メッセージが表示されるはずです。
アプリケーションの新しいバージョンをロールアウトする
サンプル・アプリケーションに変更を加えて、単純な静的メッセージではなく、もう少し面白味のあるレスポンスが返されるようにしましょう。 前のステップでは、新しいイメージをビルドしてデプロイするために、アプリケーションの元のバージョンをまるごと置き換えました。 けれども何らかの時点で、新しい機能を徐々にユーザーにロールアウトする必要も出てくるでしょう。 その場合は、service yaml ファイル内で「リリース」モードという機能を使用します。
以下に、次に使用する yaml ファイル helloworld2.yaml を記載します。
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
release:
# Ordered list of 1 or 2 revisions.
# First revision is traffic target "current"
# Second revision is traffic target "candidate"
revisions: ["helloworld-go-00001", "helloworld-go-00002"]
rolloutPercent: 50 # Percent [0-99] of traffic to route to "candidate" revision
configuration:
build:
apiVersion: build.knative.dev/v1alpha1
kind: Build
spec:
serviceAccountName: build-bot
source:
git:
url: https://github.com/IBM/knative-routing-tutorial
revision: master
template:
name: kaniko
arguments:
- name: IMAGE
value: registry.ng.bluemix.net/<NAMESPACE>/helloworld-go:2
- name: DOCKERFILE
value:/workspace/helloworld2/Dockerfile
revisionTemplate:
spec:
serviceAccountName: build-bot
container:
image: registry.ng.bluemix.net/<NAMESPACE>/helloworld-go:2
このファイルでは、ビルドするサービスのポッド構成を変更して別のイメージを使用しているだけでなく、前の yaml ファイルの「runLatest」の部分を「release」で置き換えています。リリース・モードを使用すると、次のことが可能になります。
- 2 つのバージョンのリストを指定して、それらのバージョンの間でトラフィックを分割する。
この例では、前のリビジョン
helloworld-go-00001
と新しく作成するリビジョンhelloworld-go-00002
の間でトラフィックを分割します。 - 上記のリストにある 2 番目のリビジョンにルーティングするトラフィックのパーセンテージを指定する。この例では、トラフィックの 50 パーセントが新しいリビジョンに転送されるようになっています。
独自のコンテナー・レジストリーの名前空間を指すように helloworld2.yaml ファイルを編集します。<NAMESPACE>
のすべてのインスタンスを、Knative ラボで作成したコンテナー・レジストリーの名前空間で置き換えてください。
この作業が完了したら、helloworld2.yaml ファイルをクラスターに適用します。
kubectl apply -f helloworld2.yaml
前と同じように kubectl get ksvc helloworld-go
を使用して、新しいリビジョンが使用可能になるまでモニタリングします。使用可能な状態になったら、次のコマンドを使用して、ルートが 2 つのリビジョン間でトラフィックを分割していることを確認します。
knctl route list
次のような出力が表示されます。
Routes in namespace 'default'
Name Domain Traffic Annotations Conditions Age
helloworld-go helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud 50% -> helloworld-go-00001 - 3 OK / 3 15m
50% -> helloworld-go-00002
0% -> helloworld-go
curl
を何回か実行すると、最初のバージョンから返されたレスポンスの他に新しいレスポンスも表示されるはずです。
$ curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello and have a wonderful day!
$ curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello Go Sample v1!
Grafana を使用してトラフィックをモニタリングする
この Knative インストール済み環境には、Prometheus と Grafana も組み込まれています。 Prometheus は、多次元の時系列データを収集して保管できるオープンソースのモニタリング・ツールです。 Grafana は、グラフとダッシュボードでメトリクス・データを視覚化するために使用できるメトリクス分析プラットフォームです。 この 2 つのツールを使用すれば、サービスの 2 つのバージョンの間でトラフィックが分割される様子を観察することができます。
Grafana を開くには、次のコマンドを入力します。
kubectl port-forward --namespace knative-monitoring \ $(kubectl get pods --namespace knative-monitoring \ --selector=app=grafana --output=jsonpath="{.items..metadata.name}") \ 3000
これにより、Grafana のローカル・プロキシーがポート 3000 上で起動します。
http://localhost:3000 にアクセスして Grafana UI を表示します。
ページが開いたら、画面の上部にあるドロップダウンのダッシュボード選択メニューをクリックし、「Knative Serving – Revision HTTP Requests (Knative Serving – リビジョン HTTP リクエスト)」を選択します。 ダッシュボードが開いたら、「Configuration (構成)」ドロップダウン・メニューをクリックし、「
helloworld-go
」を選択します。別のシェルで、
helloworld-go
サービスに対する curl リクエストのループを実行します。それには次のようにします。for i in `seq 1 5000`; do curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud; done
「
Request Volume By Revision
(リビジョンごとのリクエスト量)」ダッシュボードで、リビジョン 1 と 2 の間でトラフィックが均等に分割されていることを確認できるはずです。後でまた戻れるよう、Grafana ウィンドウは開いたままにしておきます。
リリース・モードでのサービス・ホスト名の追加
サービス・リリース・モードを使用すると、特定のバージョンにアクセスするためのサービス・ホスト名が追加で作成されます。 これらのホスト名を確認するには、次のコマンドを使用します。
knctl route show --route helloworld-go
次のような出力が表示されます。
Route 'helloworld-go'
Name helloworld-go
Domain helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Internal Domain helloworld-go.default.svc.cluster.local
Age 1h
Targets
Percent Revision Service Domain
50% helloworld-go-00001 - current.helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
~ helloworld-go-00002 - candidate.helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
0% helloworld-go-00002 - latest.helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Conditions
Type Status Age Reason Message
AllTrafficAssigned True 1h - -
IngressReady True 1h - -
Ready True 1h - -
以下のサブドメインが追加されています。
current
。リビジョン・リスト内の最初のリビジョン (この例の場合、helloworld-go-00001) にトラフィックをルーティングします。candidate
。リビジョン・リスト内の 2 番目のリビジョン (この例の場合、helloworld-go-00002) にトラフィックをルーティングします。latest
。サービスの最新リビジョン (この例の場合、2 番目のリビジョンと同じ helloworld-go-00002) にトラフィックをルーティングします。
必要に応じて、これらのホスト名を使用して特定のリビジョンを試すことができます。
$ curl current.helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello Go Sample v1!
$ curl candidate.helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello and have a super day!
アプリケーションの以前のバージョンにロールバックする
ロールアウトをテストしていて、サービスの新しいリビジョンで何らかの問題が見つかったとしたら、新しいユーザーをそのリビジョンにはルーティングしたくないはずです。
その場合、サービスを編集するには次のコマンドを使用します。
kubectl edit ksvc helloworld-go
編集用のウィンドウが開き、サービスの現在の yaml 定義が表示されます。rolloutPercent
というキーを見つけて、その値を 0
に変更してからファイルを保存します。
これにより、すべてのトラフィックがリビジョン・リスト内の最初のリビジョンにルーティングされるようになります。
$ curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello Go Sample v1!
$ curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello Go Sample v1!
Grafana ウィンドウを見ると、すべてのトラフィックがリビジョン 1 にルーティングされるようになったことを確認できるはずです。
アプリケーションの最新バージョンにロールフォワードする
テストがうまく行って、すべてのユーザーを新しいリビジョンにルーティングしたいとします。 その場合、サービスの yaml ファイルを編集して、リビジョン・リストを変更します。現時点で、rolloutPercent は次のようになっているとします。
revisions:
- helloworld-go-00001
- helloworld-go-00002
rolloutPercent: 50
次のように変更します。
revisions:
- helloworld-go-00002
rolloutPercent: 0
これにより、すべてのトラフィックがサービスの最新バージョンにルーティングされるようになります。
$ curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello and have a wonderful day!
$ curl helloworld-go.default.mycluster6.us-south.containers.appdomain.cloud
Hello and have a super day!
Grafana ウィンドウを見ると、すべてのトラフィックがリビジョン 2 にルーティングされるようになったことを確認できるはずです。
次のステップ
お疲れさまでした!これでチュートリアルは完了です。このチュートリアルでは、Knative のルーティング機能を使用して、アプリケーションの新しいリビジョンをロールアウトする方法、以前のリビジョンにロールバックする方法を学びました。次のステップとして、クラウド上での Knative パイプラインの開発または Knative を使用した CD パイプラインのセットアップに挑戦してください。さらに、このリンク先のページで他のさまざまな Knative 関連のコンテンツを調べることもできます。