Posted on
Artificial Intelligence

Artificial Intelligence for Site Reliability Engineers

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Artificial Intelligence for Site Reliability Engineers (SREs): A Bash‑First Playbook

Incidents always seem to land at 3 a.m., alerts multiply like rabbits, and capacity questions show up right after a product launch. What if you could add a thin layer of AI—invoked from good old Bash—to catch anomalies earlier, deduplicate noisy alerts, and forecast capacity before things melt?

This article shows you practical, low-friction ways to add AI to your Linux SRE toolkit without overhauling your stack. We’ll wire up a few small scripts, lean on Python libraries where it makes sense, and orchestrate everything with systemd timers. You’ll end up with:

  • A 1‑minute metrics collector (CPU load, memory).

  • An anomaly watchdog to flag weird system behavior.

  • An alert de‑duplicator that groups similar errors.

  • A daily capacity forecaster so you can stay in front of growth.

All of this remains Bash-first, transparent, and easy to tear back out if it doesn’t help.

Why AI for SRE Is Worth Your Time

  • It’s not “boil the ocean.” Lightweight models like Isolation Forest (for anomalies) and TF‑IDF + clustering (for alert grouping) are proven, low-risk, and easy to run locally.

  • You already have the data. Linux exposes rich signals via /proc, journald, and sysstat. Feed those into simple models and you get meaningful wins without a data engineering project.

  • It scales your attention. Let machines sift noise and highlight the outliers. You stay focused on the few events that matter.

What You’ll Build

  • Metrics collector: writes timestamp, 1‑minute load, and memory usage to CSV every minute.

  • Anomaly watchdog: learns “normal” from recent data and flags outliers.

  • Alert de‑duplicator: groups similar error logs so on-call sees one item instead of twenty.

  • Capacity forecaster: estimates tomorrow’s load and warns if you’ll cross safe utilization.

Everything is controlled via systemd timers and lives under /opt/sre-ai (code) and /var/lib/sre-ai (data).


Prerequisites and Install

We’ll use Python for the small AI parts, and Bash/systemd for glue.

Install OS packages:

  • Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y python3 python3-venv python3-pip jq sysstat
  • Fedora/RHEL (dnf):
sudo dnf install -y python3 python3-pip python3-virtualenv jq sysstat
  • openSUSE/SLE (zypper):
sudo zypper refresh
sudo zypper install -y python3 python3-pip python3-virtualenv jq sysstat

Create directories and a Python virtual environment for the AI bits:

sudo mkdir -p /opt/sre-ai /var/lib/sre-ai /var/log/sre-ai
sudo chown -R "$USER":"$USER" /opt/sre-ai /var/lib/sre-ai /var/log/sre-ai

python3 -m venv /opt/sre-ai/venv
source /opt/sre-ai/venv/bin/activate
pip install --upgrade pip
pip install numpy pandas scikit-learn statsmodels
deactivate

Note:

  • If python3 -m venv isn’t available, install the “venv/virtualenv” packages shown above per distro.

  • sysstat gives you sar/iostat; we’ll use /proc directly for the minimal collector, but sysstat is handy for deeper troubleshooting.


1) Collect Metrics Every Minute (Bash + systemd)

Write a minimal collector that appends one CSV line per minute:

/opt/sre-ai/collect_metrics.sh

#!/usr/bin/env bash
set -euo pipefail

DIR=/var/lib/sre-ai
FILE="$DIR/metrics.csv"
mkdir -p "$DIR"

if [ ! -s "$FILE" ]; then
  echo "ts,load1,mem_used_pct" > "$FILE"
fi

ts=$(date -Iseconds)
load1=$(cut -d' ' -f1 /proc/loadavg)
mem_total_kb=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
mem_avail_kb=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo)
mem_used_pct=$(awk -v t="$mem_total_kb" -v a="$mem_avail_kb" 'BEGIN{printf "%.2f", (t-a)/t*100}')

echo "$ts,$load1,$mem_used_pct" >> "$FILE"

Make it executable:

chmod +x /opt/sre-ai/collect_metrics.sh

Create a systemd service and timer:

/etc/systemd/system/sre-metrics.service

[Unit]
Description=SRE AI - Collect metrics

[Service]
Type=oneshot
ExecStart=/opt/sre-ai/collect_metrics.sh

/etc/systemd/system/sre-metrics.timer

[Unit]
Description=Run SRE metrics collector every minute

[Timer]
OnCalendar=*:0/1
Persistent=true

[Install]
WantedBy=timers.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now sre-metrics.timer
systemctl status sre-metrics.timer --no-pager

You should see /var/lib/sre-ai/metrics.csv grow each minute.


2) Detect Anomalies with Isolation Forest

When recent behavior is “learned,” outliers jump out. This watchdog reads recent metrics and flags unusual spikes.

