I have a small application that I want to deploy to AWS with least cost as possible that would still allow the application to be accessible in the public internet and to grow further when required. In addition to that I wanted to streamline my pipeline and automate everything.
That's why I've chosen the following setup:
I wanted to go without load balancer for now because it's simply too costly to start with, especially when I want to scale down the application completely from time to time.
What have so far:
AWSTemplateFormatVersion: "2010-09-09"
Description: ECS deployment
Parameters:
Image:
Type: String
Application:
Type: String
Namespace:
Type: String
Cluster:
Type: String
Cpu:
Type: String
Memory:
Type: String
Resources:
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Ref Application
ExecutionRoleArn: arn:aws:iam::**:role/ecsTaskExecutionRole
NetworkMode: awsvpc
Cpu: !Ref Cpu
Memory: !Ref Memory
RequiresCompatibilities:
- FARGATE
ContainerDefinitions:
- Name: !Ref Application
Image: !Ref Image
Cpu: !Ref Cpu
Memory: !Ref Memory
PortMappings:
- HostPort: 8080
ContainerPort: 8080
Essential: true
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
ServiceDiscoveryService:
Type: AWS::ServiceDiscovery::Service
Properties:
Name: !Ref Application
DnsConfig:
DnsRecords:
- Type: A
TTL: 300
NamespaceId: !Ref Namespace
HealthCheckCustomConfig:
FailureThreshold: 1
ECSService:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
ServiceName: !Ref Application
TaskDefinition: !Ref TaskDefinition
DesiredCount: 1
CapacityProviderStrategy:
- Base: 0
CapacityProvider: FARGATE_SPOT
Weight: 1
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !GetAtt SecurityGroup.GroupId
Subnets:
- **
- **
- **
ServiceRegistries:
- RegistryArn: !GetAtt ServiceDiscoveryService.Arn
I am not sure if I am at all able to run a container on Fargate with a different port than 80 if I am not using a load balancer. Because I read that SRV records can't be interpreted by curl and httpie. And I would definitely want to be able to call my api with that. And as I don't have a load balancer I can't configure a dynamic host mapping because that's not possible with Fargate.
If you are using the Fargate launch type, the awsvpc network mode is required. With the host and awsvpc network modes, exposed container ports are mapped directly to the corresponding host port (for the host network mode) or the attached elastic network interface port (for the awsvpc network mode), so you cannot take advantage of dynamic host port mappings.
With the deployment above I was able to deploy everything to AWS and the task is running successfully. It has a public ip and I am able to query it from my laptop successfully with
http PUBLIC_IP/stocks/MMM
I have now registered a new domain, let's say test-1234.com
and registered the name servers of my created hostzones.
Using dig
for my-service.test-1234.com
results in the private ip of the running task.
I would assume that's the expected answer for a successfully registered task but I am not sure.
Querying it with
http my-service.test-1234.com/stocks/MMM
is failing with Failed to establish a new connection
Does anyone know how to make it work?
To summarize the comments:
It's currently not possible to do that with Fargate. More details here.
Nevertheless there are two other options that could work:
awsvpc
and can configure the port mapping.