Admiralty is a Kubernetes operator for multi-cluster scheduling and workload federation. Instead of deploying pods directly to a target cluster, it intercepts pod creation in a source cluster and uses a "proxy pod" pattern: a lightweight proxy pod stays in the source cluster while Admiralty's controllers schedule the real pod onto one or more registered target clusters. The source cluster runs the multicluster-scheduler controller; each target cluster runs the multicluster-scheduler agent, and the source cluster sees each target as a virtual node. When the source controller crashes, new cross-cluster scheduling stops silently — pods stay Pending with no explanation. When the target agent crashes, proxy pods are created but never transition to Running. These failures have no representation in either cluster's standard health checks.
In this tutorial you'll set up comprehensive uptime monitoring for your Admiralty deployment using Vigilmon — free tier, no credit card required.
Why Admiralty deployments need external monitoring
Admiralty introduces a category of scheduling failure that neither the source nor the target cluster exposes through normal Kubernetes observability:
- Source controller crash silently stops cross-cluster scheduling — the
multicluster-schedulercontroller in the source cluster exits; new pods that should be federated to target clusters stayPendingindefinitely with aSchedulerNamethat no local scheduler recognizes; no event fires, no node condition changes - Target agent crash means proxy pods never become Running — the
multicluster-scheduleragent in the target cluster stops reconciling; proxy pods in the source cluster reportPendingor show stale status; actual workload pods in the target cluster may still be running but no new ones can be started - Virtual node registration drops — Admiralty registers each target cluster as a virtual node (e.g.
admiralty-my-target-cluster) in the source cluster; if that registration lapses, Kubernetes marks the nodeNotReadyand stops scheduling to it, breaking the entire target cluster's capacity without alerting the target cluster operators - Cross-cluster authentication tokens expire — Admiralty uses kubeconfig secrets to authenticate from the source controller to target clusters; when these tokens rotate or expire, scheduling attempts fail silently inside the controller with auth errors that never surface as Kubernetes events or pod conditions
- Candidate pod feedback loop breaks — Admiralty uses a CandidatePod mechanism to negotiate placement across clusters; if the feedback loop between source and target breaks (network partition, API server degradation), pods are left in an intermediate
Pendingstate that never resolves without manual intervention
These failures are especially damaging in mixed environments where some workloads schedule locally and others federate — a partial failure looks like normal operation until a specific workload type fails to start.
What you'll need
- An Admiralty deployment with at least one source cluster running the
multicluster-schedulercontroller and one target cluster running the agent - A federated workload or test deployment that routes through at least one virtual node, exposed via Service or Ingress
- A free Vigilmon account (sign up takes 30 seconds)
Step 1: Expose a health endpoint for monitoring
Admiralty's controller and agent both expose metrics and health endpoints on port 8080. First, verify your components and virtual nodes are healthy:
# Check the multicluster-scheduler controller (context: source)
kubectl --context source get pods -n admiralty
# NAME READY STATUS RESTARTS AGE
# multicluster-scheduler-6d9f8c7b5-xk2pq 1/1 Running 0 7d
# Check the multicluster-scheduler agent (context: target)
kubectl --context target get pods -n admiralty
# NAME READY STATUS RESTARTS AGE
# multicluster-scheduler-7f8b9d6c4-mn3rt 1/1 Running 0 7d
# Check virtual nodes registered in the source cluster
kubectl --context source get nodes
# NAME STATUS ROLES AGE VERSION
# admiralty-my-target-cluster Ready agent 7d v0.0.0-admiralty
# source-node-1 Ready worker 14d v1.27.3
# Port-forward to check controller health endpoint
kubectl --context source port-forward -n admiralty deploy/multicluster-scheduler 8080:8080
curl http://localhost:8080/healthz
# ok
Deploy a federated probe workload that Admiralty schedules onto the target cluster. This validates the full scheduling path end-to-end:
# admiralty-probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: admiralty-probe
namespace: admiralty
annotations:
multicluster.admiralty.io/elect: ""
spec:
replicas: 1
selector:
matchLabels:
app: admiralty-probe
template:
metadata:
labels:
app: admiralty-probe
annotations:
multicluster.admiralty.io/elect: ""
spec:
schedulerName: admiralty
containers:
- name: probe
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
readinessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 5
periodSeconds: 10
volumes:
- name: config
configMap:
name: admiralty-probe-nginx
---
apiVersion: v1
kind: ConfigMap
metadata:
name: admiralty-probe-nginx
namespace: admiralty
data:
default.conf: |
server {
listen 80;
location /healthz {
return 200 '{"status":"ok","component":"admiralty-probe","scheduler":"admiralty"}';
add_header Content-Type application/json;
}
}
---
apiVersion: v1
kind: Service
metadata:
name: admiralty-probe
namespace: admiralty
spec:
type: LoadBalancer
selector:
app: admiralty-probe
ports:
- port: 80
targetPort: 80
protocol: TCP
kubectl --context source apply -f admiralty-probe.yaml
# Get the LoadBalancer IP (assigned in the target cluster, surfaced via Admiralty)
kubectl --context source get svc admiralty-probe -n admiralty
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# admiralty-probe LoadBalancer 10.96.31.200 203.0.113.84 80/TCP 3m
# Verify proxy pod in source cluster
kubectl --context source get pods -n admiralty -l app=admiralty-probe
# NAME READY STATUS RESTARTS AGE
# admiralty-probe-5d8c7f9b4-ab3mn 1/1 Running 0 3m
# Verify real pod in target cluster
kubectl --context target get pods -n admiralty -l app=admiralty-probe
# NAME READY STATUS RESTARTS AGE
# admiralty-probe-5d8c7f9b4-ab3mn 1/1 Running 0 2m
# Confirm the health endpoint responds
curl http://203.0.113.84/healthz
# {"status":"ok","component":"admiralty-probe","scheduler":"admiralty"}
Step 2: Set up HTTP monitoring in Vigilmon
With your probe endpoint exposed, add it to Vigilmon:
- Log in to vigilmon.online and go to Monitors → New Monitor
- Choose HTTP / HTTPS as the type
- Set the URL to your probe endpoint:
http://203.0.113.84/healthz - Set the check interval to 1 minute
- Under Expected response, set:
- Status code:
200 - Response body contains:
"status":"ok"
- Status code:
- Save the monitor
This monitor validates the entire Admiralty scheduling path: the source controller must be running and reconciling, the virtual node for the target cluster must be Ready, the target agent must be placing real pods, and the LoadBalancer must be routing from the target cluster back to the public endpoint. A single failed 200 means at least one of these components has degraded.
Why external monitoring catches what Kubernetes misses
When Admiralty's source controller crashes, pods that should federate simply stay Pending in the source cluster. Kubernetes generates no alerts — the pod is scheduled to the admiralty scheduler, which is simply absent. Vigilmon detects the resulting outage in under a minute because the probe pod stops responding as soon as the target's instance is unreachable. Its multi-region consensus model eliminates false positives from transient probe-path blips.
Step 3: Monitor TCP ports and the Admiralty controller health endpoint
Add monitors to detect failures at the controller and virtual node level:
Probe service TCP check:
- Go to Monitors → New Monitor
- Choose TCP Port
- Enter: Host
203.0.113.84, Port80 - Save the monitor
Admiralty controller health via Ingress:
Expose the controller's /healthz endpoint through an Ingress in the source cluster so Vigilmon can probe it directly:
# admiralty-controller-ingress.yaml
apiVersion: v1
kind: Service
metadata:
name: admiralty-controller-health
namespace: admiralty
spec:
selector:
app: multicluster-scheduler
ports:
- port: 8080
targetPort: 8080
name: metrics
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: admiralty-controller-health
namespace: admiralty
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /healthz
spec:
rules:
- host: admiralty-health.your-source-cluster.com
http:
paths:
- path: /healthz
pathType: Exact
backend:
service:
name: admiralty-controller-health
port:
number: 8080
kubectl --context source apply -f admiralty-controller-ingress.yaml
Add an HTTP monitor in Vigilmon for https://admiralty-health.your-source-cluster.com/healthz expecting status 200 and body ok.
Also add a TCP monitor for the controller metrics port to detect process-level failures even when the HTTP layer is unreachable:
- Go to Monitors → New Monitor
- Choose TCP Port
- Enter: Host
admiralty-health.your-source-cluster.com, Port8080 - Save the monitor
Step 4: Configure alert channels
An Admiralty failure silently stops cross-cluster workload placement — new deployments pend forever while on-call has no signal.
Email alerts
- In Vigilmon, go to Alert Channels → Add Channel → Email
- Enter your platform team's on-call email
- Assign the channel to all Admiralty monitors
Webhook alerts (Slack, PagerDuty, etc.)
- Go to Alert Channels → Add Channel → Webhook
- Enter your webhook URL
- Assign the channel to your monitors
Example payload when the Admiralty probe goes down:
{
"monitor_name": "Admiralty Probe Health",
"status": "down",
"url": "http://203.0.113.84/healthz",
"started_at": "2024-01-15T14:05:00Z",
"duration_seconds": 120
}
Run these diagnostics immediately when an alert fires:
# Check source controller
kubectl --context source get pods -n admiralty
kubectl --context source logs -n admiralty -l app=multicluster-scheduler --tail=100
# Check virtual node status in source cluster
kubectl --context source get node admiralty-my-target-cluster
kubectl --context source describe node admiralty-my-target-cluster
# Check target agent
kubectl --context target get pods -n admiralty
kubectl --context target logs -n admiralty -l app=multicluster-scheduler --tail=100
# Check proxy pods and their status annotations
kubectl --context source get pods -n admiralty -l app=admiralty-probe -o yaml | grep -A10 annotations
# Check for pending federated pods stuck in source
kubectl --context source get pods -A --field-selector status.phase=Pending
# Check authentication secrets are present and not expired
kubectl --context source get secrets -n admiralty | grep kubeconfig
Step 5: Create a public status page
Multi-cluster platforms built on Admiralty often underpin internal developer platforms where teams self-service workload placement. Give them a status page.
- In Vigilmon, go to Status Pages → New Status Page
- Give it a name: "Admiralty Multi-Cluster Scheduler Status"
- Add your monitors: Admiralty Probe HTTP, Probe TCP 80, Controller Health HTTP, Controller TCP 8080
- Group them: Workload Federation, Controller Health, Port Availability
- Publish the page
Share this URL with application teams whose deployments rely on Admiralty for cross-cluster scheduling.
Putting it all together
Here's a summary of the monitors to create for an Admiralty deployment:
| Monitor | Type | What it catches |
|---------|------|-----------------|
| http://203.0.113.84/healthz | HTTP | Full federation path (controller → virtual node → target agent → pod → response) |
| 203.0.113.84:80 | TCP | Probe service TCP reachability |
| https://admiralty-health.your-source-cluster.com/healthz | HTTP | Source controller process health |
| admiralty-health.your-source-cluster.com:8080 | TCP | Controller metrics port reachability |
And the Admiralty diagnostics to run when an alert fires:
# Quick triage: controller or target agent?
kubectl --context source get pods -n admiralty
kubectl --context target get pods -n admiralty
# Check virtual node readiness in source
kubectl --context source get nodes | grep admiralty
kubectl --context source get node admiralty-my-target-cluster -o yaml | grep -A10 conditions
# Check controller logs for auth or scheduling errors
kubectl --context source logs -n admiralty deploy/multicluster-scheduler | grep -E "error|401|403|token|expired"
# Check proxy pod placement annotations in source
kubectl --context source get pods -n admiralty -l app=admiralty-probe -o jsonpath='{.items[*].metadata.annotations}' | python3 -m json.tool
# Check real pod in target cluster
kubectl --context target get pods -n admiralty -o wide
# Check events across both clusters
kubectl --context source get events -n admiralty --sort-by='.lastTimestamp' | tail -20
kubectl --context target get events -n admiralty --sort-by='.lastTimestamp' | tail -20
What's next
- SSL certificate monitoring — add SSL monitors for any HTTPS endpoints served from workloads federated through Admiralty to target clusters
- Heartbeat monitoring — run a scheduled job that federates to a target cluster on a cron schedule and sends a Vigilmon heartbeat on completion, confirming the scheduling path works end-to-end
- Per-target coverage — if you register multiple target clusters as virtual nodes, create a dedicated monitor set per target to isolate which cluster's agent is failing when an alert fires
Get started free at vigilmon.online — no credit card, monitors start running in under a minute.