EKS on FargateでMetrics Serverをインストールしたらエラーが出た
完全Fargate構成、つまりEC2ノードをゼロにしたEKSクラスターを作成しました。このクラスター上にて、一部のdeploymentのスケールを自動化すべくHPA(Horizontal Pod Autoscaler)を導入しました。しかし、途中問題が発生して結局HPA導入はひとまず断念しました。詳細をリポートします。
HPAのために Metrics Serverをインストールする
HPAは、CPU等のリソース使用率に基づいてdeployment等のPodの数を自動的にスケールする機能です。つまりリソース使用率を把握する必要があります。その役割を担うのがMetrics Serverです。Metrics ServerはEKSクラスターにはデフォルトではインストールされていませんので、HPAを利用するにはまずMetrics Serverをインストールする必要があります。インストール方法は以下を参照ください。
Metrics Serverインストール後エラーログが大量発生
Metrics Serverのインストール自体は問題なく終わりました。が、インストール以降Metric ServerのPodが以下のようなログを吐き続けていることに気づきました。
\"Failed to scrape node\" err=\"Get \\\"https://192.168.106.50:10250/metrics/resource\\\": dial tcp 192.168.106.50:10250: connect: connection refused\" node=\"fargate-ip-192-168-106-50.ap-northeast-1.compute.internal\"
1分あたりだいたい10回以上このログを吐いています。Fluent Bit経由でCloudWatch Logsにログを転送していたので課金が気になります…
10250ポートはKubeletのデフォルトポート番号です。 Metrics Serverはリソース使用率をKubeletに問い合わせて取得しています。この問い合わせが失敗していることになります。
Metrics Serverがメトリクスを取得できていると、kubectl top node (node名)
でノードのリソース使用率がわかります。が、上記ノードのメトリクス取得は失敗しました。
% kubectl top node fargate-ip-192-168-106-50.ap-northeast-1.compute.internal Error from server (NotFound): nodemetrics.metrics.k8s.io "fargate-ip-192-168-106-50.ap-northeast-1.compute.internal" not found
※ 他のノードは取得できています。
% kubectl top node fargate-ip-192-168-96-204.ap-northeast-1.compute.internal NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% fargate-ip-192-168-96-204.ap-northeast-1.compute.internal 28m 1% 191Mi 5%
Metric Server Podが稼働している自身のNodeのKubeletにアクセスできていないことが判明
前述のエラーでアクセス失敗しているNodeは特定の一台のみということがわかりました。さらに調査を続けると、その一台というのが、エラーを吐いているMetric Server Pod自身が稼働しているFargate Nodeであることが判明しました。
% kubectl describe pod metrics-server-5c4bb95695-jhwvp -n kube-system | grep Node: Node: fargate-ip-192-168-106-50.ap-northeast-1.compute.internal/192.168.106.50
さらに調査
さらに調査を続けると、Metrics ServerのGitHubリポジトリのIssueにて このようなコメントを発見しました。
I had the same issue and opened a ticket with AWS support. This was their reply:
> I was able to replicate the same behaviour when tested in my lab environment. On further checking internally, I came to know that Fargate pods currently cannot ping the kubelet on the same node and this is by design. In other words, local pods cannot directly access the kubelet that is hosting them. Also, it is not planned to support local kubelet curl'ing on fargate nodes at this time. Apologies for the inconvenience that this limitation would have caused. Please help with your use-case so that I can suggest you an alternative workaround/ take your request forward as a feature request.
要約すると、AWSサポートが以下のように回答したとのことでした。
- 現状Fargate Podは自身の稼働しているノードのkubeletに通信できない
- これは仕様
- 今の所修正予定もない
なるほど…
修正依頼issueもcontainer-roadmapリポジトリに作成されていました。
取り得る次善策
というわけで、現状完全Fargate構成でMetrics Serverをインストールするとエラーは回避でき無さそうです。代替案を考えました。
HPAを諦める
現状Metrics ServerはHPAを使いたいがためだけにインストールしたのものなので、HPAを諦めればMetrics Serverはアンインストール可能です。今回はひとまずこの案を採用しました。いずれ再度HPA導入を検討する予定です。
ログを無視する
Metrics ServerはHPAを使いたいがためだけにインストールしたのもので、さらにHPAの対象にしたいのはMetrics Serverではない別のdeploymentです。つまり、現状でもやりたいHPAは実現できます。そのためログを無視して運用を続けるのもアリなのではと思います。
前述の通り、今回はFluent Bit経由でCloudWatch Logsにログを転送していたので課金が気になるという状況でした。ですので、この案を採るのであればこのログだけfilterで弾いてCloudWatch Logsに転送されないようにするのが良いでしょう。
EC2ノードも使う
完全Fargate構成を諦めて、Metrics ServerのためだけにEC2ノードも残します。Fargateプロファイルのセレクターを工夫して、Metrics Serverだけ対象外になるようにしましょう。
Metrics Server以外のものをHPAで使う
Metrics Serverが提供するメトリクスではないもので、HPAのスケール設定を行ないます。私はまだ試していませんが、Prometheusメトリクスを使ったりすることができるようです。