DMM.comの、一番深くておもしろいトコロ。

Amazon EKSの採用とAWS Well-Architected フレームワークの実践

Amazon EKSの採用とAWS Well-Architected フレームワークの実践

  • このエントリーをはてなブックマークに追加

はじめに

はじめまして。合同会社EXNOA プラットフォーム開発本部 プラットフォームインフラ部の角です。

当社では、昨年からEKSなどのモダンな技術スタックを導入してGAMESプラットフォーム事業の運用を行っています。

今回の投稿では、安定して効率良くシステムを運用させるために採用した技術スタックや、運用して見えてきた課題を紹介したいと思います。

目次は以下のとおりです。

 

1 . システム構成とEKSを採用した理由

 

f:id:dmmlabotech:20210507065340j:plain

 

構成の重要なポイントは以下のとおりです。

  • AWS + Cloudfront + EKS + Managed Database
  • すべてのアプリケーション, ミドルウェアをコンテナで実行 ※ Databaseへのログインやkubectlを実行するためのオペレーション用のサーバ等を除く
  • 構成管理にTerraform Cloud, ArgoCDを採用
  • モニタリングツールにDatadogを採用

アプリケーションのコンテナは以下の2種類で、一部のPodはEFSをマウントしています。

  • Nginx + PHP-FPM
  • Java

利用しているkubernetesのaddonは、以下のとおりです。

  • ArgoCD
  • Amazon EBS CSI ドライバー
  • Amazon EFS CSI ドライバー
  • AWS Node Termination Handler
  • Cluster Autoscaler
  • Datadog
  • Jenkins
  • mcrouter
  • Metrics Server
  • Nginx Ingress Controller
  • Prometheus Operator
  • RELOADER
  • Rabbit MQ
  • Sealed Secret

Databaseは、Aurora MySQL, DocumentDB, ElastiCache, Redshiftを利用しており、全般的にManagedサービスを採用しています。

Batchは、CronJobとJenkinsを利用して実行しています。

構成管理は、AWSのリソースをTerraformで、kubernetesのManifestをArgoCDで管理しています。

モニタリングは、Datadogを利用しており、一部のメトリクスの収集のみにPrometheusを利用しています。

なぜ、EKSを採用したのか?

主に3つの理由があります。

  • ベースイメージが同一で、動作させるプログラムが違うコンテナを10個以上デプロイする必要があったため
  • 金銭的なコスト効率の最適化のため
  • ただコンテナを運用するだけでなくKubernetesのエコシステムの恩恵を受けたかったため

EKSにはおよそ20 Deployment, 200 Podがデプロイされている状態で、アプリケーションの数は多くも少なくもないというのが現状です。

この数のアプリケーションを動かす必要があるということは、事前にほぼ決まっていました。

その時に、EC2, ECS, EKSのうちどれが一番効率的にアプリケーションをデプロイ・運用できるかを考えて、そこで出た答えがEKSでした。

個人的には、EC2, ECS, EKSどれもできることはほとんど変わらないと考えています。

ただし、アプリケーションの数が10を超えてくる場合、Terraform + Code3兄弟で構築運用するよりもAWSのリソースをTerraformで、Kubernetesの世界をArgoCDで管理したほうがリソースの管理をしやすいと考えました。

さらに、EKSを利用していることで、以下の要因による金銭的なコスト削減に繋がっています。

  • 開発、ステージング環境のコンテナを少ないEC2インスタンスに詰め込んで運用できる
  • Spotインスタンスが利用できる
  • Datadog Agentなどのホスト単位で課金される製品のAgent数の削減

ECSでも同じようなメリットがありますが、普通にEC2で運用するよりも大幅なコスト削減はできていると思います。

ECSと大きく違うところは、Kubernetesのエコシステムの恩恵を受けることができるということです。

利用しているkubernetesのaddonを見ていただければ分かるとおり、多くのaddonを利用しています。

Nginx Ingress, ArgoCD、Sealed Secretは、多くの企業でも導入されているaddonかと思います。

こういった、便利ですぐに利用できるaddonを活用することによってシステムの継続したグロースに繋がると考えEKSを採用しました。

 

2 . AWS Well-Architectedフレームワークを通して、安定運用させるために実践していることの紹介

AWS Well-Architectedとは?

