tutorial

How to Monitor Kraan Kubernetes Add-on Manager with Vigilmon (HTTP + TCP + Alerts)

Kraan is a GitOps-native add-on manager for Kubernetes. It organizes your cluster's HelmReleases, Kustomizations, and other Flux-based resources into depende...

Kraan is a GitOps-native add-on manager for Kubernetes. It organizes your cluster's HelmReleases, Kustomizations, and other Flux-based resources into dependency-aware layers, ensuring that foundational add-ons (like cert-manager or ingress-nginx) are fully ready before dependent add-ons deploy on top of them. When the Kraan controller fails or an AddonsLayer gets stuck, the entire add-on dependency chain freezes — upstream layers block downstream layers, and your cluster drifts from its desired Git state without alerting.

In this tutorial you'll set up comprehensive uptime monitoring for your Kraan-managed Kubernetes cluster using Vigilmon — free tier, no credit card required.


Why Kraan clusters need external monitoring

Kraan adds a dependency graph on top of Flux's GitOps reconciliation. Failures here compound:

  • Kraan controller pod crashes — all AddonsLayer reconciliation halts; running add-ons continue but nothing is updated, rolled back, or newly installed; Git divergence accumulates silently
  • AddonsLayer stuck in Deploying — if a layer's Helm release or Kustomization fails, the layer never reaches Deployed; every downstream layer waits indefinitely; there is no timeout or self-healing built in
  • Source repository unreachable — if Kraan's GitRepository source loses connectivity, all layers stop reconciling; the cluster runs on its last-applied state with no indication that new commits are being ignored
  • HelmRelease conflict within a layer — if two resources in the same layer conflict, Kraan may repeatedly reconcile without making progress; the layer oscillates and blocks its dependents
  • RBAC misconfiguration — if Kraan's service account loses permissions, reconciliation fails silently; pods run but no changes from Git are applied

These failure modes are particularly hard to detect because add-ons keep running from their last-deployed state — the cluster looks healthy while continuously drifting from what Git declares.


What you'll need

  • A Kubernetes cluster with Kraan and Flux installed
  • At least one add-on managed by Kraan that exposes a health endpoint
  • A free Vigilmon account (sign up takes 30 seconds)

Step 1: Expose a health endpoint for monitoring

Verify that Kraan is running and check the state of your AddonsLayers:

# Check Kraan controller
kubectl get pods -n gotk-system -l app=kraan-controller
# NAME                                READY   STATUS    RESTARTS   AGE
# kraan-controller-5f7d9c8b4-xp2mn    1/1     Running   0          7d

# Check all AddonsLayers
kubectl get addonslayer -A
# NAMESPACE      NAME            VERSION   STATUS
# default        base-layer      v1.0.0    Deployed
# default        platform-layer  v1.0.0    Deployed
# default        apps-layer      v1.0.0    Deployed

# Check AddonsLayer details
kubectl describe addonslayer apps-layer -n default

Kraan-managed add-ons like ingress-nginx or cert-manager expose their own health endpoints. Use the most critical one as your primary health signal:

# Example: ingress-nginx health check (managed by Kraan's base-layer)
kubectl get svc -n ingress-nginx ingress-nginx-controller
# NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)
# ingress-nginx-controller   LoadBalancer   10.96.100.50    203.0.113.100     80/TCP,443/TCP

# Test the ingress health endpoint
curl http://203.0.113.100/healthz
# ok

For a dedicated end-to-end probe, deploy a health check app via a Kraan-managed AddonsLayer:

# Add to your apps-layer HelmRelease or Kustomization source:
# health-check-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kraan-health
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kraan-health
  template:
    metadata:
      labels:
        app: kraan-health
    spec:
      containers:
        - name: health
          image: nginx:alpine
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config
              mountPath: /etc/nginx/conf.d
      volumes:
        - name: config
          configMap:
            name: kraan-health-nginx
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: kraan-health-nginx
  namespace: default
