起
ある日、運用しているEKSクラスタで、subnetのIPが足りなくてnodeが起動できないというエラーが出ました
クラスタのサブネットは/24なのでそれはまあ少なかったんですが、小規模なクラスタだったのでまあ問題にはならないと思っていました
実際クラスタ内で起動しているpodの数はどう見ても256には届いてない
ということで調査です
結
以下は、ポッドネットワーキングにamazon-vpc-cniを使っている前提です
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/pod-networking.html
podに割り振られるIPは、nodeのENIに割り当てられたセカンダリIPになっています
podがnodeのipを消費していくと、新しいENIをアタッチするようになっています
ENIとそれに割り当て可能なセカンダリIPの数はインスタンスタイプにより異なるのですが、デフォルトでは割と余裕を持って新しいENIを用意するようになっています
それで、デフォルトではENIがアタッチされると同時に最大数のセカンダリIPを確保します
(セカンダリIPの数についてはこちらを参照してください https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-eni.html )
つまり、podが起動していなくてもnodeが結構な数のIPを消費します
大きいインスタンスほどENIあたりのセカンダリIPの最大数が多いので。例えば大きいインスタンスにリソースを大量消費する少数のpodというようなクラスタ構成だと、使わないipが大量に確保されている状況になります
起動中のnodeがサブネットのipをすべて確保してしまうと、当然新しいnodeが起動できません
これが今回起動しているpodの数に見合わずipが枯渇していまった経緯でした
解
じゃあどうすればいいのかという話ですが、ENIの起動タイミングや確保するIPの数は設定が可能です
環境変数で設定します
(解説間違ってたらすいません、怪しいと思ったら元のドキュメントで https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/eni-and-ip-target.md )
- WARM_ENI_TARGET
- 確保しておくENIの数
- デフォルトは1
- たとえば1の場合、1つめのENIに割り当てられたセカンダリipがpodに使われると、次のENIをひとつ用意するということ(のはず)
- なので、ほとんどの場合nodeが起動すると2つENIがアタッチされる
- WARM_IP_TARGET
- podに消費されたipより余分に確保するipの数
- デフォルトは0
- 0の場合は、eniあたりの最大数を確保する(のはず)
- MINIMUM_IP_TARGET
- nodeがipを確保する最低数
- デフォルトは0
これらを設定してクラスタの用途といい感じに合わていくのですが、割と面倒な注意事項があって
WARM_IP_TARGET
を0以外に設定すると、podを起動・削除するごとにセカンダリipが増減するので、podの出入りが激しいクラスタだとawsのapi制限にひっかかりやすいそうです
nodeあたりに配置されるpodの数が大体わかってる場合はMINIMUM_IP_TARGET
を少し余裕を持って設定して、補助的にWARM_IP_TARGET
を使用すれば使えなくはないかも?(当然デフォルトより消費ipが少なくできる場合)
正直使いにくいな、と思いました
確保したipが残りいくつになったら次のeniを用意する、みたいな設定があればよかったです
で
私はこの設定を使いこなせる気がしないので、サブネットを大きくして終わりにしました