Description
What we're changing
On March 7, 2019, the AWS App Mesh team will release a new, backward incompatible version of our APIs in the AWS SDKs. The primary change is the introduction of a new resource type, VirtualService, which replaces the use of ServiceNames in the current APIs. These changes are primarily focused on addressing potential confusion around ServiceNames in VirtualNodes and VirtualRouters (see #77).
A VirtualService in AWS App Mesh is an abstraction of the real service implementation behind it. Dependent services will call your VirtualService by its name (formerly the ServiceName), and you are free to implement how your VirtualService is provided to those dependencies through VirtualNodes and VirtualRouters.
A full description of changes is available in the FAQ below.
What we're asking
We're inviting developers to try out these new APIs and provide feedback before we officially release them as part of the AWS SDK. We would especially love to hear your feedback on whether you feel this is an improvement over the existing APIs from the standpoint of issue #77.
How can you give feedback?
You can leave feedback on this issue. Or, you can email your feedback to aws-appmesh-feedback@amazon.com.
How can you test this?
You can try the new APIs by downloading the trial JSON CLI file and add it to your existing AWS CLI via:
$ aws configure add-model \
--service-name appmesh-trial \
--service-model https://s3-us-west-2.amazonaws.com/aws-appmesh-cli-trials/app-mesh-2019-01-25.trial.json
Once you've added this model, you can begin using the new APIs on your existing mesh.
As a brief example, if you've setup the colorapp example from our aws-app-mesh-examples repository, you can use the new VirtualService API to determine where the ServiceName tcpecho.default.svc.cluster.local
points to in your mesh:
$ aws appmesh-trial describe-virtual-service \
--mesh-name colorapp \
--virtual-service-name tcpecho.default.svc.cluster.local
{
"virtualService": {
"status": {
"status": "ACTIVE"
},
"metadata": {
"createdAt": 1543434909.84,
"version": 1,
"arn": "arn:aws:appmesh:us-west-2:123456789012:mesh/colorapp/virtualService/tcpecho.default.svc.cluster.local",
"lastUpdatedAt": 1543434909.84,
"uid": "3a222219-fd1f-410b-93f8-852338307046"
},
"meshName": "colorapp",
"virtualServiceName": "tcpecho.default.svc.cluster.local",
"spec": {
"provider": {
"virtualNode": {
"virtualNodeName": "tcpecho-vn"
}
}
}
}
}
In the above example we can see that the VirtualService (formerly ServiceName) points to the VirtualNode named tcpecho-vn
by showing it as the VirtualService provider. This means that requests sent to tcpecho.default.svc.cluster.local
in the mesh will be routed to the tcpecho-vn
. The provider can also be a VirtualRouter, as would be the case for the colorteller.default.svc.cluster.local
ServiceName.
We would love to hear your feedback on whether you feel these changes clarify the use of ServiceNames in App Mesh. Let us know in the comments below!
Walkthrough
Using the existing colorapp example as a guide, let's walk through what setting up the mesh would look like in the new APIs. To simplify things, we'll ignore the tcpecho
service in the existing example and focus just on colorgateway
, colorteller
, and how we connect them through the use of a VirtualRouter and VirtualService.
To start, we'll create the VirtualNodes for colorgateway
and colorteller
(white).
$ aws appmesh-trial create-mesh --mesh-name colorapp
$ aws appmesh-trial create-virtual-node \
--mesh-name colorapp \
--cli-input-json file://colorgateway-virtualnode.json
// colorgateway-virtualnode.json:
{
"spec": {
"listeners": [
{
"portMapping": {
"port": 9080,
"protocol": "http"
}
}
],
"serviceDiscovery": {
"dns": {
"hostname": "colorgateway.default.svc.cluster.local"
}
},
"backends": [
{
// Note: Although the VirtualService does not yet exist,
// you can still specify it as a backend, just as you could
// in the original APIs. When the VirtualService is created later,
// App Mesh will make the necessary connections in your mesh.
// ¯\_(ツ)_/¯
"virtualService": {
"virtualServiceName": "colorteller.default.svc.cluster.local"
}
}
]
},
"virtualNodeName": "colorgateway-vn"
}
$ aws appmesh-trial create-virtual-node \
--mesh-name colorapp \
--cli-input-json file://colorteller-virtualnode.json
// colorteller-virtualnode.json:
{
"spec": {
"listeners": [
{
"portMapping": {
"port": 9080,
"protocol": "http"
},
"healthCheck": {
"protocol": "http",
"path": "/ping",
"healthyThreshold": 2,
"unhealthyThreshold": 2,
"timeoutMillis": 2000,
"intervalMillis": 5000
}
}
],
"serviceDiscovery": {
"dns": {
"hostname": "colorteller.default.svc.cluster.local"
}
}
},
"virtualNodeName": "colorteller-vn"
}
Now we'll setup the VirtualRouter and an initial Route for the colorteller
service.
$ aws appmesh-trial create-virtual-router \
--mesh-name colorapp \
--cli-input-json file://colorteller-virtualrouter.json
// colorteller-virtualrouter.json:
{
"spec": {},
"virtualRouterName": "colorteller-vr"
}
$ aws appmesh-trial create-route \
--mesh-name colorapp \
--virtual-router-name colorteller-vr \
--cli-input-json file://colorteller-route.json
// colorteller-route.json:
{
"routeName": "colorteller-route",
"spec": {
"httpRoute": {
"action": {
"weightedTargets": [
{
"virtualNode": "colorteller-vn",
"weight": 1
}
]
},
"match": {
"prefix": "/"
}
}
},
"virtualRouterName": "colorteller-vr"
}
With the VirtualNodes, VirtualRouter, and Route setup, the final step is to create the VirtualService for the colorteller
service and point it to the VirtualRouter by specifying it as a provider.
$ aws appmesh-trial create-virtual-service \
--mesh-name colorapp \
--cli-input-json file://colorteller-virtualservice.json
// colorteller-virtualservice.json:
{
"spec": {
"provider": {
"virtualRouter": {
"virtualRouterName": "colorteller-vr"
}
}
},
"virtualServiceName": "colorteller.default.svc.cluster.local"
}
Once the VirtualService has been created, requests made to colorteller.default.svc.cluster.local
from the colorgateway
VirtualNode will now be routed by the colorteller
VirtualRouter to the colorteller
VirtualNode.
Frequently Asked Questions
Why are we introducing this change?
The existing App Mesh APIs use the concept of a ServiceName to bind specific resources (VirtualNodes, VirtualRouters) together into a traversable service graph. A ServiceName is a fully qualified domain name (FQDN) that a client references in network calls to other services. This is used to route calls to a specific resource within Envoy Proxy, which may be discoverable by a different FQDN.
Today, there are several scenarios in the current APIs where a change to one resource's ServiceName setting may adversely affect that resource, or a different resource, with no indication of a problem to the customer. Additionally, it was discovered during the Public Preview period that the use of ServiceNames in our APIs is difficult to reason about for many customers (see #49, #71).
These changes seek to resolve the potential confusion around ServiceNames by treating the ServiceName as a first-class resource in AppMesh, which we're calling a VirtualService.
What specifically is being changed?
VirtualService
This new resource type is being introduced to formalize the existing concept of a ServiceName and provide clarity on how the entity is used within App Mesh.
This new resource type is used to point a ServiceName (e.g. “service-a.mesh.local”) to a specific networking resource (VirtualRouter, VirtualNode). Today this is done implicitly through fields on VirtualNodes and VirtualRouters. A VirtualService's name (formerly a ServiceName) points to a specific VirtualNode or VirtualRouter by way of the provider
field in its spec.
This new resource type also allows customers to discover what ServiceNames exist in the mesh (i.e. aws appmesh-trial list-virtual-services
), and where a particular ServiceName is pointing. Finally, it will allow a single actor to own the existing ServiceName and control how it is implemented through resource-based authorization in AWS Identity Access Management.
VirtualNode
- The
spec.backends
field is being changed from a list of Strings to a list of structured objects to allow for additional upcoming features in AWS App Mesh. For example, egress policies like retries, circuit breakers, and timeouts will be available here.
// Current:
{"spec": {
"backends": [
"colorteller.default.svc.cluster.local"
]
}}
// Future:
{"spec": {
"backends": [
{
"virtualService": {
"virtualServiceName": "colorteller.default.svc.cluster.local"
}
}
]
}}
- The
spec.serviceDiscovery.dns.serviceName
field is being renamed tospec.serviceDiscovery.dns.hostname
and will no longer be used as a ServiceName. The original field was used as both a ServiceName and for DNS discovery. In the new API, this field will only be used for DNS discovery. Instead of specifying an applicable ServiceName here, you can now create your VirtualService by the same name and set the VirtualNode as its provider.
VirtualRouter
- The
spec.serviceNames
field is being removed. Instead of specifying applicable ServiceNames on the VirtualRouter, you can now create your VirtualService by the same name and set the VirtualRouter as its provider.
Will existing meshes still work?
Yes. Existing meshes will continue to work after the introduction of the new APIs.
Can I use the new APIs to see my existing meshes?
Yes. The new APIs were designed to work with the existing data in AWS App Mesh, and we encourage you to use the new APIs to get better clarity on how your existing mesh is configured.
Can I still use the existing APIs?
Yes. The new APIs are compatible with the existing APIs and data, so you are free to use either API during the trial period. Once the trial period is over, VirtualService will replace ServiceName.