🔮

AWS App Meshを導入してみた

2024/09/12に公開

はじめに

こんにちは。株式会社トリドリでバックエンドエンジニアをしている向井です。

社内の新規プロジェクトで、既存ECS環境へのAWS App Meshの導入を行ないました。

今回はApp Meshをこれから導入しようか検討する方向けに、サービスメッシュ導入の意義とクロスアカウント環境での導入方法について記事に残します。

実装の詳細は省略しているため、気兼ねなくコメントいただけると幸いです!

 

👇 AWSの公式で記載されているApp Mesh(正式名称はAWS App Mesh)の定義はこちらです 👇

AWS App Mesh は、サービスのモニタリングとコントロールを容易にするサービスメッシュです。サービスメッシュは、サービス間通信の処理専用のインフラストラクチャレイヤーであり、通常、アプリケーションコードと一緒にデプロイされる一連の軽量ネットワークプロキシを介して行われます

https://docs.aws.amazon.com/ja_jp/app-mesh/latest/userguide/what-is-app-mesh.html

「AWS App Mesh は、サービスのモニタリングとコントロールを容易にするサービスメッシュ」

🙄

サービスメッシュとは何者でしょうか?

マイクロサービスアーキテクチャの話の中でよく出てくる「サービスメッシュ」ですが、そもそもなんで必要なのかを考察してみます。

サービスメッシュとは

近年、モノリシックアーキテクチャからマイクロサービスアーキテクチャを採用する会社が増えているように思います。

ここでは、マイクロサービスアーキテクチャに関しては詳しくは触れませんが、各サービスの独立性が高くなり、大規模な開発チームがより俊敏になり、多くのデプロイを実現できること大きなメリットです。一方で、マイクロサービスアーキテクチャ特有の課題も生じます。

マイクロサービス化によって発生する問題の多くは、ネットワーク由来の課題が多いです。
発生するネットワーク課題として以下が主に挙げられると思います。

  • トラフィック管理

    • サービス検出
    • スロットリング
       ...
       
  • 可観測性(オブザーバビリティ)

    • モニタリング
    • ロギング
    • トレーシング
       
  • セキュリティ

    • サービス間認可
       ...
       

この課題に対して、解決する手段として各言語のライブラリを用いて実装することは可能ではあります。例えば、Typescriptを使ったサービスで、トラフィック管理のスロットリングを実装したいとなった時に、bottleneckなどのライブラリを利用して実装するなどです。

多きときには100を超えるマイクロサービスアーキテクチャに対して、各サービス個別に導入することは大変です。
仮に導入を終えられたとしても、例えばスロットリング機能の更新、可観測性、セキュリティなど、導入後もサービス個別に保守を行うこととなります。

本来はマイクロサービスは他のサービスの実装に依存するべきではないのです。
そこで、全てのマイクロサービス間の通信で、統一した仕組みを各アプリケーションに実装せずに実現したいと言う考えが出てきます。

これを解決するのがサービスメッシュです。

サービスメッシュのアーキテクチャは2つのコンポーネントに分かれます。

データプレーン

実際のサービス間の通信を処理するプロキシです。

AWS App Meshでは、プロキシはオープンソースであるEnvoyを利用していて、このプロキシ内で前述した課題解決の機能を提供しています。

通常は、各アプリケーションのサイドカーとしてデプロイされます。

今回だと、ECSと同一のホスト上で動作し、サービス間の通信をインターセプトして管理します。アプリケーション側は一切App MeshやEnvoy Proxyについて意識する必要がありません。

コントロールプレーン

サイドカーとしてデプロイされているデータプレーンを管理・制御するのがコントロールプレーンである。AWSサービスとしてのApp Meshは、このコントロープレーンを提供しています。

 

App Meshを構成するコンポーネントについて

App Meshには以下の主要なコンポーネントが存在します。

  • 仮想サービス

    サービスメッシュ内での論理的なサービスエンドポイントを表現します。

    リクエストをどの仮想ノード、仮想ルーターにルーティングするかを定義します。

     

  • 仮想ノード

    特定の物理リソースへの論理的ポインタを表現します。

    今回のECSを利用した構成では、物理リソースはECSサービスが該当します。

     

  • 仮想ルーター

    トラフィックのルーティングルールを管理します。

    App Mesh内のロードバランサー的な立ち位置。

    仮想ノードの分散トラフィックにより、カナリーデプロイやBlue/Green Deploymentが実現可能。

     

  • 仮想ゲートウェイ

    外部トラフィックをサービスメッシュに導入するエントリーポイント。

仮想という名前がついているのは、これらのコンポーネントがEC2やLambdaなどの物理的(実際にアプリケーションコードが実行される)なリソースではなく、論理的な抽象化を提供するためです。抽象化により、App Meshは物理的なリソースに依存せずに、サービス間の通信の管理を行うことができます。

 

App Meshを導入したインフラ構成

