tutorial

How to Monitor kubens with Vigilmon

kubens is a command-line utility that accelerates Kubernetes namespace switching — replacing `kubectl config set-context --current --namespace=` with a singl...

kubens is a command-line utility that accelerates Kubernetes namespace switching — replacing kubectl config set-context --current --namespace=<ns> with a single short command. It is the companion tool to kubectx and is used constantly in day-to-day Kubernetes development to target the correct namespace before running kubectl get, kubectl apply, or kubectl exec commands. When the Kubernetes API server becomes unreachable, RBAC permissions for namespace listing are revoked, or the namespace a developer has selected is deleted, kubens silently produces stale or empty output — leaving engineers working in the wrong namespace without realising it.

In this tutorial you'll set up uptime monitoring for the Kubernetes infrastructure that kubens depends on using Vigilmon — free tier, no credit card required.


Why kubens's dependencies need external monitoring

kubens is a wrapper around kubectl get namespaces and kubectl config set-context. Its failure modes are all infrastructure-level:

  • Namespace deletion after selection — kubens sets the active namespace in kubeconfig, but if that namespace is subsequently deleted, all kubectl commands silently operate against a non-existent namespace; the error surfaces per command, not as a kubens failure
  • RBAC permission loss for namespace listing — when the user's ClusterRole loses list namespaces permission, kubens returns an empty list or an authorization error rather than the expected namespace menu
  • Kubernetes API server unavailability — kubens cannot list namespaces or update context configuration when the API server is down; it fails immediately but the failure is not forwarded to any alert channel
  • Namespace quota exhaustion — a namespace that kubens can list and switch to may be resource-exhausted; pods scheduled there fail silently while kubens continues reporting the namespace as available
  • Kubeconfig context drift — after a cluster migration, the active context in kubeconfig may point to a decommissioned API server; kubens lists namespaces from memory rather than detecting the stale state

External monitoring from Vigilmon watches the namespace listing infrastructure kubens depends on and alerts you when the API layer degrades.


What you'll need

  • A Kubernetes cluster with kubens installed
  • kubectl access with permission to list namespaces
  • A node or load balancer endpoint to expose a health check
  • A free Vigilmon account

Step 1: Expose a health endpoint for kubens namespace access

kubens exposes no HTTP interface. Deploy a small health exporter that validates namespace listing and context switching are working:

# kubens-health.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kubens-health
  namespace: observability
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kubens-health-reader
rules:
  - apiGroups: [""]
    resources: ["namespaces", "resourcequotas"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubens-health-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubens-health-reader
subjects:
  - kind: ServiceAccount
    name: kubens-health
    namespace: observability
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubens-health
  namespace: observability
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kubens-health
  template:
    metadata:
      labels:
        app: kubens-health
    spec:
      serviceAccountName: kubens-health
      containers:
        - name: checker
          image: bitnami/kubectl:latest
          command:
            - /bin/sh
            - -c
            - |
              while true; do
                # Simulate what kubens does: list all namespaces
                if kubectl get namespaces -o jsonpath='{.items[*].metadata.name}' > /tmp/ns_raw 2>/tmp/err; then
                  NS_COUNT=$(wc -w < /tmp/ns_raw)
                  # Verify key namespaces exist
                  for REQUIRED in kube-system default; do
                    if ! echo "$(cat /tmp/ns_raw)" | grep -qw "$REQUIRED"; then
                      echo "degraded missing_namespace=$REQUIRED ns_count=$NS_COUNT" > /tmp/status
                      break 2
                    fi
                  done
                  echo "healthy ns_count=$NS_COUNT" > /tmp/status
                else
                  ERR=$(head -1 /tmp/err)
                  echo "unhealthy error=$ERR" > /tmp/status
                fi
                sleep 30
              done
        - name: health-server
          image: busybox:latest
          command:
            - /bin/sh
            - -c
            - |
              while true; do
                STATUS=$(cat /tmp/status 2>/dev/null || echo "starting")
                if echo "$STATUS" | grep -q "^healthy"; then
                  printf "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: ${#STATUS}\r\n\r\n$STATUS" | nc -l -p 8080 -q 1
                elif echo "$STATUS" | grep -q "^degraded"; then
                  printf "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: ${#STATUS}\r\n\r\n$STATUS" | nc -l -p 8080 -q 1
                else
                  printf "HTTP/1.1 503 Service Unavailable\r\nContent-Type: text/plain\r\nContent-Length: ${#STATUS}\r\n\r\n$STATUS" | nc -l -p 8080 -q 1
                fi
              done
          ports:
            - containerPort: 8080
              name: health
          volumeMounts:
            - name: status
              mountPath: /tmp
      volumes:
        - name: status
          emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: kubens-health
  namespace: observability
spec:
  type: NodePort
  selector:
    app: kubens-health
  ports:
    - name: health
      port: 8080
      targetPort: 8080
      nodePort: 30083
kubectl apply -f kubens-health.yaml

# Verify
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
curl http://$NODE_IP:30083/
# healthy ns_count=12

Step 2: Audit namespace listing permissions and critical namespaces

Before setting up monitoring, confirm the RBAC permissions kubens requires are intact and that expected namespaces exist:

#!/bin/bash
# check-kubens-health.sh

echo "=== Namespace listing permissions ==="
kubectl auth can-i list namespaces && echo "OK: list namespaces" || echo "MISSING: list namespaces"
kubectl auth can-i get namespaces && echo "OK: get namespaces" || echo "MISSING: get namespaces"

echo ""
echo "=== Namespace inventory ==="
kubectl get namespaces --no-headers | awk '{print $1, $2}'

echo ""
echo "=== Active namespace in kubeconfig ==="
kubectl config view --minify -o jsonpath='{.contexts[0].context.namespace}'
echo ""

echo ""
echo "=== Resource quota status per namespace ==="
for NS in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}'); do
  USED=$(kubectl get resourcequota -n "$NS" --no-headers 2>/dev/null | wc -l)
  if [ "$USED" -gt 0 ]; then
    echo "Namespace $NS has resource quotas — check for exhaustion"
  fi
