本記事はZOZO Advent Calendar 2021その1の15日目の記事です。
はじめに
最近地方移住を進めており、ワクワクすっぞな亀井と申します。
さて、ZOZOTOWNはモノリシックなアーキテクチャからマイクロサービスアーキテクチャにリプレイスを進めており、マルチテナントなEKSクラスタを運用しております。
また、ZOZOTOWNは毎年正月にセールを行っており、ありがたいことに1年のピークとなるトラフィックが流れるイベントとなっております。
リプレイスによるサービスの増加と、正月セールのためのPodスケールにより、EKSでPrivate IPアドレスが枯渇してしまう事態に遭遇しました。その際対応したaws-node daemonsetの設定変更について記事にしようと思います。
Podが多数稼働するEKSクラスタを運用されている方の参考になれば幸いです。
Private IPアドレス枯渇?
Podスケールを行った際にPodがPendingで起動しない事態に遭遇しました。
AWSマネジメントコンソールでEKSの該当ノードグループを確認したところ、下記のような問題が出力されておりました。
Amazon Autoscaling was unable to launch instances because there are not enough free addresses in the subnet associated with your AutoScaling group(s).
Privateサブネットは、サブネットマスクが/20(IPアドレス数 4096)で3AZを使用しており4096*3=12,288のIPアドレスが使用可能な、比較的大きめのサブネットを用意しておりました。Podスケールを行ったとはいえ、起動ノードは合計で400台程だったため、400台で12,288のIPアドレスが足りない・・・だと?という状態でした。
Private IPアドレス枯渇の原因
aws-nodeの下記パラメータの初期設定により、稼働Pod以上のIPアドレス数がノードごとに確保されてしまっていることがIPアドレス枯渇の原因でした。
WARM_ENI_TRAGET: 1
(ノードが確保する余剰ENI数)
ref. https://github.com/aws/amazon-vpc-cni-k8s#warm_eni_target
上記設定により最低確保されるIPアドレスは「ENIごとのIPアドレス数(インスタンスタイプごとに異なる)2(ENI数。標準の1+WARN_ENI_TARGET:1)」で計算され、例えばインスタンスタイプm5.xlargeのノードでは「152」で最低で30IPが確保されてしまいます。
400台程のノードが稼働していたので、400ノード*30IP=12,000IPが使用されておりました。実際にはm5.xlargeよりサイズの大きいインスタンスタイプも存在したため、12,288IPに到達してしまっていたようです。
ノードで確保されているIPアドレスは、AWSマネージドコンソールから該当のノードのEC2 Instance、ネットワーキングタブで確認可能です。
aws-nodeの設定見直し
IPアドレス枯渇の対応として、下記が考えられましたが
- (1)ノードの確保IPアドレスを減らし起動可能なノード数を増やす
- (2)Privateサブネットを拡張しPrivate IPアドレスを増やす
まずは(1)を進めることにしました。
ノードの確保IPアドレスを減らす
aws-nodeの下記パラメータをチューニングしました。
-
MINIMUM_IP_TARGET
- ノードが確保する最低IPアドレス数
- デフォルトnone
- 搭載予定Pod数+αの値を設定する
-
WARM_IP_TARGET
- ノードが確保する余剰IPアドレス数
- デフォルトnone
- このパラメータが設定されると、
WARM_ENI_TARGE
は無視される
1ノードに8Pod程度(deamonset、deploymentなど)搭載が予想されたため、下記の様に設定を行いました。
MINIMUM_IP_TARGE: 10
WARM_IP_TARGET: 2
aws-nodeではこれらのパラメータを環境変数で設定出来、下記コマンドで設定が可能です。
kubectl set env -n kube-system daemonset/aws-node MINIMUM_IP_TARGET=10 WARM_IP_TARGET=2
または、aws-node daemonsetのmanifestに下記を追加しapplyすることでも設定が可能です。(該当箇所のみ記載しております)
spec:
template:
spec:
containers:
- name: aws-node
env:
- name: "MINIMUM_IP_TARGET"
value: "10"
- name: "WARM_IP_TARGET"
value: "2"
設定された環境変数は下記コマンドで確認が可能です。
kubectl get daemonset -n kube-system aws-node -o yaml |yq -r '.spec.template.spec.containers[] |select ( .name == "aws-node" ).env'
この設定により、インスタンスタイプm5.xlargeのノードが確保するIPは 30→12 に減らすことが出来ました。
EKSアドオン環境における設定方法
EKS v1.18以降では、いくつかのdaemonsetをEKSアドオンとしてeksctlやCFnなどから管理が可能となりました。aws-nodeも対応しており、弊社はCFnでaws-nodeをEKSアドオンとして管理しております。
残念ながら、CFnでは環境変数を設定するオプションは現在提供されておりません・・・。そのため、上記のkubectl set env
を実行する方法でお茶を濁している状況です。
AWSのコンテナロードマップには、EKSアドオンからMINIMUM_IP_TARGET
やWARM_IP_TARGET
を設定を変更できるようにするissueが発行されているので、ゆくゆくはCFnからオプションとして設定が可能になるだろうと期待しております。
同じ気持ちの方は、是非issueへ👍をお願いします。
まとめ
- EKSのノードはaws-node daemonsetのデフォルト設定により、多数のPrivate IPアドレスが確保されてしまい(m5.xlargeの場合最低で30IP)、思いがけずPrivate IP枯渇に直面する可能性があります。
- aws-nodeの環境変数
MINIMUM_IP_TARGET
やWARM_IP_TARGET
を設定することで、ノードが確保するIPアドレスを抑制することが出来、IP枯渇を回避することが可能です。 - ただし、環境変数は現在EKSアドオンからは設定できず、
kubectl set env
コマンドなどを実行し設定する必要があります。(ゆくゆく設定が可能になるだろうと期待しております)