App Meshを利用した背景には、新たなプロジェクトとしてインターナルサービスを既存サービスに提供する機会が生まれたことがあります。インターナルサービスの提供だけであれば、ロードバランサーを使用して実現することも可能です。しかし、弊社はAWSアカウントをマルチアカウントで運用しているため、クロスアカウント環境での提供が可能なApp Meshを利用する構成にしました。


クロスアカウントでのApp Mesh導入

上記インフラの実装手順ですが、ECSへのApp Mesh導入実装に関しては以下のユーザーガイドで細かく書かれていますのでこちらを参照してください。
https://docs.aws.amazon.com/ja_jp/app-mesh/latest/userguide/getting-started-ecs.html#update-services

  1. Meshリソースのクロスアカウントでの共有

    App MeshはResource Access Mangerの対応リソースとなっているため、こちらを使ってアカウント間でメッシュを参照できる状態にしましょう。

    RAMについて

     

  2. VPCピアリング接続

    以下手順に従って、接続元のアカウントVPCと接続先のVPC間のネットワーク接続を有効化しましょう。

    手順はこちら

     

  3. Cloudmapで生成されたホストゾーンのクロスアカウントでの共有

    ECSサービスのサービス検出にCloudmapを利用する場合は、ECSサービスに紐づけただけでは接続元のアカウントからは接続ができない状況です。以下のCLIを実行して接続元のVPCとホストゾーンを共有します。

    CloudMapの共有についてはこちら

 

導入時にハマったこと

DBに接続できない

App Meshを設定したことにより、Envoyプロキシを全ての通信が通過するようになります。このEnvoyプロキシがTCP通信を全て遮断するため、DB接続や、外部ツールなどのプロキシを経由したくないトラフィックは明示的に指定する必要があります。

EgressIgnoredPortsで指定可能です。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-proxyconfiguration.html

コンテナが起動しない

Mesh導入前のCPU/メモリ利用料が上限に近かったためでした。

今回、サービスメッシュ導入のために各アプリケーションコンテナのサイドカーとしてそれぞれEnovyコンテナを1つ、トレーシング用のエージェントコンテナとしてXrayデーモンコンテナを1つ接続対象のECSタスクに増やしました。

弊社では元々1タスク1コンテナの運用を行っていたため、今回の複数コンテナへの運用に変更する際にコンテナに割り当てるリソーススペックが従来よりも多く必要でした。特にEnvoyコンテナに512CPUユニットであることはサーバースペックを見直す必要がありました。また、トラフィックが多くなった時のインスタンスのリソースが足りなくなることが、移行時にはあり得るため今後も導入時には気をつけたいです。

EC2のENI制限に引っかかった

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/container-instance-eni.html

App Mesh利用時に、ECSのネットワークモードにはawsvpcモードを選択する必要がありました。ドキュメントに記載の通り、awsvpcネットワークモードを使用するECSタスクはそれぞれENIが割り当てられます。弊社ではコンテナインスタンス上に複数タスクを配置する設定にしているため、このENIの制限は移行時に厳しいものがありました。弊社のほとんどのインスタンスタイプは汎用系(t3.medium)であり、ENIの最大数は3つです。EC2のままでも、ENIトランキングにより制限の引き上げは可能ですが影響範囲などのメリデメを踏まえて、ENIの割り当て数を考慮する必要のないFargateに変更をしました。

 

まとめ

弊社のようにAWSサービスで統一されている環境で、サービスメッシュを導入するとなるとApp Meshを最初に利用することになると思います。

サービスメッシュとしてデファクトスタンダードなIstioのような豊富な機能が備わっているわけではないですが、AWSとシームレスに統合でき、X-Rayと統合することで可観測性の向上がシンプルに実装できるという点でサービスメッシュのスモールスタートとしては選択して良いサービスだと思いました。

今回は基本的な導入の説明を行いましたが、App Meshを利用したカナリーデプロイやブルーグリーンデプロイの実現もできるので、是非気になった方は調べてみてください!

https://aws.amazon.com/jp/blogs/news/create-a-pipeline-with-canary-deployments-for-amazon-ecs-using-aws-app-mesh/

 

App Meshの導入にてサービス間通信のトレース用にAWS Xrayを導入してみましたが、次回はサービス間だけでなくアプリケーションのトレースもAWS Xrayに統合し、監視基盤の作成まで行ってみたいと思います。

以上、ここまで読んでくださりありがとうございました😽

開発部の紹介

株式会社トリドリのプロダクト開発部では通年採用を実施しています!

ユーザの幸せについて真剣に議論したり、「やってみたい」で新しい技術に挑戦をしてみたり、気づいたら30分雑談していたり、ゆるく真面目に開発しています。もし興味を持ってもらえたら、こちらを読んでみてください!

https://toridori.notion.site/toridori-7e9c804bcfc249d6a932cdb99b83e1f6

toridori tech blog

Discussion