docs/integrations/prefect-azure/aci_worker.mdx
ACI (Azure Container Instances) is a fully managed compute platform that streamlines running your Prefect flows on scalable, on-demand infrastructure on Azure.
In this guide, you will:
prefect.yamlBefore starting this guide, make sure you have:
prefect and prefect-azure installed in your local Python environment.Install the required Python packages:
pip install -U "prefect[azure]"
Authenticate with Azure:
az login
If you're using a self-hosted Prefect server, make sure it is reachable from the Azure container instance that will run your worker. Starting prefect server start on your local machine is not sufficient unless that server is exposed to Azure.
For example, if you're running a local server for development, you can start it with:
prefect server start
Before continuing, confirm which Prefect profile is active:
prefect config view
If you're using Prefect Cloud, make sure your PREFECT_API_URL and PREFECT_API_KEY point at your workspace.
Azure resource groups serve as containers for managing groupings of Azure resources.
Replace <resource-group-name> with the name of your choosing, and <location> with a valid Azure location name, such as eastus.
export RG_NAME=<resource-group-name> && \
az group create --name $RG_NAME --location <location>
Throughout the rest of the guide, we'll need to refer to the scope of the created resource group, which is a string describing where the resource group lives in the hierarchy of your Azure account. To save the scope of your resource group as an environment variable, run the following command:
RG_SCOPE=$(az group show --name $RG_NAME --query id --output tsv)
You can check that the scope is correct before moving on by running echo $RG_SCOPE in your terminal. It should be formatted as follows:
/subscriptions/<subscription-id>/resourceGroups/<resource-group-name>
In order for the worker to create, monitor, and delete the other container instances in which flows will run, we'll need to create a custom role and an identity, and then affiliate that role to the identity with a role assignment. When we start our worker, we'll assign that identity to the container instance it's running in.
The custom Container Instances Contributor role has all the permissions your worker will need to run flows in other container instances. Create it by running the following command:
az role definition create --role-definition '{
"Name": "Container Instances Contributor",
"IsCustom": true,
"Description": "Can create, delete, and monitor container instances.",
"Actions": [
"Microsoft.ManagedIdentity/userAssignedIdentities/assign/action",
"Microsoft.Resources/deployments/*",
"Microsoft.ContainerInstance/containerGroups/*"
],
"NotActions": [
],
"AssignableScopes": [
'"\"$RG_SCOPE\""'
]
}'
Create a user-managed identity with the following command, replacing <identity-name> with the name you'd like to use for the identity:
export IDENTITY_NAME=<identity_name> && \
az identity create -g $RG_NAME -n $IDENTITY_NAME
We'll also need to save the principal ID and full object ID of the identity for the role assignment and container creation steps, respectively:
IDENTITY_PRINCIPAL_ID=$(az identity list --query "[?name=='$IDENTITY_NAME'].principalId" --output tsv) && \
IDENTITY_ID=$(az identity list --query "[?name=='$IDENTITY_NAME'].id" --output tsv)
Now let's assign the Container Instances Contributor role we created earlier to the new identity:
az role assignment create \
--assignee $IDENTITY_PRINCIPAL_ID \
--role "Container Instances Contributor" \
--scope $RG_SCOPE
Since we'll be using ACR to host a custom Docker image containing a Prefect flow later in the guide, let's also assign the built in AcrPull role to the identity:
az role assignment create \
--assignee $IDENTITY_PRINCIPAL_ID \
--role "AcrPull" \
--scope $RG_SCOPE
Before running this command, set your PREFECT_API_URL and PREFECT_API_KEY as environment variables.
Use a PREFECT_API_URL that the ACI worker container can actually reach:
/api endpoint.Do not use http://127.0.0.1:4200/api or another localhost address here. Inside ACI, 127.0.0.1 resolves to the worker container itself, not to a Prefect server running on your local machine.
export PREFECT_API_URL=<PREFECT_API_URL_HERE> PREFECT_API_KEY=<PREFECT_API_KEY_HERE>
Running the following command will create a container instance in your Azure resource group that will start a Prefect ACI worker. If there is not already a work pool in Prefect with the name you chose, a work pool will also be created.
Replace <work-pool-name> with the name of the ACI work pool you want to create in Prefect. Here we're using the work pool name as the name of the container instance in Azure as well, but you may name it something else if you prefer.
az container create \
--name <work-pool-name> \
--resource-group $RG_NAME \
--assign-identity $IDENTITY_ID \
--image "prefecthq/prefect-azure:latest" \
--secure-environment-variables PREFECT_API_URL=$PREFECT_API_URL PREFECT_API_KEY=$PREFECT_API_KEY \
--command-line "/bin/bash -c 'prefect worker start --pool <work-pool-name> --type azure-container-instance'"
This container instance uses default networking and security settings. For advanced configuration, refer to the az container create CLI reference.
In order to build and push images containing flow code to Azure, we'll need a container registry. Create one with the following command, replacing <registry-name> with the registry name of your choosing:
export REGISTRY_NAME=<registry-name> && \
az acr create --resource-group $RG_NAME \
--name <registry-name> --sku Basic
Once your work pool is created, navigate to the Edit page of your ACI work pool. You will need to update the following fields:
This will be your IDENTITY_ID. You can get it from your terminal by running echo $IDENTITY_ID. When adding it to your work pool, it should be formatted as a JSON array:
["/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>"]
ACRManagedIdentity is required for your flow code containers to be pulled from ACR. It consists of the following:
IDENTITY_ID as above, as a string/subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<identity-name>
<registry-name>, followed by .azurecr.io<registry-name>.azurecr.io
Both the subscription ID and resource group name can be found in the RG_SCOPE environment variable created earlier in the guide. View their values by running echo $RG_SCOPE:
/subscriptions/<subscription-id>/resourceGroups/<resource-group-name>
Then click Save.
This guide uses ACR to store a Docker image containing your flow code.
In the Prefect UI, open your work pool and verify that the worker you started in Azure shows as online before deploying a flow.
Use the following commands to log in to ACR:
TOKEN=$(az acr login --name $REGISTRY_NAME --expose-token --output tsv --query accessToken)
docker login $REGISTRY_NAME.azurecr.io --username 00000000-0000-0000-0000-000000000000 --password-stdin <<< $TOKEN
Create a file named my_flow.py:
from prefect import flow
from prefect.logging import get_run_logger
@flow
def my_flow():
logger = get_run_logger()
logger.info("Hello from ACI!")
Choose either the Python-based deployment flow or a prefect.yaml-based deployment flow.
Add a deployment section to my_flow.py and run the file:
from prefect import flow
from prefect.docker import DockerImage
from prefect.logging import get_run_logger
@flow
def my_flow():
logger = get_run_logger()
logger.info("Hello from ACI!")
if __name__ == "__main__":
my_flow.deploy(
name="aci-deployment",
work_pool_name="<work-pool-name>",
image=DockerImage(
name="<registry-name>.azurecr.io/example:latest",
platform="linux/amd64",
),
)
python my_flow.py
This builds the image, pushes it to ACR, and creates a deployment in Prefect.
</Tab> <Tab title="Deploy with prefect.yaml">If you want to use the Docker build and push steps shown below, install prefect-docker first:
pip install prefect-docker
Create a prefect.yaml file in the same directory:
build:
- prefect_docker.deployments.steps.build_docker_image:
id: build-image
image_name: <registry-name>.azurecr.io/example
tag: latest
dockerfile: auto
push:
- prefect_docker.deployments.steps.push_docker_image:
image_name: "{{ build-image.image_name }}"
tag: "{{ build-image.tag }}"
pull:
- prefect.deployments.steps.set_working_directory:
directory: /opt/prefect
deployments:
- name: aci-deployment
entrypoint: my_flow.py:my_flow
work_pool:
name: <work-pool-name>
job_variables:
image: "{{ build-image.image }}"
Then create the deployment:
prefect deploy --prefect-file prefect.yaml --all
Once the deployment is created, you can run it from either the Prefect UI or the CLI:
prefect deployment run "my-flow/aci-deployment"
If everything is configured correctly, the worker will pull the image from ACR and start a new Azure Container Instance for the flow run.