Bug Fix: Reconciliation Feedback Loop
This release fixes a critical bug where the BGP and pool sync controllers entered a tight reconciliation loop (~4 events/second), causing unnecessary CPU usage and event spam in etcd.
Problem
Three interacting issues created an infinite reconciliation cycle:
- BGPSyncReconciler unconditionally updated
CiliumBGPAdvertisementresources on every reconcile, even when the spec was unchanged - PoolSyncReconciler watched
DynamicPrefixwithout predicate filters, so status-only updates triggered pool reconciliation - Pool updates always wrote a new
last-synctimestamp annotation, which triggered BGPSyncReconciler's pool watch, restarting the cycle
Impact
- ~176m CPU consumed continuously by the operator for no useful work
- Thousands of unnecessary Kubernetes events flooding etcd
- Increased apiserver memory pressure from watch event processing
Fix
- Skip no-op updates to
CiliumBGPAdvertisementand pool resources by comparing existing vs desired spec before calling Update - Add
GenerationChangedPredicatetoDynamicPrefixand pool watches so status-only changes don't trigger cross-controller reconciliation - Preserve
LastTransitionTimeon conditions when status hasn't actually transitioned (per Kubernetes convention)
Result
Operator CPU usage dropped from 176m to 2m (99% reduction).
Installation
Using Helm (recommended)
helm install dynamic-prefix-operator \
oci://ghcr.io/jr42/dynamic-prefix-operator/helm/dynamic-prefix-operator \
--version 0.0.2Using kubectl
kubectl apply -f https://github.com/jr42/dynamic-prefix-operator/releases/download/v0.0.2/install.yamlDocker Images
Multi-arch images (amd64, arm64):
ghcr.io/jr42/dynamic-prefix-operator:v0.0.2