社内勉強会で使用した資料になります。Istio入門に少しでもお役に立てれば幸いです。
入門2022/06 李 俊起
View Slide
本日のゴールWho• Istio導入を検討している(すでに導入している)システムの担当者• Istioという単語を聞いたことはあるけど何をするものかよく分からない方What• Istioの機能(何を解決してくれるか)を理解した上で、担当システムへのIstio導入について適切に判断できるようになる• Istioについて何となく分かった気になれる!(李含む)
本日の構成• 座学• Service Meshとは• Service Meshが登場した(必要となった)背景• Istioの機能• Istioの構成• デモ• Traffic Management• Observerbility• まとめ
Service Meshとは• 各アプリ(Service)の隣にProxyを配置し、アプリ(Service)同士のすべての通信を、プロキシーを経由するよう(Mesh)にした状態
Service Meshが登場した背景• マイクロサービスアーキテクチャの台頭A 機能 B 機能D 機能モノリスC 機能マイクロサービスA 機能 B 機能D 機能 C 機能API APIAPIAPI
マイクロサービスに潜む課題マイクロサービスA 機能 B 機能D 機能 C 機能API APIAPIAPI• ネットワークは不安定という前提→リトライ、タイムアウト• 過剰なAPI Callから自身を守る必要がある→流量制限• カスケード障害の恐れ→サーキットブレーカー• 障害/遅延発生時、原因箇所の特定が困難→俯瞰的な監視• サービス同士でネットワーク通信が発生→通信の暗号化Istioですべて解決!
Istioの機能✓ タイムアウト✓ リトライ✓ フォールトインジェクション✓ カナリアリリース✓ B/Gデプロイメント✓ 流量制限✓ サーキットブレーカー✓ Kiali✓ テレメトリーデータの生成(OSSツールとの高い親和性)✓ mTLS
Istioの構成• Control Plane➢ サービスメッシュ全体を司る司令塔(istiod)✓ トラフィックの設定をProxyに反映✓ 証明書管理/配布✓ Proxyからテレメトリーデータを収集• Data Plane➢ Sidecar Proxy(Envoy)✓ 実際トラフィックを制御✓ テレメトリーデータを生成
v1.5からIstioの構成がシンプルに1.5からistiodという1つのPodになった
Demo
デモ用アプリの構成Client CalculateDBImage・以下をまとめてHTMLをレンダリング- Imageからのペット写真- DBからのペット情報- Calculateからの計算結果・計算結果を返すAPI・DB/Image API Gateway・ペットの情報を返すAPI・ペットの写真を返すAPI
Istioインストール/アプリデプロイ• istioctlインストール➢ curl -sL https://istio.io/downloadIstioctl | sh -• istioインストール➢ istioctl install --set profile=default -y• istioインストール確認➢ kubectl get po,svc –n istio-system
Sidecar Proxy(Envoy)がない!?• Sidecar Proxyを挿入したいnamespace(ns)に以下のラベルを付与➢ kubectl label ns <対象namespace> istio-injection=enabled• アプリを削除後、再デプロイ• PodのREADY列の値が「1/1」→「2/2」に変わったことを確認• IstioのSidecar Injectorが「istio-injection=enabled」ラベルが付いているnsにPodが払い出される時、PodにEnvoyコンテナを挿入
インストール(デプロイ)直後の状態ELBEKS ClusterIngressGatewayClient CalculateDBImageClient CalculateDBImageIngress GatewayとClientのServiceを関連付ける必要があるIngress Gatewayの受付設定が必要エッジProxy メッシュProxy
IngressGatewayとServiceの紐づけVirtualServiceIngressGatewayClientGatewayIngress Gatewayが受け付けるPort番号とProtocolを指定このルールを適用するIngress Gatewayを指定webサイトのドメインを指定Gatewayのhostsに合せる紐づけるIngress Gatewayを指定※Gatewayの[metadata.name]に合せる設定反映トラフィックを流すServiceとポート番号を指定ClientELB8080
①Traffic Management
タイムアウト、リトライを試すための設定Client CalculateClientから計算を求められた時に20秒間Sleepするようにアプリを修正Calculate向け通信にタイムアウト時間を設定して、タイムアウトさせる12 Calculate向け通信にタイムアウト時間を設定して、タイムアウトが発生した際、リトライする3タイムアウト リトライ
タイムアウト、リトライ• タイムアウト • リトライCalculate向けの通信に2秒のタイムアウトを設定「retryOn」に指定した事象が発生した時に「attempts」の数の分リトライする。「perTryTimeout」は最初のリクエスト &リトライ時のタイムアウト時間
フォールトインジェクションClient CalculateCalculate向け通信で503エラー発生「httpStatus」のエラーを「percentage.value」の確率で発生させる
カナリアリリース、 B/GデプロイメントClientCalculatedog-with-multiCalculatecat-with-plus90%10%Calculate向け通信において「version: cat-plus」ラベルのPodは「cat-with-plus」というsubsetとして定義Calculate向け通信において「version: dog-multi」ラベルのPodは「dog-with-multi」というsubsetとして定義Calculate向け通信の90%を「cat-with-plus」subsetにルーティングCalculate向け通信の10%を「dog-with-multi」subsetにルーティング
Darkリリース (Dark Launching)• Darkリリースとはユーザに影響を与えず(もしくは一部のユーザのみに)新機能をリリースしてリスクなしに(もしくは少ないリスクで)新機能を試すリリース方式HTTPヘッダーに「version: dog」がある場合はdog-with-multiに、それ以外場合はcat-with-plusにルーティングするClientCalculatecat-with-plusCalculatedog-with-multiversion: dogヘッダー有version: dogヘッダー無
流量制限(Rate Limit)• 2種類のRate Limitが存在1. Global Rate Limit➢ クラスター全体に適用する流量制限2. Local Rate Limit➢ 特定のインスタンス(アプリ)に適用する流量制限
Global Rate Limit• rate limit serviceという別コンポーネントのデプロイが必要• リクエストのたびにrate limit serviceに加算され、クォータを超えたら“429 Too Many Requests”を返すIngressGatewayratelimit429クォータ超過時※今回は1分以内に5回以上リクエストが発生したら429を返すように設定rate limit service
Local Rate Limit• rate limit serviceなど別コンポーネント不要• tokenのbucketがあり、リクエストのたびにtokenが消費され、tokenを使い切ったら“429 Too Many Requests”を返す• tokenは一定時間後補充される
サーキットブレーカー10s以内にErrorが3回以上発生したら30s間対象Podを切り離すClientCalculatedog-with-multiCalculatecat-with-plus5秒間SleepCalculate向け通信に1秒のタイムアウト時間を設定して、cat-with-plus向け通信をタイムアウトさせる。タイムアウトが3回以上発生したらcat-with-plusへのルーティングを取りやめる
②Observability
Kiali• Istio専用の観測ツール• Service Map等、クラスター全体の状態が確認できる• サービス(アプリ)ごとのメトリクス/ログも確認可能• Istioの設定確認/変更もできる
メトリクス• Prometheus形式でメトリクスを生成(Envoy)• Istio自身に関するメトリクス• トラフィック関連メトリクス• GrafanaでIstio専用ダッシュボードが用意されている※ダッシュボードをImportするだけ
分散トレーシング• Envoyがトレースデータを生成• Jaeger等、バックエンド側を用意するだけでOK• が、Istioの分散トレーシングには1つ注意点が・・・。
トレースがつながってない理由• Envoyは自動でContextを生成/伝搬• アプリはトレースの存在について知らない(伝搬しない)• ヘッダーにあるContextを伝搬するようアプリ側の実装が必要Client CalculateIngressGateway・x-b3-traceid・x-b3-spanid・x-b3-traceid・x-b3-spanid・x-b3-traceid・x-b3-spanid・x-b3-traceid・x-b3-spanidContext生成・x-b3-traceid・x-b3-spanid新Context生成・x-b3-traceid・x-b3-spanid・x-b3-traceid・x-b3-spanid新Context生成
③Security
mTLS• クラスター内のIn/Outすべての通信を暗号化• デフォルトで適用Client CalculateDBImageIngressGatewayEKS Cluster
まとめ
Service Meshは本当に必要なのか• Istio利用にはそれなりの稼働が必要。(定期的なバージョンアップなど)• システムにService Meshのどの機能が必要で、代替手段はないか確認• 必要な機能によってはマネージドサービス(App Mesh)の利用を検討※YouTubehttps://www.youtube.com/watch?v=ZwfdLAClzsc※資料https://speakerdeck.com/toricls/service-meshes-do-we-really-need-them-what-problems-do-they-solve
✓ タイムアウト✓ リトライ→ 共通ライブラリ✓ カナリアリリース✓ フォールトインジェクション→ 利用シーンが少ない✓ B/Gデプロイメント→ Argo Rollouts等✓ 流量制限→ OWL、OWX✓ サーキットブレーカー→ 閾値設定の難しさ✓ Kiali✓ テレメトリーデータ→ Opentelemetry、X-RayDatadog、Prometheus等✓ mTLS→ 閉域網内で完結する場合がほとんどService Meshは本当に必要なのか
Istio VS AWS App Mesh機能 / ツール Istio AWS App MeshProxy Envoy EnvoyOperations Cost High(自前構築/運用)Low(マネージドサービス)(追加料金なし)Retry / Timeout 〇 〇Weighted routing 〇 〇Rate Limit 〇 X (※1)Curcuit Breaker 〇 〇mTLS 〇 〇Observability 〇 〇 (※2)※1 一応ロードマップにはRate Limitの機能追加が載っている※2 分散トレーシング利用のためには有効化する必要がある
資材公開しています• 本日使用した資材はすべてgitに上げています!ぜひ付録のハンズオン手順をもとに実際手を動かして試してみて下さい!• 実行環境• EKS v1.21
※付録ハンズオン手順
Istioインストール• istioctlインストール➢ curl -sL https://istio.io/downloadIstioctl | sh -• istioインストール➢ istioctl install --set profile=default -y• istioインストール確認➢ kubectl get po,svc –n istio-system• default namespaceに以下のラベルを付与➢ kubectl label ns default istio-injection=enabled
デモ用アプリ/Gatewayデプロイ• デモ用アプリのデプロイ➢ git clone https://github.com/nutslove/python.git➢ cd python/FastAPI➢ kubectl apply -f 00_Application/• Gatewayデプロイ➢ kubectl apply –f 01_IngressGateway/• ブラウザから下記コマンドで出力されるLoadBalancerのEXTERNAL-IPにアクセスし、デモ用アプリが表示されることを確認➢ kubectl get svc –n istio-system※ELBのSGから80ポートを、ワーカーノードのSGから30000~32767を許可しておくこと
タイムアウト• Timeout用アプリのデプロイし、新しいcalculate-v1のPodが動いていることを確認➢ kubectl apply -f 02_Timeout/calculate_v1_sleep.yml• ブラウザから画面下部の数字1と数字2に適当に数字を入れて「足し算」を押下し、しばらく(20秒間)結果が返ってこないことを確認• IstioのTimeoutの設定を適用する➢ kubectl apply -f 02_Timeout/Istio_Timeout.yml• 再度ブラウザから数字1と数字2に適当に数字を入れて「足し算」を押下し、2秒後「Timeout Error」が返ってくることを確認• IstioのTimeoutの設定を削除する➢ kubectl delete -f 02_Timeout/Istio_Timeout.yml
リトライ• IstioのRetryの設定を適用する➢ kubectl apply -f 03_Retry/• ブラウザから数字1と数字2に適当に数字を入れて「足し算」を押下し、8秒後「Timeout Error」が返ってくることを確認• IstioのRetryの設定を削除する➢ kubectl delete -f 03_Retry/➢ kubectl apply -f 00_Application/
フォールトインジェクション• IstioのFault Injectionの設定を適用する➢ kubectl apply -f 04_Fault_Injection/• ブラウザからアクセスし、「503 Service Unavailable」が表示されることを確認• IstioのFault Injectionの設定を削除する➢ kubectl delete -f 04_Fault_Injection/
カナリアリリース• v2のcalculateをデプロイ➢ kubectl apply -f 05_CanaryRelease_BG_Deployment/calculate_v2/• ブラウザから何回かアクセスし、犬/猫が交互に表示されることを確認• IstioのWeighted routingの設定を適用する➢ kubectl apply -f 05_CanaryRelease_BG_Deployment/• ブラウザから何回かアクセスし主に猫が、たまに犬が表示されることを確認
B/Gデプロイメント• viでdogのweightを100、catのweightを0にして再適用する➢ vi 05_CanaryRelease_BG_Deployment/Istio_Canary_Release.yml➢ kubectl apply –f 05_CanaryRelease_BG_Deployment/• ブラウザからアクセスし、犬だけが表示されることを確認• IstioのCanary Releaseの設定を削除する➢ kubectl delete -f 05_CanaryRelease_BG_Deployment/
Darkリリース• ブラウザ(Chrome/Edge)の拡張機能「Mod Header」をインストールする• IstioのDark Releaseの設定を適用する➢ kubectl apply -f 06_Dark_Release/• ブラウザからアクセスし、猫だけが表示されることを確認• Mod HeaderのRequest headersから「version: dog」を設定した後、ブラウザからアクセスし、犬だけが表示されることを確認• IstioのDark Releaseの設定を削除する➢ kubectl delete -f 05_CanaryRelease_BG_Deployment/calculate_v2/➢ kubectl delete -f 06_Dark_Release/
流量制限(Global Rate Limit)• IstioのGlobal Rate Limitの設定を適用する➢ kubectl apply -f 07_RateLimits/Istio_Global_RateLimiting.yml• ブラウザから6回目のアクセスで429エラーが表示されることを確認• IstioのGlobal Rate Limitの設定を削除する➢ kubectl delete -f 07_RateLimits/Istio_Global_RateLimiting.yml
流量制限(Local Rate Limit)• IstioのLocal Rate Limitの設定を適用する➢ kubectl apply -f 07_RateLimits/Istio_Local_RateLimiting.yml• ブラウザから数字1と数字2に適当に数字を6回入れて、6回目で「Too Many Requests」が返ってくることを確認※初回は6回目以上クリックが必要だったり、60s経過前に制限が解除されたりすることがある• IstioのLocal Rate Limitの設定を削除する➢ kubectl delete -f 07_RateLimits/Istio_Local_RateLimiting.yml
サーキットブレーカー• IstioのCircuit Breakerの設定をデプロイ➢ kubectl apply -f 08_CircuitBreakers/• 以下curlで一定数の“Timeout Error”が発生した後、“犬と掛け算の部屋”だけが表示されることを確認➢ while true; do curl -s http:/// ¥| grep '' && sleep 0.5 ;done• IstioのCircuit Breakerの設定を削除する➢ kubectl delete -f 08_CircuitBreakers/➢ kubectl apply -f 00_Application/
Observability• 各種Observabilityツールをデプロイ➢ kubectl apply -f 09_Observability/• トレースのサンプリングの数値を修正➢ kubectl -n istio-system edit deploy istiod➢ 「PILOT_TRACE_SAMPLING」の値を100に修正してから「:wq」で保存• Kiali → ブラウザより「<ワーカーノードのPublic IP>:32000」にアクセス• Grafana →ブラウザより「<ワーカーノードのPublic IP>:32001」にアクセス• Jaeger → ブラウザより「<ワーカーノードのPublic IP>:32002」にアクセス
ヘッダーの伝搬• ヘッダー伝搬対応バージョンをデプロイ➢ kubectl apply -f 10_Header_Propagation/• JaegerにてトレースがIngress GatewayからDB/Imageまでつながっていることを確認