Share
Embed
Transcript
48 slides
-
負荷を予測して事前スケーリングする HPA の Custom Controller 実装 @zuiurs (Mizuki Urushida) KubeFest
Tokyo 2020 (2020/06/13) -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 4
負荷を予測してスケールできたら もっと良いと思いませんか❓ -
負荷を予測して事前スケーリングする HPA の Custom Controller 実装 @zuiurs (Mizuki Urushida) KubeFest
Tokyo 2020 (2020/06/13) -
自己紹介 7 • Mizuki Urushida (@zuiurs) • 2018~ CyberAgent, Inc.
• 最近やったこと ◦ Kubernetes-native Testbed の構築・実装 ◦ Cluster Autoscaler の Cloud Provider 実装 ◦ Prow による CI/CD 基盤作成中 ◦ HPA に時系列予測を組み込む Custom Controller の実装 • 夕方までマンションが断水してます -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 9
☺ Horizontal Pod Autoscaler ☺ Background / Motivation ☺ About Intelligent HPA ☺ Architecture ☺ Tips of implemtation -
Horizontal Pod Autoscaler 12 • 指定したメトリクスのしきい値を 基準に Pod を増減させる仕組み apiVersion:
autoscaling/v2beta2 kind: HorizontalPodAutoscaler spec: minReplicas: 1 maxReplicas: 30 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 Deployment ( 66% / Pod ) 40% 70% Deployment ( 50% / Pod ) 90% 40% 60% 70% 30% * -
複数メトリクスの監視 13 • 最大レプリカ数が選択される ◦ 一方が小さくなったときに 誤ってスケールダウンされない apiVersion: autoscaling/v2beta2 kind:
HorizontalPodAutoscaler spec: metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 - type: External external: metric: name: nginx.net.request_per_s target: type: AverageValue averageValue: 10 5 replicas 7 replicas 7 replicas -
外部メトリクスの参照 14 • Datadog/Prometheus のメトリクスを参照できる HPA metrics.k8s.io/v1beta1 external.metrics.k8s.io/v1beta1 kube-system/ metrics-server
default/ datadog-cluster-agent-metrics-api -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 16
HPA は実測値をもとに スケールします -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 17
負荷上がったし レプリカ数増やすかー -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 18
負荷上がったし レプリカ数増やすかー 負荷が上がらないと増えない -
しきい値設定に注意する 19 • 許容負荷ギリギリに設定していると間に合わない ◦ 余裕をもたせたしきい値にする ◦ 余裕をもたせすぎるとリソースの無駄遣いになってしまう • READY
まで時間のかかるアプリケーションだと設定が難しい ◦ StatefulSet は比較的そういうものが多い 起動ラグ -
しきい値設定に注意する 20 • 許容負荷ギリギリに設定していると間に合わない ◦ 余裕をもたせたしきい値にする ◦ 余裕をもたせすぎるとリソースの無駄遣いになってしまう • READY
まで時間のかかるアプリケーションだと設定が難しい ◦ StatefulSet は比較的そういうものが多い 起動ラグ -
Cluster Autoscaler 併用時の懸念 21 • Pod が起動するためのリソースがクラスタにないかも ◦ CA は仕組み上
Pending Pod が現れないと Node を増やせない ◦ Cluster Autoscaler の仕組みの詳細はこちら • READY までの時間が Node の起動時間と一致してしまう ノード起動ラグ -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 24
cyberagent-oss/intelligent-hpa -
Intelligent HPA (IHPA) 25 • HPA への予測エントリの注入と 予測ジョブやメトリクスの管理をするコントローラー ◦ Kubebuilder
v2 を使用して実装 ◦ 社内向けに作ったものを OSS 化 • メトリクス管理は Datadog のみ実装している ◦ いずれ Prometheus (未検証) でクラスタ内完結させたい Intelligent HPA HPA Deployment 生成 操作 -
Minimum Usage 27 • HPA を使っているようなイメージで使えるように設計 apiVersion: ihpa.ake.cyberagent.co.jp/v1beta2 kind: IntelligentHorizontalPodAutoscaler
spec: metricProvider: name: datadog datadog: apikey: xxx appkey: yyy template: spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 - type: External external: metric: name: forecasted_cpu target: type: AverageValue averageValue: 10M 注入された 予測エントリ Applied manifest Generated HPA -
• 予測値の参照は Datadog を経由 • 先に参照するために時間をずらす ◦ 例) 9:00 の予測値は
8:55 にずらす ◦ → 8:55 になると 9:00 の値が見える 予測値を参照するためのずらし 28 apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 - type: External external: metric: name: forecasted_cpu target: type: AverageValue averageValue: 10M 注入された 予測エントリ Generated HPA 実測値 予測値 -
• 実測値のエントリを残して実負荷の レプリカ数を下回らないようにする ◦ 予測値は先に上昇する一方で 先に下降し始める 実測値のエントリの残存 29 apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: nginx metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 - type: External external: metric: name: forecasted_cpu target: type: AverageValue averageValue: 10M 注入された 予測エントリ Generated HPA 実測値 予測値 -
CRD とその役割 32 • 責任の分割と単独利用性を考慮 • IntelligentHorizontalPodAutoscaler (IHPA) ◦ IHPA
に関わる全リソースの CRUD に集中 • FittingJob ◦ 予測ジョブを実行して対象の ConfigMap に結果を出力 • Estimator ◦ ConfigMap 内の予測データを Datadog などのプロバイダに送信 -
CRD とその役割 33 • 責任の分割と単独利用性を考慮 • IntelligentHorizontalPodAutoscaler (IHPA) ◦ IHPA
に関わる全リソースの CRUD に集中 • FittingJob ◦ 予測ジョブを実行して対象の ConfigMap に結果を出力 • Estimator ◦ ConfigMap 内の予測データを Datadog などのプロバイダに送信 生成 予測 送信 -
IntelligentHorizontalPodAutoscaler 35 • HPA の対象メトリクスの予測エントリを生成 ◦ cpu とかは例外的に kubernetes.cpu.usage.total に変換するなど
• 各種リソースをつなぎこむ ◦ FittingJob/Estimator は独立しているため、 データ共有用の ConfigMap を統一 ◦ ConfigMap に書き込むための RBAC をそれぞれ紐付ける 予測データとして “cm1” を監視させる 出力先として “cm1” 指定する -
FittingJob • 指定時刻周辺で学習を実行 ◦ Affinity などで実行ノードを指定可能 • デフォルトイメージは Prophet を使用した時系列予測
◦ Datadog へのアクセス・各種入出力はライブラリにしているので 予測モデルの実装に集中できるようにしている n 時台に実行 { "provider":{ "datadog":{ "apikey":"xxx", "appkey":"yyy" } }, "targetMetricsName":"nginx.net.request_per_s", "targetTags":{ "kube_deployment":"nginx" }, "seasonality":"daily", "dataConfigMapName":"cm1", "dataConfigMapNamespace":"loadtest", "customConfig":"" } 36 -
Estimator 37 • 予測データをずらして送信 ◦ READY になるまでの時間 = ずらす時間として設定すると良い ▪
時間のかかるアプリでも、かからないものとして値を考えられる timestamp,yhat,yhat_upper,yhat_lower 1582253873,176.89,244.83,50.89 1582253933,126.80,251.26,8.17 1582253993,134.48,268.67,75.97 -
Estimator の予測値調整 38 • Upper/Lower の値の範囲で予測値を調整する ◦ Prophet の設定では 90%ile/10%ile
の値を吐き出す ◦ 予測の外れ度合いをチェック -
Kubebuilder のマニフェストカスタマイズ 41 • マニフェスト生成は kustomize が使用されている ◦ 大体のパラメータは自由に変えられる ▪
Namespace や Label など resources: - manager.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: controller newName: cyberagentoss/intelligent-hpa-controller newTag: latest apiVersion: apps/v1 kind: Deployment metadata: name: controller-manager namespace: system spec: template: spec: imagePullSecrets: - name: pull-secret • イメージを置換したり • パッチをあてたり -
controller-runtime の Watch と Own 42 • Watch() ◦ 対象
API の全リソースに対して発火 • Own() ◦ 対象 API のうち自身の OwnerReference のついたものに対して発火 ◦ Estimator の ConfigMap への予測データ格納監視はこれが役立った • 仕組みや基本的な機能についてはこちらの資料が詳しい ◦ Kubebuilder/controller-runtime 入門 Estimator ConfigMap ConfigMap ConfigMap Watch() Estimator ConfigMap ConfigMap ConfigMap Own() -
マニフェスト設計における下位リソースの定義方法 43 apiVersion: databases.spotahome.com/v1 kind: RedisFailover spec: redis: replicas: 3
image: redis:4.0-alpine imagePullPolicy: IfNotPresent Redis Operator 直接的 パッチ的 (?) なにそれ ・書いたものがそのまま作られる ・省略できない ・一部のフィールドだけ書ける ・省略できる 例 ・Deployment の Pod 定義 ・CronJob の Job 定義 ・Redis Operator の Redis/Sentinel 定義 ・TiDB Operator の PD などの定義 定義 ・k8s.io/api から引っ張るだけなので楽 ・YAMLを書くときの階層が深くなる ・本家と同じような定義をするので面倒 ・階層がフラットになる Defaulting コード内で行う必要がある CRD の機能でできる • IHPA はパッチ的な定義を選択 ◦ 下位リソースを隠蔽するのに こちらの方が都合が良かった -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 44
type JobPatchSpec struct { // related to Job ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"` BackoffLimit *int32 `json:"backoffLimit,omitempty"` Completions *int32 `json:"completions,omitempty"` // related to Pod Affinity *corev1.Affinity `json:"affinity,omitempty"` ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` NodeSelector map[string]string `json:"nodeSelector,omitempty"` ServiceAccountName string `json:"serviceAccountName,omitempty"` Tolerations []corev1.Toleration `json:"tolerations,omitempty"` Volumes []corev1.Volume `json:"volumes,omitempty"` // related to Container Args []string `json:"args,omitempty"` Command []string `json:"command,omitempty"` Env []corev1.EnvVar `json:"env,omitempty"` EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` Image string `json:"image,omitempty"` ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` Resources corev1.ResourceRequirements `json:"resources,omitempty"` } -
Predictive HPA 45 • 対抗馬 ◦ 名前が良いので嫉妬している • 作り終わってホッとしていたらなんか出てきた •
アプローチの違い ◦ IHPA: メトリクスを予測・HPA 経由でスケール ◦ PHPA: レプリカ数を予測・Scale Subresource 経由でスケール • 詳細はこちら -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 46
cyberagent-oss/intelligent-hpa -
まとめ (3 行) 47 • HPA は一部ケースではしきい値決定が非常に難しい • 予測値に対してスケールすると HPA
がうまく働きやすくなる • 予測値エントリを注入する Custom Controller を作りました -
Implement custom controller for metrics prediction @KubeFest Tokyo 2020 48
Thank you for your watching! Any Question?