Kubernetes 1.20: SIG autoscaling の変更内容

# はじめに

ここでは、[Kubernetes 1.20 の CHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#v1200) と [cluster-autoscaler 1.20](https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.20.0
) から SIG autoscaling の取り組みについてまとめています。
 
:memo: 以下は筆者の補足になります。

# Kuberentes 1.20

## API Changes

- コンテナリソースの使用量に基づいたスケーリングを可能にする HPA の MetricsSource を導入しました ([#90691](https://github.com/kubernetes/kubernetes/pull/90691), [@arjunrn](https://github.com/arjunrn))
  - KEP: https://github.com/kubernetes/enhancements/blob/master/keps/sig-autoscaling/0001-container-resource-autoscaling.md

:memo: コンテナ毎にリソースの使用傾向が異なったり、オートスケールの対象としたいメトリクスと相関しない場合などに相関するコンテナを対象にできるようになりました

KEP によると以下のような MetricsSource が追加されています。

```golang
type ContainerResourceMetricSource struct {
	Container string
	Name v1.ResourceName
	Target MetricTarget
}
```

従来の ResourceMetricSource から Container の指定が追加された形です。
これによって以下のようにコンテナ毎にオートスケールのパラメータを設定することができるようになります。

```yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: mission-critical
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mission-critical
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: ContainerResource
    resource:
      name: cpu
      container: application
      target:
        type: Utilization
        averageUtilization: 30
  - type: ContainerResource
    resource:
      name: memory
      container: application
      target:
        type: Utilization
        averageUtilization: 80
  - type: ContainerResource
    resource:
      name: cpu
      container: authnz-proxy
      target:
        type: Utilization
        averageUtilization: 30
  - type: ContainerResource
    resource:
      name: memory
      container: authnz-proxy
      target:
        type: Utilization
        averageUtilization: 80
  - type: ContainerResource
    resource:
      name: cpu
      container: log-shipping
      target:
        type: Utilization
        averageUtilization: 80
```

## Bug or Regression

- SelectPolicy MinPolicySelect を scaleUp 動作または scaleDown 動作に設定すると、Horizontal Pod Autoscalerは自動的に正しくポッド数をスケーリングしません ([#95647](https://github.com/kubernetes/kubernetes/pull/95647), [@JoshuaAndrew](https://github.com/JoshuaAndrew))
  - :memo: `.spec.behavior.scale[Up/Down].selectPolicy` に MinPolicySelect を設定していた場合の話です。デフォルトは MaxPolicySelect なので個別に設定していたユーザ以外は影響ないと思います。

# cluster-autoscaler 1.20.0 ChangeLog

https://github.com/kubernetes/autoscaler/releases/tag/cluster-autoscaler-1.20.0
各クラウドベンダーの変更点については記載しませんので、必要な方は公式の内容を参照ください。

## General

リポジトリや開発時の運用スクリプトの変更なども含まれているので筆者の判断で適宜分類します。また変更点と PR の紐付けがないため独自で探して付与します。

- 新機能
  - メトリクスとして `max-node-total` を公開します ([#3435](https://github.com/kubernetes/autoscaler/pull/3435))
     - :memo: `max_nodes_count` メトリクスとして 起動オプションで渡された `--max-node-total` の値を公開するようになったようです
  - Virtual Kubelet によって作成された Node は、Node として扱わないようになりました ([#3152](https://github.com/kubernetes/autoscaler/pull/3152))
     - :memo: `type=virtual-kubelet` ラベルが付与されている Node が対象外となるようです
  - denominator のノードの利用率の計算時に DaemonSet Pod のリクエスト値を含めないようになりました([#3641](https://github.com/kubernetes/autoscaler/pull/3641))
  - ノードが未準備/まだ起動しているかどうかを判断する際の条件に Taint を含めるようになりました([#3653](https://github.com/kubernetes/autoscaler/pull/3653))
     - :memo: 具体的には `TaintNodeNotReady`, `TaintNodeDiskPressure`, `TaintNodeNetworkUnavailable` の Taint の状況を見るようになりました。
  - 空ではないノードをスケールダウンで削除する際に、DaemonSet Pod をベストエフォート での eviction を行う処理を追加しました([#3701](https://github.com/kubernetes/autoscaler/pull/3701))
     - :memo: スケールダウン時に動作している Pod を退去(evict)する処理がありますが、これに DaemonSet の Pod も含まれるようになったようです。ただ DaemonSet の Pod は依存している Pod があることがあるので同時に evict されると問題になりそうな気がしています。
     - 弊社でも DaemonSet の Pod は Node の通常の Pod が退去されたあとに evict するようにしており、この配慮が無効化されてしまいそうなので対応を検討する必要がありそうです :cry:
  - ARM64 のビルドサポートを追加([#3714](https://github.com/kubernetes/autoscaler/pull/3714))
  - PreFilter の呼び出し回数を減らして binpacking を高速化しました (#pods*#nodes 回ではなく、ポッドごとに 1 回呼び出す)([#3429](https://github.com/kubernetes/autoscaler/pull/3429))
  - PreFilterの呼び出し回数を減らすことで、非常に大規模なクラスタで不要なノードの発見を5倍以上に高速化しました([#3482](https://github.com/kubernetes/autoscaler/pull/3482))
  - IncreaseSize のエラーが apiError 型から cloudProviderError 型に変更されました。([#3509](https://github.com/kubernetes/autoscaler/pull/3509))
  - 冗長なログ行を削除し、kubeEnvのパース時の深刻度を低減しました。([#3635](https://github.com/kubernetes/autoscaler/pull/3635))

  - ノードの利用率を計算する際の冗長なロギングを削除([#3642](https://github.com/kubernetes/autoscaler/pull/3642))
- バグ修正
  - 優先度の高い選択肢がある場合でも、優先度の高い expander がランダムな選択肢に戻ってしまうのを修正しました([#3308](https://github.com/kubernetes/autoscaler/pull/3308))
  - スケールダウンシミュレーションで Pod の移動先を見つける際に、既存のノードが移動先候補として考慮されていなかったエラーを修正しました(issueが見つからず...)
      - 原文: `Fix an error where existing nodes were not considered as destinations while finding place for pods in scale-down simulations`
      - :memo: PR が見当たらなかったためこの変更が今回のこの修正が含まれたのかはよくわかりませんでした
- 開発ツールやスクリプトに対する変更
  - update-vendor.sh の際に全てのリビジョンを取得するのではなく必要なリビジョンのみ kubernetes/kubernetes を clone します
  - SELinux を有効にした Linux システムで build-in-docker と test-in-docker を動作できるようになりました
  - Makefile に docker 用の設定可能な --network と --rm フラグを追加しました
  - OSX および zsh で動作するように update-vendor.sh を修正しました