本稿はJCB Advent Calendar 2024の12月4日の記事です。
SREチームの鳩貝です。
JDEPでは、マイクロサービス間の通信制御にGoogle CloudのマネージドIstioであるCloud Service Mesh (CSM)を採用しています。JDEPの規模拡大に伴い、アプリリリース時にJDEP基盤全体のCPU使用量がスパイクする事象が発生しました。本挙動はIstioのxDS APIの仕様が原因であり、サービスメッシュ全体の規模が大きくなるにつれて顕著になっていました。
上記に対処するため、IstioのexportTo設定を活用することで負荷軽減と安定化を図りました。本記事では当該設定導入による効果検証の結果を共有します。
1.概要
CSM(Istio)はデフォルト仕様として、istio-proxyをsidecarとして各Podにinjectionし、コントロールプレーンがxDS APIを介して経路等の設定をクラスタ内の全istio-proxyに通知します。本挙動がリリース時におけるコントロールプレーンからクラスタ内istio-proxyへ大量のxDS APIプッシュにつながり、結果JDEP全体におけるCPU使用率スパイクの原因となっていました。 JDEPは単一Kubernetesクラスタに複数アプリを稼働させるマルチテナント構成であるため、稼働アプリの増加に伴いPod数やIstioリソースは日々増加/大規模化しています。今後のリソース増加に伴いリリース時のCPU使用率スパイクの悪化が予期されることもあり、基盤の安定性確保のため上記事象の改善は急務でした。
本事象に対し、xDSのpush量に関連するリソース(VirtualService、 Kubernetes Service、etc)にexportTo設定を導入し、設定通知範囲をクラスタ全体から特定namespaceに制限しました。これによりxDSのプッシュ数/1プッシュあたりのデータサイズを削減することで、負荷軽減と安定化を目指しました。

2-1.VirtualService(Istio関連リソース)への適用例
Istio関連リソースへの設定例として、VirtualServiceへのexportTo設定を示します。
本VirtualServiceはns:apl1上で設定されており、ns:istio-system上で稼働するIstio Ingress Gatewayおよびns:apl2上で稼働するPodとの通信要件がある、とします。この要件を踏まえたexportToの記載は 27〜29行目のようになります。
なお、ServiceEntry や DestinationRule など、他のIstio関連リソースへの適用方法も同様となります。詳細はリンク先のIstio公式マニュアルを参照ください。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: apl1-virtualservice
namespace: apl1
spec:
hosts:
- apl1.example.com
gateways:
- istio-system/external-gateway
http:
- name: apl1-frontend
match:
- uri:
prefix: "/"
route:
- destination:
host: apl1-frontend.apl1.svc.cluster.local
port:
number: 8080
subset: stable
- destination:
host: apl1-frontend.apl1.svc.cluster.local
port:
number: 8080
subset: canary
exportTo:
- "istio-system" # Istio Ingress Gatewayからのリクエスト受信に必要
- "apl1"
- "apl2" # namespace間通信要件が存在する場合のみ設定
2-2.Kubernetes Service(k8s関連リソース)への適用例
Kubernetes関連リソースへの設定例として、Kubernetes ServiceへのexportTo設定を示します。以下記載例のとおり、Serviceの場合はannotationとしてexport先のnamespaceを指定可能です。
なお、前提の通信要件は上記VirtualServiceと同様とします。
apiVersion: v1
kind: Service
metadata:
annotations:
networking.istio.io/exportTo: "istio-system,apl1,apl2"
name: apl1-service
namespace: apl1
spec:
selector:
app: apl1
ports:
- protocol: TCP
port: 80
targetPort: 8080
3.評価
アプリチームによる設定適用を確認した後、 JDEP標準のモニタリングツールであるDatadog/Cloud Monitoringを用い、exportTo設定適用前後におけるistio-proxyのパフォーマンスを以下メトリクスに着目して分析しました。
- xDS push数:istio-proxy にプッシュされたxDS設定情報の回数
- xDS pushサイズ:istio-proxy にプッシュされたxDS設定情報のサイズ
- CPU使用率:istio-proxyのCPU使用率のピーク値と平均値
3-1.exportTo設定前
- アプリAのリリースを11:00〜11:10の範囲で実施。なお、JDEPではCDツールとしてArgoCDを採用しているため、リリースタイミングはArgoCDが生成するメトリクスで表示。

exportTo設定前ArgoCDイメージ - Cloud Logging上で合計2518件のEDS/RDS pushイベントを確認。

exportTo設定前Cloudloggingイメージ - EDS push一件あたりのサイズは252.9kB。
EDS: PUSH request for node:xxxxx resources:480 size:252.9kB empty:66 cached:100/480
- 結果としてリリースタイミングで別アプリBが利用するistio-proxyのCPU使用率がスパイク。

exportTo設定前CPUイメージ
3-2.exportTo設定後
- アプリAのリリースを17:15〜17:25の範囲で実施。

exportTo設定後ArgoCDイメージ - Cloud Logging上で合計251件のEDS/RDS pushイベントを確認。 → pushイベント数が約1/10に減少

exportTo設定後Cloudloggingイメージ - EDS push一件あたりのサイズは176.6kB。 → データ量は約30%削減
EDS: PUSH request for node:xxxxx resources:400 size:176.6kB empty:0 cached:398/400
- 結果としてリリースタイミングで別アプリBが利用するistio-proxyのCPU使用率がスパイクしないことを確認。

exportTo設定後CPUイメージ
4.まとめ
exportTo設定を適用することにより、istiodからistio-proxyへの不要なxDSプッシュを削減し、以下の効果が確認できました。
- istio-proxyへのxDSプッシュ数の削減とプッシュサイズの縮小による負荷軽減
- リリース時におけるistio-proxyのCPU使用率とメモリ使用率のスパイク抑制
今回の検証結果を受け、Prod環境へのexportTo設定適用を現在推進中です。これにより、JDEP全体の安定性、パフォーマンスの向上が期待されます。
なお、Istio 1.22からDelta xDSがDefaultになりました。これによりIstioの構成変更時、従来のように全経路情報を全体に通知するのではなく、変更分のみ通知するようになるようです。よって1.22以後は本検証で実施したexportToによる明示的な制限が不要になるかもしれません。今後注視していきたいですね。
終わりに
JCBでは我々と一緒に働きたいという人材を募集しています。 詳しい募集要項等については採用ページをご覧下さい。
本文および図表中では、「™」、「®」を明記しておりません。 記載されているロゴ、製品名は各社及び商標権者の登録商標あるいは商標です。
また、記事の内容は、公開時点の情報に基づいています。最新の情報については、Google Cloud の公式ドキュメントをご確認ください。