-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add finalizer to workflow pod to prevent pod deleted
. Fixes #8783
#9058
Conversation
@rohankmr414 could you write a test case or add an example of this to your PR description? @juliev0 @sarabala1979 the e2e tests for this PR are all failing with 15m0 timeout, something to note I assume |
@rohankmr414 Regarding the test failures, we should determine if they're "real" or intermittently failing. Have you tried to run them locally? You should be able to do "make [testname]" like "make TestMarkDaemonedPodSucceeded" |
@rohankmr414 It is a nice fix. Please add unit test and e2e test. Fix the test failures. |
@sarabala1979 @juliev0 For some reason, the tests are passing on my local env with the finalizer, not sure what's happening here |
Hmm, sometimes there are intermittent failures unfortunately. We have a bug logged for that (there's an idea that the issue is caused by some overall timeout being too short). Can you push an "empty commit" (i.e. add a space or line or something) to re-trigger the tests? Then you can see if the same tests are failing every time or are intermittent? (Sorry for the trouble) |
@juliev0 actually I did a rebase and force push which re-triggered the tests, the same tests are failing again. I think the reason behind this is that in some tests pods are being terminated and they are being stuck in a terminating state due to the finalizer which somehow prevents the next test from being run. It happened in my local env as well. If I remove the finalizer manually, after which the stuck pods are terminated, the tests are running fine. |
Oh, so it was after you did a rebase, meaning some recent commit in master caused it to change for you? Sorry about that. When you say "some test pods are being terminated" do you mean the Controller is not the one deleting them and therefore they're not going through your logic to remove the finalizer? Unfortunately, I'm not an expert on those tests. Can you investigate and modify the tests if needed? |
@juliev0 the error is not because of the rebase, ig it is because of some bug in pod deletion logic |
Okay, thanks for the clarification. If you are able to investigate the bug that would be great. |
762c791
to
b164fd4
Compare
@juliev0 @sarabala1979 the issue occurs when running multiple tests, some pods are being terminated without being labelled as completed from the previous test, preventing the next test from being run. On running the tests individually the pods are being labelled as completed successfully and getting cleaned up later, not really sure what's happening here |
Sorry for the lack of response. I'm new to the project so don't have any insider information. :) It looks like you've made some recent commits - are you able to address this issue of the test? |
68ff951
to
f1ff236
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think any e2e tests should be changed. If you changed them, then maybe code does not work.
Code looks correct to me otherwise.
* fix: Fix test fail flakey on finalizer branch Signed-off-by: Atsushi Sakai <sakai.at24@gmail.com> Signed-off-by: Rohan Kumar <rohan@pipekit.io>
da8d6c8
to
091a766
Compare
Signed-off-by: Rohan Kumar <rohan@pipekit.io>
Sorry for the late response. Thanks for fixing the DCO. I know that can be annoying. (For the future, it seems reasonable that we could make an exception here and there for that but I’m not sure what the precedent is.) |
Thank you for fixing the DCO error. However, another CI test is now failing... @juliev0 |
Unfortunately there are flakey tests. The typical thing to do in that case is repeated “empty commits” until it all passes |
@rohankmr414 |
Thank you for your help. @juliev0 |
Operation: "replace", | ||
Path: "/metadata/labels/workflows.argoproj.io~1completed", | ||
Value: "true", | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this label right? It's not supposed to be "workflows.argoproj.io/completed"
, is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if so, you can use common.LabelKeyCompleted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
~1
is escape for JSON Pointer.
https://fdatatracker.ietf.org/doc/html/rfc6901#section-3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, thanks
propagation := metav1.DeletePropagationBackground | ||
err := pods.Delete(ctx, podName, metav1.DeleteOptions{ | ||
err = pods.Delete(ctx, podName, metav1.DeleteOptions{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that in general, a given Pod reaches labelPodCompleted
and then deletePod
logic? Do you know if it's possible for that not to happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The execution of the deletePod logic is decided by the following function.
argo-workflows/workflow/controller/pod_cleanup.go
Lines 46 to 72 in 5b6ad2b
func determinePodCleanupAction( | |
selector labels.Selector, | |
podLabels map[string]string, | |
strategy wfv1.PodGCStrategy, | |
workflowPhase wfv1.WorkflowPhase, | |
podPhase apiv1.PodPhase, | |
) podCleanupAction { | |
switch { | |
case !selector.Matches(labels.Set(podLabels)): // if the pod will never be deleted, label it now | |
return labelPodCompleted | |
case strategy == wfv1.PodGCOnPodNone: | |
return labelPodCompleted | |
case strategy == wfv1.PodGCOnWorkflowCompletion && workflowPhase.Completed(): | |
return deletePod | |
case strategy == wfv1.PodGCOnWorkflowSuccess && workflowPhase == wfv1.WorkflowSucceeded: | |
return deletePod | |
case strategy == wfv1.PodGCOnPodCompletion: | |
return deletePod | |
case strategy == wfv1.PodGCOnPodSuccess && podPhase == apiv1.PodSucceeded: | |
return deletePod | |
case strategy == wfv1.PodGCOnPodSuccess && podPhase == apiv1.PodFailed: | |
return labelPodCompleted | |
case workflowPhase.Completed(): | |
return labelPodCompleted | |
} | |
return "" | |
} |
This belongs by Pod GC strategy.
https://argoproj.github.io/argo-workflows/fields/#:~:text=pod%20GC%20queue.-,strategy,-string
argo-workflows/examples/pod-gc-strategy.yaml
Lines 10 to 15 in dbf4215
# Pod GC strategy must be one of the following: | |
# * OnPodCompletion - delete pods immediately when pod is completed (including errors/failures) | |
# * OnPodSuccess - delete pods immediately when pod is successful | |
# * OnWorkflowCompletion - delete pods when workflow is completed | |
# * OnWorkflowSuccess - delete pods when workflow is successful | |
# Default: do not delete pods |
@@ -168,6 +168,9 @@ const ( | |||
// Finalizer to block deletion of the workflow if deletion of artifacts fail for some reason. | |||
FinalizerArtifactGC = workflow.WorkflowFullName + "/artifact-gc" | |||
|
|||
// Finalizer blocks deletion of pods until we're captured their status. | |||
Finalizer = workflow.WorkflowFullName + "/status" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe these 2 finalizers should be named to distinguish what they're being applied on? Like:
FinalizerWorkflowArtifactGC
FinalizerPodStatus
What do you think?
There is a danger in this PR of there being some edge case which causes that finalizer to remain on the pod and for the pod to not be deletable unless manually patched...hence Alex's request to add a feature flag (I think that would generally be an environment variable - not sure if it should default to false or true). Also, do you know for a fact that the |
…rgoproj#8783 Continuing Work of argoproj#9058 Signed-off-by: Atsushi Sakai <sakai.at24@gmail.com>
…rgoproj#8783 Continuing Work of argoproj#9058 Signed-off-by: Atsushi Sakai <sakai.at24@gmail.com>
I still have a strong need for the finalizer logic in my organization. However, since this PR is not mine, it is difficult for me to contribute to it quickly. Therefore, I have created the following PR in respect of this one.
I implemented a feature flag in the above PR.
As far as I know, yes.
Currently, Argo Workflows allows users to choose the pod deletion logic, as noted in the comments below. If the pod deletion logic were solely reliant on OwnerReference, users would not have this choice. Therefore, I believe the current pod deletion logic is necessary. |
Closing this as superseded by #12413, which was just merged. Big thanks to everyone who worked on it! |
Good call |
…rgoproj#8783 Continuing Work of argoproj#9058 (argoproj#12413) Signed-off-by: Atsushi Sakai <sakai.at24@gmail.com>
…rgoproj#8783 Continuing Work of argoproj#9058 (argoproj#12413) Signed-off-by: Atsushi Sakai <sakai.at24@gmail.com>
Hi, can you give us an approximate date when this will be released please? Even with automatic retries, pods are being randomly deleted, happens almost on a daily basis. |
pod deleted
. Fixes #8783
For anyone waiting for 3.6 to fix this issue (like I was/am), I thought I'd drop a Kyverno policy that works well for us to block OpenShift from evicting "Completed" pods that haven't been seen/accounted for by Argo. It blocks the evict call until Argo labels the pod with apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disable-eviction-too-fast
spec:
admission: true
background: false
rules:
- context:
- apiCall:
method: GET
urlPath: /api/v1/namespaces/{{request.object.metadata.namespace}}/pods/{{request.object.metadata.name}}
name: wfpod
match:
any:
- resources:
kinds:
- v1/Pod.eviction
operations:
- CREATE
name: Prevent race condition on Workflow Pods
skipBackgroundRequests: true
validate:
deny:
conditions:
all:
- key: "{{ wfpod.metadata.ownerReferences[].kind }}"
operator: AnyIn
value:
- Workflow
- key: "{{ wfpod.status.phase }}"
operator: Equals
value: Succeeded
- key:
'{{ wfpod.metadata.labels."workflows.argoproj.io/completed" || foo
| to_string(@) }}'
operator: Equals
value: "false"
message: Eviction is too soon after job completion
validationFailureAction: Enforce |
Signed-off-by: Rohan Kumar rohan@pipekit.io
Fixes #8783