---
title: "Deploy Alloy"
description: "Deploy Grafana Alloy on AWS ECS Fargate via CloudFormation for Aerospike Cloud monitoring."
---

# Deploy Alloy

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

This page guides you through deploying Grafana Alloy using a CloudFormation template. The template creates all required AWS resources with a single command.

This tutorial uses AWS CloudFormation because it requires no additional installation. For production deployments, consider translating the template to Terraform if your organization standardizes on it.

## What the template creates

The CloudFormation template creates:

-   An ECS Fargate cluster to run the Alloy container
-   IAM roles for ECS task execution
-   A CloudWatch log group for troubleshooting
-   An ECS service that keeps Alloy running

You do not need to understand CloudFormation to use this template.

## Create the template file

1.  Run the following command to create the CloudFormation template file:
    
    Terminal window
    
    ```shell
    cat > alloy-monitoring.yaml << 'EOF'
    
    AWSTemplateFormatVersion: '2010-09-09'
    
    Description: Deploy Grafana Alloy on ECS Fargate to monitor Aerospike Cloud
    
    Parameters:
    
      DatabaseHostname:
    
        Type: String
    
        Description: Your Aerospike Cloud database hostname
    
      GrafanaRemoteWriteUrl:
    
        Type: String
    
        Description: Your Grafana Cloud Prometheus remote write URL
    
      GrafanaInstanceId:
    
        Type: String
    
        Description: Your Grafana Cloud instance ID (numeric)
    
      GrafanaApiToken:
    
        Type: String
    
        NoEcho: true
    
        Description: Your Grafana Cloud API token
    
      SubnetId:
    
        Type: AWS::EC2::Subnet::Id
    
        Description: Subnet ID in your VPC with peering to Aerospike Cloud
    
      SecurityGroupId:
    
        Type: AWS::EC2::SecurityGroup::Id
    
        Description: Security group allowing outbound to ports 9145 and 443
    
    Resources:
    
      ECSCluster:
    
        Type: AWS::ECS::Cluster
    
        Properties:
    
          ClusterName: alloy-monitoring
    
      LogGroup:
    
        Type: AWS::Logs::LogGroup
    
        Properties:
    
          LogGroupName: /ecs/alloy-aerospike
    
          RetentionInDays: 7
    
      TaskExecutionRole:
    
        Type: AWS::IAM::Role
    
        Properties:
    
          RoleName: alloy-task-execution-role
    
          AssumeRolePolicyDocument:
    
            Version: '2012-10-17'
    
            Statement:
    
              - Effect: Allow
    
                Principal:
    
                  Service: ecs-tasks.amazonaws.com
    
                Action: sts:AssumeRole
    
          ManagedPolicyArns:
    
            - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
    
      TaskRole:
    
        Type: AWS::IAM::Role
    
        Properties:
    
          RoleName: alloy-task-role
    
          AssumeRolePolicyDocument:
    
            Version: '2012-10-17'
    
            Statement:
    
              - Effect: Allow
    
                Principal:
    
                  Service: ecs-tasks.amazonaws.com
    
                Action: sts:AssumeRole
    
      TaskDefinition:
    
        Type: AWS::ECS::TaskDefinition
    
        Properties:
    
          Family: alloy-aerospike
    
          NetworkMode: awsvpc
    
          RequiresCompatibilities:
    
            - FARGATE
    
          Cpu: '256'
    
          Memory: '512'
    
          ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
    
          TaskRoleArn: !GetAtt TaskRole.Arn
    
          ContainerDefinitions:
    
            - Name: alloy
    
              Image: grafana/alloy:latest
    
              Essential: true
    
              Environment:
    
                - Name: ALLOY_DATABASE_HOSTNAME
    
                  Value: !Ref DatabaseHostname
    
                - Name: ALLOY_GRAFANA_URL
    
                  Value: !Ref GrafanaRemoteWriteUrl
    
                - Name: ALLOY_GRAFANA_USER
    
                  Value: !Ref GrafanaInstanceId
    
                - Name: ALLOY_GRAFANA_TOKEN
    
                  Value: !Ref GrafanaApiToken
    
              EntryPoint:
    
                - /bin/sh
    
                - -c
    
              Command:
    
                - printf 'prometheus.scrape "aerospike" {\n  targets = [{"__address__" = "%s:9145"}]\n  scrape_interval = "15s"\n  forward_to = [prometheus.remote_write.grafana_cloud.receiver]\n}\nprometheus.remote_write "grafana_cloud" {\n  endpoint {\n    url = "%s"\n    basic_auth {\n      username = "%s"\n      password = "%s"\n    }\n  }\n}\n' "$ALLOY_DATABASE_HOSTNAME" "$ALLOY_GRAFANA_URL" "$ALLOY_GRAFANA_USER" "$ALLOY_GRAFANA_TOKEN" > /tmp/config.alloy && /bin/alloy run /tmp/config.alloy
    
              LogConfiguration:
    
                LogDriver: awslogs
    
                Options:
    
                  awslogs-group: /ecs/alloy-aerospike
    
                  awslogs-region: !Ref AWS::Region
    
                  awslogs-stream-prefix: alloy
    
      ECSService:
    
        Type: AWS::ECS::Service
    
        Properties:
    
          ServiceName: alloy-aerospike
    
          Cluster: !Ref ECSCluster
    
          TaskDefinition: !Ref TaskDefinition
    
          DesiredCount: 1
    
          LaunchType: FARGATE
    
          NetworkConfiguration:
    
            AwsvpcConfiguration:
    
              Subnets:
    
                - !Ref SubnetId
    
              SecurityGroups:
    
                - !Ref SecurityGroupId
    
              AssignPublicIp: ENABLED
    
    Outputs:
    
      ClusterName:
    
        Description: ECS Cluster name
    
        Value: !Ref ECSCluster
    
      ServiceName:
    
        Description: ECS Service name
    
        Value: !Ref ECSService
    
      LogGroupName:
    
        Description: CloudWatch Log Group for troubleshooting
    
        Value: !Ref LogGroup
    
    EOF
    ```
    
