Vertical Pod Autoscaler の limits 周りの挙動について
Kubernetes で memory の requests を管理するのに Vertical Pod Autoscaler (VPA) を使っている。
VPA はリソースの使用量の実績に基づいて良い感じに limits と requests を調整してくれるものだが、 limits の設定に関してちょっと困ったのでメモ。
参考: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#limits-control
VPA がどう limits を設定するか
VPA が limits を設定するときは、 LimitResources などの制約がない場合、以下のようなアルゴリズムで設定される。
- VPA が requests を算出する
- 算出した requests に、元々設定されていた requests と limits の比をかけて新しい limits とする
すなわち、メモリの requests を 500Mi, limits を 1000Mi とした Pod に対して、VPA が新しい requests を 700Mi とすれば、新たな limits は 1400Mi となる。
requests を設定していないとき問題
ここで、Pod に limits のみを設定し、requests を設定していない場合はどうなるか。このとき、k8s は requests を limits と同じ量に設定するので、VPA は requests と同量の limits を推奨するようになる *1
requests は普段の使用量ベースで自動設定されるので、limits に同じ値が設定されるとほとんど burst できない Pod となってしまう。 起動時ちょっとだけメモリを多めに使う、みたいな Pod がある場合に OOM killer で落ち続けるようになってしまった。
解決策
解決策としては以下が考えられる。
limits だけではなく request を設定する
request を設定する際には VPA の挙動を考慮する必要がある
limits を設定せず request のみを設定する
こうすると VPA によって limits が減ることはない
今回はめんどくさかったので後者にした。
limits がない結果ノードのメモリが不足する可能性があるが、 requests は普段調整されるためそれほど起こらないはず。もし頻繁に起きるなら、普段は問題ないが Burst したときにメモリが足りないということであり、それは各ノードの余剰メモリが足りないということであるので、そういった問題として対処することにした *2。
*1:requests が何らかの理由で設定されない場合も VPA によって同量になる https://github.com/kubernetes/autoscaler/blob/2542e8c884a8e25634d3b8f43243fa8706007f30/vertical-pod-autoscaler/pkg/utils/vpa/limit_and_request_scaling.go#L69-L72
*2:LimitRanges ぐらいは設定してもいいかもしれない