EKS Kubernetes NodeとPodのAutoscaling

みんな大好き Autoscaling の時間です☆ 少し長めになっちゃったのですが、分割するとわかりづらくなりそうだったので1つでぶっ込んでいきます。

さてここで新たに、helm という仕組みが登場します。Kuberntes におけるパッケージ管理みたいなもので、これも Terraform でやっつけちゃうので安心して・・・うーん、最後までいければいいですね!くらいな感じです。



EKS における Autoscaling の仕組み

まずおさらいとして、ALB + EC2 の時はどうやっていたかというと、Autoscaling Group に CloudWatchAlarm を組み合わせて、例えばCPU使用率を条件に、何%を超えたら既存台数の何%を増加、何%より低くなったら既存台数の何%を減少、のように実現していました。

これがガラリと変わって CloudWatchAlarm とオサラバします。そして、EC2 Node と Pod という2種類のリソースがあるため、Autoscaling の仕組みも2段階になります。

まず、Pod のスケーリングですが、helm の metrics-server でCPU等のリソース使用率を取得し、Horizontal Pod Autoscaler(※以下、HPA)がリソース使用状況からPod数増減の判断をして、Deployment のPod数を編集します。

Nodeリソースが不足して、Pod数を増やせなくなった場合、helm の cluster-autoscaler が AutoscalingGroup の desired を編集し、Nodeを増やすことで HPA の詰まりを解消します。Nodeリソースが不要になった場合は、減少してくれます。

ここで特徴的なのは、Pod は旧来通り、リソース使用率によって増減しますが、Node は Pod の増減状況に依存するという点です。Pod のリソース状況は、EC2 のようには CloudWatch では管理できないので、Kubernetesクラスタ内で解決することになるのが自然な成り行きなのかな、と思います。また、Nodeの増減は CloudWatchAlarm によるグループの平均CPU使用率でもできないことはないのですが、おそらく、cluster-autoscaler に任せた方が素早く適切な対応となる、と思われます。

と、いうことで、
 metrics-server でPodリソース監視をし、
 HPA がPodリソース状況を見てPodを増減し、
 cluster-autoscaler がNode過不足ならAutoscalingGroupイジってNode増減する!

な感じで、早速 mertics-server を動かす!
・・・ための、helm の準備から入りましょう。


helm の準備

