Closed
Description
Problem statement
- If for a resource we need an input what is an output (or status in K8S of the other resource). (Ideally these would be detected automatically? probably that is not feasable)
- When we want to make sure that something happens after an other resource is ready. Like if database is deployed, and want to create a specific default schema.
Solution
Both of these issues, can be addressed by with notions.
dependsOn
- If a dependent resourceB
depends on an other dependentA
, this will ensure thatB
will be reconciled afterA
is ready (see optionalReadyCondition
).ReconcilePrecondition
is optional for a dependent, if available it is evaluated if a resource should be reconciled or not.ReadyPostcondition
is optional, is provided the dependent is considered reconciled if the certain state reached. The condition check is async.DeletePostcondition
- on cleanup (backwards workflow) checks if the resource is deleted successfully (or delete completed) , or the cleanup execution should be re-scheduled (the finalizer not removed).
@ControllerConfiguration( ... ,
dependents = {
@Dependent(name="dep1", type = DeploymentDependentResource.class, readyPostcondition = ReadyCondition.class )
@Dependent(name="ser1", type = ServiceDependentResource.class, reconcilePrecondition = MyCondition.class),
@Dependent(type = OtherResource.class, reconcilePrecondition = OtherCondition.class,
deletePostcondition = DeleteCondition.class , dependsOn = {"dep1","ser1"}
})
})
public class MyResourceReconciler implements Reconciler<MyResource>, EventSourceInitializer<MyResource> {
....
}
Behavior Details
- If a dependent resource
B
depends onA
, butA
has aReconcilePrecondition
is evaluated as false, thenB
will not be reconciled either. - If a
ReconcilePrecondition
is evaluated false onA
dependent resource it is aDeleter
, delete should be called on it. And all the resources which are dependent onA
and are deleters should be deleted. This should work in a transitive manner too ( in reveres order, so the resource with reconcile condition closer to the top is deleted later). (See: https://github.com/java-operator-sdk/java-operator-sdk/blob/4d63e1260efeb70ac7550d52e48117bf8982fabb/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStandaloneDependentsReconciler.java#L68-L72 ) - if
ReadyPostcondition
can define anUpdateControl
to return if the condition is now reached, this means that effectively wait is always async. It can also defined time delay to reschedule the reconciliation. - For cleanup (TBD) - we could dry run the actual workflow (evaulating the conditions), and execute deleters backwards, also taking in mind delete post conditions (this might be an issue if dependent changes just parallel with the CR deletion). - Alternatively, what might a more bulletproof way is just based on the backwards order red the state of all the resources defined, and delete them if present.
- Eventually a possible concurrency option could be implemented (maybe think of it from early design). Not dependent resources could be reconciled concurrently.
Sync and Async Waiting Condition
Note that waiting for a state condition can happen synchronously or asynchronously, thus if we know that we will wait for deployment quite a long time to be ready, the scheduling algirthm can just exit the reonciliation and schedule a new reconciliation for a specified delay (UpdateControl.noUpdate().rescheduleAfter(2, TimeUnit.MINUTES)
if the condition not holds at the moment.
UPDATE: we discussed, for now and sync wait will be out of scope
Notes
- Not that without cycles the result is a DAG, what can be nicely scheduled for execution, more precisely a set of DAGs.
- The cycle detection will be needed, to help developers detect cycles as early as possible.
- This is an implementation detail, but 1 thing to think about is actually how to manage state, so if it's not in the status but a ConfigMap/Secret/CR the execution of two dependent resource reconciliation in the DAG cannot be parallel. Or at least not of those which update the state, so there are no conflicts. Maybe those should be marked explicitly as an improvement later?
- DeletePostcondition makes sense only for
Deleter
dependent resources.
To Discuss
DeletePostcondition
could be replaced by returning a boolean fromdelete
ofDeleter
.