2.  Verify the file was created:
    
    Terminal window
    
    ```shell
    ls -la alloy-monitoring.yaml
    ```
    

## Deploy the stack

1.  Run the CloudFormation deploy command. Replace the placeholder values with your information from the prerequisites:
    
    Terminal window
    
    ```shell
    aws cloudformation deploy \
    
      --template-file alloy-monitoring.yaml \
    
      --stack-name alloy-monitoring \
    
      --capabilities CAPABILITY_NAMED_IAM \
    
      --parameter-overrides \
    
        DatabaseHostname=DATABASE_HOSTNAME \
    
        GrafanaRemoteWriteUrl=GRAFANA_REMOTE_WRITE_URL \
    
        GrafanaInstanceId=GRAFANA_INSTANCE_ID \
    
        GrafanaApiToken=GRAFANA_API_TOKEN \
    
        SubnetId=SUBNET_ID \
    
        SecurityGroupId=SECURITY_GROUP_ID
    ```
    
    Replace:
    
    -   `DATABASE_HOSTNAME` - Your Aerospike Cloud database hostname
    -   `GRAFANA_REMOTE_WRITE_URL` - Your Grafana Cloud Prometheus remote write URL
    -   `GRAFANA_INSTANCE_ID` - Your Grafana Cloud instance ID (numeric)
    -   `GRAFANA_API_TOKEN` - Your Grafana Cloud API token
    -   `SUBNET_ID` - Your VPC subnet ID
    -   `SECURITY_GROUP_ID` - Your security group ID
    
    ```plaintext
    Waiting for changeset to be created..
    
    Waiting for stack create/update to complete
    
    Successfully created/updated stack - alloy-monitoring
    ```
    
    Expected result (after 2-3 minutes)
    

The deployment takes 2-3 minutes. CloudFormation creates the resources in the correct order and waits for each to be ready.

## Verify the deployment

1.  Check that the ECS service is running:
    
    Terminal window
    
    ```shell
    aws ecs describe-services \
    
      --cluster alloy-monitoring \
    
      --services alloy-aerospike \
    
      --query 'services[0].{Status:status,Running:runningCount,Desired:desiredCount}'
    ```
    
    ```json
    {
    
        "Status": "ACTIVE",
    
        "Running": 1,
    
        "Desired": 1
    
    }
    ```
    
    Expected result
    
    If `Running` is 0, wait 30 seconds and try again.
    
2.  Check the container logs for any errors:
    
    Terminal window
    
    ```shell
    aws logs tail /ecs/alloy-aerospike --since 5m
    ```
    
    You should see Alloy startup messages. Look for lines indicating successful scraping.
    

::: undefined
-   I’ve downloaded the CloudFormation template.
-   I’ve deployed the monitoring stack.
-   I’ve verified the deployment is running.
:::

[Previous  
Tutorial prerequisites](https://aerospike.com/docs/cloud/monitor-cloud-with-grafana/step/1/part/0/prerequisites) [Next  
Configure Grafana Cloud](https://aerospike.com/docs/cloud/monitor-cloud-with-grafana/step/1/part/2/configure-grafana-cloud)