AWS Well-Architected は、クラウドアーキテクトがアプリケーションやワークロード向けに高い安全性、性能、障害耐性、効率性を備えたインフラストラクチャを構築する際に役立ちます。AWS Well-Architected では、5 つの柱(優れた運用効率、セキュリティ、信頼性、パフォーマンス効率、コストの最適化)に基づいて、お客様とパートナーがアーキテクチャを評価し、時間と共に拡大できる設計を実装するための一貫したアプローチを提供しています。

https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/index.ja.html

ホワイトペーパーには、AWS上に構築されたシステムを安定的に運用するための原則とプラクティスがまとめられています。

ここからは、AWS Well-Architected フレームワークのなかで参考にしている5つのフレームワークの柱と原則のみをピックアップして、私たちの組織でどのように実践しているかを説明したいと思います。

運用上の優秀性

運用上の優秀性には、「運用をコードとして実行する」、「小規模かつ可逆的な変更を頻繁に行う」、「運用手順を定期的に改善する」、「障害を予想する」、「運⽤上のすべての障害から学ぶ」の5つの設計原則が挙げられています。

それぞれの原則について、私たちの組織では以下のとおりに実践しています。

  • AWSのリソースをHCL、kubernetesのmanifestをHelmのChart or yamlとしてGit管理
  • Terraform Cloud, ArgoCDによるGitopsの導入
  • 手動で実行していたオペレーションをTerraformやAnsible, CronJobを用いて自動化しつつ、障害対応手順を日々更新する
  • 障害の発生を前提にした設計とリリース前の障害テストの実施
  • ポストモーテムの作成と障害の振り返りの実施とDatadogのモニタリングダッシュボードの継続的な改善

運用上の優秀性を担保するために、「システムに疎外されていないか」ということ特に意識しています。

ここで言う「疎外」とは、哲学や経済学で使われる「人間が作った物(システム)が逆に人間を支配するような力として現れること」を意味します。

つまり、パフォーマンス向上や運用の負荷を減らすために導入したサービスやツールが、逆に運用の負荷を高めてしまっていないかを考えるということです。

以下の2つは、運用の負荷を軽くして、効率を高める要因になっています。

  • EKSやManged Databaseの利用
  • Terraform CloudやArgoCDでのGitOpsなどの比較的新しいサービスやツールの利用

EKSを利用しているおかげでkubernetesのバージョンアップに追従することができており、Terraform Cloud, ArgoCDのおかげで開発者が各環境へ新しいアプリケーションを素早くデプロイできるようにもなっています。

また、「継続的な改善」をするということも意識しています。

例えば、障害が発生した時には、必ずポストモーテムを作成して振り返りが実施されます。

そして、次に障害が起きた時に

  • 今回よりも早く障害を検知できるように
  • 今回よりも早く復旧できるように

するために、アラートの見直しやダッシュボードを更新し、手順を最適化することを行っています。

信頼性

信頼性には、「障害から自動復旧する」、「復旧手順をテストする」、「水平方向にスケールしてワークロード全体の可用性を高める」、「キャパシティを推測することをやめる」、「オートメーションで変更を管理する」の5つの設計原則が挙げられています。

それぞれ私たちの組織では、以下のとおりに実践しています。

  • Kubernetesのオートヒーリング、Aurora MySQLの自動フェイルオーバーの利用
  • リリース前の障害試験と復旧のテスト
  • KubernetesのHPA, Cluster Autoscalerによるオートスケーリング
  • オートスケーリングやRate Limitingの導入
  • Terraform CloudとArgoCDの利用

サービスの運用を開始してから、数回のAWSの障害を経験しました。

KubernetesのNodeの障害であれば、自動的にPodが別のWorker Nodeで起動されます。Aurora MySQLのPrimaryの障害であれば、自動的にフェイルオーバが実行されReplicaがPrimaryに昇格します。

障害時の手動で実行したオペレーションは、不安定なNodeのdrainやPodのterminate, Aurora MySQLのカスタムエンドポイントから障害が発生しているAZのレプリカを一時的に削除する作業のみでした。

システムを構成する各コンポーネントが自動復旧することで、障害時の復旧や確認作業を減らすことができ、ゆとりをもってエスカレーションやDatadogのダッシュボードで障害の影響を把握することができるようになります。

