Amazon EKS on Fargate - HPA

# はじめに

Kubernetes Horizontal Pod Autoscaler(HPA) は、そのリソースの CPU 使用率に基づいて設定されたデプロイ、レプリケーションコントローラー、またはレプリカセット内の Pods の数を自動的にスケーリングします。

HPA を動作させるには、メトリクスソース (metrics-server など) が EKS クラスターにインストールされている必要があります。

# Cluster

cluster は、以前書いた下記の記事の「cluster」を参考に準備します。

https://qiita.com/leomaro7/items/4d12cd6fba4c8178d839#cluster

# metrics-server

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/metrics-server.html

```
# metrics-server をデプロイ
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    serviceaccount/metrics-server created
    clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
    clusterrole.rbac.authorization.k8s.io/system:metrics-server created
    rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
    clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
    clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
    service/metrics-server created
    deployment.apps/metrics-server created
    apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

# metrics-server がデプロイされたことを確認
kubectl get deploy metrics-server -n kube-system 
    NAME             READY   UP-TO-DATE   AVAILABLE   AGE
    metrics-server   1/1     1            1           108s
```

なお、metrics-server の pod が自身の node の kubelet にアクセスできないという仕様があるようです。

https://dev.classmethod.jp/articles/metrics-server-on-eks-fargate/

```
# metrics-server の pod を確認
kubectl get pod metrics-server-5d875656f5-4xt6b -n kube-system -o wide
    NAME                              READY   STATUS    RESTARTS   AGE   IP                NODE                                                         NOMINATED NODE   READINESS GATES
    metrics-server-5d875656f5-4xt6b   1/1     Running   0          10m   192.168.105.150   fargate-ip-192-168-105-150.ap-northeast-1.compute.internal   <none>           <none>

# CPU MEMORY を確認すると、metrics-server　の　node のみ　メトリクス　の取得ができていない
kubectl top node                                                      
    NAME                                                         CPU(cores)   CPU%        MEMORY(bytes)   MEMORY%     
    fargate-ip-192-168-104-238.ap-northeast-1.compute.internal   16m          0%          125Mi           6%          
    fargate-ip-192-168-120-144.ap-northeast-1.compute.internal   17m          0%          130Mi           7%          
    fargate-ip-192-168-105-150.ap-northeast-1.compute.internal   <unknown>    <unknown>   <unknown>       <unknown>   

# metrics-server　のログを確認
kubectl logs metrics-server-5d875656f5-4xt6b -n kube-system
    E1110 02:31:36.639649       1 scraper.go:140] "Failed to scrape node" err="Get \"https://192.168.105.150:10250/metrics/resource\": dial tcp 192.168.105.150:10250: connect: connection refused" node="fargate-ip-192-168-105-150.ap-northeast-1.compute.internal"
```

# Horizontal Pod Autoscaler

Apache Web Server Application のサンプルです。
これは、 `500 millicpu` の CPU limits があります。

```php-apache.yaml
apiVersion: apps/v1
kind: Deployment

metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: registry.k8s.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache
```

HPA は CPU 使用率が 50% で、最小 1 個の Pod、最大 10 個 の Pods を使用するオートスケーラーです。

```php-apache-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler

metadata:
  name: php-apache

spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50
```

```
# php-apache.yaml　を apply
kubectl apply -f php-apache.yaml
    deployment.apps/php-apache created
    service/php-apache created

# deploy,pod,service を確認
kubectl get deploy,pod,service -o wide
    NAME                         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                        SELECTOR
    deployment.apps/php-apache   1/1     1            1           46m   php-apache   registry.k8s.io/hpa-example   run=php-apache
    
    NAME                              READY   STATUS    RESTARTS   AGE   IP                NODE                                                         NOMINATED NODE   READINESS GATES
    pod/php-apache-5bdbb8dbf8-4skcc   1/1     Running   0          46m   192.168.124.189   fargate-ip-192-168-124-189.ap-northeast-1.compute.internal   <none>           <none>

    NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE     SELECTOR
    service/php-apache   ClusterIP   10.100.61.142   <none>        80/TCP    46m     run=php-apache

# php-apache-hpa.yaml を apply 
kubectl apply -f php-apache-hpa.yaml  
    horizontalpodautoscaler.autoscaling/php-apache created

# hpa を確認
kubectl get hpa
    NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    php-apache   Deployment/php-apache   0%/50%    1         10        1          19s
```

# 動作確認

```
# kubectl run -i --tty load-generator: 新しいPodを作成し、そのPod内で対話的なセッションを開始します。このPodはload-generatorと呼ばれます。
# --rm: Podが終了するときに削除されるようにします。これにより、一時的なジョブの実行に便利です。
# --image=busybox: 使用するDockerイメージを指定します。この場合、busyboxという軽量なLinuxディストリビューションが使用されます。
# --restart=Never: Podが終了したら再起動しないように指定します。これはジョブを一度だけ実行する場合に役立ちます。
# /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done": Pod内で実行されるコマンド。具体的には、wgetを使用してhttp://php-apacheに対して0.01秒ごとにHTTPリクエストを行います。これにより、指定されたエンドポイントに対して継続的な負荷がかかるようになります。
kubectl run -i \
    --tty load-generator \
    --rm --image=busybox \
    --restart=Never \
    -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"

# hpa で　TARGETS　が上昇していることを確認
kubectl get hpa php-apache
    NAME         REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
    php-apache   Deployment/php-apache   114%/50%   1         10        ２          4m43s   

# pod が増加していることを確認
kubectl get pod           
    NAME                          READY   STATUS    RESTARTS   AGE
    load-generator                1/1     Running   0          2m19s
    php-apache-5bdbb8dbf8-4skcc   1/1     Running   0          8m22s
    php-apache-5bdbb8dbf8-bh4wg   0/1     Pending   0          47s
```

# 参考

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/horizontal-pod-autoscaler.html

https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/