/opt/sre-ai/detect_anomalies.py

#!/usr/bin/env python3
import sys, json, pathlib
import pandas as pd
import numpy as np
from sklearn.ensemble import IsolationForest

DATA = pathlib.Path("/var/lib/sre-ai/metrics.csv")

def main():
    if not DATA.exists():
        print("no metrics yet", file=sys.stderr)
        return 0

    df = pd.read_csv(DATA, parse_dates=["ts"])
    if len(df) < 200:
        print("insufficient data for anomaly detection", file=sys.stderr)
        return 0

    df = df.tail(2880)  # ~2 days if 1-min sampling
    X = df[["load1", "mem_used_pct"]].astype(float).values

    model = IsolationForest(n_estimators=200, contamination=0.01, random_state=42)
    model.fit(X)

    latest = X[-1].reshape(1, -1)
    pred = model.predict(latest)[0]   # 1 normal, -1 anomaly
    score = float(model.decision_function(latest)[0])

    result = {
        "ts": df["ts"].iloc[-1].isoformat(),
        "load1": float(df["load1"].iloc[-1]),
        "mem_used_pct": float(df["mem_used_pct"].iloc[-1]),
        "is_anomaly": pred == -1,
        "anomaly_score": score
    }
    print(json.dumps(result))

    # Exit code 2 on anomaly so systemd/journal can highlight it
    return 2 if pred == -1 else 0

if __name__ == "__main__":
    sys.exit(main())

Make it executable and a thin wrapper to log anomalies:

/opt/sre-ai/run_anomaly_watchdog.sh

#!/usr/bin/env bash
set -euo pipefail
source /opt/sre-ai/venv/bin/activate
OUT=$(/opt/sre-ai/detect_anomalies.py || true)
echo "$OUT"
if echo "$OUT" | jq -e '.is_anomaly == true' >/dev/null 2>&1; then
  logger -t sre-ai "ANOMALY: $(echo "$OUT" | jq -c '.')"
  # Optional: trigger webhooks/alerts here
  exit 2
fi
chmod +x /opt/sre-ai/detect_anomalies.py /opt/sre-ai/run_anomaly_watchdog.sh

Systemd unit and timer:

/etc/systemd/system/sre-anomaly.service

[Unit]
Description=SRE AI - Anomaly watchdog

[Service]
Type=oneshot
ExecStart=/opt/sre-ai/run_anomaly_watchdog.sh

/etc/systemd/system/sre-anomaly.timer

[Unit]
Description=Run anomaly watchdog every 5 minutes

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now sre-anomaly.timer
journalctl -u sre-anomaly.service -n 5 --no-pager

You’ll get JSON in logs and a syslog line when an anomaly is detected.


3) De‑duplicate Noisy Alerts with TF‑IDF + Clustering

Group similar errors so one incident doesn’t fire a dozen near-duplicates. We’ll cluster recent high-priority logs from journald.

/opt/sre-ai/dedupe_alerts.py

#!/usr/bin/env python3
import sys, json
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import DBSCAN

lines = [ln.strip() for ln in sys.stdin if ln.strip()]
if not lines:
    sys.exit(0)

# Vectorize log messages
vec = TfidfVectorizer(stop_words="english", ngram_range=(1,2), max_features=4000)
X = vec.fit_transform(lines)

# Cluster by cosine similarity
clu = DBSCAN(eps=0.5, min_samples=2, metric="cosine").fit(X)
labels = clu.labels_

clusters = {}
for i, lbl in enumerate(labels):
    clusters.setdefault(int(lbl), []).append(lines[i])

summary = []
for lbl, msgs in clusters.items():
    if lbl == -1:  # noise
        continue
    # Pick a representative message (shortest)
    rep = min(msgs, key=len)
    summary.append({"cluster": lbl, "count": len(msgs), "example": rep})

print(json.dumps({"groups": summary, "total": len(lines)}, indent=2))

Wrapper to read last 5 minutes of errors, cluster, and write a report:

/opt/sre-ai/run_dedupe.sh

#!/usr/bin/env bash
set -euo pipefail
source /opt/sre-ai/venv/bin/activate

OUT=$(
  journalctl -p err..alert -S -5m -o short-iso -q \
  | sed 's/^[^]]*] *//' \
  | /opt/sre-ai/dedupe_alerts.py
)

echo "$OUT" | tee /var/log/sre-ai/alert_groups.json
logger -t sre-ai "DEDUPE: $(echo "$OUT" | jq -c '{groups: [.groups[] | {count, example}], total}')"
chmod +x /opt/sre-ai/dedupe_alerts.py /opt/sre-ai/run_dedupe.sh

Systemd unit and timer:

/etc/systemd/system/sre-dedupe.service

