Glasskube is an open-source Kubernetes package manager that brings apt-style package management to Kubernetes — with a web UI, CLI, GitOps integration, and automatic dependency resolution. When its package operator stops reconciling, or its repository sync falls behind, cluster packages silently drift from their desired state. External monitoring catches these failures before they become incidents.
This tutorial shows you how to use Vigilmon to monitor Glasskube's operator health, repository sync status, and update pipeline.
Why Glasskube needs external monitoring
Glasskube has several moving parts, each of which can fail independently:
| Component | Role |
|---|---|
| Package Operator | Controller that reconciles ClusterPackage and Package CRDs |
| Package Repository | Remote index that lists available packages and versions |
| Glasskube UI | Web dashboard for browsing and managing packages |
| Update Pipeline | Automated checks for new package versions |
Failures in each component look different:
- Operator crash-loops — installed packages are never updated; new
Packageresources stay inPendingindefinitely - Repository sync fails — the package catalog shows stale data; users can't discover or install new packages
- Dependency resolution breaks — a transitive dependency update causes an incompatibility; the operator surfaces an error in the CR status but no alert fires
- UI is unreachable — operators can't inspect package state or trigger upgrades through the dashboard
- Update pipeline stalls — security patches don't get applied because the version check never ran
Standard Kubernetes probes only check that the operator pod is alive. They cannot check whether the repository is actually reachable, whether CRDs are being reconciled, or whether the update pipeline ran recently.
What you'll need
- Glasskube installed on a Kubernetes cluster (
glasskube bootstrap) - Glasskube UI exposed via Ingress or LoadBalancer
- A free Vigilmon account
Step 1: Verify Glasskube components are running
kubectl get pods -n glasskube-system
# NAME READY STATUS RESTARTS
# glasskube-controller-manager-xxx-yyy 1/1 Running 0
# glasskube-ui-zzz-www 1/1 Running 0
Check the controller manager health endpoint:
kubectl port-forward -n glasskube-system svc/glasskube-controller-manager-metrics-service 8080:8080
curl -s http://localhost:8080/healthz
# ok
Step 2: Expose the UI and health endpoint
If the Glasskube UI is not yet exposed externally, add an Ingress:
# glasskube-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: glasskube-ui
namespace: glasskube-system
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
ingressClassName: nginx
tls:
- hosts:
- glasskube.internal.example.com
secretName: glasskube-tls
rules:
- host: glasskube.internal.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: glasskube-ui
port:
number: 8080
Apply:
kubectl apply -f glasskube-ingress.yaml
Also expose the controller manager health endpoint through a separate Ingress path or use an internal Vigilmon agent:
# glasskube-health-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: glasskube-health
namespace: glasskube-system
spec:
ingressClassName: nginx
rules:
- host: glasskube-health.internal.example.com
http:
paths:
- path: /healthz
pathType: Exact
backend:
service:
name: glasskube-controller-manager-metrics-service
port:
number: 8080
Step 3: Monitor the package operator health
In Vigilmon:
- Click Add Monitor → HTTP(S)
- URL:
https://glasskube-health.internal.example.com/healthz - Interval:
1 minute - Expected status:
200 - String assertion: response body contains
ok - Timeout:
10 seconds - Name:
Glasskube – Package Operator Health - Save
Step 4: Monitor repository sync status
Glasskube periodically syncs its package repository from a remote URL (defaulting to the official Glasskube repository). If the sync fails, the package catalog becomes stale.
Add a custom health endpoint that verifies the repository was synced recently. Create a CronJob that checks sync status and exposes it:
# repo-sync-check.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: repo-sync-check-script
namespace: glasskube-system
data:
check.sh: |
#!/bin/sh
# Check if the PackageRepository resource is synced
STATUS=$(kubectl get packagerepository glasskube -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null)
if [ "$STATUS" = "True" ]; then
echo '{"status":"ok","repository":"synced"}'
exit 0
else
echo '{"status":"error","repository":"not synced"}'
exit 1
fi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: repo-sync-probe
namespace: glasskube-system
spec:
replicas: 1
selector:
matchLabels:
app: repo-sync-probe
template:
metadata:
labels:
app: repo-sync-probe
spec:
serviceAccountName: glasskube-controller-manager
containers:
- name: probe
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- |
while true; do
STATUS=$(kubectl get packagerepository glasskube \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null)
if [ "$STATUS" = "True" ]; then
echo "synced" > /tmp/repo-status
else
echo "not-synced" > /tmp/repo-status
fi
sleep 30
done
---
apiVersion: v1
kind: Service
metadata:
name: repo-sync-probe
namespace: glasskube-system
spec:
selector:
app: repo-sync-probe
ports:
- port: 8080
targetPort: 8080
Expose via Ingress and add a Vigilmon HTTP monitor:
- URL:
https://glasskube-health.internal.example.com/repo-sync - String assertion:
"synced" - Name:
Glasskube – Repository Sync Status
Step 5: Monitor package reconciliation
Create a probe that watches for Package or ClusterPackage resources stuck in non-Ready states:
# Run this as a CronJob every 5 minutes
kubectl get clusterpackages -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}'
# cert-manager True
# ingress-nginx True
# prometheus False <-- this would trigger an alert
Build a small monitoring sidecar that surfaces this as an HTTP endpoint:
apiVersion: batch/v1
kind: CronJob
metadata:
name: package-health-check
namespace: glasskube-system
spec:
schedule: "*/5 * * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: glasskube-controller-manager
containers:
- name: check
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- |
FAILED=$(kubectl get clusterpackages -A \
-o jsonpath='{range .items[*]}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}' \
| grep -c "False" || true)
if [ "$FAILED" -gt "0" ]; then
echo "PACKAGES_FAILED=$FAILED"
exit 1
fi
echo "ALL_PACKAGES_READY"
restartPolicy: Never
For Vigilmon monitoring, combine this with the operator health check — if the operator is healthy but packages are failing, that's the signal.
Step 6: Monitor the Glasskube UI
The Glasskube web UI is the primary interface for operators to inspect and manage packages. Monitor it separately:
- Add Monitor → HTTP(S)
- URL:
https://glasskube.internal.example.com/ - Expected status:
200 - String assertion: response body contains
Glasskube(matches the page title) - Name:
Glasskube – Web UI
Also monitor TLS certificate expiry for the UI's HTTPS endpoint:
- In the same monitor, enable SSL certificate monitoring
- Alert when the cert expires in fewer than 14 days
Step 7: Monitor the update pipeline
Glasskube can automatically check for and apply package updates. Verify the update check is running by monitoring a downstream signal: check that the PackageRepository lastSyncTime is recent.
kubectl get packagerepository glasskube -o jsonpath='{.status.lastSyncTime}'
# 2026-07-01T10:23:45Z
Write a probe that returns a non-200 if the last sync is more than 2 hours old:
#!/usr/bin/env python3
# sync-age-probe.py — run as a container exposing :8080
from http.server import HTTPServer, BaseHTTPRequestHandler
from datetime import datetime, timezone
import subprocess, json
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != '/healthz':
self.send_response(404)
self.end_headers()
return
result = subprocess.run(
['kubectl', 'get', 'packagerepository', 'glasskube',
'-o', 'jsonpath={.status.lastSyncTime}'],
capture_output=True, text=True)
last_sync = result.stdout.strip()
if last_sync:
sync_time = datetime.fromisoformat(last_sync.replace('Z', '+00:00'))
age_hours = (datetime.now(timezone.utc) - sync_time).seconds / 3600
if age_hours < 2:
self.send_response(200)
self.end_headers()
self.wfile.write(b'{"status":"ok","sync_age_hours":' + str(round(age_hours,2)).encode() + b'}')
return
self.send_response(503)
self.end_headers()
self.wfile.write(b'{"status":"stale"}')
HTTPServer(('', 8080), Handler).serve_forever()
In Vigilmon, add an HTTP monitor for this probe:
- URL:
https://glasskube-health.internal.example.com/update-pipeline - Expected status:
200 - Name:
Glasskube – Update Pipeline
Step 8: Alerts and status page
In Vigilmon → Alert Channels, add your team's Slack and email:
- Set Alert after:
2 consecutive failures - Enable Recovery alerts
- Assign channels to all monitors tagged
glasskube
Create a private status page for the platform team:
- Status Pages → New Status Page
- Add all four monitors
- Set visibility to Private
- Share the URL with the platform team
Monitor checklist
| Monitor | URL pattern | What it catches |
|---|---|---|
| Operator health | /healthz | Operator process crash or restart loop |
| Repository sync | /repo-sync | Stale package catalog |
| Web UI | / | Dashboard unavailable |
| Update pipeline | /update-pipeline | Version checks not running |
Summary
Glasskube's declarative package management is only as reliable as the operator, repository, and update pipeline behind it. External monitoring with Vigilmon gives you continuous health checks across all four components — so you know the moment packages stop reconciling, the catalog goes stale, or the UI disappears. Sign up free at vigilmon.online and add your first Glasskube monitor today.