Kubernetes Meetup Tokyo #57 アーカイブもあります: https://www.youtube.com/watch?v=DczWeNL-4-A
1ConfidentialMercariにおけるKubernetesのリソース最適化のこれまでとこれからKensei Nakada / @sanposhiho
View Slide
2Mercari JP Platform Infra team / 2022卒新卒 Kubernetes upstream reviewer (SIG-Scheduling) Kubernetes Contributor award 2022 winner Kensei Nakada / sanposhiho
3Mercari Kubernetes Cluster OverviewAgenda01Workloads on cluster + About FinOpsa.Node Level Optimization02Cluster Autoscalinga.Node machine typeb.Workload Optimization03Workload Autoscaling (HPA & VPA) / Resource recommendera.HPA fine tuningb.🐢を使用したWorkload Autoscaling04
4Kubernetes Cluster OverviewWorkloads on cluster + FinOps
5Kubernetesクラスター概要- GKEを使用 (Standard mode)- 一つのClusterで、Mercari/Merpayほぼ全てのWorkloadが動いている- namespace: 500+ / deployment 1000+- PlatformチームがCluster adminとして運用
6Workload について- ほとんどがGoで実装されたWorkload- この登壇に含まれる調査結果等はGoのWorkloadということを前提としてください- その他、ElasticSearch, php 等も居る- Istioを一部namespaceで使用 (全体の半分ほど) (拡大予定)- sidecarコンテナーがついているPodが割と存在する- ほとんどの大規模workloadがHPAを使用 (全体の半分ほど) (拡大予定)
7FinOps!- 直近メルカリでは全社的な目標としてFinOpsを掲げている- Monolith -> Microserviceのマイグレーションを経て、アーキテクチャを洗練していくフェーズ- Platformチームでもインフラリソースの効率化を推進- 殆どのサービスが乗っているのでインパクトが超絶大きい- あくまでも安全性を担保しつつ、リソースの効率化を行う
8Node Level OptimizationCluster Autoscaling
9
10余分なNodeを減らしたい
11Probably, we want tochange the placement forcost reduction.新しいPodが来た時には
12But… what if new Podscome after reducingNodes?もう一度Nodeを増やしたい
13Automated way: Cluster AutoscalerCluster Autoscalerがいい感じに:- リソースがスカスカだったら、Podを詰めてNodeを減らす- Unschedulable Podsが居たら、Nodeを増やすをやってくれる
14Trade-off: Cost 💴 vs Reliability🛡Nodeの空きを常に余裕を持っておくことで-> 👍 🛡 Nodeの障害やリソースの需要の急増に強くなる-> 👎 💸 常に余分にお金がかかる
15GKE Autoscaling profilesGKE では Autoscaling profile を通してoptimize-utilization 💴 or balanced🛡 を選択できる:- Cluster Autoscaler がどのようにNodeを削除していくか- Aggressive 💴 vs Conservative🛡- SchedulerがどのようにPodをスケジュールするか- MostAllocated(Bin packing) 💴 orLeastAllocated🛡
16GKE Autoscaling profilesMercariではoptimize-utilization 💴を選択- Cluster Autoscaler がどのようにNodeを削除していくか- Aggressive 💴 vs Conservative🛡- SchedulerがどのようにPodをスケジュールするか- MostAllocated(Bin packing) 💴 orLeastAllocated🛡
17overprovisioning PodsNodeに空きが無くなりすぎるのを防ぐoverprovisioning Podsを採用- overprovisioning Pods = 低いPriorityのPod- 他のPodがunschedulableになるとoverprovisioning PodsがPreemptされ、リソースに空きを生んでくれる- Cluster AutoscalerはUnschedulableになったoverprovisioning Podsに気がついてNodeを増やす
18overprovisioning PodsOverprovisioning Podsが多すぎると、bin Packingの意味が無い→ Overprovisioning Podsの数をNodeの全体数に対して自動で調整(sigs/cluster-proportional-autoscaler)将来的にはもう少し賢く調整したい(先週のNode数の変化から需要の変化の予測とかできそう、等のアイデアはある)
19Node Level OptimizationNode instance type
20Node machine type現状MercariではE2 machine typeを広く使用している。→ コスパがいいと評判の、新たに追加されたTau T2Dの検討
21Tau T2D migrationいくつかの大きなWorkloadのmachine typeをE2からT2Dに変更- T2Dのinstance単位の単価はE2よりも高い- しかし、パフォーマンスが高く、多くのWorkloadでCPU使用量の減少を確認- プログラミング言語等の様々な要素によってCPU使用量の減少率が違う- Goの場合、大体 ~50%の減少- HPAが正しく動作している場合、CPU使用量の減少はそのままPod数の減少につながる→ 総合的に見てコスパ 👍👍👍 (migration後のnodepoolではコスト3割削減)
22Workload Level OptimizationWorkload Autoscaling (HPA & VPA) / Resource recommender
23
24レプリカ数を減らしてutilizationを上げる
25Traffic が増えるにつれて、utilizationが大きくなる
26レプリカ数を増やす
27HorizontalPodAutoscaler: resource utilizationをベースにいい感じにScalingしてくれるAutomated way: HorizontalPodAutoscalerCPU utilizationが常に54 - 66%になるように調整してくれる
28HPA for multi-containers Podstype: Resource は個々のcontainerのresource utilizationではなく、Pod全体でのresource utilizationを使用する
29HPA for multi-containers Podstype: Resource は個々のcontainerのresource utilizationではなく、Pod全体でのresource utilizationを使用する→ 複数のcontainerがPod内に存在する場合、正確にScalingできない場合がある
30The container based HPAtype: ContainerResourceの使用を検討
31The beta graduation is done in v1.27UpstreamでのBeta graduationを推進 (GKEではalpha機能が使えないため)
32Then, what’s alternative for now?現状DatadogMetric(external metrics)を使用して、type:ContainerResourceを実現しているDatadogMetric: Datadogのqueryの結果をHPAのexternal metricsから参照できる
33DatadogMetricの設定
34External metricsとしてHPAから参照
35For more detail ↓
36
37各Podのsizeを小さくしたい
38使用量が上がってきたら …
39それに応じてもう一度大きくしたい
40リソースの使用量を常に確認し、良さげなresource request/limitの推奨値を計算して、設定してくれる。memoryの場合OOM Killも考慮に入れられるAutomated way: VerticalPodAutoscaler
41Resource RecommenderResource Recommenderと呼ばれるSlack botが動作しているユーザーは月に一度リソースの推奨のresource requestの値を受け取るHoge deploymentappcontainerXXXXXX
42Resource RecommenderResource Recommenderは過去1ヶ月のVPAの推奨値の最大値を取得し、「プラットフォーム推奨のresource request」としてユーザーに送っている
43Resource RecommenderHPAが設定されているPodのresourceにはRecommendationを適応してはいけないため、送らない等の工夫XXXXXXFuga Deployment appcontainer
44Multidimensional Pod autoscalingMultidimensional Pod autoscalingというHPAをCPUにVPAをMemoryに使用するAutoscalerがGKEに存在Mercariでもいくつかのサービスで検証を行い、今後はこの方針に舵を切りつつある(MPAを直接使用するのではなく、HPA(CPU) + VPA(mem)を設定する)将来的にRecommenderはautoscalerが設定されていないサービス向けになる
45Workload Level OptimizationHPA fine tuning
46Incident時のHPAのScale in問題- UpstreamのサービスがIncidentで落ちる- Downstreamのサービスに通信が行かなくなる- DownstreamのサービスのCPU使用量が下がるこの場合にDownstreamのサービスではHPAによるScale inが発生する
47Incident時のHPAのScale in問題- UpstreamのサービスがIncidentで落ちる- Downstreamのサービスに通信が行かなくなる- DownstreamのサービスのCPU使用量が下がるこの場合にDownstreamのサービスではHPAによるScale inが発生する↓Upstreamのサービスが復活した時に、一気にトラフィックが流れてDownstreamのサービスが死ぬというインシデントが稀に発生
48Setting higher minReplicas?minReplicasを高めに設定しておけば、解決になるがHPAの機能性を損なうので❌例: Pods数が通常のオフピーク時に3個/ピーク時に20個、targetUtilizationが70%の場合、ピーク時に障害という最悪のケースを考慮すると、minReplicasを14に設定する必要がある
49dynamic minimum replica num1週間前の同じ時間のレプリカ数の1/2のレプリカ数をsuggestするDatadogMetricsを全てのHPAに導入↓HPAは複数の指標のレプリカ数の提案から一番大きいものを採用するため、Incidentの時など通常に比べて異常にレプリカ数が減少している時にのみ動作する
50dynamic minimum replica numこのDatadogMetricsで高めに設定されていたMinReplicasを安全に下げることにも繋がった (一律で3に変更)
51HPAがレプリカ増やしすぎる問題Deploymentのresource requestが小さすぎると、ピーク時のレプリカ数がとても多くなる。
52HPAがレプリカ増やしすぎる問題Deploymentのresource requestが小さすぎると、ピーク時のレプリカ数がとても多くなる。この際、Podのサイズを大きくし、レプリカ数を小さく抑えた方が、省エネになる場合がある。とあるサービスでは、この最適化を行うことで、GKEコストが40%減少(ピーク時のレプリカ数が200->30に変化)
53HPAがレプリカ全然増やさない問題Deploymentのresource requestが大きすぎると、HPAを設定していても「レプリカ数がずっとminReplicasで制限されてる」みたいなケースが起こりうるこの場合、HPAが機能していないに等しいためCPU使用率も低くなる
54HPAがレプリカ全然増やさない問題この場合、- Podのサイズを十分に小さくしてHPAが動作するようにする- VPAにCPUも任せる等を考える必要がある
55Multiple containers Pod with HPAめんどくさい問題例: HPAのtarget utilization: sidecar: 80%/app container: 80%この場合、HPAはどちらかのcontainerのresource utilizationが88%を超えた時にスケールアウトを行う。↓これによって、sidecar or app のどちらかのリソースが常に余っているということになり得る。
56Multiple containers Pod with HPAめんどくさい問題HPAを設定していても、CPU 使用量を確認しつつ、片方のcontainerの使用量が常に低い場合、contianerのsizeを調整する必要がある。
57HPAのtarget utilization決めるの難しすぎ問題メルカリでは、HPAのtarget utilizationは70%-80%に設定されていることが多い。
58HPAのtarget utilization決めるの難しすぎ問題メルカリでは、HPAのtarget utilizationは70%-80%に設定されていることが多い。なぜ20%-30%の余分なCPUを与えておく必要があるのか?
59HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のため
60HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のためリソース使用率の平均値が80%だとしても、いくつかのcontainerの使用率は100%を超えている可能性もある
61HPAのtarget utilization決めるの難しすぎ問題HPAのtarget utilizationによって与えられる、「余分なリソース」は- Containerごとのリソース使用量のばらつき- スケールアウトの時間稼ぎの対応のため→ (次スライド)
62HPAのtarget utilization決めるの難しすぎ問題0. ピークタイムが近づくにつれて、リソース使用量が増えていく1. リソース使用率が閾値に達する2. HPAが気がついてスケールアウトを実行する3. (Cluster AutoscalerがNodeを増やす)4. 新しいPodが実際に動き出し、READYになる(1) → (4)にかかる時間の間もリソース使用量が増えているため、この間の時間稼ぎの必要性
63HPAのtarget utilization決めるの難しすぎ問題- Containerごとのリソース使用率のばらつき- トラフィックの増加のスピード- HPA controllerのリコンサイルの間隔- (Nodeに空きができるまでの時間 (via CA or overprovisioning Pods))- Podが動き出すまでにかかる時間これらを踏まえて、適切な「余分リソース」をtarget utilizationを通してPodに与える必要がある
64HPAのtarget utilization決めるの難しすぎ問題- Containerごとのリソース使用率のばらつき- トラフィックの増加のスピード- HPA controllerのリコンサイルの間隔- (Nodeに空きができるまでの時間 (via CA or overprovisioning Pods))- Podが動き出すまでにかかる時間これらを踏まえて、適切な「余分リソース」をtarget utilizationを通してPodに与える必要がある無理じゃね…?
65ここまでの話- Incident時のHPAのScale in問題- HPAがレプリカ増やしすぎる問題- HPAがレプリカ全然増やさない問題- Multiple containers Pod with HPAめんどくさい問題- HPAのtarget utilization決めるの難しすぎ問題
66ここまでの話- Incident時のHPAのScale in問題- HPAがレプリカ増やしすぎる問題- HPAがレプリカ全然増やさない問題- Multiple containers Pod with HPAめんどくさい問題- HPAのtarget utilization決めるの難しすぎ問題無理じゃね…?
67🐢を使用したWorkload Autoscaling
68🤔
69mercari/tortoise
70これからはリクガメに任せる時代です。過去のWorkloadの振る舞いを記録し、HPA, VPA, Pod resourcerequest/limitの全てをいい感じに調節してくれるKubernetes controllerhttps://github.com/mercari/tortoise
71mercari/tortoiseのモチベ- 人間の手で先ほどの最適化を全て行うのは厳しい- 最適化後もアプリケーションの変化に伴い、定期的な見直しが必要- Platform推奨の設定や新しい機能適応への移行のコスト- 現状、PRを全てのHPAに送りつけたりしている。めんどい- Datadog metricを含む外部サービスにautoscalingを依存させたくない- 外部サービスの障害の間、HPAが正しく動かず眠れぬ夜を過ごすことになる
72Simplified configurationapiVersion: autoscaling.mercari.com/v1alpha1kind: Tortoisemetadata:name: nginx-tortoisenamespace: tortoise-pocspec:updateMode: AutotargetRefs:deploymentName: nginx-deploymentDeployment name ONLY!
73Simplified configuration- ユーザーは対象のdeploymentの指定のみを行う。- Optional なフィールドはその他少し存在するが基本使用不要- HPA, VPA, resource req/limの全ては🐢がいい感じに設定する- 「コーナーケースのために柔軟な設定を与える」ことはしない- 一つのTortoiseを設定する => HPA, VPAを全てのcontainerの全てのリソースに常に最適化された状態で設定が完了
74mercari/tortoiseの機能- HPA optimization- 前章で「無理じゃね…?」と言ってたやつを全部自動で行う- VPA optimization- HPAとVPAがうまいこと同時に動けるように調整- Emergency mode
75Horizontal Scaling過去の振る舞いを元にHPAを調整し続ける- minReplicas: ½ * {過去数週間の同時刻の最大レプリカ数}- maxReplicas: 2 * {過去数週間の同時刻の最大レプリカ数}- HPA target utilization: 推奨の値を計算し、設定 (計算ロジックは複雑なので説明割愛)
76Horizontal Scaling過去の振る舞いからコンテナサイズも調整:- ほぼ常にレプリカ数が3で、リソース使用率が小さい時、一時的にVerticalに切り替える- 現在のコンテナサイズが小さく、かつピーク時にレプリカ数が多すぎる傾向にあると、コンテナサイズを大きくする- 片方のコンテナのリソース使用率が常に小さい時、そのコンテナサイズを小さくする
77Emergency mode緊急時に一時的にレプリカ数を十分に大きく変更してくれる- minReplicasをmaxReplicasと同じ値に一時的に変更- OFFにした際に、安全のため適切にゆっくりスケールダウンを行う
78Emergency mode緊急で十分にスケールアウトしたい時に使用する- 通常にはないようなトラフィックの増加を観測している場合 (テレビ, bot等)- インフラサイドのincidentが発生し、念の為あげておきたい場合 (datadog,GCP等)
79Emergency modeapiVersion: autoscaling.mercari.com/v1alpha1kind: Tortoisemetadata:name: nginx-tortoisenamespace: tortoise-pocspec:updateMode: EmergencytargetRefs:deploymentName: nginx-deployment←
80mercari/tortoiseの現状- Platformで開発しており、検証段階- 実際に本番で使用はしていない
81We are めっちゃ hiring!!!Platformで働く仲間をめっちゃ探しています!!!!今回話したこと以外にも、めっちゃ色んな面白いことやってます!!!!!!- 内製しているCI/CD基盤開発- 開発者向け抽象化レイヤーの開発- istioとかのnetworkらへん「メルカリ Platform 採用」でいますぐ検索!