https://event.cloudnativedays.jp/cndf2023/talks/1846
1Confidentialメルカリにおけるプラットフォーム主導のKubernetesリソース最適化とそこに生まれた🐢の可能性Kensei Nakada / @sanposhiho
View Slide
2Mercari JP Platform team / 2022卒新卒Kubernetes approver (SIG-Scheduling)Kubernetes Contributor award 2022 winnerKensei Nakada / sanposhiho
3台風6号により沖縄から脱出できませんでした…運営の皆様ご迷惑おかけしました‥
4Mercari Kubernetes Cluster OverviewAgenda01Workloads on cluster + About FinOpsa.Node Level Optimization02Cluster Autoscalinga.Node machine typeb.Utilize Spot VM instancesc.
5AgendaWorkload Optimization03VPA / Resource recommendera.HPA fine tuningb.🐢を使用したWorkload Autoscaling04
6Kubernetes Cluster OverviewWorkloads on cluster + FinOps
7Kubernetesクラスター概要- GKEを使用 (Standard mode)- 一つのClusterで、Mercari/Merpayほぼ全てのWorkloadが動いている- namespace: 500+ / deployment 1000+- PlatformチームがCluster adminとして運用
8Workload について- ほとんどがGoで実装されたWorkload- この登壇に含まれる調査結果等はGoのWorkloadということを前提としてください- その他、ElasticSearch, php 等も居る- Istioを一部namespaceで使用 (全体の半分ほど) (拡大予定)- sidecarコンテナーがついているPodが割と存在する
9FinOps!- 直近メルカリでは全社的な目標としてFinOpsを掲げている- Monolith -> Microserviceのマイグレーションを経て、アーキテクチャを洗練していくフェーズ- Platformチームでもインフラリソースの効率化を推進- 殆どのサービスが乗っているのでインパクトが超絶大きい- あくまでも安全性を担保しつつ、リソースの効率化を行う
10このセッションについてメルカリではその他GCPリソースに対するFinOps、Datadogに関するFinOps等様々行っていますが、このセッションではあくまでKubernetes周辺のものだけを取り上げます
11Node Level OptimizationCluster Autoscaling
12Cluster AutoscalerCluster Autoscalerがいい感じに:- リソースがスカスカだったら、Podを詰めてNodeを減らす- Unschedulable Podsが居たら、Nodeを増やすをやってくれる
13Trade-off: Cost 💴 vs Reliability🛡Nodeのスペースに常に余裕を持っておくことで-> 👍 Nodeの障害やリソースの需要の急増に強くなる🛡-> 👎 常に余分にお金がかかる 💸
14GKE Autoscaling profilesGKE では Autoscaling profile を通してoptimize-utilization 💴 or balanced🛡 を選択できる:- Cluster Autoscaler がどのようにNodeを削除していくか- Aggressive 💴 vs Conservative🛡- SchedulerがどのようにPodをスケジュールするか- MostAllocated(Bin packing) 💴 orLeastAllocated🛡
15GKE Autoscaling profilesMercariではoptimize-utilization 💴を選択- Cluster Autoscaler がどのようにNodeを削除していくか- Aggressive 💴 vs Conservative🛡- SchedulerがどのようにPodをスケジュールするか- MostAllocated(Bin packing) 💴 orLeastAllocated🛡
16Node Level OptimizationNode instance type
17Node machine type元々MercariではE2 machine typeを広く使用していた→ コスパがいいと評判の、新たに追加されたTau T2Dの検討
18Tau T2D migrationいくつかの大きなWorkloadのmachine typeをE2からT2Dに変更- T2Dのinstance単位の単価はE2よりも高い- しかし、パフォーマンスが高く、多くのWorkloadでCPU使用量の減少を確認- プログラミング言語等の様々な要素によってCPU使用量の減少率が違う- Goの場合、大体 ~40%の減少- HPAが正しく動作している場合、CPU使用量の減少はそのままPod数の減少につながる→ 総合的に見てコスパ 👍👍👍 (migration後のnodepoolではコスト3割削減)
19
20Node Level OptimizationUtilize Spot instances (検証段階)
21Spot VM instances (検証段階)Spot VMはかなりの低価格で使用可能なインスタンス (60-91% cost down!)ただし...1. GKE側の都合で急に停止される可能性がある2. いつでも利用可能か保証されていない
22Spot VM instances (検証段階)1. GKE側の都合で急に停止される可能性がある → 一旦以下のようなPodのみを対象に利用の拡大を計画- 15s以内にシャットダウンできる- ステートレスである- Batch workloads
23Spot VM instances (検証段階)2. いつでも利用可能か保証されていない → Spot VM Nodeの数が足りずPodがスケジュールできない場合は on-demand Nodeにスケジュールする (preferred NodeAffinity)また、定期的にon-demand上のPodをSpotへ移動し直すようなコンポーネントを実装予定
24Workload Level OptimizationVPA / Resource recommender
25リソースの使用量を常に確認し、良さげなresource request/limitの推奨値を計算して、設定してくれる。→メルカリでは直接VPAはまだあまり使用されていないVerticalPodAutoscaler
26Multidimensional Pod autoscalingMultidimensional Pod autoscalingというHPAをCPUに、VPAをMemoryに使用するAutoscalerがGKEに存在Mercariでもいくつかのサービスで検証を行い、今後はこの方針に舵を切りつつある(MPAを直接使用するのではなく、HPA(CPU) + VPA(mem)を設定する)
27Resource RecommenderResource Recommenderと呼ばれるSlack botが動作しているユーザーは月に一度リソースの推奨のresource requestの値を受け取るHoge deploymentappcontainerXXXXXX
28Resource RecommenderResource Recommenderは過去1ヶ月のVPAの推奨値の最大値を取得し、「プラットフォーム推奨のresource request」としてユーザーに送っている
29Resource RecommenderResource Recommenderは過去1ヶ月のVPAの推奨値の最大値を取得し、「プラットフォーム推奨のresource request」としてユーザーに送っているCPUやMemoryの推奨値には時間帯等でばらつきがあるため、1ヶ月のVPAの推奨値の最大値とすることで安全値をとっている
30Workload Level OptimizationHPA fine tuning
31クラスター上のすべてのサービスにHPAを作成すれば、クラスターのリソース使用率も上がる?↓現実はそれほど簡単ではない● HPAの各種パラメーターの調整● リソースのRequestの調整をしないとHPAがパワーを発揮できないHPAの難しさ
321) Incident時のHPAのScale in問題- UpstreamのサービスがIncidentで落ちる- Downstreamのサービスに通信が行かなくなる- DownstreamのサービスのCPU使用量が下がるこの場合にDownstreamのサービスではHPAによるScale inが発生する
331) Incident時のHPAのScale in問題- UpstreamのサービスがIncidentで落ちる- Downstreamのサービスに通信が行かなくなる- DownstreamのサービスのCPU使用量が下がるこの場合にDownstreamのサービスではHPAによるScale inが発生する↓Upstreamのサービスが復活した時に、一気にトラフィックが流れてDownstreamのサービスが死ぬというインシデントが稀に発生
34高めにminReplicasを設定すればよくね?minReplicasを高めに設定しておけば、確かに解決になるがHPAの機能性を損なうので❌例: Pods数が通常のオフピーク時に3個/ピーク時に20個、targetUtilizationが70%の場合、ピーク時に障害という最悪のケースを考慮すると、minReplicasを14に設定する必要がある
35dynamic MinReplicasの実装1週間前の同じ時間のレプリカ数の1/2のレプリカ数をsuggestするDatadogMetricsを全てのHPAに導入↓HPAは複数の指標のレプリカ数の提案から一番大きいものを採用するため、Incidentの時など通常に比べて異常にレプリカ数が減少している時にのみ動作する
362) HPAがレプリカ増やしすぎる問題Deploymentのresource requestが小さすぎると、ピーク時のレプリカ数がとても多くなる。
372) HPAがレプリカ増やしすぎる問題Deploymentのresource requestが小さすぎると、ピーク時のレプリカ数がとても多くなる。この際、Podのサイズを大きくし、レプリカ数を小さく抑えた方が、省エネになる場合がある。とあるサービスでは、この最適化を行うことで、リソースコストが40%減少(ピーク時のレプリカ数は200->30に変化)
383) HPAがレプリカ全然増やさない問題Deploymentのresource requestが大きすぎると、HPAを設定していても「レプリカ数がずっとminReplicasで制限されてる」みたいなケースが起こりうるこの場合、HPAが機能していないに等しいためCPU使用率も低くなる
393) HPAがレプリカ全然増やさない問題この場合、- Podのサイズを十分に小さくしてHPAが動作するようにする- VPAにCPUも任せる等を考える必要がある
404) Multiple containers Pod with HPAめんどくさい問題例: HPAのtarget utilization: sidecar: 80%/app container: 80%この場合、HPAはどちらかのcontainerのresource utilizationが80%を大きく超えた時にスケールアウトを行う。↓これによって、sidecar or app のどちらかのリソースが常に余っているということになり得る。
414)Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecarどちらもTarget: 80%
424)Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar リソース使用量が増えていく50%30%
434) Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar リソース使用量が増えていく50%
444) Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar SidecarのUtilizationが80%に達したので、HPAはPodの数を増やす50%
454) Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar50%Appは30%のリソース余している…
464) Multiple containers Pod with HPAめんどくさい問題HPAを設定していても、CPU 使用量を確認しつつ、片方のcontainerの使用量が常に低い場合、contianerのsizeを調整する必要がある。
474) Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar80%Appのresource requestを下げる同時に80%に達するのが一番リソースの無駄がない
485) HPAのtarget utilization決めるの難しすぎ問題メルカリでは、HPAのtarget utilizationは70%-80%に設定されていることが多い。↓なぜ20%-30%の余分なCPUを与えておく必要があるのか?
495) HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のため
505) HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のためリソース使用率の平均値が80%だとしても、いくつかのPodではcontainerの使用率は100%を超えている可能性もある
515) HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のため→ (次スライド)
525) HPAのtarget utilization決めるの難しすぎ問題0. トラフィックが増えるにつれて、リソース使用量が増えていく1. リソース使用率が閾値に達する2. HPAが気がついてスケールアウトを実行する3. (Cluster AutoscalerがNodeを増やす)4. 新しいPodが作られ実際に動き出し、READYになる(1) → (4)にかかる時間の間もリソース使用量が増えているため、この間の時間稼ぎの必要性
535) HPAのtarget utilization決めるの難しすぎ問題- Containerごとのリソース使用率のばらつき- トラフィックの増加のスピード- HPA controllerのリコンサイルの間隔- (Nodeに空きができるまでの時間 (via Cluster Autoscaler)- Podが動き出すまでにかかる時間これらを踏まえて、適切な「余分リソース」をtarget utilizationを通してPodに与える必要がある
545) HPAのtarget utilization決めるの難しすぎ問題- Containerごとのリソース使用率のばらつき- トラフィックの増加のスピード- HPA controllerのリコンサイルの間隔- (Nodeに空きができるまでの時間 (via CA or overprovisioning Pods))- Podが動き出すまでにかかる時間これらを踏まえて、適切な「余分リソース」をtarget utilizationを通してPodに与える必要がある無理じゃね…?
55ここまでの話1. Incident時のHPAのScale in問題2. HPAがレプリカ増やしすぎる問題3. HPAがレプリカ全然増やさない問題4. Multiple containers Pod with HPAめんどくさい問題5. HPAのtarget utilization決めるの難しすぎ問題
56ここまでの話1. Incident時のHPAのScale in問題2. HPAがレプリカ増やしすぎる問題3. HPAがレプリカ全然増やさない問題4. Multiple containers Pod with HPAめんどくさい問題5. HPAのtarget utilization決めるの難しすぎ問題無理じゃね…?
57🐢を使用したWorkload Autoscaling
58mercari/tortoise
59これからはリクガメに任せる時代です。過去のWorkloadの振る舞いを記録し、HPA, VPA, Pod resourcerequest/limitの全てをいい感じに調節してくれるKubernetes controllerhttps://github.com/mercari/tortoise
60mercari/tortoiseのモチベ- 人間の手で先ほどの最適化を全て行うのは厳しい- 最適化後もアプリケーションの変化に伴い、定期的な見直しが必要- Platform推奨の設定や新しい機能適応への移行のコスト- 現状、PRを全てのHPAに送りつけたりしている。めんどい- Datadog metricを含む外部サービスにautoscalingを依存させたくない- 外部サービスの障害の間、HPAが正しく動かず眠れぬ夜を過ごすことになる
61Simplified configurationapiVersion: autoscaling.mercari.com/v1alpha1kind: Tortoisemetadata:name: nginx-tortoisenamespace: tortoise-pocspec:updateMode: AutotargetRefs:deploymentName: nginx-deploymentDeployment name ONLY!
62Simplified configuration- ユーザーは対象のdeploymentの指定のみを行う。- Optional なフィールドはその他少し存在するが基本使用不要- 「コーナーケースのために柔軟な設定を与える」ことはしない- HPA, VPA, resource req/limの全ては🐢がいい感じに設定する- 一つのTortoiseを設定する => HPA, VPAを全ての
63mercari/tortoiseの機能- HPA optimization- 前章で「無理じゃね…?」と言ってたやつを全部自動で行う- VPA optimization- HPAとVPAがうまいこと同時に動けるように調整- Emergency mode
64Horizontal Scaling過去の振る舞いを元にHPAを調整し続ける- minReplicas: ½ * {過去数週間の同時刻の最大レプリカ数}- maxReplicas: 2 * {過去数週間の同時刻の最大レプリカ数}- HPA target utilization: 推奨の値を計算し、設定
65Horizontal Scaling過去の振る舞いを元にHPAを調整し続ける- minReplicas: ½ * {過去数週間の同時刻の最大レプリカ数}- maxReplicas: 2 * {過去数週間の同時刻の最大レプリカ数}- HPA target utilization: 推奨の値を計算し、設定前述のdynamic minReplicasと同様の振る舞い
66[復習] Incident時のHPAのScale in問題- UpstreamのサービスがIncidentで落ちる- Downstreamのサービスに通信が行かなくなる- DownstreamのサービスのCPU使用量が下がるこの場合にDownstreamのサービスではHPAによるScale inが発生する
67Horizontal Scaling過去の振る舞いを元にHPAを調整し続ける- minReplicas: ½ * {過去数週間の同時刻の最大レプリカ数}- maxReplicas: 2 * {過去数週間の同時刻の最大レプリカ数}- HPA target utilization: 推奨の値を計算し、設定Bug等の想定外ケースの際に、無制限にscale upするのを防ぐ
68Horizontal Scaling過去の振る舞いを元にHPAを調整し続ける- minReplicas: ½ * {過去数週間の同時刻の最大レプリカ数}- maxReplicas: 2 * {過去数週間の同時刻の最大レプリカ数}- HPA target utilization: 推奨の値を計算し、設定How?
69[復習] HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のため
70Tortoise のresource utilization計算の仕組み80%80%AppSidecarどちらもTarget: 80%
71Tortoise のresource utilization計算の仕組み80%80%AppSidecar リソース使用量が増えていく50%30%
72Tortoise のresource utilization計算の仕組み80%80%AppSidecar リソース使用量が増えていく50%
73Tortoise のresource utilization計算の仕組み80%80%AppSidecar SidecarのUtilizationが80%に達したので、HPAはPodの数を増やす50%
74[復習] HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のため
75Tortoise のresource utilization計算の仕組み80%80%AppSidecar50%実際にはPodごとに利用率のばらつきがある+Scale upが完了するまでラグがある
76Tortoise のresource utilization計算の仕組み80%実際の最大リソース使用率:90%AppSidecar50%実際にはPodごとに利用率のばらつきがある+Scale upが完了するまでラグがある
77VPAがどのように推奨値を計算しているか過去のリソースの使用量を記録↓p90 - p95 (+ OOMKilledを考慮) の値を「十分なリソースの量」としてResourcerequestに適応
78Tortoise のresource utilization計算の仕組み80%90%AppSidecarVPAの推奨値がこの時のリソース使用量を指しているとみなす50%
79Tortoise のresource utilization計算の仕組み80%90%-80% = 10%AppSidecar10%が必要な余分リソース→ target utilization: 90%がベスト50%
80Horizontal Scaling過去の振る舞いからコンテナサイズも調整:- ほぼ常にレプリカ数が3で、リソース使用率が小さい時、一時的にVerticalに切り替え、HPAが動作するようにする- 現在のコンテナサイズが小さく、かつピーク時にレプリカ数が多すぎる傾向にあると、コンテナサイズを大きくする- 片方のコンテナのリソース使用率が常に小さい時、そのコンテナサイズを小さくする
81Horizontal Scaling過去の振る舞いからコンテナサイズも調整:- ほぼ常にレプリカ数が3で、リソース使用率が小さい時、一時的にVerticalに切り替え、HPAが動作するようにする- 現在のコンテナサイズが小さく、かつピーク時にレプリカ数が多すぎる傾向にあると、コンテナサイズを大きくする- 片方のコンテナのリソース使用率が常に小さい時、そのコンテナサイズを小さくする
82[復習] HPAがレプリカ全然増やさない問題Deploymentのresource requestが大きすぎると、HPAを設定していても「レプリカ数がずっとminReplicasで制限されてる」みたいなケースが起こりうるこの場合、HPAが機能していないに等しいためCPU使用率も低くなる
83Horizontal Scaling過去の振る舞いからコンテナサイズも調整:- ほぼ常にレプリカ数が3で、リソース使用率が小さい時、一時的にVerticalに切り替え、HPAが動作するようにする- 現在のコンテナサイズが小さく、かつピーク時にレプリカ数が多すぎる傾向にあると、コンテナサイズを大きくする- 片方のコンテナのリソース使用率が常に小さい時、そのコンテナサイズを小さくする
84[復習] HPAがレプリカ増やしすぎる問題Deploymentのresource requestが小さすぎると、ピーク時のレプリカ数がとても多くなる。この際、Podのサイズを大きくし、レプリカ数を小さく抑えた方が、省エネになる場合がある。とあるサービスでは、この最適化を行うことで、GKEコストが40%減少(ピーク時のレプリカ数は200->30に変化)
85Horizontal Scaling過去の振る舞いからコンテナサイズも調整:- ほぼ常にレプリカ数が3で、リソース使用率が小さい時、一時的にVerticalに切り替え、HPAが動作するようにする- 現在のコンテナサイズが小さく、かつピーク時にレプリカ数が多すぎる傾向にあると、コンテナサイズを大きくする- 片方のコンテナのリソース使用率が常に小さい時、そのコンテナサイズを小さくする
86[復習] Multiple containers Pod with HPAめんどくさい問題例: HPAのtarget utilization: sidecar: 80%/app container: 80%この場合、HPAはどちらかのcontainerのresource utilizationが80%を大きく超えた時にスケールアウトを行う。↓これによって、sidecar or app のどちらかのリソースが常に余っているということになり得る。
87[復習] Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar50%Appは30%のリソース余している…
88[復習] Multiple containers Pod with HPAめんどくさい問題80%80%AppSidecar80%Appのresource requestを下げる同時に80%に達するのが一番リソースの無駄がない
89Emergency mode緊急時に一時的にレプリカ数を十分に大きく変更してくれる- minReplicasをmaxReplicasと同じ値に一時的に変更- OFFにした際に、安全のため適切にゆっくりスケールダウンを行う
90Emergency modeapiVersion: autoscaling.mercari.com/v1alpha1kind: Tortoisemetadata:name: nginx-tortoisenamespace: tortoise-pocspec:updateMode: EmergencytargetRefs:deploymentName: nginx-deployment←
91Emergency mode緊急で十分にスケールアウトしたい時に使用する- 通常にはないようなトラフィックの増加を観測している場合 (テレビ, bot等)- インフラサイドのincidentが発生し、念の為あげておきたい場合 (datadog, GCP等)
92mercari/tortoiseの現状- Platformで開発しており、検証段階- 実際に本番で使用はしていない
93● インスタンスタイプやGKEのクラスターレベルの設定から始められるリソース最適化もある● 大量のHPAの最適化を人の手で継続的にやり続けるのは難しい○ メルカリでは🐢を検証し育てていく予定です● 台風の時期に沖縄に行くのは慎重になったほうがいいまとめ
94We are めっちゃ hiring!!!Platformで働く仲間をめっちゃ探しています!!!!今回話したこと以外にも、めっちゃ色んな面白いことやってます!!!!!!- 内製しているCI/CD基盤開発- 開発者向け抽象化レイヤーの開発- istioとかのnetworkらへん「メルカリ Platform 採用」でいますぐ検索!
95Thanks for listening!