Post

Should Kubernetes controllers+CRDs managing resources in the external world (non-k8s APIs) try to fix drifts (such as out of band modifications made in the external API) periodically –or assume they're the only actor, and wait for the next modification to reconfigure? This makes scaling harder.

0 reposts14 likes

CR is the intended config, so I expect it to overwrite the reality –the question is whether it should try to course-correct periodically. There are some systems (like Prodspec/Annealing) that learn from the current state and bring it back to the configuration SoT, but they're few and rare.

My interpretation is that the CR is the intended state during reconciliation, not forever. If something/someone changes the actual state, they'll be surprised to find it asynchronously revert. I don't think the CR can realistically be a SoT most of the time.

For most folks that ship has sailed. KRM-based tools like Crossplane manage infra in many shops. That’s why probably as a platform team, the moment you give users access to CRs, take the access away to modify the resource another way.

Concrete example: imagine a Bucket resource creates/configures buckets on s3 API. Someone goes to the s3 console and edits bucket configuration. Unless your controller periodically queries s3 API, it won't overwrite the out-of-band modifications until next time Bucket resource is modified.

Ideally an operator would watch the resources it manages and revert drift as soon as possible, to minimize downtime. But in the case where watching is not possible, polling may be acceptable. For scaling, consider adding a component that centralizes the polling and transforms it into watches.

To convert data polled from external API to watches, would you bring data from external API back into KRM APIs? I feel if there's an assumption like CRD will always overwrite the external API, not sure if there's value in reconciling sooner (vs eventually when the resource.generation++).

Depends on the use case. In ConfigSync we have multiple layers and user can decide which they want: 1. Periodic Remediation 2. (Reactive) Drift Remediation 3. Drift Prevention

It’s the old terraform (you’re the only actor) versus kubernetes resource model (reconciliation loops/annealing) conflict. In both cases they seem to have taken a conscious approach.

The problem with the first is that it implies a need for much more ordering (where TF benefits from having a resource graph, which has its own issues), as on a single run you’re expected to completely converge to the model.

The problem with the second is that you can’t be sure you can ever converge to the model, since it’s part of a he design to rerun rerun rerun until spec and status converge.

I'd expect that they're periodically querying the S3 API in this case. At a high-level, operators are supposed to continuously reconcile the current and desired states (which imply watching out for drift). Unfortunately, most external systems lack APIs to listen for changes, hence the polling.

If your controller is managing 20,000 buckets, you'll make 20k external API calls during controller startup full sync to verify buckets exist and their config is up-to-date (99.99% are) –during which you won't get to processing a new object soon enough, bc the workqueue is still full.

This sounds like foreground and background tasks are sharing the same queue. You could consider two task queues internally, with weighted fair sharing or priorities in how they are drained. This way, the 20K external API calls during startup don't starve the more important new object processing.

Same in k8s with load-balancers. If you have 100 services with LBs, and someone modifies one behind the scenes, we don't know to reconcile, because (AFAICT) none of the clouds have watch APIs and they all have API quota. Polling 100 LBs every 10 seconds = 10 QPS of 99.999% do-nothing traffic.