また、復旧だけでなくAWSやKubernetesのリソースの構成変更もTerraform CloudやArgoCDを利用して自動化しています。

 

f:id:dmmlabotech:20210507070015j:plain

 

 構成を変更する時は、

  • 必ず開発環境とSTG環境に変更が反映されてから本番環境に反映されるワークフロー
  • 変更を反映する時に、Datadogのダッシュボードでサービスのエラー率をモニタリングする

の2点で、安全に安心して、変更を適応できるようにしています。もしも、本番反映で障害が発生した場合は、エラー率の増加などのアラートが通知されてTerraformはGitのrevert, ArgoCDはrollbackの機能で即時に切り戻しできるようになっています。 

 

f:id:dmmlabotech:20210507070153j:plain
 

 

さらに、信頼性を担保するために、挑戦的なチャレンジと保守的な判断を組み合わせるということも行っています。

挑戦的なチャレンジの具体例は、Rabbit MQをkubernetes上にデプロイしていることです。現在は、Rabbit MQのManaged Serviceがリリースされましたが、設計段階では、EC2で構築するかkubernetes上にデプロイするかの二択でした。

以下のテストや設定によりkubernetes上に構築しても運用ができるという判断をして、kubernetes上にデプロイすることを決定しました。

  • rabbitmq-perf-test(Rabbit MQのパフォーマンス計測ツール)によるテスト
  • 1AZ 1NodeでのClustering, ha-mode=allによる可用性の担保
  • アプリケーションログからenqueue, dequeueエラーが検出された時に通知

現状、kubernetes上にデプロイしても安定運用できており、Savings Planを適応したWorker Nodeにデプロイしていることもあり、コストパフォーマンス良く運用できているというメリットも生まれています。

保守的な判断の具体例では、サービスメッシュの導入の見送りです。

サービスメッシュの機能で使いたいと思っていた機能、役割は以下の3つでした。

  • Rate Limiting
  • Distributed Tracing
  • Network Mapを含むObservability

この3つの機能のみであれば、Nginx Ingress ContollerとDatadog APM, Datadog Network Performance Monitoringの機能で実現可能です。

新しいコンポーネントが追加されることで、以下のデメリットが発生します。

  • アーキテクチャ全体が複雑になり、構成を理解する難易度が高くなる
  • AWSの料金と運用コストの増加

ここで重要なのは、上記のデメリットを組織やチームで受け入れることができるかどうかを見の極めです。置かれた状況に応じては、導入を見送る保守的な判断も信頼性を担保するために大切になると考えています。

 

パフォーマンス効率

パフォーマンス効率には、「最新テクノロジーの標準化」、「わすか数分でグローバル展開する」、「サーバーレスアーキテクチャを仕様する」、「より頻繁に実験する」、「システムに対する精通の程度を考慮する」の5つの設計原則が挙げられています。

私たちの組織では、以下のとおりに実践しています。

  • Managed Kubernetes, Managed Databaseの利用
  • フロントエンド, APIサーバの前段に、Cloudfrontを利用
  • ステージング、開発環境を本番同様の構成にして、本番環境と同じ条件で実験できる環境を用意
  • AWSのManaged ServiceやDatadog, Terraform Cloud, SendgridなどEnterprise製品の利用を選択

 

 

f:id:dmmlabotech:20210507070123j:plain

 


まず、以下の2つの要因による通信のアクセラレーションの効果の恩恵を受けることができるように、エンドユーザとの通信を全てCloudfrontを経由となるように設定しています。

  • Cloudfrontとオリジンサーバ間をAWS Global Networkで通信
  • TLSのハンドシェイクのレイテンシの低減

国内だけでなく、北米圏やアジア圏など大陸を横断して通信することもあるので、Cloudfrontによる通信の高速化はプラットフォームのパフォーマンス向上に大きく貢献しています。

 

f:id:dmmlabotech:20210507070420j:plain

 

 

また、パフォーマンス効率を高めるために、以下のフローを継続的に回しています。

  1. メトリクスをDatadogへ送信
  2. ダッシュボードを作成
  3. 日々の傾向を観察する
  4. ボトルネックの発見
  5. なにかしらのアクションを実行

例えば、PodのCPU, Memoryの使用率を追跡して、最適なRequest, Limitの値を設定し、Nodeの台数を最適化するなどです。

