Skip to content

where resources already exist but requests are generated by CREATE #2290

Closed

Description

@10000-ki

Bug Report

io.fabric8.kubernetes.client.KubernetesClientException: Failure executing: PATCH at: https://172.23.0.1:443/apis/policy/v1/poddisruptionbudgets/os-osfarm-cluster-manager-pdb?fieldManager=opensearchreconciler&force=true. Message: Operation cannot be fulfilled on poddisruptionbudgets.policy "os-osfarm-cluster-manager-pdb": the object has been modified; please apply your changes to the latest version and try again. Received status: Status(apiVersion=v1, code=409, details=StatusDetails(causes=[], group=policy, kind=poddisruptionbudgets, name=os-osfarm-cluster-manager-pdb, retryAfterSeconds=null, uid=null, additionalProperties={}), kind=Status, message=Operation cannot be fulfilled on poddisruptionbudgets.policy "os-osfarm-cluster-manager-pdb": the object has been modified; please apply your changes to the latest version and try again, metadata=ListMeta(_continue=null, remainingItemCount=null, resourceVersion=null, selfLink=null, additionalProperties={}), reason=Conflict, status=Failure, additionalProperties={}).
	at io.fabric8.kubernetes.client.KubernetesClientException.copyAsCause(KubernetesClientException.java:238)
	at io.fabric8.kubernetes.client.dsl.internal.OperationSupport.waitForResult(OperationSupport.java:507)
	at io.fabric8.kubernetes.client.dsl.internal.OperationSupport.handleResponse(OperationSupport.java:524)
	at io.fabric8.kubernetes.client.dsl.internal.OperationSupport.handlePatch(OperationSupport.java:419)
	at io.fabric8.kubernetes.client.dsl.internal.OperationSupport.handlePatch(OperationSupport.java:397)
	at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.handlePatch(BaseOperation.java:713)
	at io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation.lambda$patch$2(HasMetadataOperation.java:232)
	at io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation.patch(HasMetadataOperation.java:237)
	at io.fabric8.kubernetes.client.dsl.internal.HasMetadataOperation.patch(HasMetadataOperation.java:252)
	at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.serverSideApply(BaseOperation.java:1132)
	at io.fabric8.kubernetes.client.dsl.internal.BaseOperation.serverSideApply(BaseOperation.java:92)
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource.create(KubernetesDependentResource.java:140)
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource.create(CRUDKubernetesDependentResource.java:16)
	at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.handleCreate(AbstractDependentResource.java:114)
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource.handleCreate(KubernetesDependentResource.java:111)
	at io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResource.handleCreate(KubernetesDependentResource.java:32)
	at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.reconcile(AbstractDependentResource.java:62)
	at io.javaoperatorsdk.operator.processing.dependent.SingleDependentResourceReconciler.reconcile(SingleDependentResourceReconciler.java:19)
	at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.reconcile(AbstractDependentResource.java:52)
	at io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileExecutor$NodeReconcileExecutor.doRun(WorkflowReconcileExecutor.java:115)
	at io.javaoperatorsdk.operator.processing.dependent.workflow.NodeExecutor.run(NodeExecutor.java:22)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)

at io.javaoperatorsdk.operator.processing.dependent.AbstractDependentResource.handleCreate(AbstractDependentResource.java:114)

스크린샷 2024-03-15 오후 5 41 05

What did you do?

Creating PDB with DependentResource

However, even though resources are already created

k get PodDisruptionBudget                                                                                                                                                                                                                                           ✔  10357  17:43:26
NAME                            MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
os-osfarm-cluster-manager-pdb   N/A             1                 1                     88m

When running additional 'reconcile' loop

The request was created as Create rather than Update

If there is a secondary resource, shouldn't the request go to update right?

Why is it created as create?

409 errors continue to occur, which is a problem

What did you expect to see?

What did you see instead? Under which circumstances?

no

Environment

Kubernetes cluster type:

Kubernetes

$ Mention java-operator-sdk version from pom.xml file

v4.4.4

$ java -version

jdk21

$ kubectl version

v1.23.15

Possible Solution

no

Additional context

no

