2
2
title : How to guarantee allocated values for next reconciliation
3
3
date : 2025-05-22
4
4
author : >-
5
- [Attila Mészáros](https://github.com/csviri)
5
+ [Attila Mészáros](https://github.com/csviri) and [Chris Laprun](https://github.com/metacosm)
6
6
---
7
7
8
8
We recently released v5.1 of Java Operator SDK (JOSDK). One of the highlights of this release is related to a topic of
@@ -11,13 +11,13 @@ so-called
11
11
).
12
12
13
13
To describe the problem, let's say that our controller needs to create a resource that has a generated identifier, i.e.
14
- a resource which identifier cannot be directely derived from the custom resource's desired state as specified in its
15
- ` spec ` field. In order to record the fact that the resource was successfully created, and to avoid attempting to
14
+ a resource which identifier cannot be directly derived from the custom resource's desired state as specified in its
15
+ ` spec ` field. To record the fact that the resource was successfully created, and to avoid attempting to
16
16
recreate the resource again in subsequent reconciliations, it is typical for this type of controller to store the
17
17
generated identifier in the custom resource's ` status ` field.
18
18
19
19
The Java Operator SDK relies on the informers' cache to retrieve resources. These caches, however, are only guaranteed
20
- to be eventually consistent. It could happen, then, that, if some other event occurs, that would result in a new
20
+ to be eventually consistent. It could happen that, if some other event occurs, that would result in a new
21
21
reconciliation, ** before** the update that's been made to our resource status has the chance to be propagated first to
22
22
the cluster and then back to the informer cache, that the resource in the informer cache does ** not** contain the latest
23
23
version as modified by the reconciler. This would result in a new reconciliation where the generated identifier would be
@@ -59,10 +59,8 @@ The trick is to intercept the resource that the reconciler updated and cache tha
59
59
of the informer's cache. Subsequently, if the reconciler needs to read the resource, the SDK will first check if it is
60
60
in the overlay cache and read it from there if present, otherwise read it from the informer's cache. If the informer
61
61
receives an event with a fresh resource, we always remove the resource from the overlay cache, since that is a more
62
- recent resource. But this ** works only** if the reconciler updates the resource using ** with optimistic locking** , which
63
- is handled for you by ` PrimaryUpdateAndCacheUtils ` provided you pass it a "fresh" (i.e. a version of the resource that
64
- only contains the fields you care about being updated) copy of the resource since Server-Side Apply will be used
65
- underneath. If the update fails on conflict, because the resource has already been updated on the cluster before we got
62
+ recent resource. But this ** works only** if the reconciler updates the resource using ** optimistic locking** .
63
+ If the update fails on conflict, because the resource has already been updated on the cluster before we got
66
64
the chance to get our update in, we simply wait and poll the informer cache until the new resource version from the
67
65
server appears in the informer's cache,
68
66
and then try to apply our updates to the resource again using the updated version from the server, again with optimistic
@@ -85,13 +83,10 @@ The following diagram sums up the process:
85
83
86
84
``` mermaid
87
85
flowchart TD
88
- A["Update Resource with Lock"] --> B{"Successful?"}
89
- B -- Fails on conflict --> D{"Resource updated from cluster?"}
90
- D -- " No: poll until updated " --> D
91
- D -- Yes --> n4["Apply desired changes on the resource again"]
86
+ A["Update Resource with Lock"] --> B{"Is Successful"}
87
+ B -- Fails on conflict --> D["Poll the Informer cache until resource updated"]
88
+ D --> A
92
89
B -- Yes --> n2{"Original resource still in informer cache?"}
93
90
n2 -- Yes --> C["Cache the resource in overlay cache"]
94
91
n2 -- No --> n3["Informer cache already contains up-to-date version, do not use overlay cache"]
95
- n4 --> A
96
-
97
92
```
0 commit comments