How to manually deploy an ECS worker to an ECS cluster
Step-by-step guide for manually setting up ECS infrastructure to run Prefect workers with full control over cluster configuration, IAM roles, and task definitions.
This guide is valid for users of self-hosted Prefect server or Prefect Cloud users with a tier that allows hybrid work pools.
This guide walks you through manually setting up ECS infrastructure to run Prefect workers. For architecture concepts and overview, see the ECS Worker overview.
No further configuration is required for this guide, as we will use the Fargate launch type and the default VPC.
For production deployments, it is recommended that you create your own VPC with appropriate security policies based on your organization’s recommendations.If you want to create a new VPC for this guide, follow the VPC creation guide.
First, create an ECS work pool for your deployments to use. You can do this either from the CLI or the Prefect UI.If doing so from the CLI, be sure to authenticate with Prefect Cloud or run a local Prefect server instance.
Run the following command to create a new ECS work pool named my-ecs-pool:
Copy
prefect work-pool create --type ecs my-ecs-pool
Because this guide uses Fargate as the capacity provider, this step requires no further action.
If you are using a Prefect self-hosted server and have authentication disabled, you can skip this step.
The Prefect worker needs to authenticate with your Prefect server to poll the work pool for flow runs. For authentication, you must provide a Bearer token (PREFECT_API_KEY) or Basic Auth string (PREFECT_API_AUTH_STRING) to the Prefect API. As a security best practice, we recommend you store your Prefect API key in AWS Secrets Manager or Systems Manager Parameter Store.
1
Find your secret
You can find your Prefect API key several ways:
Prefect Cloud - Paid Plans
If you are on a paid plan you can create a service account for the worker.
Prefect Cloud - Free Plans
If you are on a free plan, you can use a user’s API key.To find your API key, use the Prefect CLI:
Copy
# If not already authenticated, log in firstprefect cloud loginprefect config view --show-secrets
Self-hosted Prefect server
There is no concept of a PREFECT_API_KEY in a self-hosted Prefect server.Instead, you use the PREFECT_API_AUTH_STRING containing your basic auth credentials (if your server uses basic authentication).You can find this information on the Settings page for your Prefect server.
2
Create a secret
Choose between AWS Secrets Manager or Systems Manager Parameter Store to store your Prefect API key. Both services allow you to securely store and manage sensitive information such as API keys, passwords, and other secrets.
Make a note of the Amazon Resource Name (ARN) of the secret that is returned in the command output. You will need it later when configuring the ECS worker task definition.
The trust policy will allow the ECS service containing the Prefect worker to assume the role required for calling other AWS services. This is called a service-linked role. The trust policy is a JSON document that specifies which AWS service can assume the role.Save this policy to a file, such as trust-policy.json:
The ECS task execution role will be used to start the ECS worker task. We will assign it a minimal set of permissions to allow the worker to pull images from ECR and publish logs to CloudWatch.
aws iam create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://trust-policy.json
Make a note of the ARN (Amazon Resource Name) of the role that is returned in the command output. You will need it later when creating the ECS task definition.
2
Create the Secret Policy
The following is a minimal policy that grants the necessary permissions for ECS to obtain the current value of the secret and inject it into the ECS task. Save this policy to a file, such as secret-policy.json:
If your secret is encrypted with a customer-managed key (CMK) in AWS Key Management Service (KMS), you will also need to add the kms:Decrypt permission to the policy. For example:
Create a new IAM policy named ecsTaskExecutionPolicy using the policy document you just created.
Copy
aws iam create-policy --policy-name ecsTaskExecutionPolicy --policy-document file://secret-policy.json
4
Attach the Policies
The AmazonECSTaskExecutionRolePolicy managed policy grants the minimum permissions necessary for starting ECS tasks. See here for other common execution role permissions.Attach this policy to your task execution role using the aws iam attach-role-policy:
Copy
aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Attach the custom policy you created in the previous step so that the ECS task can access the Prefect API key stored in AWS Secrets Manager or Systems Manager Parameter Store:
Copy
aws iam put-role-policy --role-name ecsTaskExecutionRole --policy-name PrefectECSWorkerSecretPolicy --policy-document file://secret-policy.json
The worker ECS task role will be used by the Prefect worker to interact with the AWS API to run flows as ECS containers. This role will require the ability to describe, register, and deregister ECS task definitions, as well as the ability to start and stop ECS tasks.
1
Create the role
Use the following command to create the role. The same trust policy is also used for this role.
Copy
aws iam create-role --role-name ecsTaskRole --assume-role-policy-document file://trust-policy.json
2
Create the task policy
The following is a minimal policy that grants the necessary permissions for the Prefect ECS worker to run your flows as ECS tasks. Save this policy to a file, such as worker-policy.json:
This step is optional, but recommended if your flows require access to other AWS services.
Depending on the requirements of your flows, it is advised to create a separate role for your ECS tasks. This role will contain the permissions required by the ECS tasks in which your flows will run. For example, if your workflow loads data into an S3 bucket, you would need a role with additional permissions to access S3.
Create flow run IAM role
1
Create the role
Use the following command to create the role:
Copy
aws iam create-role --role-name PrefectECSRunnerTaskRole --assume-role-policy-document file://trust-policy.json
2
Create the task policy
The following is an example policy that allows reading/writing to an S3 bucket named prefect-demo-bucket. Save this policy to a file, such as runner-task-policy.json:
To enable the ECS worker to monitor and update the status of flow runs, we need to set up SQS queues and EventBridge rules that capture ECS task state changes. This infrastructure allows the worker to:
Track when ECS tasks (flow runs) start, stop, or fail
Update flow run states in real-time based on ECS task events
Provide better observability and status reporting for your workflows
This step sets up the same event monitoring infrastructure that the prefect-aws ecs-worker deploy-events command creates automatically. The worker will use the environment variable PREFECT_INTEGRATIONS_AWS_ECS_OBSERVER_SQS_QUEUE_NAME to discover and read from the events queue.
1
Create SQS queues for event monitoring
Create an SQS queue to receive ECS task state change events and a dead-letter queue for handling failed messages.First, create the dead-letter queue:
<aws-arn-of-secret> with the ARN of the resource from Secrets Manager or Systems Manager Parameter Store.
my-ecs-pool-events in the PREFECT_INTEGRATIONS_AWS_ECS_OBSERVER_SQS_QUEUE_NAME environment variable with your actual queue name from the event monitoring setup.
Finding your Secret ARN
Your secret ARN is based on the service you are using:
Secrets Manager
You can find the ARN of your secret using the following command:
Copy
aws secretsmanager describe-secret --secret-id PrefectECSWorkerAPIKey --query 'ARN' --output text
Systems Manager Parameter Store
You can find the ARN of your parameter using the following command:
Copy
aws ssm get-parameter --name "/prefect/my-ecs-pool/api/key" --query 'Parameter.ARN' --output text
Self-hosted Prefect server
As PREFECT_API_KEY is not used with a self-hosted Prefect server, you will need to replace the PREFECT_API_KEY environment variable in the task definition secrets with PREFECT_API_AUTH_STRING.
Notice that the CPU and Memory allocations are relatively small. The worker’s main responsibility is to submit work through API calls to AWS, not to execute your Prefect flow code.
Replace task-definition.json with the name of your task definition file.
3
Create the ECS service
Finally, create a service that will manage your Prefect worker.Ensure you replace the placeholders for:
<ecs-cluster> with the name of your ECS cluster.
<task-definition-arn> with the ARN of the task definition you just registered.
<subnet-ids> with a comma-separated list of your VPC subnet IDs.
Replace <security-group-ids> with a comma-separated list of your VPC security group IDs.
Get default VPC info
If you are using the default VPC, you will need to gather some information about it to use in the next steps.We will use the default VPC for this guide. To find the default VPC ID, run the following command:
Copy
aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query "Vpcs[0].VpcId" --output text
This will output the VPC ID (e.g. vpc-abcdef01) of the default VPC, which you can use in the next steps in this section.To find the subnets associated with the default VPC:
Copy
aws ec2 describe-subnets --filters "Name=vpc-id,Values=<vpc-id>" --query "Subnets[*].SubnetId" --output text
Which will output a list of available subnets (e.g. subnet-12345678 subnet-23456789).Finally, we will need the security group ID for the default VPC:
Copy
aws ec2 describe-security-groups --filters "Name=vpc-id,Values=<vpc-id>" "Name=group-name,Values=default" --query "SecurityGroups[*].GroupId" --output text
This will output the security group ID (e.g. sg-12345678) of the default security group.Copy the subnet IDs and security group ID for use in Step 3.
Use the aws ecs create-service command to create an ECS service running on Fargate for the Prefect worker:
Now that your infrastructure is deployed, you should update your ECS work pool configuration with the resource identifiers so they don’t need to be specified on every deployment.
1
Update work pool via the UI
Navigate to your work pool in the Prefect UI and update the following fields in the Infrastructure tab:
Cluster ARN: Set to your ECS cluster ARN (e.g., arn:aws:ecs:us-east-1:123456789012:cluster/my-cluster)
VPC ID: Set to your VPC ID (e.g., vpc-12345678)
Subnets: Add your subnet IDs (e.g., subnet-12345678,subnet-87654321)
Execution Role ARN: Set to the task execution role ARN (e.g., arn:aws:iam::123456789012:role/ecsTaskExecutionRole)
These settings will be used as defaults for all deployments using this work pool, but can be overridden per deployment if needed.
2
Alternative: Update work pool via API
You can also update the work pool configuration programmatically using the Prefect API:
This guide uses the AWS Elastic Container Registry (ECR) to store a Docker image containing your flow code. To do this, we will write a flow, then deploy it using build and push steps that copy flow code into a Docker image and push that image to an ECR repository.
1
Write a simple test flow
my_flow.py
Copy
from prefect import flowfrom prefect.logging import get_run_logger@flowdef my_flow(): logger = get_run_logger() logger.info("Hello from ECS!!")if __name__ == "__main__": my_flow()
2
Create an ECR repository
Use the aws ecr create-repository command to create an ECR repository. The name you choose for your repository will be reused in the next step when defining your Prefect deployment.
If your worker does not appear in the Prefect UI, check the following:
Ensure that the ECS service is running and that the task definition is registered correctly.
Check the ECS service logs in CloudWatch to see if there are any errors.
Verify that the IAM roles have the correct permissions.
Ensure that the PREFECT_API_URL and PREFECT_API_KEY environment variables are set correctly in the task definition.
For self-hosted Prefect servers, ensure that you replaced PREFECT_API_KEY from the example with PREFECT_API_AUTH_STRING in the task definition.
Ensure your Prefect ECS worker has network connectivity to the Prefect API. If you are using a private VPC, ensure that there is a NAT gateway or internet gateway configured to allow outbound traffic to the Prefect API.
Now that you are confident your ECS worker is healthy, you can experiment with different work pool configurations.
Do your flow runs require higher CPU?
Would an EC2 Launch Type speed up your flow run execution?
These infrastructure configuration values can be set on your ECS work pool or they can be overridden on the deployment level through job_variables if desired.