Isolated network workloads in AWS: ECS Fargate
Serverless workload cluster with no internet connectivity
In a typical setup, compute nodes such as AWS Fargate tasks within an Amazon ECS cluster require internet access to pull container images, push logs, and other tasks. However, in certain scenarios, you might want to restrict internet access due to security or compliance requirements. This is where a Fargate ECS cluster with no internet connectivity comes into play.
In this post, we leverage VPC endpoints, which allow private connectivity between your VPC and supported AWS services. This means your Fargate tasks can communicate with necessary AWS services without requiring access to the public internet to the point where there is no network traffic that leaves your private VPC network beyond reaching out to integrations via PrivateLink endpoints.
Use Cases
Regulated Industries: For industries like finance (PCI DSS) or healthcare (HIPAA), where data security is paramount, this setup provides an additional layer of security by eliminating unnecessary internet access.
Data-Intensive Applications: For applications that require high-throughput, low-latency access to AWS services, using VPC endpoints can provide performance benefits.
Multi-Tier Applications: For applications with strict network segmentation requirements, you can use this setup to enforce network boundaries between tiers.
Advantages
Enhanced Security:
By eliminating the need for internet access, you reduce the attack surface that bad actors can leverage. This setup is particularly beneficial for sensitive workloads that require stringent security controls such as PCI DSS compliant systems.
Network Performance:
VPC endpoints enable private connectivity to AWS services, which can lead to lower latency and higher throughput compared to internet-based connections as they do not leave the AWS backbone network and follow the shortest possible path to target servers.
Cost Optimization:
Data transfer costs for VPC endpoints within the same region are typically lower than data transfer costs over the public internet.
Disadvantages
Complexity:
This of course comes with the added complexity of setting up more resources that are more laborious and knowledge intensive resulting in a more complex network architecture.
Service Limitations:
Not all AWS services support VPC endpoints. You'll need to ensure that the services your tasks depend on can be accessed via VPC endpoints for this to be a viable approach for you.
Cost:
While you can save on data transfer costs, there are costs associated with using VPC endpoints, unless you are only using S3/DynamoDB which will can add a pretty penny to your bill.
Example
In this example we will create a simple ECS Fargate service that is auto-scaled across AZ, which pulls it’s image from a private ECR repository and logs data to CloudWatch logs, without any network connectivity.
Step 1: Initialize the CDK App
First, we need to initialize a new CDK app in our preferred language, which for me is currently TypeScript. Let’s open up a terminal and run the following commands to get started:
> mkdir -p isolated-network-workloads/fargate
> cd isolated-network-workloads/fargate
> npx cdk init app --language=typescript
This will create a new CDK app in TypeScript with the following structure
Step 2: Define the VPC Stack
Next, we define the VPC stack where Fargate will place the container ENI.
Open up the lib
folder and create a new file called vpc-stack.ts
. Add the following code to create a new VPC with a private subnet and the required 4 VPC Endpoints:
ECR-API
ECR-Docker
S3
Logs
The ECR-API, ECR-Docker & S3 endpoints are needed for pulling the image and Logs is needed to send logs to CloudWatch.
Step 3: Define the Fargate Workload Stack
In this stack we will create the log group, security group, security group rules, cluster and service definition.
Create a file named fargate-stack.ts
with the following content:
Step 4: Define the App Stack
Deploying this stack is done via the main of:
Step 5: Deploy app
> AWS_PROFILE=<profile> npx cdk deploy --all
Do note that in-between the “VpcStack” and “FargateStack” ideally you should also populate the ECR repository with the image from DockerHub as we do not have any WAN access to pull it from there.
As such you should run the following commands in the terminal
> export REGION=<region> && export ACCOUNT_ID=<account_id>
> docker pull amazonlinux:2023.0.20230607.0
> docker tag amazonlinux:2023.0.20230607.0 $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/workload-service:latest
> aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com
> docker push $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/workload-service:latest
After the ECR repository is populated with the "amazonlinux” image, we can proceed with the second stack deployment:
Now we can see in the ECS console the running task processing our workload.
And this task is running completely disconnected from the internet on a compute cluster that can easily be configured to scale, react to inputs and process varying payloads in isolation.
Step 6: Cleanup
Now that we have created all the needed resources and have gained access within the estate, time to delete all the resources to avoid accruing unwanted charges to our account:
> npx cdk destroy --all
Conclusion
Running a Fargate ECS cluster with no internet connectivity is a powerful strategy for enhancing security and performance. However, it's not a one-size-fits-all solution. As with any architectural decision, it's crucial to weigh the benefits against the potential drawbacks and costs.
Remember, the goal is not to apply every possible security measure, but to apply the right measures for your specific use case. As always, keep your business requirements, regulatory landscape, and risk tolerance in mind when making these decisions.
I hope this deep dive has provided you with valuable insights into this advanced networking setup. As always, I'm here to answer any questions you might have. Let's continue to push the boundaries of what's possible with AWS!
You can find the entire codebase for the above example in my GitHub repo here.