Bug description
On operator/vmcp v0.43.0, a VirtualMCPServer with config.operational.failureHandling.statusReportingInterval: 1m produces a DeploymentUpdated event pair every minute, and the operator logs Updating Deployment on the same cadence.
The backing Deployment’s pod template does not change (same ReplicaSet for days, no new rollout). The event text still says “rolling out new configuration”.
This is the same symptom class as #5819, but it happens with no external admission webhook / sidecar injector writing pod-template labels or annotations. The live pod template only has operator-owned keys (toolhive.stacklok.dev/runconfig-checksum + the usual toolhive labels).
Sibling VirtualMCPServers in the same namespace without statusReportingInterval set do not emit these events.
Steps to reproduce
- Install ToolHive operator v0.43.0 on Kubernetes.
- Create a
VirtualMCPServer that already has a Ready Deployment, and set:
spec:
config:
operational:
failureHandling:
statusReportingInterval: 1m
healthCheckInterval: 5m
healthCheckTimeout: 15s
unhealthyThreshold: 3
partialFailureMode: fail
- Watch:
kubectl get events -n <ns> --field-selector involvedObject.kind=VirtualMCPServer
kubectl logs -n <ns> deploy/toolhive-operator | grep 'Updating Deployment'
kubectl get deploy <vmcp-name> -n <ns> \
-o custom-columns='GEN:.metadata.generation,REV:.metadata.annotations.deployment\.kubernetes\.io/revision'
kubectl get rs -l toolhive-name=<vmcp-name> -n <ns>
Expected behavior
- Status reporting updates
VirtualMCPServer.status (backend health / phase) only.
ensureDeployment is a no-op when the desired pod template is unchanged.
DeploymentUpdated / “rolling out new configuration” is emitted only when a new ReplicaSet is actually created.
Actual behavior
- Every ~60s (exactly the configured
statusReportingInterval): two DeploymentUpdated events and two Updating Deployment log lines (two reconcile IDs at the same timestamp).
- Deployment
metadata.generation can move; deployment.kubernetes.io/revision and the active ReplicaSet stay put.
- Event stream is unusable for real config changes. Extra apiserver write load on every status tick.
Observed on one tenant (11 backends, unique podTemplateSpec + telemetryConfigRef). Three other vMCPs in the same cluster, same operator, no statusReportingInterval, stay quiet.
Environment (if relevant)
- OS/version: Talos Linux, single-node Kubernetes
- ToolHive version: operator +
proxyrunner + vmcp images v0.43.0
Additional context
Docs say statusReportingInterval “controls how often the vMCP runtime reports backend health and phase changes” and that lower values increase API server load. That should mean status patches, not Deployment writes.
Likely: a VMCP status update re-enqueues the VirtualMCPServer reconciler, and ensureDeployment treats something as drift (hash / map equality / defaulting) and calls Update + DeploymentUpdated even when spec.template is identical.
Related: #5819 (hot-loop when an external controller annotates the pod template — different trigger, same event). #5817 / #5818 (other ensureDeployment hot-loops, already closed).
No credentials or private hostnames in this report.
Bug description
On operator/vmcp v0.43.0, a
VirtualMCPServerwithconfig.operational.failureHandling.statusReportingInterval: 1mproduces aDeploymentUpdatedevent pair every minute, and the operator logsUpdating Deploymenton the same cadence.The backing Deployment’s pod template does not change (same ReplicaSet for days, no new rollout). The event text still says “rolling out new configuration”.
This is the same symptom class as #5819, but it happens with no external admission webhook / sidecar injector writing pod-template labels or annotations. The live pod template only has operator-owned keys (
toolhive.stacklok.dev/runconfig-checksum+ the usualtoolhivelabels).Sibling VirtualMCPServers in the same namespace without
statusReportingIntervalset do not emit these events.Steps to reproduce
VirtualMCPServerthat already has a Ready Deployment, and set:Expected behavior
VirtualMCPServer.status(backend health / phase) only.ensureDeploymentis a no-op when the desired pod template is unchanged.DeploymentUpdated/ “rolling out new configuration” is emitted only when a new ReplicaSet is actually created.Actual behavior
statusReportingInterval): twoDeploymentUpdatedevents and twoUpdating Deploymentlog lines (two reconcile IDs at the same timestamp).metadata.generationcan move;deployment.kubernetes.io/revisionand the active ReplicaSet stay put.Observed on one tenant (11 backends, unique
podTemplateSpec+telemetryConfigRef). Three other vMCPs in the same cluster, same operator, nostatusReportingInterval, stay quiet.Environment (if relevant)
proxyrunner+vmcpimages v0.43.0Additional context
Docs say
statusReportingInterval“controls how often the vMCP runtime reports backend health and phase changes” and that lower values increase API server load. That should mean status patches, not Deployment writes.Likely: a VMCP status update re-enqueues the VirtualMCPServer reconciler, and
ensureDeploymenttreats something as drift (hash / map equality / defaulting) and calls Update +DeploymentUpdatedeven whenspec.templateis identical.Related: #5819 (hot-loop when an external controller annotates the pod template — different trigger, same event). #5817 / #5818 (other ensureDeployment hot-loops, already closed).
No credentials or private hostnames in this report.