はじめに
2018/11/29に発表になったAWS App Meshのサンプルを試してみます。
https://aws.amazon.com/jp/blogs/news/reinvent2018-aws-app-mesh/
サンプルはこちらにあります。
https://github.com/awslabs/aws-app-mesh-examples/tree/master/examples
App Meshは、AWS上のマイクロサービスアプリケーション間の通信を簡単に監視、制御できるサービスメッシュを提供するサービスとなります。サービスメッシュのコントロールプレーン実装としては、OSSのIstioが有名です。また、App Meshではコンテナ間のプロキシとしてOSSとして開発されているEnvoyが使われています。
サンプルアプリケーションの概要
Gatewayに対してHTTPリクエストを送ると、バックエンドのアプリケーションから任意のカラーをJSONで返します。
返されるカラーは、White/Black/Blue/Redになります。
$ curl -s http://colorgateway.default.svc.cluster.local:9080/color
{"color":"white", "stats": {"white":1}}
構成としては、物理レイヤーと論理レイヤーの2つに分けて考えた方が理解しやすいと思います。
ここでは、物理レイヤーをVPCやECSクラスタとしています。論理レイヤーはサービスメッシュを構成するコンポーネントとなります。
サンプルを手順通り作成すると以下のような物理構成が作成されます。
サービスメッシュを構成するコンポーネントの簡単な説明をします。
Mesh
複数のマイクロサービスをまとめたグループ
https://docs.aws.amazon.com/ja_jp/app-mesh/latest/userguide/meshes.html
Virtual Node
Amazon ECSサービスやKubernetesデプロイメントなどの特定のタスクグループへの論理的なポインタ
https://docs.aws.amazon.com/ja_jp/app-mesh/latest/userguide/virtual_nodes.html
Virtual Router
Virtual Node間のトラフィックをルーティングする仮想ルータ
https://docs.aws.amazon.com/ja_jp/app-mesh/latest/userguide/virtual_routers.html
Route
Virtual Routerに関連付けられたルーティング情報
https://docs.aws.amazon.com/ja_jp/app-mesh/latest/userguide/routes.html
(そもそも)Envoyとサービスメッシュについて
EnvoyはLyftが開発したプロキシソフトウェアです。
https://www.envoyproxy.io/docs/envoy/latest/intro/what_is_envoy
機能が多彩で以下の様なことが出来ます。
- L3/L4 filter architecture
- HTTP L7 filter architecture
- First class HTTP/2 support
- HTTP L7 routing
- gRPC support
- MongoDB L7 support
- DynamoDB L7 support
- Service discovery and dynamic configuration
- Health checking
- Advanced load balancing
単にEnvoyをリバプロとして使うのであれば、Envoy単体で運用も可能な場合があるが、マイクロサービス化するとEnvoyがサイドカーコンテナとして多数起動することになり、ルーティング情報などの設定情報を集中的に管理する機能が必要になってきます。
前述した、Istioが代表的なコントロールプレーンのツールです。AppMeshは、現時点(2018/12/28)ではPublic Previewのたトラフィックルーティングのみ使用可能です。
手順
前提
最新のaws-cliをインストールします。今回は1.16.67を使用します。
$ aws --version
aws-cli/1.16.67 Python/3.5.4 Darwin/16.7.0 botocore/1.12.57
事前
サンプルアプリケーションをダウンロードします。
$ git clone https://github.com/awslabs/aws-app-mesh-examples.git
Cloning into 'aws-app-mesh-examples'...
remote: Enumerating objects: 98, done.
remote: Counting objects: 100% (98/98), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 321 (delta 30), reused 85 (delta 29), pack-reused 223
Receiving objects: 100% (321/321), 83.70 KiB | 49.00 KiB/s, done.
Resolving deltas: 100% (125/125), done
作成する環境を定義します。
現時点(2018/12/28)でApp Meshが使えるリージョンは、Oregon,Virginia,East,Ohio,Irelandになります。
今回はオレゴンリージョンを使用します。
export AWS_PROFILE="default"
export AWS_REGION="us-west-2"
export AWS_DEFAULT_REGION="$AWS_REGION"
<>内は、環境にあった値に変更をお願いします。
インスタンス数は、2台とかだとawsvpcモードでENI数が足りなくてタスクが起動できなくなります。
SERVICES_DOMAINで定義したドメイン名でサービスディスカバリや名前解決ができます。
export ENVIRONMENT_NAME="AppMeshSample"
export MESH_NAME="default"
export KEY_PAIR_NAME=<key-pair to access ec2 instances where apps are running>
export ENVOY_IMAGE="111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.8.0.2-beta"
export CLUSTER_SIZE=5
export SERVICES_DOMAIN="default.svc.cluster.local"
VPC作成
VPCを作成します。スクリプトを実行するとCloudFormationが実行されて以下の環境が作成されます。
$ cd aws-app-mesh-examples/examples/
$ ./infrastructure/vpc.sh create-stack
+++ dirname ./infrastructure/vpc.sh
++ cd ./infrastructure
++ pwd
+ DIR=/aws-app-mesh-examples/examples/infrastructure
+ aws --profile default --region us-west-2 cloudformation deploy --stack-name AppMeshSample-vpc --capabilities CAPABILITY_IAM --template-file /aws-app-mesh-examples/examples/infrastructure/vpc.yaml --parameter-overrides EnvironmentName=AppMeshSample
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - AppMeshSample-vpc
メッシュのセットアップ
スクリプトのなかでaws-cliが実行されMeshのみ作成されます。
$ ./infrastructure/mesh.sh create-mesh
+ '[' '!' -z default ']'
+ PROFILE_OPT='--profile default'
+ aws --profile default appmesh create-mesh --mesh-name default
{
"mesh": {
"meshName": "default",
"status": {
"status": "ACTIVE"
},
"metadata": {
"version": 1,
"lastUpdatedAt": 1545887155.41,
"arn": "arn:aws:appmesh:us-west-2:*****:mesh/default",
"createdAt": 1545887155.41,
"uid": "c2324ff1-7308-4be0-8a9b-c74f30ee6c62"
}
}
}
ECSかEKSのクラスタを作成する
今回はECSクラスタを作成します。CloudFormationが実行されます。
$ ./infrastructure/ecs-cluster.sh create-stack
+++ dirname ./infrastructure/ecs-cluster.sh
++ cd ./infrastructure
++ pwd
+ DIR=/aws-app-mesh-examples/examples/infrastructure
+ aws --profile default --region us-west-2 cloudformation deploy --stack-name AppMeshSample-ecs-cluster --capabilities CAPABILITY_IAM --template-file /aws-app-mesh-examples/examples/infrastructure/ecs-cluster.yaml --parameter-overrides EnvironmentName=AppMeshSample KeyName=oregon-key ECSServicesDomain=default.svc.cluster.local ClusterSize=5
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - AppMeshSample-ecs-cluster
アプリケーションのデプロイ
サンプルに含まれているgatewayとcolortellerというアプリケーションをデプロイします。
最初にECRのレポジトリを手動で2つ作成します。
aws ecr create-repository --repository-name "color-gateway" --region us-west-2
aws ecr create-repository --repository-name "color-teller" --region us-west-2
環境変数に作成したリポジトリのURIを設定する。
export COLOR_GATEWAY_IMAGE=<image location for colorapp's gateway>
export COLOR_TELLER_IMAGE=<image location for colorapp's teller>
以下に、サンプルアプリケーション用のDockerfileがあります
./apps/colorapp/src/gateway/Dockerfile
./apps/colorapp/src/colorteller/Dockerfile
デプロイ用のスクリプトが用意されてるのでこちらでECRにPushします。
GatewayアプリケーションをECRにPush
$ cd ./apps/colorapp/src/gateway/
$ ./deploy.sh
+ '[' -z ******.dkr.ecr.us-west-2.amazonaws.com/color-gateway ']'
+ docker build -t ******.dkr.ecr.us-west-2.amazonaws.com/color-gateway .
Sending build context to Docker daemon 32.26kB
Step 1/11 : FROM golang:1.10 AS builder
---> a3e70d5ea200
Step 2/11 : ADD https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 /usr/bin/dep
Downloading [==================================================>] 8.499MB/8.499MB
(略)
da67ad63a8b3: Pushed
latest: digest: sha256:634f329a49fd15dc1cad2b20cc694794a3340530e6041056b6b0b9923e3448d5 size: 528
ColorTellerアプリケーションをECRにPush
$ cd ../
$ cd colorteller/
$ ./deploy.sh
+ '[' -z ******.dkr.ecr.us-west-2.amazonaws.com/color-teller ']'
+ docker build -t ******.dkr.ecr.us-west-2.amazonaws.com/color-teller .
Sending build context to Docker daemon 8.192kB
Step 1/11 : FROM golang:1.10 AS builder
---> a3e70d5ea200
Step 2/11 : ADD https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 /usr/bin/dep
Downloading [==================================================>] 8.499MB/8.499MB
(略)
8c7a1b9b5ec0: Pushed
latest: digest: sha256:c4b21221d55272295ddce74eb891451d34714d7c09ad826deba3b1eb3db14fad size: 528
ここまでで以下のような環境が作成されます。
サービスメッシュのセットアップ
Virtual Node,Virtual Router,Routeを作成します。aws-cliが実行されます。
$ cd ../../
$ pwd
/aws-app-mesh-examples/examples/apps/colorapp
$ ./servicemesh/deploy.sh
[MESH] [Thu Dec 27 15:53:37 JST 2018] : Creating virtual nodes
[MESH] [Thu Dec 27 15:53:37 JST 2018] : ======================
[MESH] [Thu Dec 27 15:53:37 JST 2018] : cli_input={
"spec": {
"listeners": [
(略)
[MESH] [Thu Dec 27 15:54:09 JST 2018] : --> a529b027-6176-4324-9e56-423e6ada8c94
[MESH] [Thu Dec 27 15:54:09 JST 2018] : --> a529b027-6176-4324-9e56-423e6ada8c94
ECSにアプリケーションをデプロイ
CloudFormationが実行されて、ECRからコンテナイメージがECSクラスタにデプロイされます。
$ ./ecs/ecs-colorapp.sh
+++ dirname ./ecs/ecs-colorapp.sh
++ cd ./ecs
++ pwd
+ DIR=/aws-app-mesh-examples/examples/apps/colorapp/ecs
+ aws --profile default --region us-west-2 cloudformation deploy --stack-name AppMeshSample-ecs-colorapp --capabilities CAPABILITY_IAM --template-file /aws-app-mesh-examples/examples/apps/colorapp/ecs/ecs-colorapp.yaml --parameter-overrides EnvironmentName=AppMeshSample EnvoyImage=111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.8.0.2-beta ECSServicesDomain=default.svc.cluster.local AppMeshMeshName=default ColorGatewayImage=******.dkr.ecr.us-west-2.amazonaws.com/color-gateway ColorTellerImage=******.dkr.ecr.us-west-2.amazonaws.com/color-teller
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - AppMeshSample-ecs-colorapp
動作確認
踏み台サーバを準備するかSession ManagerでECSクラスタ用のEC2インスタンスにログインする。
Gatewayに対してcurlしてみる。
$ curl -s http://colorgateway.default.svc.cluster.local:9080/color
{"color":"white", "stats": {"white":1}}
Whiteが返される。これはルーティング設定(Route)でvirtualNodeがcolorteller-vnのみ設定してあり、colorteller-vnは「White」を返すコンテナになります。
$ cat servicemesh/config/routes/colorteller-route.json
{
"routeName": "colorteller-route",
"spec": {
"httpRoute": {
"action": {
"weightedTargets": [
{
"virtualNode": "colorteller-vn",
"weight": 1
}
]
},
"match": {
"prefix": "/"
}
}
},
"virtualRouterName": "colorteller-vr"
}
Blueを返すように変更してみます。まずは、Virtual Nodeを確認します。
$ aws appmesh list-virtual-nodes --mesh-name default
{
"virtualNodes": [
{
"arn": "arn:aws:appmesh:us-east-1:******:mesh/default/virtualNode/colorteller-vn",
"meshName": "default",
"virtualNodeName": "colorteller-vn"
},
{
"arn": "arn:aws:appmesh:us-east-1:******:mesh/default/virtualNode/colorteller-red-vn",
"meshName": "default",
"virtualNodeName": "colorteller-red-vn"
},
{
"arn": "arn:aws:appmesh:us-east-1:******:mesh/default/virtualNode/colorteller-blue-vn",
"meshName": "default",
"virtualNodeName": "colorteller-blue-vn"
},
{
"arn": "arn:aws:appmesh:us-east-1:******:mesh/default/virtualNode/colorteller-black-vn",
"meshName": "default",
"virtualNodeName": "colorteller-black-vn"
},
{
"arn": "arn:aws:appmesh:us-east-1:******:mesh/default/virtualNode/colorgateway-vn",
"meshName": "default",
"virtualNodeName": "colorgateway-vn"
}
]
}
Blueですが、virtualNodeNameがcolorteller-blue-vnになりますので、colorteller-route.jsonを編集します。
$ emacs servicemesh/config/routes/colorteller-route.json
{
"routeName": "colorteller-route",
"spec": {
"httpRoute": {
"action": {
"weightedTargets": [
{
"virtualNode": "colorteller-blue-vn",
"weight": 1
}
]
},
"match": {
"prefix": "/"
}
}
},
"virtualRouterName": "colorteller-vr"
}
更新します。
$ aws appmesh update-route --mesh-name default --cli-input-json file://servicemesh/config/routes/colorteller-route.json
virtualNodeがcolorteller-blue-vnとなっていることを確認する。
$ aws appmesh describe-route --mesh-name default --route-name colorteller-route --virtual-router-name colorteller-vr
{
"route": {
"meshName": "default",
"spec": {
"httpRoute": {
"action": {
"weightedTargets": [
{
"weight": 1,
"virtualNode": "colorteller-blue-vn"
curlコマンドで確認すると、blueが返ってきます。
sh-4.2$ curl -s http://colorgateway.default.svc.cluster.local:9080/color
{"color":"blue", "stats": {"blue":0,"white":1}}sh-4.2$
トラフィックの30%をBlackのマイクロサービス、70%をRedのマイクロサービスといったようにルーティングすることも可能です。
落ち穂拾い
GatewayのEnvoyコンテナにログインして設定情報を確認してみます。
GatewayのEnvoyコンテナが起動しているEC2インスタンスにログイン via SSM or 踏み台経由してSSH
コンテナIDを確認
sh-4.2$ sudo su -
Last login: Fri Dec 28 05:10:11 UTC 2018 on pts/6
[root@ip-10-0-126-201 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
13591540c2b5 111345817488.dkr.ecr.us-west-2.amazonaws.com/aws-appmesh-envoy:v1.8.0.2-beta "/bin/sh -c /usr/bin…" 24 hours ago Up 24 hours ecs-AppMeshSample-ecs-colorapp-ColorGatewayTaskDefinition-1P2K347XVMJFW-1-envoy-fec5ebb5a1fbec900a00
コンテナにログイン
root@ip-10-0-126-201 ~]#
[root@ip-10-0-126-201 ~]# docker exec -it 13591540c2b5 /bin/bash
bash-4.2$
Envoyの設定情報確認
Virtual Nodeがcolorgateway-vn|colorteller-blue-vnになっていることが確認できます。
bash-4.2$ curl localhost:9901/config_dump
{
"configs": [
{
"@type": "type.googleapis.com/envoy.admin.v2alpha.BootstrapConfigDump",
(略)
{
"@type": "type.googleapis.com/envoy.admin.v2alpha.RoutesConfigDump",
"dynamic_route_configs": [
{
"version_info": "61077530",
"route_config": {
"name": "rds|egress|default|colorgateway-vn|http|9080|61077530",
"virtual_hosts": [
{
"name": "rds|egress|default|colorgateway-vn|http|9080|colorteller.default.svc.cluster.local|61077530",
"domains": [
"colorteller.default.svc.cluster.local",
"colorteller.default.svc.cluster.local:9080"
],
"routes": [
{
"match": {
"prefix": "/"
},
"route": {
"weighted_clusters": {
"clusters": [
{
"name": "cds|egress|default|colorgateway-vn|colorteller-blue-vn|http|9080|59827320",
"weight": 1
}
],
"total_weight": 1
}
}
}
]
}
]
},
"last_updated": "2018-12-28T04:19:28.852Z"
},
お約束
投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。