[Unit]
Description=SRE AI - Alert de-duplication

[Service]
Type=oneshot
ExecStart=/opt/sre-ai/run_dedupe.sh

/etc/systemd/system/sre-dedupe.timer

[Unit]
Description=Group recent alerts every 5 minutes

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now sre-dedupe.timer
tail -n +1 /var/log/sre-ai/alert_groups.json

This creates compact summaries you can forward to Slack/PagerDuty instead of raw floods.


4) Forecast Capacity Daily (SARIMA)

Forecast the next 24 hours of load and warn if you’ll cross safe levels (e.g., 80% of CPU capacity).

/opt/sre-ai/forecast_capacity.py

#!/usr/bin/env python3
import sys, json, pathlib, math
import pandas as pd
from statsmodels.tsa.statespace.sarimax import SARIMAX

DATA = pathlib.Path("/var/lib/sre-ai/metrics.csv")

def cpu_count():
    try:
        with open("/proc/cpuinfo") as f:
            return sum(1 for ln in f if ln.startswith("processor"))
    except:
        return 1

def main():
    if not DATA.exists():
        print("no metrics", file=sys.stderr)
        return 0

    df = pd.read_csv(DATA, parse_dates=["ts"])
    if len(df) < 300:
        print("insufficient history", file=sys.stderr)
        return 0

    s = df.set_index("ts")["load1"].astype(float).resample("1H").mean().bfill().astype(float)
    # Simple model; tune orders as needed
    model = SARIMAX(s, order=(1,1,1), seasonal_order=(0,1,1,24), enforce_stationarity=False, enforce_invertibility=False)
    res = model.fit(disp=False)

    steps = 24
    fc = res.get_forecast(steps=steps).predicted_mean
    cap = cpu_count()
    warn_level = 0.8 * cap

    breaches = [(str(ts), float(val)) for ts, val in fc.items() if val >= warn_level]
    out = {
        "cpu_cores": cap,
        "warn_threshold_load": round(warn_level, 2),
        "forecast": [{ "ts": str(ts), "load1": float(val)} for ts, val in fc.items()],
        "breaches": [{"ts": ts, "pred_load": val} for ts, val in breaches]
    }
    print(json.dumps(out, indent=2))

    return 2 if breaches else 0

if __name__ == "__main__":
    sys.exit(main())

Wrapper and systemd timer:

/opt/sre-ai/run_forecast.sh

#!/usr/bin/env bash
set -euo pipefail
source /opt/sre-ai/venv/bin/activate
OUT=$(/opt/sre-ai/forecast_capacity.py || true)
echo "$OUT" | tee /var/log/sre-ai/forecast.json
if echo "$OUT" | jq -e '.breaches | length > 0' >/dev/null 2>&1; then
  logger -t sre-ai "FORECAST-WARN: $(echo "$OUT" | jq -c '{breaches, warn_threshold_load, cpu_cores}')"
  exit 2
fi
chmod +x /opt/sre-ai/forecast_capacity.py /opt/sre-ai/run_forecast.sh

/etc/systemd/system/sre-forecast.service

[Unit]
Description=SRE AI - Daily capacity forecast

[Service]
Type=oneshot
ExecStart=/opt/sre-ai/run_forecast.sh

/etc/systemd/system/sre-forecast.timer

[Unit]
Description=Run capacity forecast daily at 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now sre-forecast.timer
journalctl -u sre-forecast.service -n 5 --no-pager

You now get a daily JSON forecast at /var/log/sre-ai/forecast.json and a syslog warning if future load is likely to exceed safe levels.


Real‑World Notes and Tips

  • Start simple. Even basic features (load1, mem_used_pct) catch many issues. You can add disk IO, network, and app metrics later.

  • Keep state close. CSV in /var/lib/sre-ai is easy to inspect, back up, and rotate.

  • Tune thresholds. Isolation Forest contamination=0.01 is a conservative start. Raise it if you never see anomalies; lower if too chatty.

  • Pipe to your tools. Replace “logger” lines with curl to your alert manager of choice.

  • Governance. Keep a changelog of models and parameters. It helps explain why a particular alert fired.


Conclusion and Next Steps (CTA)

You just added practical AI helpers to your SRE workflow—without new servers, SaaS lock‑in, or opaque magic. From here:

  • Wire outputs to your incident channel (Slack/PagerDuty) and weekly ops review.

  • Add features: disk saturation, application error rate, p99 latency.

  • Put the dedupe summary into your alert pipeline to trim noisy pages.

  • Iterate model params monthly based on feedback.

If you want a deeper dive (e.g., Prometheus scraping + PromQL + model training on richer signals), or to integrate with Kubernetes node metrics, say the word—I can extend this playbook with distro‑specific install steps and manifests.