EKS で Auto Scale 導入した後のトラブルを解消する
今回のトラブルとは
Auto Scale によって workernode 自体は増えたのにその workernode に pod が作られた時に IP が
調査をする
正常に pod が起動する workernode と正常に pod が起動しない workernode を比べると後者は セカンダリプライベート IP の欄に IP がない事がわかった。さらにその workernode のサブネットをみると 利用可能な IPv4 アドレス が 0 になっているというのが確認できた。
数時間後にそのサブネットの 利用可能な IPv4 アドレス をみると数字が増えていることわかった。
つまり workernode の セカンダリプライベート IP に割り当てられた IP が workernode が Auto Scale によって削除された後に再利用可能になるまでに時間がかかり過ぎて IP が足らなくなるという現象ということを突き止めた。
対応する
利用可能な IPv4 アドレス を増やす
上記の現象を AWS の中の人に共有した際に「もともと大量の IP を用意して使うものなので...」(意訳)ということを言われて、ですよね〜となったので単純に workernode に割り当てられるサブネットの IPv4 CIDR を変更して利用可能な IPv4 アドレス を増やすということをやった。
これで上記のトラブルは発生しなくなった。がしかし仮に今後アクセスが増えて workernode の数が大量に必要になった場合などに同じ現象に遭遇しないとも限らないということでもう一つ対応を行ってみた。
ネットワークインターフェイスを定期的に掃除する
workernode(というか EC2) の IP 周りはネットワークインターフェイスを見る事によって現在の status を確認できる。
status が available のものは定期的に削除されている模様というのがわかった。がしかしこの間隔が長すぎるので上記の問題が発生する
という事でこちら側で短い間隔でネットワークインターフェイスを掃除するという対応を行った。
Kubernetes の CronJob でやって貰った。
ネットワークインターフェイスを掃除するスクリプト
まずは AWS SDK for Ruby | AWS を使用してネットワークインターフェイスを掃除するスクリプトを作成
require 'aws-sdk' ec2 = Aws::EC2::Client.new() filters = { filters: [ { name: :status, values: [:available] }, { name: :description, values: ["aws-K8S-i-*"] # 今回は workernode 用に作成されたものだけ削除する } ] } ec2.describe_network_interfaces(filters).network_interfaces.each do |network| ec2.delete_network_interface({network_interface_id: network.network_interface_id}) end
これだけ
CronJob の yaml を用意する
15 分ごとに上記のスクリプトを実行する CronJob を用意する。
aws-sdk の install が遅いので aws-sdk 入りの image を用意しても良いと思います。(自分はそうしている)
apiVersion: batch/v1beta1 kind: CronJob metadata: name: network-interface-releaser spec: failedJobsHistoryLimit: 1 jobTemplate: spec: template: spec: containers: - command: - gem - install - aws-sdk - && - ruby - network-interface-releaser.rb env: - name: AWS_REGION value: ap-northeast-1 image: ruby:2.7.0 name: network-interface-releaser restartPolicy: Never schedule: '*/15 * * * *'
アクセス権限周りの設定
下記のアクセス権限を持つユーザを追加して アクセスキー ID などを kubernetes の Secret にして使う(この場合上記の yaml に env などの追記が必要)か workernode の IAM に追加すると CronJob からネットワークインターフェイスの操作が可能になる。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DeleteNetworkInterface", "ec2:DescribeNetworkInterfaces" ], "Resource": "*" } ] }
さいごに
個人の見解ですが、調査する時に正常に動作しているものと正常に動作していないものが既に両方存在してると勝ったなって思いますよね。