tutorial

How to Monitor ingress-nginx with Vigilmon

ingress-nginx is the most widely deployed Kubernetes Ingress controller. It proxies external HTTP and HTTPS traffic into your cluster using NGINX under the h...

ingress-nginx is the most widely deployed Kubernetes Ingress controller. It proxies external HTTP and HTTPS traffic into your cluster using NGINX under the hood, handles TLS termination, path-based routing, and rate limiting — all driven by Kubernetes Ingress resources. When ingress-nginx breaks, every application behind it goes dark simultaneously.

This tutorial shows you how to set up external uptime monitoring for ingress-nginx using Vigilmon — free tier, no credit card required.


Why ingress-nginx needs external monitoring

ingress-nginx manages traffic for your entire cluster from a single set of pods. That concentration of responsibility means a single misconfiguration or pod crash can silently take down every service it routes.

Internal health checks can't catch the full range of failures:

  • Ingress pod crash with no restart — if the NGINX process dies and the pod fails to restart (OOMKilled, image pull error), Kubernetes marks the pod as CrashLoopBackOff but keeps reporting Running briefly — users see connection refused
  • ConfigMap reload failure — a bad annotation on any Ingress resource triggers a NGINX config reload failure; the controller logs an error but existing traffic may continue while new routes silently 404
  • Admission webhook blocking valid Ingress resources — the ingress-nginx ValidatingWebhookConfiguration can reject Ingress updates even when NGINX itself is healthy
  • Service weight drift — weighted canary routing via annotations can silently shift 100% of traffic to a broken backend after a botched deployment
  • TLS certificate not picked up — cert-manager issues a new certificate, but ingress-nginx doesn't hot-reload it; users see expired cert errors that no internal probe detects
  • Upstream connection pool exhaustion — NGINX worker processes hit file descriptor limits; upstream health probes pass but new requests time out

External monitoring from multiple geographic regions is the only way to catch all of these from the user's perspective.


What you'll need

  • A Kubernetes cluster with ingress-nginx installed (helm install ingress-nginx ingress-nginx/ingress-nginx)
  • At least one application exposed via an Ingress resource
  • A free Vigilmon account

Step 1: Verify ingress-nginx is reachable

Check that the ingress-nginx controller has an external IP:

kubectl get svc -n ingress-nginx ingress-nginx-controller
# NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)
# ingress-nginx-controller   LoadBalancer   10.96.200.10    203.0.113.10     80:30080/TCP,443:30443/TCP

If EXTERNAL-IP shows <pending>, your cloud provider hasn't assigned one yet. For bare-metal clusters, you need MetalLB or a NodePort service.

Get your cluster's external IP and confirm a backend application is reachable:

INGRESS_IP=$(kubectl get svc -n ingress-nginx ingress-nginx-controller \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

curl -H "Host: myapp.example.com" http://$INGRESS_IP/health
# {"status":"ok"}

Make sure your application has a /health or similar endpoint that returns HTTP 200.


Step 2: Monitor the ingress-nginx default backend

ingress-nginx ships with a default backend that responds to unmatched routes. Monitoring it gives you a fast signal that the controller itself is alive:

# The default backend serves a 404 for unknown hosts
curl -H "Host: nonexistent.example.com" http://$INGRESS_IP/
# 404 Not Found (this is expected and confirms the controller is running)

In Vigilmon:

  1. Log in and go to Monitors → New Monitor
  2. Choose HTTP / HTTPS
  3. Set the URL to http://<INGRESS_IP>/ with a custom Host header for a known application
  4. Set Expected status code to 200
  5. Set the check interval to 1 minute
  6. Save the monitor

Monitor the HTTPS endpoint too

If you use TLS (and you should), add a separate HTTPS monitor:

  1. Create a second monitor for https://myapp.example.com/health
  2. Enable SSL certificate expiry monitoring
  3. Set an alert threshold of 14 days before expiry

This catches cert-manager renewal failures before users see browser warnings.


Step 3: Monitor individual applications through ingress

Don't just monitor the ingress controller — monitor every critical application through its ingress route. This catches per-application issues like misconfigured path rewrites or broken upstream services:

# Example Ingress resource
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myapp
                port:
                  number: 80
  tls:
    - hosts:
        - myapp.example.com
      secretName: myapp-tls

Add a Vigilmon monitor for each application:

| Monitor URL | Expected Status | What it catches | |-------------|-----------------|-----------------| | https://myapp.example.com/health | 200 | App down, ingress misconfiguration, TLS failure | | https://api.example.com/v1/status | 200 | API path rewrite failure | | https://myapp.example.com | 200 | Root redirect, default backend routing |


Step 4: Monitor the metrics endpoint (optional)

ingress-nginx exposes Prometheus metrics on port 10254. If your cluster allows external access to this port, you can verify the metrics endpoint is alive:

kubectl port-forward -n ingress-nginx \
  $(kubectl get pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx -o name | head -1) 10254:10254

curl http://localhost:10254/metrics | grep nginx_ingress_controller_requests

Key metrics to watch:

  • nginx_ingress_controller_requests — total request count by status code
  • nginx_ingress_controller_ingress_upstream_latency_seconds — upstream response time
  • nginx_ingress_controller_config_last_reload_successful — whether the last config reload succeeded (0 = broken config)

Step 5: Configure alert channels

When ingress-nginx goes down, every service behind it is affected. You want alerts the moment any of your ingress-monitored services fail.

Email alerts

  1. In Vigilmon, go to Alert Channels → Add Channel → Email
  2. Enter your on-call or infrastructure team email
  3. Assign the channel to all ingress monitors

Webhook (Slack / PagerDuty)

  1. Go to Alert Channels → Add Channel → Webhook
  2. Paste your Slack incoming webhook URL or PagerDuty integration URL
  3. Assign to all ingress monitors

Example Vigilmon alert payload:

{
  "monitor_name": "myapp.example.com /health",
  "status": "down",
  "url": "https://myapp.example.com/health",
  "started_at": "2025-03-15T14:30:00Z",
  "duration_seconds": 60
}

Correlating Vigilmon alerts with ingress-nginx state

When an alert fires:

# 1. Check ingress-nginx controller pods
kubectl get pods -n ingress-nginx

# 2. Check recent events
kubectl describe pods -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx

# 3. Check NGINX config reload status
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=50 | grep -i "reload\|error\|warn"

# 4. Validate Ingress resources
kubectl get ingress -A
kubectl describe ingress myapp -n production

Step 6: Create a public status page

Group all your ingress-backed services on a public status page:

  1. In Vigilmon, go to Status Pages → New Status Page
  2. Name it "Production Services"
  3. Add all application monitors
  4. Group by function: API, Frontend, Admin, etc.
  5. Publish and share the URL with your team and customers

Monitoring summary

| Monitor | Type | What it catches | |---------|------|-----------------| | https://myapp.example.com/health | HTTP | Application down, ingress misconfiguration | | https://api.example.com/v1/status | HTTP | API path routing failure | | TLS cert for *.example.com | SSL expiry | cert-manager renewal failure | | http://<INGRESS_IP>/ | HTTP | Controller pod crash, load balancer failure |


What's next

  • Canary deployments — when using ingress-nginx canary annotations, add Vigilmon monitors for both stable and canary hostnames to catch weight drift
  • Rate limiting validation — periodically test that your rate-limit annotations are active by monitoring for expected 429 responses from a separate monitor
  • Multi-cluster — if you run multiple clusters, create one Vigilmon status page per cluster to track ingress health independently

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 →