Karpenterでなにがうれしいのか試してみた！

# Kapenterとは？

Kapenterは、新しいKubernetes クラスターオートスケーラーの アドオンです。
AWSが主体となって開発しているOSSで、re:Invent 2021 で GAになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/32385ccc-6a49-6af5-a277-83129ef3f0ba.png)


「Amazon Web Services ブログ」では、Kapenterがどんなものか、以下のように説明しています。

> karpenter は、アプリケーションのニーズを満たすジャストインタイムのコンピューティングリソースを提供し、間もなくクラスターのコンピューティングリソースのフットプリントを自動的に最適化して、コストを削減し、パフォーマンスを向上させます。

https://aws.amazon.com/jp/blogs/news/introducing-karpenter-an-open-source-high-performance-kubernetes-cluster-autoscaler/


説明を読んでも、何がどう変わるのか具体的にピンとこなかったので、実際に動かして試してみることにしました

- 今回は、Kapenter 0.5.3で検証しています。


# Kubernetes オートスケールのしくみ
Kapenterによってどう仕組みが変わるのかを理解するために、これまでのKubernetesのオートスケールの仕組みをおさらいします。
（もう知っていますという人は、読み飛ばしてください）

## Kubernetesのオートスケールは２段階に分かれている

#### ① Podの追加
Podの平均リソース使用率がしきい値を超えたら、新しいPodを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/6bd5a82f-5f19-ffe3-79b7-bf869dae15ea.png)

#### ② Nodeの追加
Podが増えていき、Podを追加できる空リソースをもったNodeが無い状態になる（ステータスがPendingのPodが発生する）と、新しいNodeを追加します。
Kapenterは、この「②Nodeの追加」の部分に該当します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/c08a13d9-9cfb-5b5c-8332-891eb3b87985.png)

## EKSのNodeの構築・制御の方法は、３種類
EKSの場合、Nodeのオートスケールは、AWSのAutoScalingGroup機能を利用して実現しています。これにより、EKSのNode追加の仕組みも、AutoScalingGroupの制約の制約を受けることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/ab2c01ff-cd0a-9523-99c9-5f91828f269e.png)

# 実際にKapenterをうごかしてみた
Kapenterのチュートリアルを参考に、EKSにKapenterを導入してみました。

## EKSでKapenterを動かすための構成
２種類のNodeを作成することになります。

Kapenterは、Node上で実行されるPodであるため、Kapenter自身が動くNodeが最低１台以上必要になります。（Node Aが該当）

もう一つは、Kapenterが制御されるアプリのPodが動作するNodeです。こちらのNode数の初期状態は０台です。（Node Bが該当）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/74ceb058-4970-263e-c930-e3be19c2ec76.png)

## 動作の流れ

#### 1. KarpenterのProvitionerを作成する  
Provitionerは、Nodeをどのように構成するかの設計図にあたる部分になります。 
どのインスタンスタイプを使うか？、オンデマンドインスタンス or SPOTインスタンスか、などの設定を行うことができます。
今回は、以下のようなProvitionerを構成して、作成してみました。

```yaml
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ['on-demand']
    - key: 'node.kubernetes.io/instance-type'
      operator: In
      values:
        [
          't3a.nano',
          't3a.micro',
          't3a.small',
          't3a.medium',
          't3a.large',
          't3a.xlarge',
          't3a.2xlarge',
        ]
  limits:
    resources:
      cpu: 20
      memory: 100Gi
  provider:
    instanceProfile: KarpenterNodeInstanceProfile-karpenter-sample
    tags:
      Name: 'KarpenterControlNode'
  # Node 空になった後に何秒後に削除するか？
  ttlSecondsAfterEmpty: 30
  # Node 有効期限、自動終了される
  ttlSecondsUntilExpired: 600
```
#### 2. Pending（配置不可）のPodが発生
Podを作成しPendingのPodが発生すると、EKSはNodeを追加しようとします。

#### 3. 起動テンプレートが自動作成される
まず最初に、Karpenterは、Provitionerの設定にあわせた起動テンプレートを作成します。

#### 4. PendingのPodに必要なスペックのインスタンスタイプを自動計算し、Node（EC2）を追加
Karpenterが、インスタンスタイプを自動計算し、EC2を起動します。

#### 5. Nodeが起動し、PendingのPodが実行中になる
あとは、通常のEKSと同じ動作です。

#### 6. その後、稼働するPodが０になったNodeは、自動で削除される
Karpenterで起動したNode上は実行中のPoｄ数が0になると、一定時間待った後、自動で削除されます。
どれくらい待つかは、設定で変更することができます。

## Kerpenterで作成されたNodeの特徴
以下の図の青枠の３台が、実際にKarpenterで追加されたNodeです。
（一番上のNodeは、Karpenterが動作しているNodeです。）

