【AWS】マイクロサービスを支える２つのサービス(AWS Cloud Map編)

## はじめに
システム設計のスタンダートとも言えるマイクロサービス。  
AWSでマイクロサービスといえば「Fargate」「Lambda」などが最初に思いつくかと思います。  
本記事ではマイクロサービスアーキテクチャ構成に当たって、  
重要な役割を持ち、縁の下ので支えてくれている「AWS Cloud Map」「AWS App Mesh」についてまとめた記事になります。

## 「Cloud Map」と「App Mesh」が解決できるマイクロサービスの課題

### 【課題①：動的にスケールされるリソースの特定】
各チームがデプロイ/スケールアウトしたりとコンテナ情報は動的にスケールされるため、
IPなどのサービス情報をサービス間で自動登録できない。
　⇒名前解決用ALBが必要なためALB管理/運用/Route53エイリアスレコードなどコスト増
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/49150e95-ddae-249a-382f-65ea561fa258.png)



### 【課題②：サービス間のヘルスチェック】
マイクロサービスを実現すると、サービス障害発生時に個々のサービスがダウンする。
そのため呼び出される側のサービスが生きているか個々のサービスが確認する必要がある。
　⇒実装の手間増加/個々のサービスにける通信量の増加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/5a698d4d-9915-09b1-77f1-4b991ac9dd95.png)

 
上記課題①②の解決手段が「サービスレジストリ/ディスカバリ」こと**Cloud Map**

### 【課題③：サービス間通信の信頼性の確保-Reliability】
ネットワーク状況/対向サービスの不具合(クラッシュなど)による失敗を想定して防御的実装が必要

<サービス間通信の信頼性を高めるために最低限必要な機能一覧>
1. 一時的な呼び出し失敗
　→リトライ機能の実装
2. 継続した呼び出しの失敗
　→サーキットブレーカー(何度呼び出しても失敗する場合、対向システム復旧まで呼び出し停止)
3. 呼び出し先サービスのパフォーマンス低下
　→タイムアウト(ユーザへの想定レスポンスタイムを守るため)
4. 呼び出し元システムの不具合
　→スロットリング(呼び出し元の実装誤りによって無限にリクエストを受ける可能性があるため)
5. 暗号化通信の実装
　→プロトコル制御、TLS暗号化、ACM(AWS Certificate Manager)と統合
### 【課題④：サービス間通信の可観測性-Observebility】
各チームにおいて「ログ/メトリクス/トレース情報」の取得を行っているが、出力形式などが不揃いだと一貫した調査が行えない。技術レベルの違い、追加設定などを考慮すると個々の設定は困難。つまり、各アプリ個別実装の場合は、全体の観測が困難となってしまう。

上記課題③④の解決手段が「サービスメッシュ」こと**App Mesh**

## Cloud Map

### 一言でいうと
サービスが他の動的に変更される正常なサービスを見つけるためのサービス。
　⇒アプリケーションのリソースに論理名をマッピングできるマネージドサービス　
 
## Cloud Mapの機能まとめ
Cloud Mapでは以下機能が使用でき、
動的に変更される正常なサービスを発見することが可能になる。

- 名前解決
	- 動的に変化するリソースの更新管理や、リソースの最新の場所を常に検出することを可能とする
	- IPアドレスがないAWSリソース（Lambda,SQSなど）へのアクセスも管理することができる
- ヘルスチェック
	- Route53のヘルスチェックを利用し、正常なエンドポイントのみが返されるようにする
	- Cloud Mapには正常なリソースの最新レジストリが常にあるようになる
- 属性ベースの検出
	- 属性情報を付与し、特定のリソースを開発環境にのみ限定するなども可能
	- 以下コマンドの通り、Cloudmap側で設定した環境識別子を限定してコマンド実行することで環境単位でのアクションが可能となる
```
aws servicediscovery discover-instances ~~~ --query-parameters env=prod(※環境識別子)
```

- AWSクラウドサービスと統合
	- ECSなど統合されているサービスを利用する場合、ECS構築時に数項目有効化するだけで自動生成

## Cloud Mapの構成要素

### サービスレジストリ
- サービス情報の登録場所
    - コンテナ/インスタンスなどサービスの起動時に起動したサービス情報を登録しておける

### サービスディスカバリ
- 動的に変更されるサービス情報の取得
    - 個々のサービスの生死を管理でき、動的な設定値も検出してくれる。
　    ※動的スケールされ自動的にIPを付与するコンテナのIPアドレスも検出できる

## 利用イメージ
ECS上に起動するコンテナ間通信をCloud Map経由で行う場合のイメージは以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/34d01b01-c754-c786-de45-9c14c3146502.png)

## 利用イメージを簡略化し構築したみた

■作成構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/cd93eac1-57c2-bcac-a82e-9a0c8f882563.png)

### 前提：Cloud Map利用にあたって抑えるべき用語
- Name Space
    - サービスの論理グループ
    - サービスの呼び出し方法(API?DNS?パブリックDNS?)
- サービス
    - サービスインスタンスを登録するためのテンプレート
        - DNSを使用する場合のルーティング設定
        - ヘルスチェック設定
- サービスインスタンス
    - 実際に稼働するリソース情報(IPアドレスなど)
    - ECSはサービス統合されているため、自動的に登録される