他にも、DatadogのNetwork Performance Monitoringを利用して、AZ同士、Node同士, Pod同士の通信を確認して、可能な限りトラフィックが最短ルートを通るように調整するなどもしています。

このような、小さな変更を何度も繰り返すことが多いので、ステージング、開発環境を本番同様の構成にして、本番環境と同じ条件で実験できる環境があることはとても大きなメリットになっています。

 

セキュリティ、コスト最適化

詳細な説明は割愛させていただきますが、AWS Well-Archetectedには、セキュリティとコスト最適化についても原則やプラクティスが説明されています。

私たちの組織でも以下のような対応をしています。

  • AWS WAFを利用した、エンドポイントプロテクション
  • ECRのイメージスキャンとDatadogのセキュリティモニタリングを組み合わせた脆弱性のあるコンテナの検知
  • AWS Config, Security Hubを利用した監査
  • EKSのworker nodeの一部にspotインスタンスを利用
  • キャパシティプランニングとSavings Planの適応

 

3 .運用して見えてきた課題

これまで、AWS Well-Architected フレームワークをどう実践しているか説明してきましたが、実践できていない部分も多くあり、いくつかの課題があります。

その課題のなかで、これから取り組んでいきたいことを3つ紹介します。

 

1つ目は、継続的なテストができるような状態にしたいということです。

小さな変更を繰り返し行った結果、以前まで正常に動作していたものが、いつの時点からか正常に動作しなくなるということも考えられます。

それが、サービスのエラー率などに顕著に現れるのであればすぐに気付くことができますが、オートスケーリング, オートヒーリング, Rate Limitingなどの何かしらのtriggerで実行されるものであればすぐに気付くことはできません。

そのため、定期的に任意の障害を起こしたり、負荷を掛けたりして小さな変更を繰り返し行っても、正しくすべての機能が動作することを保証できるようにしていきたいと考えています。

 

2つ目は、開発組織やサービスのスケールに柔軟に対応できるようにしたいということです。

kubernetesにアプリケーションをデプロイしたい時や新規のDatabaseが必要な時は、HelmのChartのテンプレートやTerraform Moduleが用意されており、すぐにプロビジョニング可能な状態になっています。

ただし、コンテナがrootユーザ以外の権限で実行されているかどうか、topologySpreadConstraintsが正しく設定されているかどうかといったサービスの監査や最適化のタスクは効率良く行えるようになっておらず改善の余地があります。

組織やサービス数がスケールしても監査や最適化のタスクを少ない労力で行うべく、この点についても試行錯誤しています。

 

最後は、Kubernetesのさらなる有効活用です。

ECSではなく、EKSを選択した理由の1つに、ただコンテナを運用するだけでなくKubernetesのエコシステムの恩恵を受けたいという点がありました。

現状でも、Rabbit MQのデプロイやArgoCD, Spotインスタンスの利用などですでにKubernetesの恩恵を受けることができていますが、さらなる活用を目指しています。

例えば、RedisをEKS上にデプロイすることです。Redisを利用したい場合は、運用が比較的容易なElastiCacheを選択する場合が多いです。

EKS上にデプロイすることで、Worker Nodeで余っているMemoryを有効活用することができ、さらにインスタンスに適応しているSavings Planの恩恵を受けて金銭的なコスト削減にも繋がります。

 

4 .最後に

私自身、1つのシステムについて構築からリリース、運用、グロースまで一貫して携わるのは、今回が初めての経験でした。

AWSやKubernetesなどのモダンな技術スタックを利用できたことは、エンジニアとしてとても楽しくやりがいを感じられるものです。

一方で、初めて採用する技術スタックも多く、安定運用させられるかどうか不安な部分もありましたが、この記事で紹介した取り組みや工夫をすることで不安が自信に変わりつつあります。

今後もより信頼性の高いシステムにするために、運用して見えてきた課題に対して継続的な改善を行っていく予定です。

そんな、GAMESプラットフォームの安定運用やグロースに携わるインフラエンジニアを、只今EXNOA プラットフォームインフラ部では、募集しています。

ご興味のある方は下記の募集要項をご覧のうえ、ぜひご応募ください。

https://dmmgames.co.jp/recruit/entry/job/id=267