K8s の HorizontalPodAutoscaler による replicas の更新と判定間隔、増減上限の設定
kubernetesHorizontalPodAutoscaler (HPA) は metrics をもとに scaleTargetRef のリソースの replicas を更新するリソース。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: testapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: testapp
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Deployment の manifest に replicas が含まれていると apply したときにその値で上書きされてしまうことがあるので含めないほうがよい。ただ、だからといって replicas を消して apply すると kubectl.kubernetes.io/last-applied-configuration との merge patch がはたらきデフォルトの 1 になってしまうことに注意が必要。
cpu などを metrics を指定する場合 Metrics Server をインストールする必要がある。
// $ kubectl top node
// error: Metrics API not available
cluster.addHelmChart('metrics-server', {
chart: 'metrics-server',
release: 'metrics-server',
repository: 'https://kubernetes-sigs.github.io/metrics-server',
namespace: 'kube-system',
createNamespace: false,
wait: true
})
Utilization はコンテナの合計使用量と request または limit リソース量で計算され、replicas は次の式によって決定される。例えば averageUtilization: 70 に対して平均 CPU 使用率が 140% のとき、replicas は現在の倍に設定される。
desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
複数の世代のインスタンスタイプを併用していると Pod ごとの CPU の使用率にばらつきがあり平均ではうまくスケールしないことがある。その場合 KEDA などが提供する external metrics を参照することもできる。
KEDA (Kubernetes Event-driven Autoscaling) で Prometheus のメトリクスや時間ベースのスケーリングを行う - sambaiz-net
ばらつきがリクエストに由来している場合 ALB のルーティングポリシーを LOR に変更するとよい。
EKSクラスタにAWS Load Balancer ControllerをインストールしてALBのIngressを立てる - sambaiz-net
複数の metrics がある場合は最大の replicas となり、エラーなどで取れないものがある場合は縮退しないようになっている。
判定間隔は kube-controller-manager の –horizontal-pod-autoscaler-sync-period で設定でき、デフォルトは 15 秒になっている。スケールを早めるためにはなるべく短くしたいところだがコントロールプレーンを触れない EKS では現状変更できない。いずれにせよリソースが足りないと Pod は起動しないので併せて PriorityClass などでリソースを確保しやすくしたりノードのスケールの高速化に取り組む必要がある。
K8s の Pod の Prirority とそれによる Preemption - sambaiz-net
CDK で EKS クラスタに Karpenter をインストールし柔軟で高速なオートスケールを行う - sambaiz-net
behavior で増減上限を設定することができデフォルトは次のような設定になっている。Percent の periodSeconds: 15 と value: 100 は 15秒間に最大で現在の pod 数の 100% 分増減することを意味する。複数の policy がある場合 selectPolicy によってどの値が適用されるかが選択され、デフォルトは Max となっている。stabilizationWindowSeconds は頻繁なメトリクスの更新によって pod 数が安定しない flapping を避けるための値で、この期間中の最大の値が採用される。
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 100
periodSeconds: 15
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max