詳細解説「AWS Cloud Map」とは #reinvent
先日のre:Invent2018で突如発表された「AWS Cloud Map」。皆さん、お使いでしょうか?
NEW:サービスディスカバリのためのAWS Cloud Mapとのアプリケーション統合
一言でいうと「クラウドリソースのサービスディスカバリ」なのですが、結構とっつきにくい概念なので、実際のところその使い所がよくわかんないという方も多いかと思います。
この記事では「AWS Cloud Map」をその概念から基本的な機能までを一通り解説することで、雲のようなこの新サービスを、使い所含めて理解してもらうことを目的としています。
マイクロサービス時代を見すえたクラウドネイティブなサービスディスカバリ、「AWS Cloud Map」ぜひともご堪能いただければと思います。
AWS Cloud Mapきたか…!! ( ゚д゚) ガタッ / ヾ __L| / ̄ ̄ ̄/_ \/ /
「AWS Cloud Map」とは
Cloud Map - Service discovery for cloud resources
一言でいうと「クラウドリソースに任意の名前をつけて、簡単かつ迅速にみつけるための仕組み」です。
このサービスが誕生した背景のキーワードを理解するのにイメージしやすいのが、「マイクロサービス」。従来のモノリシックなアプリケーションであれば、EC2とRDSのセットだけ管理しておけばよかったのですが、現在は、それ以外にも様々なサービスを組合せて使うことが当たり前。
- 動的にスケールするリソース
- ECS、EKSのコンテナ
- 様々なクラウドリソース
- Lambda、DynamoDB、SQS、Kinesis、S3
- あらゆる環境
- 開発〜ステージング〜プロダクション
- デプロイ環境(Blue/Green環境)
そんな多種多様なインフラを前提に構成されるマイクロサービスにおいて、それぞれのサービス間連携を簡単にする仕組みとして誕生したのが「AWS Cloud Map」といえます。
AWS Cloud Mapでできること
あらかじめ設定した自分の好きな名前で、あらゆるAWSリソースに対してアクセスできます。
例えばロードバランサーを作成した時はそのDNS名がAWSから払い出され、そのDNS名を利用してアクセスしていたかと思います。これが、Cloud Mapを利用すると、IPアドレスがないAWSリソース(LambdaとかSQSとか)へのアクセスも管理できてしまいます。
AWS Cloud Mapへの問い合わせ方式
Cloud Mapへの問い合わせ方式は、2種類。
- DNSクエリ
- IPアドレスでアクセスできるリソースに対して付与
- A,AAAA,SRV,CNAMEに対応
- 適用例)EC2、RDS
- APIコール
- AWSのARN(Amazon Resource Name)などでアクセスするリソースに対して付与
- あらかじめ付与した任意の属性でクエリ、および値の取得が可能
- 適用例)Lambda、DynamoDB、SQS、Kinesisなどなど
これらを使い分けて設定していきます。
AWS Cloud Mapで設定が必要なリソース
具体的に、Cloud Mapを利用していくにあたって必要な設定リソースは、以下の3つ。これらを上から順番に作成していくことで、Cloud Mapが機能します。
- 名前空間
- サービス
- サービスインスタンス
AWS Cloud Mapの全体像
Cloud Mapですが、名前空間の作成方法により利用できる機能がそれぞれ異なるので、まずは全体を整理した表を共有しておきます。この記事最後まで読んだ後に、こちらに戻ってきてもらえれば理解が深まりますよ。
名前空間種類 | インスタンスの検出方法 | Route 53のHosted Zone作成 | 利用可能なヘルスチェック |
---|---|---|---|
API呼び出し | APIコールのみ | 無し | ・Route 53ヘルスチェック ・カスタムヘルスチェック |
API呼び出しとVPCのDNSクエリ | APIコール、もしくはプライベートDNSクエリ | 有り(Private Hosted Zone) VPC指定必須 |
・カスタムヘルスチェック |
API呼び出しと公開DNSクエリ | APIコール、もしくはパブリックDNSクエリ | 有り (Public Hosted Zone) |
・Route 53ヘルスチェック ・カスタムヘルスチェック |
ほな、ここから、Cloud Mapの各リソースを解説していきます。
( ゚ Д゚) イタダキマス ( つ旦O と_)_)
名前空間の作成とインスタンス検出方法の解説
AWS Cloud MapのWebコンソールにアクセスし、「名前空間の作成」ボタンをクリックします。
名前空間の作成時重要なのが、サービスインスタンスの検出方法の違い。最初にここを完全に把握しておく必要があります。
API呼び出し(API calls)
サービスインスタンスの検出をAPIコールのみで実施します。具体的に利用するAPIはDiscoverInstancesで、ヘルスステータスやサービス名でのサービスインスタンス検出が可能です。
aws servicediscovery create-http-namespace --name hamako9999.com
API呼び出しとVPCのDNSクエリ(API calls and DNS queries in VPCs)
上記API呼び出しに加えて、DNSクエリでのサービス検出が可能です。DNSクエリはVPC内のリソースに対してのみ有効です。この名前空間を作成すると、同時にRoute 53のPrivate Hosted Zoneが作成されます。VPC内の名前解決で利用したことがある人も多いんじゃないでしょうか。アレです。
この場合、サービス名とは別に、Private Hosted Zoneを割り当てるVPCの指定も必要です。
aws servicediscovery create-private-dns-namespace --name hamako9999.com --vpc hamako9999-vpc
API呼び出しと公開DNSクエリ(API calls and Public DNS queries)
上記API呼び出しに加えて、パブリックなDNSクエリでのサービス検出が可能です。上のVPCに割り当てるものとは違い、Public Hosted Zoneが作成されるので、インターネットからの名前解決が可能となり、またRoute 53のヘルスチェックも利用が可能です。
aws servicediscovery create-public-dns-namespace --name hamako9999.com
作成した名前空間
名前空間を作成すると、しばらくして、Cloud Mapの名前空間一覧に表示されます。
Route 53のHosted Zoneを作成する名前空間利用時の注意点
Cloud MapでDNSクエリを利用する名前空間を作成すると、こんな感じでRoute 53のHosted Zoneの一覧にDomain Nameが自動的に追加され、Cloud Mapから作成されたHosted Zoneにはコメント欄にCreated by Route 53 Auto Namingと表示されます。
TypeのPublic、Privateの違いも、上で指定したサービス検出方法により異なります。
ここで一点注意なのですが、Cloud MapのRoute 53 Auto Namingを通じて作成されたHosted Zoneは、Route 53のAPI(コンソール)からは削除できません。
こんな感じでエラーとなります。
ServiceDiscoveryを通じて作成されたHosted ZoneはCloud Mapからの削除が必須となります。
また、既存のRoute 53のHosted Zoneに対してのCloud Mapの名前空間割当はできません。例えば、すでにインターネットで運用されているPublicなHosted ZoneをCloud Mapの名前空間に紐付けることはできないので、Cloud Map配下で管理したい場合は、Publicな名前空間を同じ名前で作成後、既存レジストラのネームサーバーを新しいHosted Zoneへ変更する必要があります。
これは、すでに本番運用されている環境だと非常に大きな移行作業となるので、最初に覚悟しておきましょう。
サービスの作成
名前空間登録後、その名前空間にサービスを作成していきます。サービスの単位は、名前空間に対する機能のサブセット、というイメージで良いです。マイクロサービスのサービス単位とも同じですね。
- 名前空間
- hamako9999.com
- サービス
- payment.hamako9999.com
- users.hamako9999.com
- auth.hamako9999.com
aws servicediscovery create-service --name payment --namespace-id %namespace_id%
サービス作成時には、合わせてサービス検出方法とサービスに登録するインスタンスに設定するヘルスチェックの仕様を決める必要があります。
サービスに対するDNSの設定
サービスに対してインスタンスが登録されたときのルーティングポリシーを設定します。この選択肢が有効なのは、DNSクエリが利用可能な名前空間だけです。
- ルーティングポリシー
- 加重ルーティング
- A,AAAA,SRV,CNAME
- 複数値回答ルーティング
- A,AAAA,SRV
- 各レコードタイプのTTL
が設定可能になります。
サービスに対するヘルスチェック仕様
Cloud Mapにはヘルスチェック機構が内包されています。Cloud Mapで登録される全てのサービスインスタンスは、ヘルスステータスのHEALTHYもしくはUNHEALTHYのいずれかのステータスを持っており、デフォルトでUNHEALTHYなサービスインスタンスへのルーティングはされません。
ヘルスチェック仕様は、以下の2つがあります。
Route 53ヘルスチェック
Route 53が持っているヘルスチェック機能を利用して、サービスインスタンスのヘルスチェックを実施。以下のパラメータが利用可能。
- 失敗しきい値
- ヘルスチェック失敗検知後、UNHEALTHYに遷移するまでのしきい値
- ヘルスチェックプロトコル
- HTTP
- HTTPS
- TCP
- ヘルスチェックパス(HTTP or HTTPS)
- ヘルスチェックポート
カスタムヘルスチェック
ヘルスチェックのロジックを自分で指定する方式。ユースケースは以下の通り。
- Route 53のヘルスチェックが利用できない場合
- Route 53はVPC外からヘルスチェックを実施するため、インターネットからアクセスできないVPC内部のリソースに対してのヘルスチェックは実施できません
- サードパーティツールなどを利用して、ヘルスチェックを実施する場合
- HashiCorpのConsulなどの利用を想定
- その他、自分でヘルスチェックロジックを組みたい場合
カスタムヘルスチェックのロジックは、完全にユーザーに委ねられています。例えば、Lambdaに対して、任意の処理を投げてその結果を利用するということも可能です。
具体的には、登録されているサービスインスタンスに対してUpdateInstanceCustomHealthStatusのAPIを投げることでヘルスステータスを更新できます。ヘルスステータスを更新することで、DiscoverInstancesの結果に、そのサービスインスタンスが返ってこなくなり、ルーティングが停止されます。
このあたりの動作の詳細は、以下に記載があります。
登録したサービスインスタンスに対して、任意のタイミングでヘルスステータスを変更することにより、DiscoverInstancesの検出対象の制御が可能です。
サービスインスタンスの登録
上で作成したサービスに対して、実際のリソースをサービスインスタンスとして登録していきます。サービスインスタンスタイプは3種類あります。
IPアドレス
IPアドレスで利用可能なインスタンスを登録します。DNS設定をIPアドレス系(A,AAAA,SRV)で指定したときに入力します。
CNAME
DNSクエリで返却されるCNAMEを登録します。DNS設定をCNAMEで指定したときに入力します。
別のリソースを特定するための情報
APIコールで利用する名前空間で利用する、サービスインスタンスの登録情報です。
- サービスインスタンスID
- サービスインスタンスに命名する一意の識別ID
- カスタム属性
- サービスインスタンスに付与する任意の属性。サービスインスタンスを検出するときに利用するために必要な属性を設定
- 属性設定例)環境、バージョン、ARNを指定
- env=stg
- ver=1.0
- ARN=arn:aws:lambda:ap-northeast-1:123456789012:function:mystgFunction
$ aws servicediscovery register-instance --service-id srv-3qc6q74wrgicnoko --instance-id payment01 --attributes env=stg,ver=1.0,ARN=arn:aws:lambda:ap-northeast-1:123456789012:function:mystgFunction
例えば、環境ごとにサービスの接続先を変更するような場合は、DiscoverInstancesコール時に属性を指定することで、対象のサービスインスタンスが返却されます。
$ aws servicediscovery discover-instances --namespace-name hamako9999.com --service-name payment --query-parameters env=stg,ver=1.0 { "Instances": [ { "InstanceId": "payment01", "NamespaceName": "hamako9999.com", "ServiceName": "payment", "HealthStatus": "HEALTHY", "Attributes": { "ARN": "arn:aws:lambda:ap-northeast-1:123456789012:function:mystgFunction", "env": "stg", "ver": "1.0" } } ] }
利用料金
Cloud Mapを利用するに当たり必要な料金は、以下の通り。
- 登録されたサービスリソースあたり、0.10USD/月
- ECSのサービスディスカバリで利用されるインスタンスは無料
- HTTP APIコール100万回あたり、1.00USD
IPベースで登録されたサービスリソースに対するRoute 53のヘルスチェックには別途料金が必要になります。詳細はAmazon Route 53の料金を参照。
性能面(レイテンシ)
別途測定しようと考えていますが、APIリクエストに関しては、インターネットのエンドポイントに接続する関係上1桁msecでの応答は無理でしょう。おそらく、10〜20msecぐらいの応答時間はかかると予想されます。
上の料金面とも合わせて都度APIコールをしたくない場合は、アプリケーション側へのキャッシュも検討にいれて良いかと思いますが、運用面の考慮事項も増えるので安易な実装はさけるべきでしょう。
FAQ(よくある質問)
公式のFAQ、および、よくありそうな疑問について改めて。
Route 53のオートネーミングAPIと何が違うのか?
AWS Cloud Mapは、既存のRoute 53のオートネーミングの拡張版という認識でOKです。Route 53オートネーミングは基本的にDNSのサービス名とIPアドレスベースのリソースのみが管理対象でしたが、AWS Cloud Mapは、IP、URL、ARNなどの登録が可能となっています。
AWS Cloud Mapが返却するDNSとHTTPSの違いは?
DNSクエリでは、IPアドレス(IPv4 or IPv6)、ポートの組み合わせ、CNAMEを返しますが、HTTPSのAPIベースでは、任意の値(URL、ARN、IP、IPポート)の全てを返すことができます。
APIベースのクエリでは、アプリケーション側でのAPI実行が必要となります。
ECSとCloud Mapの統合の意味は?
ECSのサービスディスカバリは、自動的にコンテナの増減に合わせて予め設定した名前空間とサービスにAレコードを自動登録する機能です。サービスディスカバリー自体の機能の詳細はこちらをご参照ください。
ECSのサービスディスカバリを設定すると、自動的にCloud Mapに名前空間、サービス、サービスインスタンスが登録されています。
実は、今までもServicediscoveryのAPI自体は存在していたのですが、Webコンソールが用意されておらず、名前空間の削除などもAWS CLIやSDKが必須でした。
それが、AWS Cloud Mapの機能としてWebコンソールも提供され新機能に統合されたことで、より使いやすくパワフルで汎用性高く使えるようになったと理解してよいです。
Systems Managerのパラメータストアに登録するのと何が違うの?
ぶっちゃけそう思う人も多いんじゃないでしょうか。機能的な差分としては、ECSやEKSと完全に統合されていること、ヘルスチェック機構を持っていること、任意の属性を付与しクエリすることで、一貫したサービス名での環境切替が容易なこと、などが挙げられると思います。
パラメータストアのキー名で環境を切り替える場合、別途環境ごとの差分をキー名の命名規約で管理する必要があり正直煩雑です。環境差異はあくまで属性の違いとして登録しておき、サービス名を一意にしておくのが、利用上のポイントになるかと思います。
検証予定記事
今後、ここらへんの動作検証もやってみようと思います。
- 「徹底検証、Systems Manager パラメータストアとの性能差」
- 「カスタムヘルスチェックをConsulと合わせて試してみた」
- 「RDSの複数リードレプリカをCloud Mapで設定してみた」
- 「GKEとEKSとECSクラスタの切替をCloud Mapでやってみた」
「いろんなクラウドリソースが混ざりあうマルチクラウド環境でのサービスディスカバリを統一的に処理する仕組み」
ここまでいろいろ話してきましたが、見ていただいたとおり、登録リソースは、別にAWSのリソースに限定する必要はありません。それこそ、GCPのGKEクラスタエンドポイントへのアクセスや、マネージドSQSサービスの利用など、マルチクラウドな環境でも威力を発揮する機能です。
なんにでも使える汎用性があるので、実際の利用方法さまざまあるかと思います。主要リージョンですでにレディで使える機能なので、皆さんの環境における適用方法を模索してみてください。
それでは、今日はこのへんで。濱田(@hamako9999)でした。