プラットフォームチームでSREをしている id:masayosu です。 プラットフォームチームでは、はてなのサービスの基盤となるサービスを開発・運用しています。 さらに、はてラボ(はてなアンテナ、はてな匿名ダイアリーなど)も担当しています。
これらはAmazon EKS(Elastic Kubernetes Service)というマネージドコンテナサービス上で、マルチテナントなクラスタとして運用されています。 EKSは2年前から運用を始め、現在は30近いサービスがクラスタ上で動作しています。
この記事ではEKS周辺の構成と、EKSを維持する運用について紹介します。
EKSクラスタの全体構成
EKS全体の構成は、以下の図のようになっています。
図の登場人物について簡単に説明します。
- AWS EKS
-
AWSのAmazon EKSは、マネージドなKubernetesサービスです。
Kubernetesの知見を社内に蓄積することを目的として、2020年から運用しています。
もともとAmazon EC2上で動作していたサービスが多く、データベース等でもAWSのマネージドサービスを利用していました。 そのため継続してAWS上で動作するように、アプリケーションをコンテナ化してEKSに移行しました。 - Spot Ocean
- Spotが提供するOceanは、Kubernetesのノードを管理してくれる有料サービスです。 ポッドのスケジューリング状況とクラスタの制約を考慮しながら最適にスポットインスタンスを利用してノードをスケールしてくれます。 コストやリソースを管理できるダッシュボード機能もあり、ノードの状態を俯瞰して管理できる便利なツールです。 スポットの詳細は後述します。
- Argo CD
-
Argo CDは、GitOpsと相性の良いプル型のCD(継続的デリバリー)ツールです。
不足している機能もArgoファミリーのツールとして提供されているため、拡張性もあります。
Kubernetesのリソースの状態やポッドのログをほぼリアルタイムに見ることができるため、簡易的な調査をする際に役立ちます。
Kubernetes上で動作するため構築が容易で、利用方法もシンプルで扱いやすいため、継続して利用しています。 これも詳細は後述します。 - CDKリポジトリ(cdk repo)
- EKSは、AWS CDK(クラウド開発キット)でコード管理しています。 後述のようにクラスタをバージョンアップするたびに新規作成しており、コード化によって構築コストを下げることができます。 TypeScriptで記述しているためアプリケーションエンジニアにも取っ付きやすく、構成の把握に役立っています。
- Manifestリポジトリ(manifest repo)
- 各サービスのManifestが集約されたリポジトリです。 アプリケーションとManifestのリポジトリを別にして、CIとCDの役割を明示的に分割することで、デプロイフローをシンプルに保つことができるといったメリットがあります。
この構成の特徴的な部分についてもう少し詳しく説明していきます。
ノード管理とスケーリング
クラスタのノード管理には、前述のようにSpotのOceanを利用しています。 利用したいマシンタイプをあらかじめ選択しておくことで、自動でスポットインスタンスを立ち上げてくれます。
ノードのリソースが不足してポッドのスケジューリングが失敗したことを検知すると、自動でスケーリングしてくれます。 Oceanには、ノードに余剰リソースを確保しておくHeadroomという機能があり、ノードに余裕をもたせることができるので、安全にスケールすることができます。
また、ノード管理以外の機能も豊富で、さまざまなダッシュボードが備わっています。 ダッシュボードでは、スポットインスタンスとオンデマンドインスタンスの台数の遷移を確認でき、不要なオンデマンドインスタンスが立ち上がって余計なコストが発生していないかを確認することができます。
さらにOceanのダッシュボードで得たVPA(Vertical Pod Autoscaling)の推奨値をポッドのリクエスト値に適用することで、コストを最適化する運用も行っています。
最近は、EKSのマネージド型ノードグループ(managed node group)でもスポットインスタンスが対応しているということや、スケーリングについてもKarpenterといった高性能なオートスケーラーがリリースされているため、その利用も検討しています。
デプロイの自動化
CIにはGitHub Actionsを、CDには前述のようにArgo CDを利用しています。
各アプリケーションのリポジトリとは別に、前述のようにKubernetesのManifestファイルを1つのリポジトリで管理してしています。 これは、Argo CDのベストプラクティスに倣ったものです。
▶ 5 GitOps Best Practices. by Alex Collins | Argo Project
Manifestに更新があるとArgo CDが検知して、EKSクラスタにデプロイを実施します。 デプロイのフローは、以下の図のようになります。
- エンジニアが、アプリケーション用リポジトリにプルリクエストを作成
- プルリクエストをレビューしてマージ
- GitHub Actionsで、イメージのビルド&プッシュを行い、Manifest内のイメージタグを書き換えたプルリクエストをManifestリポジトリに作成
- リリースしたいタイミングで、エンジニアがプルリクエストをマージ
- Argo CDがManifestリポジトリの変更を検知して、EKSにデプロイを実施
エンジニアが行う作業はGitHubの操作のみなので、リリース作業の負担がかなり軽減されています。
EKSを維持する
ここからはEKSを維持するためにやっていることを紹介します。
クラスタのバージョンアップ
Kubernetesクラスタを運用していると、必ず直面するのがクラスタのバージョンアップ作業です。 私たちはこれにBlue-Green方式を採用しています。
ざっくりとした流れは以下の通りです。
- AWS CDKを用いて新バージョンのクラスタを構築
- Argo CDに新クラスタ用のデプロイ設定を追加
- アプリケーションのデプロイ&確認
- エンドポイントの切り替えを実施して、リクエストを新クラスタに向ける
Blue-Green方式を採用している理由として、できるだけバージョンアップによるリスクを緩和したいことがあります。 インプレース方式のアップデートは不可逆のため、問題が発生した際に切り戻すことができません。
また、チームの限られたリソースでKubernetesのアップデート間隔についていくことも難しく、アップデートを見送るバージョンも出てきます。 インプレース方式では1バージョンずつのアップデートのみに対応しているため、複数バージョンを一気に上げる運用をしたい私たちのチームには、Blue-Green方式が合っています。
Manifestのテスト
Polarisを導入して、Manifestのテストを行っています。 このツールでは、Manifestの内容がKubernetesのベストプラクティスに沿っているかをチェックできます。
またベストプラクティスの他に、カスタムチェックも設定できます。 例えば「Docker Hubからのイメージのpullは、rate limitがあるため禁止したい」といった場合に、イメージを取得可能なレジストリを許可リスト/拒否リストで制御できます。
Polarisでは、以下のような2種類の動作方法を選択することができます。
- CLIで実行可能のため、CIによってテストのワークフローに組み込む
- Kubernetesのクラスタでadmission controllerとして起動し、デプロイされたMinifestの内容をチェックする
どちらの手段も同じ設定ファイルで動作可能なため、動作方法の変更が容易であり、チームの運用に適した方法を柔軟に選択することが可能です。
まとめ
プラットフォームチームが利用しているAmazon EKSの構成と運用において、特徴的なことを紹介しました。 運用においては、紹介した以外にも必要なことが数多くあります。 チームに合った運用方法を検討し続け、それに見合ったサービスやツールを選定していくことで、より良いKubernetesクラスターを維持していけると思います。
はてなでは、Kubernetesに興味のあるエンジニアを募集しています。 良い運用方法を議論して、一緒に作っていきましょう!
id:masayosu
前澤 正宜(まえざわ・まさよし)。2020年7月入社時よりプラットフォームチームでSREを務める。
Twitter: @masayosu
GitHub: mmasayosu
blog: masayosu’s blog