Skip to content

Deploy Alloy

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
    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
    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
    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
    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
    aws ecs describe-services \
    --cluster alloy-monitoring \
    --services alloy-aerospike \
    --query 'services[0].{Status:status,Running:runningCount,Desired:desiredCount}'
    {
    "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
    aws logs tail /ecs/alloy-aerospike --since 5m

    You should see Alloy startup messages. Look for lines indicating successful scraping.

Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?