Private Fargate Deployment with VPC Endpoints
Tags: aws, vpc, fargate, ecr
Published: 2020-01-25 20:41:10

VPC Endpoints allow you to have private containers, pulled from ECR repositories, with no external network ingress or egress. These containers can enhance your infrastructure security posture by utilizing AWS PrivateLink, restricting packets from going over the public internet.

### Assumptions/Prereqs
- You have a private ECR repository, with a tagged image created in your AWS Region.
- The example code definitions will contain statically coded capacity metrics, as a low-cost deployment. If you are using this in your environment, it is recommended you variablize, or increase the static values.
- The code __will not__ restrict the endpoints, as it is expected the roles on your resources will preform that restriction, however, there will be linked AWS reference documentation, if you require.
- The architecture will have zero public subnets or internet egress. You may require this additional infrastructure, but is outside the scope, and shouldn't impact the defined code.

### Architecture
The environment will use a trimmed-down version of a common VPC configuration, with only 2 private subnets, and a Fargate instance. It will also include the respective VPC Endpoints needed for pulling an image and posting logs.

![Architecture Diagram](https://prod.tournamentmgr.com/archive/07-20-2017/img/Private+Subnet+Gateways.png)

### Process
To enable containers to pull from ECR several steps are needed. Below broken down terraform code will walk through an end to end build, but this is the process that code will perform.

1. Configure a VPC with 2 private subnets and allow DNS Hostname Resolve and Support
1. Configure a VPC Endpoint Security Group to allow your VPC's CIDR as Ingress
    - This will be utilized for all internal addresses to communicate with the interfaces, as private DNS will resolve to an internal address.
1. Create an ECR DKR Service Endpoint
    - Service types: `com.amazonaws.<region>.ecr.dkr`
    - [Minimal Permission Reference](https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html#ecr-vpc-endpoint-policy)
1. Create a S3 Endpoint, which will connect to the starport bucket
    - Service types: `com.amazonaws.<region>.s3`
    - Note from AWS Documentation:
    
    > The gateway endpoint is required because Amazon ECR uses Amazon S3 to store Docker image layers... The gateway endpoint is required because Amazon ECR uses Amazon S3 to store Docker image layers:
    `arn:aws:s3:::prod-<region>-starport-layer-bucket/*`
    - [Minimal Permission Reference](https://docs.aws.amazon.com/AmazonECR/latest/userguide/ecr-minimum-s3-perms.html)

1. Create Logs endpoint to allow your container to log to CloudWatch
    - Service types: `com.amazonaws.<region>.logs`
1. Configure your Fargate service with egress to the VPC and S3 private gateway

### Terraform
#### Variable Declaration
Create a variables.tf file for the ECR Image you will pass in.
{% gist https://gist.github.com/danquack/5c4ffc2b57324005a3f782366b4da3ce file=variables.tf %}

#### Provider and Account Data
Initialize the config with providers and data.
{% gist https://gist.github.com/danquack/5c4ffc2b57324005a3f782366b4da3ce file=main.tf %}

#### Security Groups
Provision the Security Groups for the VPC Endpoints and Fargate instance.
{% gist https://gist.github.com/danquack/5c4ffc2b57324005a3f782366b4da3ce file=sg.tf %}

#### VPC Endpoints
Configure the VPC Endpoints for S3, DKR, and logging.
{% gist https://gist.github.com/danquack/5c4ffc2b57324005a3f782366b4da3ce file=vpce.tf %}

#### Fargate Service
Configure your IAM Role, task definition, and Fargate service.
{% gist https://gist.github.com/danquack/5c4ffc2b57324005a3f782366b4da3ce file=fargate.tf %}

### Execution
`terraform apply -var app_image=<your ECR image name>`
 
### References 
[Amazon ECR Interface VPC Endpoints](https://docs.aws.amazon.com/AmazonECR/latest/userguide/vpc-endpoints.html)

#### Updates
This post was written with Fargate 1.3. If having issues pulling from registry, ensure to check out this [Stack Overflow solution](https://stackoverflow.com/questions/61265108/aws-ecs-fargate-resourceinitializationerror-unable-to-pull-secrets-or-registry).