N予備校のインフラを Amazon EKS に移行した話

N予備校のインフラを Amazon EKS に移行した話

はじめまして。ドワンゴの教育事業で SRE エンジニアをしている西永です。

N予備校 では Kubernetes を採用しています。 これまでは Control Planes 含めすべての構成要素を自前で構築し運用していましたが、様々な問題が発生してきたことから Amazon EKS に移行をおこないました。

この記事では、Amazon EKS への移行に取り組んだ事例にについて紹介します。

なぜ移行したのか

Kubernetes のバージョンが古い

これまでの構成では Kubernetes のバージョンアップが考慮されておらず、Kubernetes を利用した N予備校の提供開始以降バージョンアップができていない状態でした。

そのためバージョン 1.7 を利用し続けていました。

バージョン 1.7 は 2017 年にリリースされ、リリースから 7 年が経過しすでにサポートが終了しています。 これにより、新しい機能やセキュリティアップデートが利用できない状態でした。

謎の本番障害

ある日、本番環境の Control Planes で謎の障害が発生しました。

etcd のメモリリーク

N予備校ではサービス障害時に Slack に通知が飛ぶ仕組みを導入しており、ある日サービスのレスポンスが遅延している通知が届きました。

状況を確認すると、アプリケーションの pod が起動するノードのうち約半数が NodeNotReady 状態になり、想定している台数の約半数しか pod が起動できておらず、リクエストをさばけていない状態になっていました。

原因として 3 台のインスタンスで構成されている etcd のうち 1 台が Unhealthy になっている事がわかり、etcd のサービスを再起動することで状況は復旧しました。

障害復旧後に状況を確認すると、etcd のメモリ使用量が増加し続けていることがわかりました。

その後、etcd のメモリ使用量に関する監視が追加され、サービスダウン前に etcd を再起動する運用が組み込まれました。

kube-apiserver との通信不通

ある日のアプリケーションリリース時、pod が ContainerCreating の状態で止まってしまっているという連絡が入りました。

状況を確認すると、kube-apiserver との通信が不通になっていることがわかりました。 しかし、通信が行えないこと以上の状況や根本原因はわからず、通信が失敗している Control Planes を構成する EC2 インスタンスを入れ替えることで対処をおこないました。

Kubernetes のバージョンが古いことやバージョンアップの手順が確立できていないことから、SRE 内でも Amazon EKS または類する別のサービスへの移行について検討は進めていましたが、定常の運用業務に追われていたためなかなか進まない状況でした。

そんな中で発生した、根本的な原因が不明だったり対処が困難だったりする障害事例から、自前で構築した Kubernetes の運用に限界を感じ、Amazon EKS への移行を決定しました。

移行前の構成

移行前の構成では、Control Planes とアプリケーションが稼働するノードで VPC が分かれる構成となっていました。

移行後の構成

移行前の構成から大きく変わった点として、分かれていた VPC を 1 つに統合しました。理由として Amazon EKS が複数の VPC にまたがる構成をサポートしていないためです。

弊社社内システムとの通信要件などを考慮しても Control Planes が管理用 VPC に構築されている必要はないと判断し、アプリケーションが稼働する VPC に統合しました。

その他の点については、自前で構築していた Control Planes が Amazon EKS に置き換わった以外大きな変更を加えていません。

移行ついで目指したところ

Amazon EKS へ移行するだけでなく、運用負荷の削減を目指し以下の取り組みを行いました。

blue/green でのバージョンアップ

移行前の構成で課題になっていた Kubernetes のバージョンアップを行うため、blue/green デプロイをおこなえる仕組みを検討・導入しました。

Route 53 の加重レコードを利用し、切替時にリクエストを少量から新しい環境に転送する構成を取りました。

また、加重レコード以下で分散させたリソースは RDS などのデータソースになるものを除き N予備校が動作するのに必要なものは一式揃っています。

切り替えのリリース前に新しい環境に一時的なドメインを指定し、Kubernetes のバージョン更新後の新しい環境に閉じた動作確認をおこなえるようにしました。

AutoScaler での自動スケール

移行前の構成では、アプリケーションのリクエスト数が増加した際に手動で pod やインスタンスを追加する必要がありました。

Horizontal Pod AutoscalerCluster Autoscalerを導入し、アプリケーションの pod のスケールや、スケールした pod が起動できない場合にインスタンスのスケールアウト、また負荷が落ち着いた際のスケールインを自動化しました。

N予備校としてアクセス増がわかっているイベント時などは、事前のスケール作業が発生することに変わりないのですが、通常利用時での負荷増大に対しての作業工数の削減を期待し導入をおこなっています。

Terragrunt でのインフラ管理

N予備校のインフラはもともと Terraform で管理をおこなっていましたが、あらたに Terragrunt を導入しました。

積極的に Amazon EKS のアップデートをおこなっていく場合、環境の構築や削除が頻繁に発生します。

モジュールを分割して tfstate の肥大化の抑制を進めると、細かく分けたモジュールをアップデートの際に一括で適用する事が面倒になっていきます。

これらの問題を解決するために Terragrunt を利用することにしました。

Terragrunt によって各モジュールの依存関係を管理することで、モジュールを分割し各モジュールを小さく保ったまま一括で適用できるようになりました。

Argo CD を利用した CD

アプリケーションのデプロイには Argo CD を導入しました。

これまでの Kubernetes に対してマニフェストの適用は Jenkins を利用していました。Jenkins のジョブを実行した際に動作するスクリプトで kubectl apply などのコマンドを実行していました。

この Jenkins ジョブは、アプリケーションのビルドとセットになっていたため、pod 数や requests.memory などのマニフェストを変更する際にもビルドが走ってしまうなど、不要なビルドが走ることがありました。

Argo CD を導入することで、マニフェストの適用を自動化し、GitOps による運用を実現しました。

サービス不停止での移行実施

切り替えの実施手順

既存環境と Amazon EKS 移行環境で blue/green デプロイでの切り替えを実施しました。

まず既存環境の Route 53 のレコードが加重レコードになっていなかったので加重レコードに変更しました。

その後、Amazon EKS で構築された新しい環境に対して少量のリクエスト転送を開始し様子見期間に入りました。

1 日という短い期間ですが、新旧の環境が同居した状態でサービスを稼働させ、問題が発生しなかったため、全リクエストを新しい環境に転送し、移行を完了しました。

おわりに

以上の取り組みにより、Amazon EKS への移行を終え、Kubernetes のバージョンアップが可能になり、新しい機能を利用できるようになりました。

Amazon EKS を利用した環境の検証や移行計画の準備には多くの時間を費やしましたが、移行作業自体は少ない手順で問題が発生することもなく切り替えをおこなう事ができました。

また移行後の運用においても大きな障害が発生することなくサービス提供を継続できています。

本記事が Kubernetes や Amazon EKS の利用を検討している方の参考になれば幸いです。

We are hiring!

株式会社ドワンゴの教育事業では、一緒に未来の当たり前の教育をつくるメンバーを募集しています。 カジュアル面談も行っています。

本記事公開時点では SRE チームの募集をおこなっておりませんが、事業の拡大に伴って募集を再開していることもあります。

また他のチームでの募集も行っていますので、興味を持っていただけた方はお気軽にご連絡ください!

カジュアル面談応募フォームはこちら

www.nnn.ed.nico

開発チームの取り組み、教育事業の今後については、他の記事や採用資料をご覧ください。

speakerdeck.com