tutorial

Monitoring Nginx Ingress Controller with Vigilmon

The Nginx Ingress Controller is the most popular Kubernetes ingress controller. Here's how to monitor its liveness endpoint, stub_status metrics, TLS certificates, and ingress ports with Vigilmon.

The Nginx Ingress Controller routes external HTTP and HTTPS traffic into your Kubernetes cluster. It is the most widely deployed Kubernetes ingress controller, handling TLS termination, host-based routing, and path rewrites for hundreds of services. When the Nginx Ingress Controller fails — whether from a misconfigured resource, an OOM kill, or a certificate problem — every service behind it stops responding. Vigilmon lets you monitor the controller's liveness endpoint, nginx metrics, ingress ports, and SSL certificates so you catch failures before your users do.

What You'll Set Up

  • HTTP monitor for the /healthz liveness endpoint
  • HTTP monitor for the /nginx-status stub_status metrics endpoint
  • TCP port monitors for ports 80 and 443
  • SSL certificate expiry alerts for TLS-terminated ingress hostnames
  • Heartbeat monitoring to verify end-to-end routing health through the controller

Prerequisites

  • Nginx Ingress Controller (ingress-nginx) running in a Kubernetes cluster
  • Controller service exposed via LoadBalancer or NodePort
  • A free Vigilmon account

Step 1: Monitor the /healthz Liveness Endpoint

The Nginx Ingress Controller exposes a /healthz endpoint on port 10254 that reports whether the controller is alive. Kubernetes itself uses this endpoint for liveness and readiness probes, and it is the most reliable signal of controller health.

Expose the health port outside the cluster for monitoring. The controller pod exposes port 10254; you can access it via a dedicated monitoring service or port-forward:

kubectl port-forward svc/ingress-nginx-controller 10254:10254 -n ingress-nginx

For production use, expose it through a NodePort service with IP allowlisting so Vigilmon can reach it.

Add a Vigilmon monitor:

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. URL: http://your-node-ip:10254/healthz
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

A 200 response means the controller process is running and healthy. A timeout or non-200 response means the controller has crashed or become unresponsive — even if the pod still shows Running in kubectl get pods.


Step 2: Monitor the /nginx-status Metrics Endpoint

The Nginx Ingress Controller enables nginx's stub_status module at /nginx-status. This endpoint reports active connections, requests per second, and connection states — a lightweight way to confirm nginx is actively processing traffic, not just alive.

The /nginx-status endpoint is served on port 10254 alongside /healthz:

curl http://your-node-ip:10254/nginx-status
# Active connections: 42
# server accepts handled requests
#  1234 1234 5678
# Reading: 0 Writing: 3 Waiting: 39

Add a Vigilmon monitor:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://your-node-ip:10254/nginx-status
  3. Check interval: 1 minute
  4. Expected HTTP status: 200
  5. Optionally set Response body must contain: Active connections
  6. Click Save.

Checking for Active connections in the response body confirms you are getting the real nginx status page and not a cached error page or redirect.


Step 3: TCP Port Monitors for Ingress Traffic

The Nginx Ingress Controller accepts client traffic on ports 80 and 443. TCP monitors on these ports confirm the load balancer service and nginx listeners are accepting connections, independently of any application-layer check.

Get your ingress controller's external IP:

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

Add TCP monitors in Vigilmon:

  1. Click Add MonitorTCP Port.
  2. Set Host to 203.0.113.10 (or the DNS name of the LoadBalancer).
  3. Set Port to 80.
  4. Click Save.
  5. Repeat with Port 443.

These checks are your canary for load balancer misconfigurations, firewall rule changes, or nginx crashes that close the listening sockets without the pod dying.


Step 4: SSL Certificate Alerts for Ingress TLS Termination

The Nginx Ingress Controller terminates TLS for all Ingress resources that define a tls block. Certificates are typically provisioned automatically by cert-manager using ACME (Let's Encrypt), but renewal can fail silently due to DNS misconfiguration, rate limiting, or expired ACME tokens.

List all TLS-enabled Ingress resources:

kubectl get ingress -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,HOSTS:.spec.tls[*].hosts[*]'
# NS          NAME               HOSTS
# default     app-ingress        api.example.com,www.example.com
# monitoring  grafana-ingress    grafana.example.com

For each hostname in the HOSTS column:

  1. Click Add MonitorHTTP / HTTPS (or open an existing monitor for that hostname).
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

A 21-day alert window gives you time to investigate cert-manager ACME challenges before the certificate actually expires. Check cert-manager status with:

kubectl get certificaterequests -A
kubectl describe certificate <name> -n <namespace>

Step 5: Heartbeat Monitoring for End-to-End Routing

The liveness and status endpoint checks confirm the controller is alive, but they do not verify that Ingress routing rules are actually forwarding traffic to your services correctly. A heartbeat monitor that exercises a real route end-to-end catches routing misconfigurations that health checks miss.

Deploy a simple echo service and Ingress rule for the heartbeat path:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: healthcheck-echo
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: healthcheck-echo
  template:
    metadata:
      labels:
        app: healthcheck-echo
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo:latest
        args: ["-text=ok"]
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: healthcheck-echo
  namespace: default
spec:
  selector:
    app: healthcheck-echo
  ports:
  - port: 5678
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: healthcheck-ingress
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - host: your-cluster.example.com
    http:
      paths:
      - path: /ingress-health
        pathType: Prefix
        backend:
          service:
            name: healthcheck-echo
            port:
              number: 5678

Set up the heartbeat in Vigilmon:

  1. Click Add MonitorCron Heartbeat.
  2. Set the expected ping interval to 5 minutes.
  3. Copy the heartbeat URL: https://vigilmon.online/heartbeat/abc123.
  4. Deploy a Kubernetes CronJob that pings the route and signals Vigilmon on success:
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nginx-ingress-heartbeat
  namespace: default
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: ping
            image: curlimages/curl:latest
            command:
            - sh
            - -c
            - |
              curl -sf https://your-cluster.example.com/ingress-health && \
              curl -sf https://vigilmon.online/heartbeat/abc123
          restartPolicy: Never

If the Ingress rule breaks or the echo service goes down, the first curl fails and the heartbeat URL is never pinged. Vigilmon alerts after the expected interval passes.


Step 6: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add Slack, email, or a webhook.
  2. Set Consecutive failures before alert to 2 on the /healthz and /nginx-status monitors — rolling updates briefly restart the controller pod and can cause a single probe failure.
  3. Set Consecutive failures to 1 on SSL certificate monitors — expiry deadlines do not recover without intervention.

Summary

| Monitor | Target | What It Catches | |---|---|---| | HTTP — liveness | /healthz on port 10254 | Controller crash, unresponsive pod | | HTTP — metrics | /nginx-status on port 10254 | nginx process not serving requests | | TCP port 80 | Load balancer external IP | HTTP listener down, LB failure | | TCP port 443 | Load balancer external IP | HTTPS listener down, TLS failure | | SSL certificate | Each TLS ingress hostname | Certificate expiry, cert-manager failure | | Cron heartbeat | /ingress-health route | Ingress routing misconfiguration |

The Nginx Ingress Controller is the single point of entry for all cluster traffic — its health directly determines whether your users can reach any of your services. With Vigilmon watching liveness, nginx status, port availability, TLS certificates, and actual routing behavior, you get full-stack visibility into the controller at every layer.

Monitor your app with Vigilmon

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

Start free →