{
  "id": "4LHGw67ULyJvisPt",
  "name": "Prometheus_Alerts_to_Slack",
  "tags": [],
  "nodes": [
    {
      "id": "00e6a4e1-ecd9-40a2-bee1-910aad4b6487",
      "name": "\ud83d\udd52 Every 5 Min Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -640,
        -40
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4984d9e8-3380-4924-b16f-65bc805dff9a",
      "name": "\ud83d\udce4 Send Alerts to Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1000,
        -20
      ],
      "parameters": {
        "url": "https://slack.com/api/chat.postMessage",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "channel",
              "value": "#k8s-alerts"
            },
            {
              "name": "text",
              "value": "={{$json[\"text\"]}}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "580b3473-4327-4c5e-906c-3ab65efcb945",
      "name": "Format Prometheus JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        0,
        -40
      ],
      "parameters": {
        "jsCode": "const results = $json[\"data\"][\"result\"];\n\nconst grouped = {};\n\nfor (const item of results) {\n  const pod = item.metric.pod;\n  const namespace = item.metric.namespace;\n  const cpu = parseFloat(item.value[1]);\n\n  // Extract app name (prefix before first hyphen)\n  const app = pod.split('-')[0];\n\n  if (!grouped[app]) grouped[app] = [];\n\n  grouped[app].push({\n    pod,\n    namespace,\n    cpu,\n    app\n  });\n}\n\n// Convert grouped object into items for n8n SplitOut\nconst output = [];\n\nfor (const app in grouped) {\n  output.push({\n    json: {\n      app,\n      pods: grouped[app]\n    }\n  });\n}\n\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "af88e375-e0d8-4721-b9d3-2bb9284e834b",
      "name": "Check Number of Pods in Group",
      "type": "n8n-nodes-base.if",
      "position": [
        340,
        -40
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8e09814f-276a-47e4-9910-3a990f4242fb",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json[\"pods\"].length }}\n",
              "rightValue": "=1"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2,
      "alwaysOutputData": true
    },
    {
      "id": "83f68a95-089f-4ed9-8847-99c85def9f49",
      "name": "Format Batched Slack Message",
      "type": "n8n-nodes-base.code",
      "position": [
        680,
        -140
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const pods = item.json[\"pods\"];\n  const app = item.json[\"app\"];\n  const namespace = pods[0].namespace;\n\n  let msg = `:rotating_light: *High CPU Spike Alert*\\n*App:* ${app}\\n*Namespace:* ${namespace}\\n\\n`;\n\n  for (const p of pods) {\n    msg += `\u2022 Pod: \\`${p.pod}\\` \u2013 CPU: *${p.cpu.toFixed(2)}* cores\\n`;\n  }\n\n  return {\n    json: {\n      text: msg\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "6c3e1da0-645e-4f36-880c-8fee9c019552",
      "name": "Format Single Pod Slack Message",
      "type": "n8n-nodes-base.code",
      "position": [
        680,
        60
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const pods = item.json[\"pods\"];\n  const app = item.json[\"app\"];\n  const namespace = pods[0].namespace;\n\n  let msg = `:rotating_light: *High CPU Spike Alert*\\n*App:* ${app}\\n*Namespace:* ${namespace}\\n\\n`;\n\n  for (const p of pods) {\n    msg += `\u2022 Pod: \\`${p.pod}\\` \u2013 CPU: *${p.cpu.toFixed(2)}* cores\\n`;\n  }\n\n  return {\n    json: {\n      text: msg\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0b4a97e6-7516-4045-beb9-290325665423",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -700,
        180
      ],
      "parameters": {
        "color": 7,
        "height": 280,
        "content": "\u23f0 Triggers every 5 minutes to check Prometheus for CPU spikes.\n\nYou can change the interval as per need (e.g., 1 min for aggressive monitoring).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ebb55741-b49f-4ca4-9114-6e8c3c0b424b",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -380,
        180
      ],
      "parameters": {
        "color": 7,
        "height": 280,
        "content": "\ud83d\udce1 HTTP GET request to Prometheus querying high CPU usage per pod.\n\nUses PromQL to get pods exceeding CPU usage threshold (e.g., > 0.8 cores).\n\nMake sure Prometheus is accessible from n8n and the query is correctly tuned.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6d342260-4433-40e8-9eaa-c33990bd27f0",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -60,
        180
      ],
      "parameters": {
        "color": 7,
        "height": 280,
        "content": "\ud83e\udde0 Transforms raw Prometheus JSON to array of pods with:\n\n\u2022 app name\n\u2022 namespace\n\u2022 pod name\n\u2022 CPU usage (as float)\n\nFilters only those pods with CPU usage above the threshold.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3c4cff88-df27-4442-81a7-decc367019b6",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        260,
        180
      ],
      "parameters": {
        "color": 7,
        "height": 280,
        "content": "\ud83d\udd0e Checks if multiple pods from the same app have crossed the threshold.\n\n\u2022 If pods.length > 1 \u2192 grouped alert\n\u2022 Else \u2192 single pod alert\n\nExpression used:\n{{ $json[\"pods\"].length > 1 }}\n"
      },
      "typeVersion": 1
    },
    {
      "id": "43dff7d5-ff57-4d09-bdeb-f03cc74ba37d",
      "name": "Query Prometheus for CPU Spikes",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -320,
        -40
      ],
      "parameters": {
        "url": "http://prometheus-kube-prometheus-prometheus.monitoring:9090/api/v1/query?query=sum by (namespace, pod) (   rate(container_cpu_usage_seconds_total{container!=\"\", image!=\"\"}[5m]) ) / clamp_min(   sum by (namespace, pod) (     kube_pod_container_resource_limits{resource=\"cpu\", unit=\"core\"}   ),   0.001 ) > 0.8",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "3d54a57f-ef01-4d8d-be87-674a4bd3d70f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        620,
        240
      ],
      "parameters": {
        "color": 7,
        "height": 220,
        "content": "\u2709\ufe0f Formats alert for a single high-CPU pod.\n\nUseful for isolated spikes not shared across the app.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4a34d8c5-4fea-401b-8769-769fccf2c2fd",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        620,
        -420
      ],
      "parameters": {
        "color": 7,
        "height": 260,
        "content": "\ud83e\uddf7 Formats a rich Slack message for multiple pods under the same app.\n\nIncludes:\n\n\u2022 App name\n\u2022 Namespace\n\u2022 List of affected pods + CPU usage\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3c366c14-7ae1-48de-ad7f-9ee8da6506c0",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        940,
        160
      ],
      "parameters": {
        "color": 7,
        "height": 300,
        "content": "\ud83d\udce8 Sends formatted alert message to Slack via webhook or Bot API.\n\nMake sure:\n\n\u2022 Slack token is added in credentials\n\u2022 Channel ID is correct\n\u2022 Body has: { \"text\": $json[\"text\"] }\n"
      },
      "typeVersion": 1
    },
    {
      "id": "8f4d25ff-72a0-4817-acf7-4232c5a93fec",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        -420
      ],
      "parameters": {
        "color": 6,
        "width": 300,
        "height": 320,
        "content": "\ud83d\udccc Workflow: Real-Time Kubernetes CPU Spike Alerts to Slack\n\n\ud83c\udfaf What it does:\nEvery 5 minutes, the workflow queries Prometheus to check CPU usage of all Kubernetes pods. If a pod or group of pods exceeds a CPU usage threshold (e.g., > 0.8 cores), an alert is sent to Slack, grouped by application name."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "85669d77-e18f-4769-933f-ef7dd83e3b35",
  "connections": {
    "Format Prometheus JSON": {
      "main": [
        [
          {
            "node": "Check Number of Pods in Group",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd52 Every 5 Min Trigger": {
      "main": [
        [
          {
            "node": "Query Prometheus for CPU Spikes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Batched Slack Message": {
      "main": [
        [
          {
            "node": "\ud83d\udce4 Send Alerts to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Number of Pods in Group": {
      "main": [
        [
          {
            "node": "Format Batched Slack Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format Single Pod Slack Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Single Pod Slack Message": {
      "main": [
        [
          {
            "node": "\ud83d\udce4 Send Alerts to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Prometheus for CPU Spikes": {
      "main": [
        [
          {
            "node": "Format Prometheus JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}