まず、helm とは。下記ページをご参考あれ。
  • helmとは & helmの使い方 – Qiita

  • ザッとみて雰囲気でわかると思うのですが、yum みたいに install したりなんだりできて、その結果としてそのパッケージ機能を動かすための Pod が起動されたりします。

    なので、Kubernetesへのアクセスが整っている環境であれば、手元で helm install や search をできます。そのための手順はドキュメントがあって、
  • Installing Helm | HELM Documentation

  • 例えばスクリプトを実行して、初期化するとコマンドで遊べるようになります。helm のインストール自体は Terraform に任せてしまいますが、helm としての情報を色々みてみたり、Terraform に不整合が起きた時に帳尻合わせたりするのに必要になることもありますので、準備はしておくとよいでしょう。


    helm 用の変数

    Terraform にて aws, kubernetes と扱ってきたように、helm も provider を用意します。と、その前に local 変数で色々くくりだしておきます。

    前半は、次の provider用の情報ですが、最後の specs は、前の記事で書いた Pod 配置のための記述です。インストールした helm パッケージが起動する Pod は管理系なので、安定したNodeへ配置するよう、ここで指定する内容をまとめています。見ての通り、キーの配列やエスケープが、かなり特殊な書き方しているので、離脱危険地帯です。

    helm provider

    helm_*** を扱えるようにするため、provider を記述するのですが、ここから先を実行する前に、AutoscalingGroup にて(私の場合は role=master の方)、1台以上のNodeを起動しておく必要があります。これは、パッケージインストールうんぬん以前に、helm を利用するために tiller-deploy という Pod を起動するためです。この Pod がないと、helm は操作できません。

    ここで特徴的な部分を補足説明しておきます。

    kubernetes
    見たとおり、kubernetes への接続情報です。provider kubernetes の記述内容とほぼ同じです。

    override
    前述の locals 変数で定義した、Pod配置関連の情報を上書きしています。全Node に Taints が登録されているので、こんな感じで master Node の方へ強制的に案内してあげることで、tiller-deploy Pod が任意のNodeへ起動されます。

    後述の helm_release の記述と合わせて、とてもお上手にコードを書けたと思いマッスル。

    home
    helm を実行すると、実行したことによって出来上がるファイルがあり、Terraform でうまいことヤリクリするには、コード直下で管理する必要がありました。

    そのために少々特殊なことをしていて、確か repositories.yaml をローカルの helm で実行して作られたものをコピーしました。この辺は、apply して怒られるたびに調整した感じです。また、Terraformコードは Git で管理しているので、.helm/.gitignore に不要なキャッシュを除くよう /cache を記述しています。


    Service Account 作成

    さきほども書いたとおり、helm の管理のために tiller-deploy というPodが起動されます。その稼働に必要な情報として、この ServiceAccount と、次の RoleBinding が必要になります。


    Cluster Role Binding 作成

    次はこれ。

    わざわざ sleep をしているのは、コメントの通りですが、Terraform でガーッとリソースを作ると、tiller-deploy Pod が起動しきる前に helm_release でのパッケージインストールが走ってしまい、エラーが発生してしまいます。そのため、ウチの環境の場合はココで2秒待てば大丈夫だったので、仕方なく入れています。Terraform でやっていると、こういうのは慣れたものです。


    metrics-server 作成

    Node/Pod達のメトリクス管理をしてくれる、helm の metrics-server を入れます。完了すると、metrics-server という Pod が起動します。もちろん、このPodは管理系なので、前述のPod配置管理変数を dynamic – for_each を使って set をループ設定しています。

    これがちゃんと動かないと、その後いろいろダメなので、軽くコマンドを記載しておきます。


    HPA 作成

    HPA は helm ではなく、Kubernetes 付属の機能になっています。metrics-server が稼働していること前提のシステムなので、前述のコマンドなどで動作確認をキチンとしてから進むとよいでしょう。

    公式ドキュメントはこちら。
  • Horizontal Pod Autoscaler – Kubernetes
  • CPU条件

    CPU条件については別記事でまた追う予定ですが、旧来のCPU条件の扱いとは感覚がだいぶ異なるので、十分な検証が必要なところです。

    max_replicas

    基本的にEC2リソースの量や費用のコントロールは AutoscalingGroup の方でやるので、こちらで上限に引っかかって増加できなくなる、ということは避けたほうがよいと思います。1Node, 1Pod あたりのリソース設定によりますが、Nodeリソースをフルに使えるような超過的な数値が安定的になる、と思われます。

    api_version

    ドキュメントにいくつか書いてあって、例えば autoscaling/v2beta2 だとCPU以外に複数のメトリクス条件を組み込めたりするのですが、EKSでは autoscaling/v1 しか使えないようなので、apps/v1 を指定するしかありません。

    PodのCPUリソース指定が必須

    かなり大事なヤツです。Autoscaling対象となるDeployment にて、前の記事で、なにげなくCPUリソース量を指定していましたが、HPAを扱うためには、
     resources > requests > cpu
    を必ず指定する必要があります。指定しないと、PodのCPU使用率が不明になり、当然HPAも動きません。

    その記述をコチラから抜粋しておきます。

    Please note that if some of the pod’s containers do not have the relevant resource request set, CPU utilization for the pod will not be defined and the autoscaler will not take any action for that metric.


    cluster-autoscaler 作成

    cluster-autoscaler は helm で入れます。入れたら、管理Podが起動します。一部クセがありまして、要所は locals に括りだして指定しています。その上で、また同じように master用Node へ配置されるように、dynamic “set” のところで、merge して一括りのコードにしています。

    sslCertPath

    EKS では、この項目を上記値にしないとエラーになります。
  • 参考:cluster-autoscaler: pod crashing ca-certificates.crt ‘not a directory’ #9019

  • chart

    stable/cluster-autoscaler という名前です。検索すると stable/aws-cluster-autoscaler というのも出てきますが、既に非推奨となっているので注意してください。

    参考ページ

  • autoscaler/FAQ.md at master · kubernetes/autoscaler · GitHub
  • Kubernetes Autoscaling 101: Cluster Autoscaler, Horizontal Pod Autoscaler, and Vertical Pod Autoscaler




  • と、こんな感じで構築が完了です。helm を扱うために、helm関連のPodが起動するための Node が1台以上起動していないとダメっていうのが開発中は少々鬱陶しいのですが、それ以外はキレイに収まっていると思います。

    これだけでも、わりと苦労した部類なんですけど、大事なのはこれらの挙動なので、それについてはまた別記事で書いていきたいと思います。気力がもてば。