この記事は ヌーラボブログリレー2023 for Tech Advent Calendar 2023 – Adventar 24 日目の記事です。昨日の記事は Makoto Fukuda さんの イベントで撮影スタッフを依頼される時に思うこと でした。
こんにちは、SRE 課 Backlog Platform Engineering チームで Backlog のプラットフォームとして Kubernetes(Amazon EKS ※以下 EKS と記載) クラスターの開発運用をしている大野、吉岩です。この記事では EKS クラスターの運用で重要な要素の一つであるクラスターの継続的なアップデートを実現するために、私達がどのようにアップデートに取り組んでいるかについて書いています。 Backlog で利用している EKS クラスターについてはアプリケーションのコンテナ化の発表で触れていますが、EKS クラスターの運用自体について取り上げるのはこれが初めてとなります。
目次
Backlog で利用している EKS クラスター
Backlog で利用している EKS クラスターの運用について書くにあたり、 Backlog のサービス構成について簡単に紹介します。Backlog はプロジェクト管理ツールを提供するサービスとして Web でのアクセスと API でのアクセスを提供しています。サービスを外部から見るとそれぞれのアクセスを提供する各サービスが存在するように見えますが、近年の他サービスのアーキテクチャと同様に内部的には複数のアプリケーションとクラウドプロバイダーのマネージドサービスからサービス要素が構成されています。私達が扱っている EKS クラスターは各アプリケーションをホストするプラットフォームを構成しています。1 つのアプリケーションに対して、 1 つの EKS クラスタを用意しているのではなく複数のアプリケーション、あるいはテナント(サービスの提供単位)に対して EKS クラスターを利用してホストしており、1 つの EKS クラスタを使って Backlog 全体のサービスを提供しています。
検証としての開発環境と製品としてのプロダクション環境に EKS クラスターが 1 つずつ存在していて、これらを構成する要素は同じです。実質的には 1 つの EKS クラスターを利用してプラットフォームの開発運用を行っています。開発環境とプロダクション環境の EKS クラスターのアップデートは同時ではなく、開発環境で検証を行ってからプロダクション環境の EKS クラスターをアップデートしています。開発環境とプロダクション環境の EKS クラスターのアップデート手順は同じであるため、この記事ではそのアップデート手順にフォーカスして説明します。
アップデートするときのプランニング・調査
私達が EKS クラスターをアップデートするときにはいくつかの段階があります。ここではクラスターのアップデートに際して手を動かす前の段階について書いています。
プランニング
Amazon EKS のリリーススケジュールは Amazon EKS Kubernetes versions – Amazon EKS で公開されています。リリース予定のバージョンが追加され、リリース予定日が公開されたタイミングでプロジェクト化を行いアップデートの準備を始めます。
Kubernetes / Amazon EKS の変更点の確認
アップデートによる影響を確認し、アップデート時に支障となるポイントがあるかどうか、あればどのような対応を行うかを計画するために調査を行います。たとえば、Kubernetes バージョン 1.27 にアップデートするときには以下のページを見ています。
- kubernetes/CHANGELOG/CHANGELOG-1.27.md at master · kubernetes/kubernetes · GitHub
- Deprecated API Migration Guide
- Kubernetes 1.27 – What’s new? – New features and deprecations
新しく Beta 昇格した Feature Gates や、Deprecated API を確認し Issue に調査結果をまとめ、影響があれば調査対応チケットとして Issue を作成します。またアップデートで安定版の API がリリースされている場合、クラスターのアップデート後に忘れずに安定版の API に移行できるようにプロジェクトに紐づけた Issue を作成して、プロジェクトの完了条件に含めるようにします。
クラスターのアップデート前のミドルウェアのアップデート
eksctl を対応するバージョンにアップデートする
Backlog の EKS クラスターのプロビジョニングには GitHub – eksctl-io/eksctl: The official CLI for Amazon EKS を利用しています。EKS クラスターのアップデートには新しい EKS クラスターのバージョンをサポートした eksctl にアップデートする必要があります。EKS クラスターのバージョン変更点を確認するのと同様に eksctl についても変更点を確認した後にオペレーションに利用する eksctl のアップデートを行っています。
Helm Charts を対応するバージョンにアップデートする
EKS クラスターのアップデート前にはプラットフォームを構成するミドルウェアのアップデートを行います。Backlog で利用しているミドルウェアの一例を以下に書いています。
- AWS Load Balancer Controller
- Cluster Autoscaler
- Prometheus etc…
これらのミドルウェアは Helm を使ってデプロイしています。ミドルウェアは普段から可能な限り最新版を利用するようにアップデートを行っていますが、アップデートが追いついていないミドルウェアもあります。EKS クラスターのアップデート前にそれぞれの Helm Charts のバージョンを確認し、アップデートの必要があれば Issue を作成しチケット化します。
ミドルウェアにはサポートしている Kubernetes バージョンが表記されています。現在デプロイされている ミドルウェアがアップデート後の Kubernetes バージョンをサポートしていなければ、 Helm Charts のバージョンのアップデートを検討します。Helm Charts のアップデートの調査対応を行い、既存のクラスターでアップデートしても影響がなければ、既存のクラスターでアップデートします。クラスターのアップデートの前後でミドルウェアのバージョンの違いが発生しないようにすることで、クラスターアップデートのトラブル発生時に原因の切り分けにかかるコストを下げられます。
Blue-Green アップデート戦略
EKS クラスターのアップデートの具体的な手順の説明の前に、クラスターのアップデート手順の概要について説明します。
アップデートではインプレースで EKS クラスターをアップデートするのではなく、新しいバージョンの EKS クラスターを作成し、クラスター自体を移行することでアップデートを行っています。Kubernetes のリソースを古い EKS クラスターから新しい EKS クラスターに移行した後に、サービスにかかるトラフィックの向きを下図の実線から点線部分に向くように切り替えます。これによって EKS クラスターの Blue-Green デプロイを実現しています。
このアップデートの方法のメリットとして、サービスにかかるトラフィックの向きを新しいバージョンの EKS クラスターに切り替えた後に問題が発生したとき、古いクラスターにトラフィックの向きを戻すことで、安全にロールバックできます。一方でデメリットとして、一時的とはいえ新旧 2 つのクラスターを用意するために手順が複雑になることや、インフラ費用の増加があります。Backlog ではメリット・デメリットを比較検討した際にメリットの方が大きいと判断して、Blue-Green デプロイの方法を取っています。
新しい EKS クラスターの作成とセットアップ
新しいバージョンの EKS クラスターの作成には、古いクラスターを作成する際に使った eksctl の cluster.yaml
に新しいクラスターの情報を追記して作成します。こうすることで、クラスターの作成時に古いクラスターと同じ IRSA に基づいた Service Account が作成できます。EKS クラスターを作成後、クラスターのセットアップを行います。このセットアップは次のステップを含んでいます。
- namespace と RBAC ポリシーの作成
- AWS VPC CNI plugin の Security Groups for Pods の有効化
- Helm Charts(AWS Load Balancer Controller, Cluster Autoscaler, etc…)のデプロイ
セットアップのステップには EKS クラスターで利用するミドルウェアのデプロイを含んでいますが、 Backlog のサービスを提供するためのアプリケーションはデプロイされません。アプリケーションのデプロイは Velero を利用して古いクラスターから新しいクラスターにリソースを移行する形で行います。次のセクションで Velero を利用したリソースの移行について説明します。
Velero を使ったアプリケーションのセットアップ
ミドルウェアのデプロイと同じく、マニフェストをデプロイすることでアプリケーションを新しいクラスターにデプロイできますが、私達は古いクラスターから新しいクラスターにアプリケーションのリソースを移行することで、クラスターアップデート時のアプリケーションのデプロイを行っています。マニフェストを使ってアプリケーションをデプロイしないのは、古いクラスターのアプリケーションの Pod の台数が一時的に変更されている場合や計算リソースが変更されている場合といった、古いクラスターと新しいクラスターとで状態が一致しないケースが私達の運用では発生しうるためです。
Kubernetes リソースの移行には Velero を利用します。Velero はリソースのバックアップやバックアップからの回復での利用を想定したツールですが、リソースのバックアップと復元の機能をクラスター間のリソースの移行に利用できます。古いクラスターでのリソースのバックアップと新しいクラスターでのリソースの復元を実施することでリソースの移行ができ、古いクラスターから新しいクラスターにマイグレーションする準備ができます。また Velero はいくつかのリソースのマイグレーション機能を備えており、例えばリソースの復元時に Persitent Volume の Storage Class を変更できます。この機能は Persistent Volume の扱いに EBS CSI Driver を利用するようになった EKS 1.23 へのクラスターアップデート時に大変役立ちました。
Backlog で利用している EKS クラスターでは Velero でのリソースのバックアップ先、復元元として S3 バケットを利用しています。そのため、古い EKS クラスターと新しい EKS クラスターの両方の Velero から同じ S3 バケットを参照してリソースを移行しています。
私達の EKS クラスターにある Velero では定期的にバックアップを取得するように設定していますが、クラスターのアップデート時のリソースの移行の際には、最新状態のリソースで移行したいため古いクラスターで最初にバックアップを取得します。バックアップを取得するには Velero のクライアントを使って、バックアップを取得します。
velero --kubecontext blue.us-east-1.eksctl.io \ backup create all \ --wait \ --exclude-resources replicaset,pod \ --exclude-namespaces default,kube-system,logging,monitoring,velero --ttl 24h
新しい EKS クラスターにはセットアップ時に Velero がデプロイされています。新しいクラスターでのリソースの復元時には、バックアップ取得の際と同様に Velero のクライアントを使ってリソースを復元します。ただし、復元時にはただ復元するだけでなく、 Admission Webhook を考慮してカスタムリソースから復元します。例えば AWS VPC CNI プラグインが扱う SecurityGroupPolicy リソースを復元しなければ、 Security Groups for Pods の機能が Pod で利用できないため、以下のように先に SecurityGroupPolicy リソースを復元した後に、それと TargetGroupBinding と PersistentVolume を除くリソースを復元しています。
velero --kubecontext green.us-east-1.eksctl.io \ restore create \ --wait \ --include-resources securitygrouppolicies.vpcresources.k8s.aws \ --from-backup all velero --kubecontext green.us-east-1.eksctl.io \ restore create \ --wait \ --exclude-resources targetgroupbindings.elbv2.k8s.aws,securitygrouppolicies.vpcresources.k8s.aws \ --from-backup all --include-cluster-resources
ここで TargetGroupBinding リソースを復元しないようにしているのは TargetGroupBinding リソースをデプロイすることによって、ALB に対象の Pod が登録されてサービスリクエストを受け付けてしまわないようにするためです。
アプリケーションの Pod がすべて正常に作成され動作していることを確認できたら、新しいクラスターでのアプリケーションのセットアップは完了となります。サービスのトラフィックを受け入れる準備ができるようになり、クラスターアップデートの最後のステップに進むことができます。
TargetGroupBinding を利用したロードバランサーのターゲットの切り替え
新しい EKS クラスターにアプリケーションのリソースを復元し、Pod が問題なく作成できていることを確認できれば次はサービストラフィックを新しいクラスタで処理できるように切り替えます。
サービストラフィックの切り替えはロードバランサーのターゲットから古いクラスターの Pod を外し新しいクラスターの Pod に付け替えることで行います。ロードバランサーのターゲットの付け替えは EKS クラスターの AWS Load Balancer Controller の Reconcile 処理を利用します。
ロードバランサーのターゲットを切り替える前段階として古いクラスターから AWS Load Balancer Controller を削除します。古いクラスターの Pod がロードバランサーのターゲットに登録されていますが、古いクラスターから AWS Load Balancer Controller を削除しても、これらの Pod はターゲットから登録解除されません。一方、新しいクラスターでは AWS Load Balancer Controller が動作していますが、カスタムコントローラーが扱う Ingress リソースや TargetGroupBinding カスタムリソースは存在しないため、Reconcile 処理は発生しません。AWS Load Balancer Controller の Reconcile 処理を発生させて、ロードバランサーのターゲットに新しい Pod を登録するためには、 TargetGroupBinding リソースを新しいクラスターに作成します。TargetGroupBinding リソースが新しいクラスターに作成されると新しいクラスターの Pod がターゲットに登録され、同時に古いクラスターの Pod がターゲットから登録解除されます。このようにして、ロードバランサーのターゲットを付け替えることでサービストラフィックを古いクラスターから新しいクラスターに切り替えて、新しいクラスターでサービスを提供できるようになります。このときに注意していることとして、一時的にとはいえ、ロードバランサーのターゲットから Pod がすべて入れ替わるため、ユーザー影響の少ない時間を選んで作業を実施しています。また、ターゲットに新しいクラスターの Pod が登録されるまでに時間がかかるケースもあるため、ターゲットグループの重み付けをつかって Blue-Green デプロイすることを今後の課題として考えています。
ロードバランサーのターゲットを付け替えてサービストラフィックを新しい EKS クラスターに切り替えたときにトラブルでサービス提供ができていない場合は、サービストラフィックを古い EKS クラスターに切り替えることで、変更をロールバックします。サービストラフィックを新しい EKS クラスターに切り替えるときと同じく、切り替える元のクラスターにある AWS Load Balancer Controller を削除し、切り替える先のクラスターで AWS Load Balancer Controller をインストール後、 TargetGroupBinding リソースをデプロイする手順となります。
なお、サービス提供が安定していれば、アップデートを完了として、様子を見て古い EKS クラスターを削除して作業を完了とします。
まとめ
この記事では Backlog を支えるプラットフォームである Amazon EKS クラスターのアップデートについて書きました。EKS クラスターは Backlog を構成する複数のサービスをホストしており、重要な役割を持っています。アップデート前には慎重に調査を行い、アップデート時にはトラブル発生時に素早くロールバックするために Blue-Green アップデートの形をとっています。私達が行っている EKS クラスターの Blue-Green アップデートはこれまでのアップデートから改善を積み重ねて作り上げてきました。
このアップデートを進めるためには単純な技術スキル以外にプロジェクトを進めるプロジェクト管理、アップデートの変更点に対する調査対応、Velero や AWS Load Balancer Controller への精通、サービス開発チームとのやりとりといった様々なエンジニアリング能力が必要です。ヌーラボでは Amazon EKS クラスターを使ったプラットフォーム開発運用に関わるエンジニアを募集しています。この記事で書いたような技術に興味がある方からのご応募お待ちしています。
最後にこの記事を書くにあたって時間をいただいた松浦さん、安立さんに感謝いたします。
さて、明日はアドベントカレンダーもいよいよ最終日です。明日の記事の執筆は Yuichi Watanabe さんです。最後まで ヌーラボブログリレー2023 for Tech Advent Calendar 2023 – Adventar をよろしくお願いします!!