### 1.Cloud Map/Route53作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/e38b8687-f98f-0e4b-06d2-15205a7c623d.png)

#### 1-1.名前空間を作成
「AWSコンソールよりCloud map」-「名前空間」-「名前空間の作成」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/68ba5f69-972a-06e2-f545-1b1f4492411c.png)
名前空間名：任意の名称を設定
インスタンスの検出：Cloud mapに登録したサービスの呼び出し方式を選択
　⇒「API呼び出しとVPCのDNSクエリ」を選択

##### 補足：Cloud Mapのサービス呼び出し方法について
- API
    - IPアドレスが付与されないサービスに対しARNなどでアクセスするリソースに対して付与
    - 任意の属性(環境識別子など)でクエリ、および値の取得が可能
    - APIコールをPythonSDKなどに含めることで、コンテナの起動時などに情報登録/入手が可能
    - 主な対象サービス：Lambda、DynamoDB、SQS
- DNSクエリ
    - IPアドレスでアクセスできるリソースに対して付与
    - A,AAAA,SRV,CNAMEに対応
    - 主な対象サービス：EC2、ECS、RDS
    - 外部からDNS名を参照しクエリを受けたい場合は「公開DNSクエリ」を選択

#### 1-2.サービス作成
「名前空間」-「①で作成した名前空間を選択」-「サービスの作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/eff93c65-7ed8-6ff2-c263-33c916a2530d.png)
DNSの設定：Route53ホストゾーンに対してCloudmapが検出する動的情報の登録方式を選択
 ⇒今回はデフォルト設定
ヘルスチェックの設定：「ヘルスチェックなし」を選択

##### 補足
- カスタムヘルスチェック
    - プライベート空間でのヘルスチェックはこちらを設定
    - サードパーティのヘルスチェックを使用するよう設定可能だが、ヘルスチェッカーもインスタンスと同一VPC上に存在させる必要がある。

- Route 53 ヘルスチェックはプライベート DNS 名前空間では使用不可
    - パブリック DNS 名前空間の場合にのみ、AWS Cloud Map構築時に自動作成される Route 53 レコードにそのヘルスチェックを関連付けることが可能
    - ヘルスチェックの正常判断はRoute53コンソール上で確認、もしくはCloudwatch連携によるモニタリング設定

#### 1-3.Route53の確認
Route53のCloudmap用ホストゾーンはCloudmap設定後に自動構築される
「AWSコンソールよりCloud map」-「名前空間」-「名前空間の作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/2406f93e-36e4-3568-cf68-413a9b6c227e.png)

#### 1-4.作成したCloud mapのリソース情報確認
■名前空間
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/89d3a125-ec08-5397-10a8-b6df885bed76.png)

■サービス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/3ee9ffb4-d1d0-e6a3-9df2-e85e48545d9d.png)

### 2.ECSの作成と自動登録されたAレコードの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/76b157aa-e51e-ad59-ba5c-a77657febaa3.png)


※基本的には以下リンクを参考に作成
[Amazon ECS リソースを作成する](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/create-service-discovery.html#create-service-discovery-cluster)


#### 2-1.ECSクラスタの作成
「AWSコンソールよりECS」-「クラスター」-「クラスターの作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/c2cfb420-2b55-8022-8cd0-d2dc525054da.png)

#### 2-2.タスク定義の作成
「AWSコンソールよりECS」-「タスク定義」-「新しいタスク定義の作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/9354a11b-5636-7e29-8f2a-fe4dea305085.png)


#### 2-3.ECSサービスの作成
「AWSコンソールよりECS」-「クラスター」-「2-1で作成したクラスター選択」-「サービス作成」
以下項目にて「1.Cloud Map/Route53作成」で構築したサービスを設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/13855870-9dd3-e681-d704-c65d3032a024.png)

#### 2-4.Route53(Aレコード)への自動登録を確認
2-3.ECSサービスの作成よりCloudmapと関連付けを行っているため、自動的にCloudmapがRoute53へ動的情報を登録してくれている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/d348a3c4-099c-f09d-94f8-6aa55e17a326.png)

#### 3.踏み台サーバから接続、動的リソースの名前解決を確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/e1667f87-3ee3-2264-6e1b-10029a9393f8.png)

#### 3-1.DNSに向けて踏み台サーバから接続確認
接続に成功し、でもページの表示を確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/5f5782ee-fd24-8434-89f7-37a88073b9e4.png)

#### 3-2.タスク定義を変更しコンテナを再デプロイ
タスク定義の更新
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/c539fbed-6838-6a65-afe8-2fd54485ff76.png)

サービスの更新
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/f21b7078-f421-ec2d-a171-ae1a531826c6.png)

#### 3-3.コンテナ再デプロイ後のCloudmap状況確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/4773b92b-b13e-b2d3-8ee2-cca11444ce98.png)

#### 3-4.再デプロイ後に再度踏み台サーバから接続確認
再デプロイにより表示が変更されていることを確認できたため、
自動的に接続先が再デプロイした生きているコンテナに向いていると確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/28b40929-fa01-a5a9-84cd-b4772c01708c.png)

## 終わりに
今回は「AWS Cloud Map」について機能説明と実機を用いたデモを行ってみました。
次回は「AWS App Mesh」についての説明記事を記載したく思います。