kubernetes/autoscaler: addon-resizer

addon-resizer は、Deployment においてサイドカーコンテナとしてデプロイされ、対象のコンテナのリソース要求と制限を垂直スケールさせることができる。今のところノード数に応じた線形スケールのみに対応している。またシングルトンで動作させる必要があるため、レプリカ数が1でなければならない。

- https://github.com/kubernetes/autoscaler/tree/master/addon-resizer
- https://gcr.io/google_containers/addon-resizer

別名 Pod Nanny と呼ばれていて、Nanny というのは子守の人のような意味だそうな。

## モチベーション

クラスタのメトリクスを提供する Heapster や kube-state-metrics は、ノード数が多くなるとメトリクスを収集する対象が多くなるため、ノード数に応じてリソース要求を調整する必要がある。cluster-autoscaler の利用などでクラスタのサイズが動的に変更される場合はなおこれに人間が対応することはできないため、addon-resizer のような仕組みが必要になる。

- https://github.com/kubernetes/heapster
- https://github.com/kubernetes/kube-state-metrics
- https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler

## 動作

設定は全てコマンドライン引数で渡す形になっており、スケール対象は CPU, メモリ、ストレージである。それぞれベースのリソースと1ノード当たりの追加リソースを設定する。

```
      --acceptance-offset=20: A number from range 0-100. The dependent's resources are rewritten when they deviate from expected by a percentage that is higher than this threshold. Can't be lower than recommendation-offset.
      --container="pod-nanny": The name of the container to watch. This defaults to the nanny itself.
      --cpu="MISSING": The base CPU resource requirement.
      --deployment="": The name of the deployment being monitored. This is required.
      --extra-cpu="0": The amount of CPU to add per node.
      --extra-memory="0Mi": The amount of memory to add per node.
      --extra-storage="0Gi": The amount of storage to add per node.
      --memory="MISSING": The base memory resource requirement.
      --namespace="": The namespace of the ward. This defaults to the nanny pod's own namespace.
      --pod="": The name of the pod to watch. This defaults to the nanny's own pod.
      --poll-period=10000: The time, in milliseconds, to poll the dependent container.
      --recommendation-offset=10: A number from range 0-100. When the dependent's resources are rewritten, they are set to the closer end of the range defined by this percentage threshold.
      --storage="MISSING": The base storage resource requirement.
```

クラスタのノード数を監視しており、ノードの数に変更があると「ベースリソース + 追加リソース * ノード数」を `resources.limits/requests` として Deployment を更新する。リソース要求と制限の変更は Deployment の Pod template の変更を伴うことから Pod の削除と作成を伴う。

- https://github.com/kubernetes/autoscaler/blob/master/addon-resizer/nanny/estimator.go#L81

## マニフェストファイル例

下記は Heapster の例。ここではベースのリソースが CPU 80m, メモリ 140Mi、1ノード当たり CPU 0.5m, メモリ 4Mi 増加するように設定している。

```yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: heapster
  labels:
    k8s-app: heapster
  namespace: kube-system
spec:
  revisionHistoryLimit: 5
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: heapster
    spec:
      serviceAccountName: heapster
      containers:
      - name: heapster
        image: gcr.io/google_containers/heapster-amd64:v1.4.1
        imagePullPolicy: IfNotPresent
        command:
        - /heapster
        - --source=kubernetes.summary_api:''
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8082
          initialDelaySeconds: 180
          timeoutSeconds: 5
        resources:
          limits:
            cpu: 80m
            memory: 140Mi
          requests:
            cpu: 80m
            memory: 140Mi
      - name: heapster-nanny
        image: gcr.io/google_containers/addon-resizer:2.0
        imagePullPolicy: IfNotPresent
        command:
        - /pod_nanny
        - --cpu=80m
        - --extra-cpu=0.5m
        - --memory=140Mi
        - --extra-memory=4Mi
        - --deployment=heapster
        - --container=heapster
        - --poll-period=300000
        env:
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        resources:
          limits:
            cpu: 50m
            memory: 90Mi
          requests:
            cpu: 50m
            memory: 90Mi
```