data:
  default.conf: |
    server {
      listen 80;
      location /health {
        return 200 '{"status":"ok","manager":"kraan"}';
        add_header Content-Type application/json;
      }
    }
---
apiVersion: v1
kind: Service
metadata:
  name: kraan-health
  namespace: default
spec:
  type: LoadBalancer
  selector:
    app: kraan-health
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP

Commit this file to your Git repository so Kraan deploys it through its GitOps pipeline. This app becomes your most valuable monitor — it only exists if Kraan's full reconciliation chain worked.

# After Git commit and Kraan reconciliation
kubectl get svc kraan-health
# NAME           TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)   AGE
# kraan-health   LoadBalancer   10.96.110.10    203.0.113.105    80/TCP    5m

curl http://203.0.113.105/health
# {"status":"ok","manager":"kraan"}

Step 2: Set up HTTP monitoring in Vigilmon

With your health endpoint available, add it to Vigilmon:

  1. Log in to vigilmon.online and go to Monitors → New Monitor
  2. Choose HTTP / HTTPS as the type
  3. Set the URL to your endpoint: http://203.0.113.105/health
  4. Set the check interval to 1 minute
  5. Under Expected response, set:
    • Status code: 200
    • Response body contains: "status":"ok"
  6. Save the monitor

If this app was deployed via Kraan's GitOps pipeline, monitoring it validates the complete Kraan stack: Git connectivity, Kraan reconciliation, AddonsLayer dependency resolution, Helm/Kustomize execution, and pod scheduling all have to work for a response to arrive.

Why external monitoring catches what Flux and Kraan miss

Flux's Kustomization and HelmRelease objects surface reconciliation errors as conditions on their CRDs — but only if you're watching them. There's no built-in alerting when AddonsLayer gets stuck. Vigilmon probes from outside your cluster and notifies you without requiring any in-cluster tooling to be operational. Its multi-region consensus model eliminates false positives while still detecting real outages within minutes.


Step 3: Monitor TCP ports and the Kraan controller

Add monitors to detect failures at multiple layers:

Service TCP check:

  1. Go to Monitors → New Monitor
  2. Choose TCP Port
  3. Enter: Host 203.0.113.105, Port 80
  4. Save the monitor

Kraan controller metrics endpoint:

# Port-forward to Kraan controller metrics
kubectl port-forward -n gotk-system deploy/kraan-controller 8080:8080

# Check Kraan health
curl http://localhost:8080/healthz
# ok

# Check Kraan readiness
curl http://localhost:8080/readyz
# ok

Expose these via an Ingress if you want Vigilmon to probe them directly:

# kraan-controller-ingress.yaml
apiVersion: v1
kind: Service
metadata:
  name: kraan-controller-health
  namespace: gotk-system
spec:
  selector:
    app: kraan-controller
  ports:
    - name: metrics
      port: 8080
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kraan-health
  namespace: gotk-system
spec:
  rules:
    - host: kraan-health.your-cluster.com
      http:
        paths:
          - path: /healthz
            pathType: Exact
            backend:
              service:
                name: kraan-controller-health
                port:
                  number: 8080

Add an HTTP monitor in Vigilmon for https://kraan-health.your-cluster.com/healthz.

GitOps reconciliation heartbeat:

Use a Kubernetes CronJob to verify reconciliation is happening and push a heartbeat to Vigilmon:

# kraan-heartbeat-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: kraan-reconcile-heartbeat
  namespace: default
spec:
  schedule: "*/10 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: default
          restartPolicy: Never
          containers:
            - name: heartbeat
              image: bitnami/kubectl:latest
              command:
                - sh
                - -c
                - |
                  STATUS=$(kubectl get addonslayer -A -o jsonpath='{.items[*].status.state}')
                  if echo "$STATUS" | grep -qv "Deployed"; then
                    echo "Some AddonsLayers not Deployed: $STATUS"
                    exit 1
                  fi
                  curl -fsS https://uptime.vigilmon.online/api/v1/heartbeat/YOUR_HEARTBEAT_KEY

