GKEのistioでサンプルアプリを動かす(フォールトインジェクション、タイムアウト編)
前回、前々回に引き続き、GKE上のistioでサンプルアプリケーションを動かして設定を確認していきます。
今回の目標は、タイムアウトの設定と動作を確認することです。
参考にするページは以下のとおりです。
フォールトインジェクション
タイムアウトの設定を確認するまえに、タイムアウトする状態を作り出す必要があります。 そこで、フォールトインジェクションについて学びます。
まず、用意されたVirtualServiceを適用させます。
$ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
設定された内容を確認してみます。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
namespace: default
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
end-userという名前のheaderにjasonという文字列が入っている場合のみ、reviewsへのリクエストをv2に転送するという設定になっています。 その他のreviewsのリクエストはすべてv1に転送されます。
それでは、フォールトインジェクションしてトラフィックを遅延させます。
kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml
設定された内容を確認します。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
namespace: default
spec:
hosts:
- ratings
http:
- fault:
delay:
fixedDelay: 7s
percentage:
value: 100
match:
- headers:
end-user:
exact: jason
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
faultが追加されて、ratingsへのアクセスに固定の遅延7秒が100%で発生するように設定されました。
ここで、サンプルアプリケーションのタイムアウトの仕様の確認しておきます。
- reviewsからratingsの通信は、10秒でタイムアウトするようにハードコーディングされている
- productpageからreviewsへの通信は、3秒間のタイムアウトで再試行の回数は1になっている
- つまり、初回3秒と再試行3秒で、合計6秒でタイムアウトする
- productpageはreviewsに依存して、reviewsはratingsに依存する
この場合、ratingsに7秒の遅延が発生する場合、どのような影響がでるか考えてみてください。
では、実際にブラウザから検証していきます。
まず、productpageを開いてみると、遅延は発生せずに表示されます。
headerに特定の内容を含まない通常のアクセスの場合は、遅延が発生しません。
次に、jasonでログインしてみます。
すると、遅延が発生し、レビューが表示されてないことが確認できます。
reviewsからratingsへの通信は、タイムアウトが10秒なので7秒遅延しても、実際にタイムアウトすることはありません。
しかし、productpageからreviewsへの通信は6秒なので、reviewsがratingsへ7秒以上かけて通信する前に、productpage側でタイムアウトしてしまいます。
なので、reviewsからratingsへの通信は成功していても、実際にレビューを取得して表示することができなかったのです。
リクエストのタイムアウト
フォールトインジェクションの例では、ハードコードされたタイムアウトでしたが、今回はVirtualServiceでタイムアウトを設定します。
istioからタイムアウトを設定すると、アプリケーション側でタイムアウトをハードコードする必要がなくなり、よりサービス自体の役割に集中できます。
まず、ルーティングを初期化します。
$ kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
この状態だと、すべてv1へのリクエストになるのですが、reviewsからratingsへの通信を有効にしたいので、reviewsをv2にします。(v1だとratingsへアクセスしません)
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
EOF
ブラウザでアクセスすると、黒い星が表示されていて、reviewsがv2になっていることが確認できます。
次に、ratingsへ2秒の遅延をフォールトインジェクションします。
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percent: 100
fixedDelay: 2s
route:
- destination:
host: ratings
subset: v1
EOF
ブラウザでアクセスすると、2秒遅延していることが確認できます。
この状態で、reviewsサービスの呼び出しに0.5秒のタイムアウトを設定します。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
timeout: 0.5s
EOF
ブラウザでアクセスすると、約1秒でレスポンスが返り、レビューが取得できてないのが確認できます。
productpageは上記の通り、reviewsへ通信します、ここのタイムアウトは0.5秒です。
そして、reviewsはratingsへ通信しますが、2秒の遅延が発生します。
よって、reviewsがratingsへ通信している間に、productpageからreviewsの通信が0.5秒でタイムアウトしています。
実際には、約1秒かかるわけですが、これはフォールトインジェクションのところで説明したとおり、productpageは1回だけ再試行するので、実際には0.5秒+0.5秒の1秒でレスポンスが返ります。
まとめ
フォールトインジェクションとタイムアウトの設定と動作を確認しました。
フォールトインジェクションは、遅延に対するバグを発見するときに非常に有用だと思いました。
タイムアウトは、サービス側で実装する必要がなくなるので、サービスの実装コストやバグを抑えられると思います。
特に、通信の遅延から発生する障害は、サービス全体に影響を及ぼす可能性があるので、リリース前にしっかりと確認したいところです。
この記事を書いた人
-
2008年にアーティスへ入社。
システムエンジニアとして、SI案件のシステム開発に携わる。
その後、事業開発部の立ち上げから自社サービスの開発、保守をメインに従事。
ドメイン駆動設計(DDD)を中心にドメインを重視しながら、保守可能なソフトウェア開発を探求している。
この執筆者の最新記事
関連記事
最新記事
FOLLOW US
最新の情報をお届けします
- facebookでフォロー
- Twitterでフォロー
- Feedlyでフォロー