# =============================================================================
# PROMETHEUS-MCP INTEGRATION
# =============================================================================
# Add this file to your EKS Terraform to deploy prometheus-mcp
#
# Prerequisites:
# - EKS module with enable_irsa = true
# - Helm provider configured
#
# Required Input:
# - amp_workspace_id (your AMP workspace ID)
#
# QUICKSTART:
# export TF_VAR_amp_workspace_id="ws-your-workspace-id"
# terraform apply
#
# =============================================================================
# -----------------------------------------------------------------------------
# VARIABLES
# -----------------------------------------------------------------------------
variable "amp_workspace_id" {
description = <<-EOT
AWS Managed Prometheus workspace ID.
REQUIRED - Set via one of these methods (in order of preference):
1. Environment variable (recommended for CI/CD):
export TF_VAR_amp_workspace_id="ws-abc123-def456-7890"
2. Command line:
terraform apply -var="amp_workspace_id=ws-abc123-def456-7890"
3. terraform.tfvars file:
amp_workspace_id = "ws-abc123-def456-7890"
To find your workspace ID:
aws amp list-workspaces --query "workspaces[].workspaceId" --output text
EOT
type = string
validation {
condition = can(regex("^ws-", var.amp_workspace_id))
error_message = "amp_workspace_id must start with 'ws-'. Example: ws-abc123-def456-7890"
}
}
variable "prometheus_mcp_image" {
description = "Container image for prometheus-mcp"
type = string
default = "ghcr.io/deeptrace/prometheus-mcp:0.1.0"
}
variable "prometheus_mcp_dedicated_nodes" {
description = <<-EOT
Enable dedicated node group for prometheus-mcp.
When true (default):
- Pods only run on nodes with label: workload=<prometheus_mcp_node_label>
- You must add a matching node group to your EKS module (see example below)
When false:
- Pods can run on any node in the cluster
EOT
type = bool
default = true
}
variable "prometheus_mcp_node_label" {
description = <<-EOT
Node selector label value for dedicated node group.
Must match the 'workload' label on your node group.
Default: "prometheus-mcp"
Your node group should have:
labels = { workload = "prometheus-mcp" }
EOT
type = string
default = "prometheus-mcp"
}
variable "prometheus_mcp_replicas" {
description = "Number of prometheus-mcp pod replicas"
type = number
default = 2
}
# -----------------------------------------------------------------------------
# LOCALS
# -----------------------------------------------------------------------------
locals {
prometheus_mcp_namespace = "prometheus-mcp"
prometheus_mcp_serviceaccount = "prometheus-mcp"
prometheus_mcp_oidc_url = replace(module.eks.cluster_oidc_issuer_url, "https://", "")
}
# -----------------------------------------------------------------------------
# NODE GROUP EXAMPLE
# -----------------------------------------------------------------------------
#
# Add this node group to your EKS module's eks_managed_node_groups:
#
# prometheus-mcp = {
# name = "prometheus-mcp"
# instance_types = ["t3.medium"]
#
# min_size = 2
# max_size = 5
# desired_size = 2
#
# ami_type = "AL2_x86_64"
#
# # IMPORTANT: This label must match var.prometheus_mcp_node_label
# labels = {
# workload = "prometheus-mcp" # ← Must match!
# }
#
# # NOTE: EKS managed node groups AUTOMATICALLY get these IAM policies:
# # - AmazonEKSWorkerNodePolicy
# # - AmazonEC2ContainerRegistryReadOnly (for ECR image pulls)
# # - AmazonEKS_CNI_Policy
# }
#
# -----------------------------------------------------------------------------
# IAM ROLE FOR PROMETHEUS-MCP PODS (IRSA)
# -----------------------------------------------------------------------------
resource "aws_iam_role" "prometheus_mcp_pod" {
name = "${var.cluster_name}-prometheus-mcp-pod"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = module.eks.oidc_provider_arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"${local.prometheus_mcp_oidc_url}:sub" = "system:serviceaccount:${local.prometheus_mcp_namespace}:${local.prometheus_mcp_serviceaccount}"
"${local.prometheus_mcp_oidc_url}:aud" = "sts.amazonaws.com"
}
}
}
]
})
tags = {
Component = "prometheus-mcp"
}
}
# -----------------------------------------------------------------------------
# IAM POLICY - PERMISSIONS TO QUERY AMP
# -----------------------------------------------------------------------------
resource "aws_iam_policy" "prometheus_mcp_query" {
name = "${var.cluster_name}-prometheus-mcp-query"
description = "Allows prometheus-mcp pods to query AWS Managed Prometheus"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"aps:QueryMetrics",
"aps:GetLabels",
"aps:GetSeries",
"aps:GetMetricMetadata"
]
Resource = "arn:aws:aps:${var.aws_region}:${data.aws_caller_identity.current.account_id}:workspace/${var.amp_workspace_id}"
}
]
})
}
resource "aws_iam_role_policy_attachment" "prometheus_mcp_pod" {
role = aws_iam_role.prometheus_mcp_pod.name
policy_arn = aws_iam_policy.prometheus_mcp_query.arn
}
# -----------------------------------------------------------------------------
# HELM RELEASE - DEPLOY PROMETHEUS-MCP
# -----------------------------------------------------------------------------
resource "helm_release" "prometheus_mcp" {
name = "prometheus-mcp"
namespace = local.prometheus_mcp_namespace
create_namespace = true
# Path to the Helm chart (relative to Terraform working directory)
chart = "${path.module}/../charts/prometheus-mcp"
# AWS configuration
set {
name = "aws.region"
value = var.aws_region
}
# AMP configuration
set {
name = "amp.workspaceId"
value = var.amp_workspace_id
}
# IRSA configuration
set {
name = "irsa.enabled"
value = "true"
}
set {
name = "irsa.roleArn"
value = aws_iam_role.prometheus_mcp_pod.arn
}
# Container image
set {
name = "image.repository"
value = split(":", var.prometheus_mcp_image)[0]
}
set {
name = "image.tag"
value = length(split(":", var.prometheus_mcp_image)) > 1 ? split(":", var.prometheus_mcp_image)[1] : "latest"
}
# Replica count
set {
name = "replicaCount"
value = var.prometheus_mcp_replicas
}
# Node selector for dedicated nodes
# When dedicated_nodes=true (default): pods only run on nodes with matching label
# When dedicated_nodes=false: nodeSelector is empty (runs on any node)
dynamic "set" {
for_each = var.prometheus_mcp_dedicated_nodes ? [1] : []
content {
name = "nodeSelector.workload"
value = var.prometheus_mcp_node_label
}
}
# Wait for deployment to be ready
wait = true
timeout = 300
depends_on = [
module.eks,
aws_iam_role_policy_attachment.prometheus_mcp_pod
]
}
# -----------------------------------------------------------------------------
# OUTPUTS
# -----------------------------------------------------------------------------
output "prometheus_mcp_role_arn" {
description = "IAM role ARN for prometheus-mcp pods"
value = aws_iam_role.prometheus_mcp_pod.arn
}
output "prometheus_mcp_namespace" {
description = "Kubernetes namespace for prometheus-mcp"
value = local.prometheus_mcp_namespace
}
output "prometheus_mcp_service" {
description = "Kubernetes service name for prometheus-mcp"
value = "prometheus-mcp"
}
output "prometheus_mcp_node_label" {
description = "Node label required for the prometheus-mcp node group"
value = var.prometheus_mcp_dedicated_nodes ? "workload=${var.prometheus_mcp_node_label}" : "No dedicated nodes (runs on any node)"
}