Install Grafana on EC2 with Terraform

May 15, 2024

we’ll explore how Terraform’s magic can automate the heavy lifting of provisioning EC2 instances and configuring Grafana. By the end of this journey, you’ll be equipped with the knowledge and confidence to breeze through deployment tasks and unlock the insights Grafana offers for monitoring and analytics.


Prerequisites

  1. Terraform v1.7.3 >
  2. AWS Account

1. Create AWS Access Keys

AWS access keys are credentials used to access Amazon Web Services (AWS) programmatically.

1. Log in to your AWS Account

Image

2. Click on your Profile name, and then click on My Security Credentials

Image

3. Find the Access keys section and create an access key

Image

4. Download your Access Keys

Image

2. Set up the Terraform

Setting up Grafana on Terraform in EC2 streamlines the process of deploying and managing Grafana instances, making it an efficient choice, particularly for medium-scale projects. By leveraging Terraform’s infrastructure as a code approach, you encapsulate the configuration of your Grafana deployment into a single, version-controlled file. This file acts as a blueprint for your infrastructure, detailing every aspect of the deployment, from the EC2 instance specifications to networking settings and Grafana configurations.

Let’s follow the steps below to finish our setup.

  1. Make a project folder
mkdir grafana-server && cd grafana-server
  1. create a main.tf file in the folder and paste this code.
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.region
  access_key = var.access_key_prod
  secret_key = var.secret_access_key_prod
}
  1. After successfully creating our main.tf, we then create our variables.tf
variable "region" {
  type    = string
  default = "eu-central-1"
}

variable "access_key" {
  type = string
}

variable "secret_access_key" {
  type = string
}

variable "ingress_ports" {
  type = list(object({
    ports =  number
    source = string
    description = string

  })
  )
}
  1. With this we have our variable requirements, Let’s create our terraform.tfvars file now.
region            = "<your_region>"
access_key = "<your_access_key>"
secret_access_key = "<your_secret_access_key>"

#this is the SG of instance
ingress_ports = [
{
  ports = 80
  source = "0.0.0.0/0"
   description = ""
},
{
  ports = 3000
  source = "0.0.0.0/0"
   description = ""
},
{
  ports = 443
  source = "0.0.0.0/0"
  description = ""
},
]
  1. Completing our variables, we can now create resources. Let’s create our network.tf
# Networking (VPC, RT, Subnets, etc...)
resource "aws_vpc" "grafana-vpc" {
  cidr_block       = "<your_selected_cidr_block>"
  instance_tenancy = "default"

  tags = {
    Name = "grafana-vpc"
    terraform_provisioned = "true"
  }
}

resource "aws_subnet" "grafana-subnet-1" {
  vpc_id = aws_vpc.grafana-vpc.id
  cidr_block       = "<your_selected_cidr_block>"
  availability_zone = "${var.region}a"
  map_public_ip_on_launch = true
  tags = {
    Name = "grafana-subnet-1"
    terraform_provisioned = "true"
  }
}

resource "aws_subnet" "grafana-subnet-2" {
  vpc_id = aws_vpc.grafana-vpc.id
  cidr_block       = "<your_selected_cidr_block>"
  availability_zone = "${var.region}b"
  map_public_ip_on_launch = true
  tags = {
    Name = "grafana-subnet-2"
    terraform_provisioned = "true"
  }
}


resource "aws_internet_gateway" "grafana-igw" {
  vpc_id = aws_vpc.grafana-vpc.id

  tags = {
    Name = "grafana-igw"
    terraform_provisioned = "true"
  }
}

# Creating Route Table for Public Subnet
resource "aws_route_table" "rt" {
    vpc_id = aws_vpc.grafana-vpc.id

    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = aws_internet_gateway.grafana-igw.id
      }
    tags = {
        Name = "grafana-public-rt"
      }
}

resource "aws_route_table_association" "rt-associate-public-1" {
    subnet_id = aws_subnet.grafana-subnet-1.id
    route_table_id = aws_route_table.rt.id
}

resource "aws_route_table_association" "rt-associate-public-2" {
    subnet_id = aws_subnet.grafana-subnet-2.id
    route_table_id = aws_route_table.rt.id
}

  1. Lastly, we then create our ec2.tf and paste this code. Insert the EC2 AMI ID and make sure it’s the same region.

resource "aws_security_group" "grafana-sg" {
  name = "grafana-sg"
  vpc_id      = aws_vpc.grafana-vpc.id

  dynamic "ingress" {
    for_each = var.ingress_ports

    content {
      from_port   = ingress.value["ports"]
      to_port     = ingress.value["ports"]
      protocol    = "tcp"
      cidr_blocks = [ingress.value["source"]]
      description = ingress.value["description"]
    }
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "grafana-sg"
  }
}


data "aws_ami" "amazon_linux" {
  most_recent = true
  owners = [ "amazon" ]

  filter {
    name   = "name"
    values = ["al2023-ami-*"]
  }

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }

}
resource "aws_instance" "grafana_smidige" {

  ami = data.aws_ami.amazon_linux.id
  instance_type = "t3a.medium"

  vpc_security_group_ids = [ aws_security_group.grafana-sg.id]
  subnet_id = aws_subnet.grafana-subnet-1.id

  associate_public_ip_address = true

  tags = {
    Name = "smidige-grafana"
  }

  user_data =  <<-EOF
                #!/bin/bash
                yum update -y
                echo -e "[grafana]\nname=grafana\nbaseurl=https://packages.grafana.com/oss/rpm\nrepo_gpgcheck=1\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.grafana.com/gpg.key\nsslverify=1\nsslcacert=/etc/pki/tls/certs/ca-bundle.crt" >> /etc/yum.repos.d/grafana.repo
                yum install grafana -y
                systemctl start grafana-server
                systemctl daemon-reload
                systemctl enable grafana-server.service

                EOF

}

resource "aws_eip" "lb" {
  instance = aws_instance.grafana_smidige.id
  domain   = "vpc"

  depends_on = [ aws_internet_gateway.grafana-igw ]
}

3. Launch our Grafana Server

With this setup and proper variables we can now launch our Grafana Server or use this as a Disaster recovery within a couple or few commands, follow these commands below to launch the EC2 Grafana Server.

on grafana-server directory run these commands;

terraform init
Image
terraform plan
Image

If you’ve confirmed that you’re creating the right resources for your AWS account, we can now run Terraform Apply and make sure to say yes for confirmation

terraform apply
Image

Congrats!! Now you have a Grafana instance and go to your favorite browser and open

http://<EC2-instance-IP-address>:3000

If the Grafana is successfully installed, it will redirect you to the login page. To log in you can use the default auth

username: admin
password: admin
Image

Conclusion:

In conclusion, setting up a Grafana EC2 instance is a structured process that enables powerful monitoring and visualization capabilities for your infrastructure. You can create a robust and secure monitoring solution by carefully following the steps to launch, install, and configure Grafana on an EC2 instance, and optionally integrating Prometheus for enhanced metric collection. This setup not only facilitates real-time data visualization but also ensures that your system metrics are accessible and manageable, ultimately aiding in maintaining the health and performance of your applications and infrastructure​