- 異なるインスタンスタイプのNodeの混成が可能になる
  今回はT系のみ許可していますが、Tx、Mx、Cxなどの別系統のインスタンスタイプも可能です

- AutoScalingGroupが作成されず、直接KerpenterがNodeを制御する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/aa917b22-0474-1b4b-5755-557e6ae0c644.png)


# Kapenterでうれしいこととは？ 

### AutoScalerの制約から開放される
- Nodeのインスタンスタイプが、必要量にあわせて動的に選択される
  「１種類 固定」 から 「複数種類から最適なタイプを自動判断」に変わります。
  これにより
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/012a9e2c-c9b2-1e03-9d32-24763ee66ec8.png)

- リソースが「余っている」、「足らない」問題から開放される
  Nodeのインスタンスタイプが固定の場合、
  Podが１つしか稼働させていないリソースが無駄になっているNodeが発生したり、
  Nodeのスペックより、高いスペックが必要なPodを追加しようとした場合に、動かすNodeがないなどの現象が発生していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/5a718578-af1e-5512-1f21-3250855d5380.png)

### それ以外のメリット
- SPOTインスタンスとオンデマンドインスタンスを混成できるらしい
  自分の環境ではSPOTインスタンスが作成できず、試せてないです・・・

- Nodeの追加が早くなる？
  PendingのPodが発生すると、Kapenterは一瞬でNodeの追加を開始します。
  PodがRunningになるまでの時間をKubernetes Cluster Autoscalerと比較すると、Kapenterのほうが速くなりました（厳密に同じ条件ではないので、参考情報レベルです）。KapenterでNode（EC2）の起動時間が早くなるわけではないので、Node追加を判断するロジックに差があるかと思われます。
  ただし、インスタンスのスペックで、Node（EC2）の起動時間は左右されるので、追加するNodeのインスタンスタイプが変動になると、Nodeの追加が速い時と遅い時のムラが発生します。

- もちろん、作成できる上限も設定可能（vCPU、Memoryを指定）
  現時点でどれだけ作成したかは、`kubectl describe provisioner`コマンドで確認できます。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120824/b04ef886-66a2-1e0f-e0c8-d6bf3d0fed4b.png)

- Nodeを削除する（EC2自体も削除される）コマンドが追加される ！？
  Karpenterで作成したNodeだけですが、`kubectl delete node xxxxx`で削除できるようになります。

# Kapenterの気になる点、もやもやした点 
- Provitionerで起動テンプレートを作成させると、細かいカスタマイズができない。
  現段階では、Provitionerで指定できる設定項目が少なく、カスタマイズをしている場合は注意する必要があります。
  その場合は、別の方法で起動テンプレートを作成し、連携する必要があります。（試してはいませんが、ドキュメントにも記載があります）

- 予測されるピークにあわせて、「予めNodeを起動しておく」はできない？
  現段階では、一定数必ず起動しておく設定はないようです。

- KapenterのNodeに障害が発生すると、 Kapenterが作成したNode自動復旧も停止してしまう。
  Nodeが停止してしまった場合にNodeを再追加する役割は、Kapenterが担うことになります。
  仮に全Nodeが停止した場合、先にKapenterのNodeとPodが復旧した後に、Kapenterが作成したNodeを復旧する流れになるので、全復旧するまでの時間が長くなると思われます。

- 起動後に一定時間経過するとNodeを自動終了する機能は　どういう用途で使うのかよくわからない？
  実際に終了される動作は確認できたのですが、具体的な利用目的が思いつきませんでした・・・

# Kapenterのまとめ

- Karpenterを使うと、Node管理が柔軟に対応できるようになる。
  複数種類のインスタンスタイプから最適なタイプを自動判断し、Nodeを追加することができる。

- はやくAWS以外のプラットフォームでもサポートされて、今後も安心して使えるようになるとうれしい。
  現段階ではEKSのみ対応ですが、それ以外のkubernetes基盤にも対応できるように設計されてるようです。

---
#### Karpenterを動かすサンプル公開
今回使ったEKSを作成してKarpenterを動かすサンプルをGitHub公開しています。
https://github.com/takaf04/karpenter-sample

---
2021/12/18(土)のJAWS-UG横浜 「#39 AWS re:Invent 2021 Recap Container」で発表した内容を
Qiitaに転載しました。

JAWS-UG横浜支部では、定期的にイベントを開催しております。
現在（２０２１/12時点）は、re:Invent2021のRecapイベントを開催予定です。
２０２1年1月にも、引き続き開催予定ですので、みなさんの参加お待ちしております。

- JAWS-UG横浜支部  
https://jawsug-yokohama.connpass.com/event/