マイクロサービスの課題
マイクロサービスの課題の中で以下のものがあります
- 障害の連鎖
- 1つのサービスが障害でレスポンスが悪くなった場合、他のサービスのレスポンスも悪くなり、さらにはシステム全体に影響が出てしまう場合がある
- 障害が起きているもしくはレスポンスタイムが悪いサービスの特定
- 1つのレスポンスの中で複数のマイクロサービスを呼び出すと、どのマイクロサービスが原因でエラーになっているのか、またはレスポンスタイムが悪くなっているのか、特定が容易ではなくなる
- カナリーリリース
- 複数のマイクロサービスが絡み合っている場合、カナリーリリースをしようとすると複雑になりがち。
- サービスAとBとCがあって、リクエストの10%だけAとCの新バージョンにリクエストを流す場合とか
- マイクロサービス間の通信の安全性
- とあるマイクロサービスからのアクセスは本当に私達がデプロイした正規のマイクロサービスからのリクエストか?
これらの課題をサービスメッシュを使うことで解決できます。
サービスメッシュとは
サービスメッシュはサービス間通信を処理するソフトウェアレイヤーで、アプリケーションに代わってネットワーク要求を処理するヘルパーサービスです。
以下がサービスメッシュが提供する代表的な機能
- トラフィック制御
- 通信の回復性、耐障害性
- 通信の可視化、分散トレーシング
- 通信の認証、セキュリティ機能
Istioとは?
- Google, IBM, Lyft社 共同開発によりOSS化されたサービスメッシュ
- 環境非依存で複数のプラットフォームで利用可能
- Kubernetes, Nomad & Consul, etc
- Kubernetes Pod内にプロキシ(Envoy)をSidecarとしてデプロイするため コードを変更することなくサービスメッシュ機能の追加が可能
- EnvoyはCNCFホストのプロジェクトで、ハイパフォーマンスなL4/L7プロキシーサーバ(ロードバランサー)
- Envoyには以下のような機能がある
- Dynamic service discovery
- Load balancing
- TLS termination
- HTTP/2 and gRPC proxies
- Circuit breakers
- Health checks
- Staged rollouts with %-based traffic split
- Fault injection
- Rich metrics
- Envoyには以下のような機能がある
- EnvoyはCNCFホストのプロジェクトで、ハイパフォーマンスなL4/L7プロキシーサーバ(ロードバランサー)
KubernetesにIstioを入れた場合の構成図
リクエストはすべてプロキシサーバーであるEnvoyが担当します。これによりアプリケーションを修正することなく、ネットワークの制御が可能になっています。
またEnvoyはPodのサイドカーとしてデプロイされるためアプリケーションのコードを修正する必要がありません。
コントロールプレーンは、トラフィックルートのプロキシの管理や設定を行います。またポリシーの実施やテレメトリー(メトリックスやログ)の収集を行います。
Istioの機能
Load Balancing
サポートされているロードバランシングアルゴリズム
https://www.envoyproxy.io/docs/envoy/v1.5.0/intro/arch_overview/load_balancing#supported-load-balancers
- Random
- Round robin
- Original destination
- リクエスト情報をもとに、常に同じサーバーへリクエストを送る (sticky sessionのようなもの)
- Weighted least request
- 接続数が少ないサーバーへリクエストを送る
- Ring hash
- Consistent Hashingの一種
Traffic Management
Request Routing
- URLやRequest Headerの中身をみてルーティングを設定することができる
例:
リクエストヘッダーにend-user: jason
が含まれていれば、reviewsサービスのv2にリクエストがいき、
その他はreviewsサービスのv1にリクエストがいく。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
Traffic Shifting
- リクエストを流す割合を指定できる。例えば既存バージョンと新しいバージョンのアプリケーションに対して、新しいバージョンは1%しかリクエストを流さないということができる(カナリーリリース)
例:
90%のリクエストはreviewsサービスのv1にいき、残りの10%はv2にいく。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
Request Timeouts
- リクエストタイムアウト値を設定できる
- これにより、レスポンスタイムが異常に悪いマイクロサービスが存在することによって他のマイクロサービスにまで影響がでることを防げる
例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
timeout: 9s
reviews v1へのリクエストは9秒でタイムアウトする
Retry
- リトライ回数を設定することができる。これにより、とあるマイクロサービスへのリクエストがたまたまリクエスト処理に時間がかかっている場合に、リクエストをリトライさせることができる
- n秒間以上リクエストに処理がかかった場合、n回リトライさせるといった設定ができる
例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
timeout: 9s # 1
retries:
attempts: 3 # 2
perTryTimeout: 3s # 3
- 1: 1つのリクエストのタイムアウトは9秒
- 2: 3回リトライする
- 3: 1回のリトライのタイムアウト値は3秒
つまり、1リクエストの中で最大3回リトライする
Circuit Breaking
- 障害が発生したマイクロサービスによって、システム全体に影響が発生することがあります。これを防ぐための仕組みとしてサーキット・ブレーカーというものがあります。サーキット・ブレーカーは、とあるマイクロサービスに継続的に障害が発生している場合にはそのマイクロサービスからのリクエストタイムアウトを待たずにエラーを返します。
- n秒間の間に500系エラーがn回返った場合、n秒間そのマイクロサービスからのリクエストタイムアウトを待たずにエラーを返す といった設定ができる
例:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
...
outlierDetection:
consecutiveErrors: 7 # 継続した障害だと判定されるエラー(500系)数
interval: 10s # 解析を行う間隔
baseEjectionTime: 30s # consecutiveErrorsの上限を越したときに、ホストが即時エラーを返す最小期間
とあるPodから10秒間の間に7回以上500エラーが返った返った場合、30秒間そのPodへリクエストは送られないようにする
Fault Injection
- アプリケーションの信頼性をテストするために、ネットワーク層の障害を注入することができる(ネットワーク層のカオスエンジニアリング)
- 例えばn%のリクエストをn秒間遅らせたり、n%のリクエストを特定のhttp status(例えば500エラー)を返すようにできたりする。
- これによりアプリケーションの変更なしに簡単マイクロサービスの耐障害性をテストすることができる
delayを注入する例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
...
spec:
hosts:
- ratings
http:
- fault:
delay:
fixedDelay: 7s
percent: 90
match:
- headers:
end-user:
exact: jason
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
リクエストヘッダーにend-user: jason
が含まれている場合、そのリクエストの90%を7秒遅延させる
エラーを注入する例:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
...
spec:
hosts:
- ratings
http:
- fault:
abort:
httpStatus: 500
percent: 90
match:
- headers:
end-user:
exact: jason
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
リクエストヘッダーにend-user: jason
が含まれている場合、そのリクエストの90%はHttpStatus: 500を返すようにさせる
Mirroring
- 別のサービスにリクエストをコピーして送る
- これにより、本番と同等のステージング環境が作れたり、新しい機能や新しいクラスタが問題なく動くかをユーザに影響なしにテストすることが可能になる。
例:
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 100
mirror:
host: reviews
subset: v2
reviews v1へのリクエストをv2にコピーして送る
Security
Istioのセキュリティゴール
- Security by default
- アプリケーションコードとインフラの変更を必要としない
- Defense in depth
- 複数の防御レイヤーを提供するために、既存のセキュリティシステムと連携
- Zero-trust network
- 信頼できないネットワーク上にセキュリティソリューションを構築
認証機能(Authentication)
- 相互 TLS 認証
- エンドユーザ認証
- JWTトークンによるリクエストレベルの認証
- Auth0、Firebase Auth、Google Auth、カスタム認証
- 鍵管理
- Istio の鍵管理システムは、鍵と証明書の生成、配布、ローテーション、失効を自動化します。
- 役割ベースのアクセス制御(RBAC)
Policies
Rate Limits
ある一定時間のアクセス量を設定できる。
たとえば /timeline へのアクセスは1秒間100リクエストまで受け付け、100を超えたら429エラー(Too Many Requests)にできる。
Denials
特定の条件を満たすリクエストを遮断する
White/Black Listing
特定の条件を満たすリクエストのホワイトリスト/ブラックリストを定義できる
Observability
Logging
トラフィックに関するログ情報を標準出力したり、FluentdやStackdriverに送ることができる
https://istio.io/docs/reference/config/policy-and-telemetry/templates/
Metrics
トラフィックの各種統計情報
一般的には送信元/送信先、送信時刻といった情報が含まれる
Istioではこれ以外にも任意の情報をメトリックとして扱うことが可能
プラグイン機構によって以下のようなサービスにメトリックスを送信することができる
- Amazon CloudWatch
- Prometheus
- Stackdriver
- Datadog
- Fluentd
- etc
Grafana
Kiali
Istioはすべてのネットワークを把握しているので、どのコンポーネントにリクエストが送られていて、そのネットワークはどのくらい健康なのかを可視化できる。
以下はKialiを使ってネットワークグラフを表示したもの。グラフは自動で生成してくれる。
アニメーションON
アニメーションONにするとリクエストの様子が見れてちょっと楽しい
Tracing
分散トレーシングとは
分散トレーシングとはマイクロサービスのような分散されたサービスで処理されるリクエストを追跡(トレーシング)するためのもの。
マイクロサービスのような分散アーキテクチャでは、1つのリクエストが複数のサービスで処理されることになり、リクエスト全体の処理の流れの把握やボトルネックの特定が難しくなります。
このような問題を、サービスの依存関係やサービス単位のレイテンシーの可視化をすることによって、解決の手助けするためのシステムが分散トレーシングシステムです。
具体的には1リクエストの中でどのサービスが呼ばれ、どのくらい時間がかかったのかを、ユニークなidをリクエストヘッダーに付与することでトレーシングできるようにします。またそれらを可視化もできる。
サポートしているトレーシングツール
Jaeger
- Uber社で開発OSS化。CNCFプロジェクトの一つ
- Istioのデフォルトトレースはこちら。Zipkin互換、OpenTracing仕様準拠
- https://istio.io/docs/tasks/telemetry/distributed-tracing/jaeger/istio-tracing-details.png
Zipkin
- Twitter社開発でOSS化。GoogleのDapperを参考にして作られた。OpenTracing仕様準拠
- https://istio.io/docs/tasks/telemetry/distributed-tracing/zipkin/istio-tracing-details-zipkin.png
LightStep
- Saas。GUIを提供してくれる。
- OpenTracing仕様準拠
- GoogleのDapperを作ったGoogleのメインエンジニアが作ったツール
- https://lightstep.com/products/tracing/
- https://istio.io/docs/tasks/telemetry/distributed-tracing/lightstep/istio-tracing-details-lightstep.png
アプリケーション側で上記のような分散トレーシングツールを使う場合、Envoyが生成したトレースヘッダーを独自に伝播させる実装を行う必要がある。
参考
- Istioサービスメッシュ入門 https://www.slideshare.net/yokawasa/istio-114360124
- マイクロサービスアーキテクチャ向けにサービスメッシュを提供する「Istio」の概要と環境構築、トラフィックルーティング設定 https://knowledge.sakura.ad.jp/20489/
- Istioが備えるテレメトリ/ポリシー管理機能を使った統計情報取得と接続管理 https://knowledge.sakura.ad.jp/20681/
- 分散トレーシングシステムのZipkinを使ってみた話 https://qiita.com/miya10kei/items/2532b80fcd8d19eb2e75