Activity

  1. csviri commented on Mar 15, 2024

    @csviri
    Collaborator

    Hi @10000-ki there were improvements regarding to this in newer versions, pls upgrade to the newest version

  2. 10000-ki commented on Mar 15, 2024

    @10000-ki
    ContributorAuthor

    @csviri what version??
    I raised it to 4.6.0, but there was the same issue

  3. csviri commented on Mar 15, 2024

    @csviri
    Collaborator

    pls try the newest (4.8.1), if there will be still issues, we will take a look. Note that k8s 1.23 is also a bit old too, there were some issues with event sending in that version (what should be fixed now also on fabric8 client (restarting watches) ). But if the problem persist we can take a look, and try to make a reproducer. Probably the issue will be rather in the fabric8 client, since we are reading the last resource from the informer cache.

  4. 10000-ki commented on Mar 15, 2024

    @10000-ki
    ContributorAuthor

    Note that k8s 1.23 is also a bit old too, there were some issues with event sending in that version (what should be fixed now also on fabric8 client (restarting watches) )

    I'm using in-house k8s cluster in my company but v1.24 is maximum version :(
    will that be a problem?

  5. 10000-ki commented on Mar 15, 2024

    @10000-ki
    ContributorAuthor

    First, I'll increase the josdk version to the maximum v4.8.1

  6. csviri commented on Mar 15, 2024

    @csviri
    Collaborator

    AFAIK, it should not be, there were known issues, that k8s stopped sending events at some point (if remember correctly still present in 1.23) therefore the watch had to be restarted in informers periodically. But that was done in fabric8, so now it should be good.

  7. 10000-ki commented on Mar 15, 2024

    @10000-ki
    ContributorAuthor
    k get pdb --watch -n=opensearchoperatore2e-createopensearchcluster-6361d -o wide                                                                                                                                                                                  1 ↵  10373  18:15:17
    NAME                                             MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m6s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m6s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m6s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m6s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m6s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m6s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m7s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m8s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m9s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m10s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m11s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m12s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m13s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m13s
    os-test-opensearch-cluster-cluster-manager-pdb   N/A             1                 0                     2m13s
    

    Is there anything else I need to check?
    After posting the v4.8.1 version
    There are a lot of events then before

    and Create issues are still occurring

  8. csviri commented on Mar 15, 2024

    @csviri
    Collaborator

    ok, could you pls create a minimal open source reproducert project? Where we can run it on top of minikube and take a look on it, based on logs you provided it is impossible to figure out.

  9. csviri commented on Mar 15, 2024

    @csviri
    Collaborator

    Also what you can you can check if this is a problem on the newer versions of k8s.

  10. 10000-ki commented on Mar 15, 2024

    @10000-ki
    ContributorAuthor

    ok, could you pls create a minimal open source reproducert project? Where we can run it on top of minikube and take a look on it, based on logs you provided it is impossible to figure out.

    okay i will try

  11. 10000-ki commented on Mar 18, 2024

    @10000-ki
    ContributorAuthor

    @csviri
    In the k8s 1.29 version, it seems to run smoothly (i tested in my local)

    By the way, can you tell me exactly which version had the issue related to the k8s event and up to what version the impact is?

  12. csviri commented on Mar 18, 2024

    @csviri
    Collaborator

    @csviri In the k8s 1.29 version, it seems to run smoothly (i tested in my local)

    By the way, can you tell me exactly which version had the issue related to the k8s event and up to what version the impact is?

    Pls take a look on these:
    fabric8io/kubernetes-client#4781
    kubernetes/kubernetes#102464

    but there might be some newer ones. Maybe @shawkins knows more.

  13. shawkins commented on Mar 18, 2024

    @shawkins
    Collaborator

    I'm not aware of newer definitive underlying kube issues. There were several later client changes to limit any potential issues with the api server not sending events - we'll restart the watches at most every 10 minutes.

  14. 10000-ki commented on Mar 19, 2024

    @10000-ki
    ContributorAuthor

    @csviri @shawkins

    I don't know if it's related to the problem I raised.

    The problems I defined are as follows.

    1. even if secondary resource already exists, Create request sent to apserver, not update
    2. Retry occurs with 409 error
    3. Infinite retries occur as issue 1 continues to occur

    스크린샷 2024-03-19 오후 3 06 18

    mayBeActual field is null, even though resources are in k8s server

    Is it because the operator did not receive the resource creation event from k8s?

  15. csviri commented on Mar 19, 2024

    @csviri
    Collaborator

    Is it because the operator did not receive the resource creation event from k8s?

    yes, that means it is not in the cache of the informer, so no event received regarding that resource.

  16. 15 remaining items

  17. shawkins commented on Mar 20, 2024

    @shawkins
    Collaborator

    This log shows 5 updates of 5 different resources by the operator sdk. The operator then skips propogating the update event for all of them, so this appears to be expected behavior. Can you find a situation in your logs where "Propagating event for ..." appears - the surrounding logs should help determine if that resourceVersion of that resource was the result of the operator in which case there would be an event cycle.

  18. 10000-ki commented on Mar 22, 2024

    @10000-ki
    Author
  19. 10000-ki commented on Mar 22, 2024

    @10000-ki
    ContributorAuthor

    스크린샷 2024-03-22 오후 3 36 59

    @shawkins
    i think
    The spec is the same, but only the resourceVersion keeps changing
    The event seems to keep coming in without skipping.

  20. 10000-ki commented on Mar 22, 2024

    @10000-ki
    Author
  21. added a commit that references this issue on Mar 22, 2024
    8819654
  22. shawkins commented on Mar 22, 2024

    @shawkins
    Collaborator

    I don't know why resourceVersion is going up.

    resourceVersions change for any modification, not just the spec. It's the generation that typically increments with spec changes.

    The primary problem is the one captured here: #2249 - if the matcher fails to recognize that the resource is the same, then it adds the new annotation value, which due to a kube bug will increment the Deployment generation, and the cycle repeats.

    The SSA logic is not trying to be generation aware in this case, but sees the generation change as something you are requesting in the desired state - which is not correct.

    #2309 will address this specific case by ignoring all server managed fields in the comparison - this is similar to what the kubernetes client does in the PatchUtils class when generating a patch.

    @csviri not sure if that is sufficient to fully close #2249 as the doc changes would be good too.

    I changed it to csa, but there was no difference.

    What do you mean?

  23. 10000-ki commented on Mar 25, 2024

    @10000-ki
    ContributorAuthor

    The primary problem is the one captured here: #2249 - if the matcher fails to recognize that the resource is the same, then it adds the new annotation value, which due to a kube bug will increment the Deployment generation, and the cycle repeats.
    The SSA logic is not trying to be generation aware in this case, but sees the generation change as something you are requesting in the desired state - which is not correct.
    #2309 will address this specific case by ignoring all server managed fields in the comparison - this is similar to what the kubernetes client does in the PatchUtils class when generating a patch.

    @shawkins oh i see..
    thank you for explaining

    I changed it to csa, but there was no difference.

    https://javaoperatorsdk.io/docs/dependent-resources#comparing-desired-and-actual-state-matching

    WARNING: Older versions of Kubernetes before 1.25 would create an additional resource version for every SSA update performed with certain resources - even though there were no actual changes in the stored resource - leading to infinite reconciliations. This behavior was seen with Secrets using stringData, Ingresses using empty string fields, and StatefulSets using volume claim templates. The operator framework has added built-in handling for the StatefulSet issue. If you encounter this issue on an older Kubernetes version, consider changing your desired state, turning off SSA for that resource, or even upgrading your Kubernetes version. If you encounter it on a newer Kubernetes version, please log an issue with the JOSDK and with upstream Kubernetes.

    i found this guide, and turned SSA off
    but it wasn't work well

  24. csviri commented on Mar 25, 2024

    @csviri
    Collaborator

    @csviri not sure if that is sufficient to fully close #2249 as the doc changes would be good too.

    still thinking of revisiting the other algorithm with event recording, thus providing both, but I will get back to that a bit later.

  25. 10000-ki commented on Mar 28, 2024

    @10000-ki
    ContributorAuthor

    @shawkins @csviri hello

    After �i upgrade to v4.8.2

    스크린샷 2024-03-29 오전 12 18 52

    javaoperatorsdk.io/previous label value keeps changing

    스크린샷 2024-03-29 오전 12 20 23

    Is the k8s version bug the reason resourceversion keeps increasing?

    What's interesting is that this issue does not occur in josdk version v4.4.4 (under v4.5.0)

  26. csviri commented on Mar 28, 2024

    @csviri
    Collaborator

    @10000-ki can you create a simple reproducer pls?

    ( Ideally with 1 deployment dependent )

  27. shawkins commented on Mar 28, 2024

    @shawkins
    Collaborator

    @csviri @10000-ki with the full yaml it's clear that there's another matching issue in play. The SSA matching logic sees the n3r.navercorp.com annotations as part of the desired state, but does not think that they are owned by the operator, thus it's trying the operation again.

  28. shawkins commented on Mar 28, 2024

    @shawkins
    Collaborator

    @10000-ki I should have realized with the previous incarnation of this issue that you were creating the desired state on top of the existing state - are you doing something like new StatefulSetBuilder(existing)... ?

    That is why the desired state had the generation set. Here with the state from the other field managers populated you see a similar issue.

    The SSA matching logic expects you to only provide your managed desired state when creating the entry - and nothing else.

    @csviri is it worth guarding against this more?

  29. 10000-ki commented on Mar 29, 2024

    @10000-ki
    Author
  30. shawkins commented on Mar 29, 2024

    @shawkins
    Collaborator

    The problem is the same even if we remove the n3r.navercorp.com annotations

    Please don't just remove the annotations, construct your desired state starting with a fresh object and don't copy anything from one obtained by the server - the point of SSA is that the server will figure out which manager is managing which fields.

    If the problem still persists after that it would be good to determine where the matching is failing. At the debug level, you should see logs like:

    2024-03-29 06:59:21,095 1 i.j.o.p.d.k.SSABasedGenericKubernetesResourceMatcher [DEBUG] Pruned actual:
    ...
    

    That will show what the matcher thinks your desired state is vs what is on the api server. Any descrepency between the two will cause another reconciliation. We can determine from there if there is SSA / Kube issue in play (that requires a workaround in the operator sdk) or if it's a problem with the matching logic.

    When i change the previousAnnotationForDependentResources setting to false

    That is expected. This optimization is based upon the matching logic working as intended. As mentioned on #2249 it is probably fine to just default this to false and allow users to opt in if they want greater performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions