-
Notifications
You must be signed in to change notification settings - Fork 436
Description
I'm really interested in integrating service discovery, by default for our apps. This design doesn't include App Mesh integration, but I think that'd be additive.
What is service discovery?
Service discovery allows two services to communicate using an internal (within the same VPC) DNS.
An example would be, if you have two apps, backend and frontend, the frontend app might have a public loadbancer, but the backend might be isolated in a private subnet.
The frontend would be able to communicate with the backend service using a VPC-local DNS like backend.local. The backend would also be able to contact the frontend through a VPC-local DNS in the same way. This has the benefit of the data not transiting the internet and the inter-service communicate doesn't rely on the LB url.
What services to use?
- AWS CloudMap
- ECS's ServiceDiscovery (same thing, but handles the registering of tasks into CloudMap)
What do we have to do?
It's actually really easy.
- In the environment, create a ServiceDiscovery Namespace (this is the DNS suffix). I'm thinking
.local.
ServiceDiscoveryNamespace:
Type: AWS::ServiceDiscovery::PrivateDnsNamespace
Properties:
Name: local
Vpc: !Ref VPC-
Export the Namespace ID
-
In the app stack, create a discovery service (this is the actual DNS for this app):
DiscoveryService:
Type: AWS::ServiceDiscovery::Service
Properties:
Description: Discovery Service for the ECS CLI V2 services
DnsConfig:
RoutingPolicy: MULTIVALUE
DnsRecords:
- TTL: 60
Type: A
- TTL: 60
Type: SRV
HealthCheckCustomConfig:
FailureThreshold: 1
Name: !Ref AppName
NamespaceId:
Fn::ImportValue:
!Sub '${ProjectName}-${EnvName}-NamespaceID'- Update the service to use ServiceRegistries
ServiceRegistries:
- RegistryArn: !GetAtt DiscoveryService.Arn
Port: !Ref ContainerPort-
This will set up everything, but one tricky thing is our security groups don't permit inter-app communication right now (since each app gets its own security group and each security group only allows traffic from the ALB and itself. So, what we could do is move the security group up to the env, and have each app use the same security group. This is definitely the trickiest part.
-
Pass in
dnsSearchDomainsto the Task Definition. When we create the.localnamespace it'd be rad if customers didn't have to include it in their actual http requests. A feature called Search Domains (which we can set in our task definitions) lets us add automatic suffixes if a request is made without a fully qualified domain. This means if we add a.localsearch domain, if the customer's container makes a request tobackend- it'll be resolved tobackend.local.
Example
Calling a backend app from the frontend app. The backend is running on port 8080:
resp, err := http.Get("http://backend:8080/")