2021-01-18

初めてのEKSバージョンアップデート

taxagawa

SREの@taxagawaです。

弊社ではIoTを用いた在庫管理・発注自動化ソリューションを実現するスマートマットを提供しており、そのシステム基盤には現在、AWSのManaged KubernetesサービスであるAmazon EKSを用いています。本記事では昨年(2020年)12月に実施したクラスタのKubernetesバージョンアップデートに関して、備忘録的な意味も込めてその内容を記していきたいと思います。

アップデート概要

今回のアップデートでは本番環境のクラスタを稼働させ始めた当時の最新版であったEKSバージョン1.14から、現時点での最新版であるEKSバージョン1.18へのアップデートを行いました。そもそも今回アップデートを実施した背景として、まずEKSにおいてサポートされるバージョンはk8sの新しいマイナーバージョンとその直近三世代分までであるということがあります。(今回で言うと、最新の1.18から1.15までがサポートされます)このサポート対象の範囲外のバージョンで稼働するクラスタについては、最新バージョンのリリース後約一ヶ月で強制アップデートが実施されてしまいます。当然この強制アップデートには多少なりともダウンタイムが伴いますので、安全なバージョンアップ対応を実施する必要があったということになります。

今回のアップデートでは、稼働中のクラスタ(以降、旧クラスタと呼びます)に加えてもう1台、バージョン1.18のクラスタ(新クラスタと呼びます)を用意し、DNSを切り替えることで移行するというベーシックな手法を採用しました。(これ以外に良い方法があるのか分かりませんが...)本番稼働のクラスタはterraformコマンドを叩けば直ぐに作成できるようにしていたため、一見すると比較的簡単な作業のように思えますが、後で言及しますとおり考慮すべき事項が多々あり、そのピックアップと対応に大変苦労することとなりました。

クラスタの構成

本題に入る前に、ここで一旦今回のアップデート対象となるクラスタの概要について説明します。

アップデート実施時点でk8sのバージョンが1.14、ノード数が12、稼働するマイクロサービスが29個でPod数が約250個となっています。

また、クラスタとその周辺のAWSサービスレベルでのシステム全体図は以下のようになっています。

cluster structure

クラスタの更なる詳細に関しては、拙文ではありますが以前私が書いたこちらのブログをご参考ください。

考慮した事項

それでは移行の計画段階および実施段階で特に考慮した点を3つほど挙げたいと思います。

Deprecated あるいは Terminatedとなった機能の確認

AWS公式のEKSバージョンに関する説明を眺めると、そのバージョンで追加された機能やバージョンアップに伴い対応が必要な箇所が挙げられています。これを参考にすれば万事問題なさそうですが、どこに落とし穴があるか分かりませんので、今回はkubernetes公式のChange Logを精読しました。AWS公式が信用できないというわけではなく、4つもマイナーバージョンが上がるため何かしらの抜け漏れがないかをきちんと確認したいと言う思いでした。当たり前ですが、一次情報を参照することは非常に大切です。マネージドなk8sを利用している場合は関係のない情報も多いですが、知らなかった情報を得るのは学びにもなります。

CronJobの移行

各マイクロサービスにおけるほとんどのPodは同時に2つのクラスタに存在していても問題ないものであったのですが、CronJobで動作するPodだけは特別に気を遣う必要がありました。というのも、各Jobの実行結果に関する冪等性は担保されていますので理論上は複数同時に実行されても問題ないはずなのですが、自動発注などのサービスの根幹を成すクリティカルなJobが万が一予期せぬ動作を起こしてしまった際のリカバリにかかる手間などを考慮すると、この移行は慎重に行わざるを得なかったからという理由になります。幸いにして毎分実行されるような短いスパンのCronJobは存在していなかったため、移行の手順としては旧クラスタでのCronJobの実行後そのCronJobをターミネートし、新クラスタに反映させるという原始的な作業となりました。本当はこの辺りの作業もなるべく人の手を介さない形にしたかったのですが、絶対に失敗できなかった背景を考えると、止むを得なかったと思います。

DBの接続数の増加

本番の移行作業で漏れていた考慮点がこのDBの接続数の増加でした。クラスタ自身とその内部の状況に多くの思考を巡らせていたため、周辺サービスのリソースに細かく気を配り切れていなかったのが悪かったのではと今では思っています。我々が使用しているDB(Aurora MySQL)は、コストと通常時のCPU利用率を鑑みてバランスの取れたサイズを選択しているのですが、今回の移行の際は一時的にクラスタが2つになるため、接続数が単純計算で平時の2倍になるという考えが抜け漏れていたというわけです。実際の移行では一部のPodが新クラスタでCrashLoopBackOffのステータスを出し続け、原因も分からぬまま即時切り戻し作業を行うはめになってしまいました。(あらかじめ切り戻し手順は用意していたので事なきを得ましたが) 結局2回目の作業では事前にDBのサイズを一段階スケールさせておくことでこの問題を対処しました。SPOFであるDBにはクラスタ同様に細心の注意を払うべきだと心に誓った出来事でした。

まとめ

Podの自動復旧などのおかげで普段はほとんど手のかかからないk8sクラスタですが、今回ばかりは細心の注意を払う必要がある作業であったため、対応期間中は失敗への不安を常に抱えていました。結果的には無事移行を完了できて安心しています。終わってから考えると、まだクラスタの規模がそこまで大きくない段階でこのようなアップデートを経験できたのは今後の為になるものだったと強く思います。次がいつになるか分かりませんが、自信を持ってアップデートを実施できるはずです。

なお、k8sのマイナーバージョンのリリースは約三ヶ月に一度行われており、EKSの方もそれに追従しています。したがって最長でも一年に一回はクラスタのバージョンアップ作業を実施する必要があります。ギリギリでの対応とならないように事前に移行計画を入念に立てておくことでスムーズな移行ができるかと思いますし、クラスタ構成の振り返りやアドオンの要不要を考慮する良い機会となると思います。

今回の記事が読んでくださった方の参考となれば幸いです。

最新の記事