done
chmod +x check-kubens-health.sh
./check-kubens-health.sh

Step 3: Set up HTTP monitoring in Vigilmon

With the health endpoint running, add it to Vigilmon:

  1. Log in to vigilmon.online and go to Monitors → New Monitor
  2. Choose HTTP / HTTPS
  3. Add monitors for your cluster namespace access layer:

| Monitor name | URL | Expected status | |---|---|---| | kubens namespace health | http://your-node-ip:30083/ | 200 | | Kubernetes API livez | https://your-api-server:6443/livez | 200 | | Kubernetes API readyz | https://your-api-server:6443/readyz | 200 |

  1. Set the check interval to 1 minute
  2. Under Expected response, set status code 200 and optionally match healthy in the body
  3. For private CA clusters, add the CA certificate under TLS settings
  4. Save each monitor

Step 4: Add a TCP monitor for the Kubernetes API port

Add a TCP monitor to catch network-level failures before the HTTP health check fires:

  1. Go to Monitors → New Monitor
  2. Choose TCP Port
  3. Enter your Kubernetes API server hostname and port 6443
  4. Save the monitor

A TCP failure on port 6443 while the node health endpoint is still reachable typically indicates a network policy or firewall rule was changed to block API server traffic rather than a cluster outage.


Step 5: Configure alert channels

A kubens failure during development means engineers are running commands against an unexpected namespace. In production this can lead to accidental resource modifications in the wrong namespace. Alert immediately so the team can verify their active namespace before proceeding.

Email alerts

  1. Go to Alert Channels → Add Channel → Email
  2. Enter your SRE on-call and platform engineering addresses
  3. Assign the channel to all kubens monitors

Webhook alerts

  1. Go to Alert Channels → Add Channel → Webhook
  2. Enter your incident management webhook URL (PagerDuty, Opsgenie, Slack)
  3. Sample Vigilmon webhook payload:
{
  "monitor_name": "kubens namespace health",
  "status": "down",
  "url": "http://your-node-ip:30083/",
  "started_at": "2024-01-15T09:10:00Z",
  "duration_seconds": 60
}

Route this to a runbook that tells engineers to verify their active namespace with kubectl config view --minify before executing any namespace-scoped commands.


Step 6: Correlate Vigilmon alerts with kubens diagnostics

When you receive a namespace health downtime alert, run these checks:

# 1. List available namespaces (the core kubens operation)
kubectl get namespaces

# 2. Check what namespace is currently active
kubectl config view --minify -o jsonpath='{.contexts[0].context.namespace}'
echo ""

# 3. Verify namespace listing RBAC
kubectl auth can-i list namespaces

# 4. Test a specific namespace that kubens relies on
kubectl get pods -n kube-system --request-timeout=5s | head -5

# 5. Check for recently deleted namespaces
kubectl get events --all-namespaces --field-selector reason=NamespaceDeleted

# 6. Inspect the kubens health pod
kubectl logs -n observability -l app=kubens-health -c checker --tail=20

# 7. Check resource quotas in critical namespaces
kubectl describe resourcequota -n production 2>/dev/null || echo "No quotas in production"

# 8. Verify Kubernetes API server connectivity
kubectl cluster-info

If the health endpoint returns 503 with error=Forbidden, the RBAC binding for namespace listing was removed. Add it back and restart the health deployment to confirm recovery.


Step 7: Create a status page for namespace switching infrastructure

Make namespace health visible to the whole team:

  1. Go to Status Pages → New Status Page
  2. Name it: "Kubernetes Namespace Access"
  3. Add your kubens health monitor, API livez, and API readyz monitors
  4. Share the URL with the engineering team

Developers can check this page before running namespace-scoped operations, preventing unintended modifications to the wrong namespace.


Summary

| What you set up | What it catches | |---|---| | HTTP monitor on health endpoint | Namespace listing failures, RBAC permission loss, API unavailability | | HTTP monitor on livez/readyz | API server degradation before kubens fails | | TCP monitor on port 6443 | Network path failures to the Kubernetes API server | | Email + webhook alert channels | Immediate notification when namespace switching breaks | | Status page | Team-wide visibility into namespace access health |

kubens is the tool that determines which Kubernetes namespace every subsequent command runs against. Monitoring its underlying infrastructure is the only way to catch namespace switching failures before they cause engineers to inadvertently modify the wrong environment.

Get started at vigilmon.online — free tier, no credit card required.

Monitor your app with Vigilmon

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

Start free →