Step 4: Configure alert channels

An AddonsLayer stuck in Deploying can cascade and freeze your entire add-on stack. Alert the moment reconciliation breaks.

Email alerts

  1. In Vigilmon, go to Alert Channels → Add Channel → Email
  2. Enter your platform team's on-call email
  3. Assign the channel to all Kraan monitors

Webhook alerts (Slack, PagerDuty, etc.)

  1. Go to Alert Channels → Add Channel → Webhook
  2. Enter your webhook URL
  3. Assign the channel to your monitors

Example payload when the Kraan health endpoint goes down:

{
  "monitor_name": "Kraan Add-on Health",
  "status": "down",
  "url": "http://203.0.113.105/health",
  "started_at": "2024-01-15T11:00:00Z",
  "duration_seconds": 240
}

Run these diagnostics when an alert fires:

# Check Kraan controller
kubectl get pods -n gotk-system -l app=kraan-controller
kubectl logs -n gotk-system -l app=kraan-controller --tail=100

# Check all AddonsLayer states
kubectl get addonslayer -A
kubectl describe addonslayer -A | grep -A10 "Status:"

# Find stuck layers
kubectl get addonslayer -A -o json | \
  jq '.items[] | select(.status.state != "Deployed") | {name: .metadata.name, state: .status.state}'

# Check HelmReleases managed by Kraan
kubectl get helmrelease -A
kubectl get kustomization -A

# Check Flux GitRepository source
kubectl get gitrepository -A
kubectl describe gitrepository -n flux-system flux-system

# Check RBAC
kubectl auth can-i --list --as=system:serviceaccount:gotk-system:kraan-controller

Step 5: Create a public status page

Kraan manages foundational infrastructure add-ons. A status page gives all engineering teams visibility when the add-on layer is degraded.

  1. In Vigilmon, go to Status Pages → New Status Page
  2. Give it a name: "Cluster Add-on Status"
  3. Add your monitors: Kraan Health HTTP, Service TCP, Controller Health, Reconciliation Heartbeat
  4. Group them: Add-on Services, Kraan Controller, GitOps Reconciliation
  5. Publish the page

Share this URL with your platform, application, and DevOps teams.


Putting it all together

Here's a summary of the monitors to create for a Kraan-managed cluster:

| Monitor | Type | What it catches | |---------|------|-----------------| | http://203.0.113.105/health | HTTP | Full GitOps chain (Git → Kraan → AddonsLayer → pod → response) | | 203.0.113.105:80 | TCP | Service reachability | | https://kraan-health.your-cluster.com/healthz | HTTP | Kraan controller process health | | AddonsLayer reconciliation heartbeat | Heartbeat | All layers remain in Deployed state |

And the Kraan diagnostics to run when an alert fires:

# Quick triage: controller or layer?
kubectl get pods -n gotk-system | grep kraan
kubectl get addonslayer -A

# Which layer is stuck?
kubectl get addonslayer -A -o custom-columns=NAME:.metadata.name,STATE:.status.state,MSG:.status.reason

# Check the layer's resources
kubectl get helmrelease -A | grep -v "True"
kubectl get kustomization -A | grep -v "True"

# Force a Kraan reconciliation
kubectl annotate addonslayer apps-layer reconcile.fluxcd.io/requestedAt="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

# Check Git source freshness
kubectl get gitrepository -A -o custom-columns=NAME:.metadata.name,READY:.status.conditions[0].status,MSG:.status.conditions[0].message

What's next

  • SSL certificate monitoring — add SSL monitors for HTTPS endpoints of Kraan-managed add-ons like ingress-nginx and cert-manager
  • Heartbeat monitoring — use Vigilmon heartbeats to validate that each AddonsLayer stays in Deployed on schedule
  • Layer-by-layer coverage — create separate monitors for the critical add-ons in each Kraan layer (base, platform, apps) to pinpoint failures at the right dependency level

Get started free at vigilmon.online — no credit card, monitors start running in under a minute.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →