x-appmesh

Warning

This module is still under development and we would love to get any feedback on the syntax and how to make it easier.

Syntax

x-appmesh:
  Properties:
    MeshName: str
    MeshOwner: str
    EgressPolicy: str
  Settings:
    Nodes:
      - <node>
    Routers:
      - <router>
    Services:
      - <service>

The properties for the mesh are very straight forward. Even though, the wish with ECS ComposeX is to keep the Properties the same as the ones defined in CFN as much as possible, for AWS AppMesh, given the simplicity of the properties, we are going with somewhat custom properties, mostly to allow for more features integration down the line.

Warning

There is only one mesh that will be either created or used to deploy the services into.

x-appmesh:
  Properties: {}
  Settings: {}

Properties

MeshName

This is the name of the mesh. However, if you do not specify the MeshOwner, then the name is ignored and the root stack name is used.

The MeshName is going to be used if you specify the MeshOwner, in case you are deploying into a Shared Mesh.

AllowedPattern: ^[a-zA-Z0-9+]+$

MeshOwner

The MeshOwner as described above, doesn’t need to be specified, if you are creating your Nodes, Routers and Services (virtual ones) into a Mesh shared with you from another account.

AllowedPattern: [0-9]{12}

EgressPolicy

The mesh aims to allow services, nodes to communicate to each other only through the mesh. So by default, ECS ComposeX sets the policy to DROP_ALL. Meaning, no traffic out of the nodes will be allowed if not to a defined VirtualService in the mesh.

For troubleshooting and otherwise for your use-case, you might want to allow any traffic to get out of the node anyway. If so, simply change the policy to ALLOW_ALL

AllowedValues: DROP_ALL, ALLOW_ALL

Settings

The settings section is where we are going to define how our services defined in Docker compose are going to integrate to the mesh.

nodes

Syntax

Name: str # <family name>
Procotol str
Backends:
  - <service_name> # Only services can be defined as backend

Examples

This section represents the nodes. The nodes listed here must be either a service as listed in docker-compose or a family name.

Nodes:
  - Name: app01
    Procotol Http
  - Name: app02
    Procotol Tcp
    Backends:
      - service-abcd

routers

Definition

Routers as mentioned in the module description, are here to allow developers to define how packets should be routed from one place to another.

For TCP ones, one can only really set timeout settings, in addition to TLS etc. However for Http, Http2 and gRPC it allows you to define further more rules. The example below shows how a request to the router on path / it should send requests with the POST method to app02, but requests with the GET method to app01.

Syntax

Name: str
Listener
  Procotol str
  port: int
Routes:
  Http:
    - <match>

match

This is simplistic version of the AWS Route Match specifications : HTTP Route, TCP Route

Definition

The match allows to define how to route packets to backend nodes

Syntax
Match:
  Prefix: str
Method: str
Scheme:: str
Nodes:
  - <node_name>
Example
Routers:
  - Name: Httprouter
    Listener
      Procotol Http
      port: 8080
    Routes:
      Http:
        - Match:
            Prefix: /
          Method: GET
          Scheme:: Http
          Nodes:
            - app01
        - Match:
            Prefix: /
          Method: POST
          Nodes:
            - app02

services

The VirtualServices are what acts as backends to nodes, and as receiver for nodes and routers. The Virtual Services can use either a Node or a Router as the location to route the traffic to.

Syntax

Services:
  - Node: <node_name>
    Name: str
  - Router: <router_name>
    Name: str
Services:
  - Name: service-xyz
    Router: Httprouter
  - Name: service-xyz
    Node: app03

Examples

---
# Simple mesh definition for new mesh of Services

x-appmesh:
  Properties: {}
  Settings:
    Nodes:
      - Name: app03
        Protocol: Tcp
      - Name: youtoo
        Protocol: Http
      - Name: bignicefamily
        Protocol: Http
        Backends:
          - dateteller # Points to the dateteller Service, not Router!
    Routers:
      - Name: dateteller
        Listener:
          Port: 5000
          Protocol: Http
        Routes:
          Http:
            - Match:
                Prefix: /date
                Method: GET
                Scheme: Http
              Nodes:
                - Name: youtoo
                  Weight: 1
      - Name: datetellertcp
        Listener:
          Port: 5000
          Protocol: Tcp
        Routes:
          Tcp:
            - Nodes:
                - Name: app03
                  Weight: 1
    Services:
      - Name: api
        Node: bignicefamily
      - Name: dateteller
        Router: dateteller

AWS AppMesh & AWS Cloud Map for services mesh & discovery

AWS AppMesh is a service mesh which takes care of routing your services packets logically among the different nodes. What this allows you to do, it to explicitly declare which services have access to others, either on http, tcp or gRPC.

See also

ComposeX x-appmesh syntax reference

Note

For HTTP, it supports both http2 and http.

There are a lot more features to know about, so I would recommend to head to the AWS Appmesh official documentation.

Warning

At the time of working on this feature, mutualTLS is not available, for lack of $$ to use AWS ACM CA and do the dev work.

Warning

By default in ECS ComposeX, the EGRESS policy for nodes it to DROP_ALL so that only explicitly allowed traffic can go across the mesh, in/out the services.

Nodes

The nodes are a logical construct to indicate an endpoint. With ECS ComposeX, it will either be

  • a service defined and deployed in ECS

  • a database

  • any DNS discoverable target.

When you enable AWS AppMesh in ECS ComposeX, it will automatically add all the necessary resources for your ECS task to work correctly:

  • envoy container

  • update task definition with proxy configuration

  • add IAM permissions for envoy to discover services and the mesh settings.

Routers

Routers are logical endpoints that apply the logic you define into routes. For TCP routers, it mostly is about defining TCP settings, such as timeouts.

For HTTP and gRPC however, it is far more advanced. You can define routes based on path, method etc. I also can perform healthcheck for you, to evaluate the nodes health. It effectively is a virtual ALB listener with a long set of rules.

Note

From experimenting and testing however, you cannot mix routes protocols within the same router.

Services

The virtual services are once again, a logical pointer to a resource. That resource will either be a Node or a Router. But again, it is aimed to be a virtual pointer, therefore, you do not need to call your virtual service with the same name as one of the services defined in the compose services.

What does that mean?

In essence, when you define a VirtualService as the backend of a virtual node, this means this node and its services will be granted access to the nodes of the VirtualService itself. But, you might have called your services clock and watch, and yet the virtual service will be called time.

Problem: when trying to connect to the endpoint time, your application won’t be able to resolve time. Solution: ECS ComposeX will create a virtual service in the same AWS CloudMap as where the ECS Services are registered, and create a fake instance of it, for which the IPv4 address will be 169.254.255.254 How does it work?: your microservice in ECS will try to resolve time. The DNS response will be an IP address, here, 169.254.255.254. Which obviously does not exist in a VPC (see RFC 3927 for more details) but, it will allow your application to establish the connection. The connection is intercepted by the envoy proxy container, which internally figures out, where to connect and how. It will then take your package, and send it across to the destination, to the right IP address. Which is why resolving the IP in DNS is important, but the value of the record is not.

The other things ECS ComposeX takes care of for you

In addition to configuring the ECS Task definition appropriately etc, ECS ComposeX also will take care of the security groups opening between the Virtual Nodes, and to other backends.

Yes, a mesh with DROP_ALL will ensure that communication between nodes only happens if explicitly allowed, but this does not mean we should not also keep the underlying network in check.

The security group inbound rule defined is from the source node to the target node(s), allowing all traffic for now between the nodes.

Note

For troubleshooting, you can use the ClusterWide Security Group which is attached to all containers deployed with ECS ComposeX, and allow all traffic within the security group to allow your ECS Services to communicate.