Skip to content

Commit eaef25c

Browse files
authored
docs(progressivesync): Proposal of Deletion strategy for progressive sync (argoproj#22843)
Signed-off-by: Kanika Rana <krana@redhat.com>
1 parent a8cae97 commit eaef25c

1 file changed

Lines changed: 341 additions & 0 deletions

File tree

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
---
2+
title: Neat-enhancement-idea
3+
authors:
4+
- "@ranakan19" # Authors' github accounts here.
5+
sponsors:
6+
- TBD # List all interested parties here.
7+
reviewers:
8+
- TBD
9+
approvers:
10+
- TBD
11+
12+
creation-date: 2025-04-30
13+
last-updated: 2025-05-01
14+
---
15+
16+
# Deletion Strategy for Progressive Sync
17+
18+
This proposal is building upon the ideas presented in https://github.com/argoproj/argo-cd/pull/14892 to introduce
19+
deletion strategy for progressive sync. While the original proposal laid the groundwork, this proposal extends to address
20+
some unanswered sections and changes implementation details.
21+
22+
Introduce a new functionality of ArgoCD ProgressiveSync that will allow users to configure order
23+
of deletion for applicationSet's deployed applications. The deletion strategies can be:
24+
25+
- AllAtOnce (current behaviour - where all applications are deleted in no particular order without waiting for an application
26+
to be deleted; can be the default value)
27+
- reverse ( delete applications in the reverse order of deployment, configured in progressiveSync. This expects the
28+
rollingSync field to have a specified order and implements deletion in the reverse order specified.
29+
Waits for one application to be fully deleted before moving onto the next application.)
30+
31+
## Open Questions [optional]
32+
33+
The original proposal mentions another strategy - `custom` wherein the user can provide a specific order of deletion.
34+
Is such a usecase needed?
35+
36+
37+
## Summary
38+
39+
This feature can extend the application dependency from deployment to deletion as well. Ability to provide deletion order
40+
can complete the ProgressiveSync feature.
41+
42+
## Motivation
43+
44+
Current deletion/removal strategy which ArgoCD use works fine if there aren't any dependencies between the different applications.
45+
However, it does not work when there are dependencies between the applications. This was noticed when some kubernetes core services
46+
were deployed in specific order and to be removed in reverse order.
47+
48+
### Goals
49+
50+
Following goals should be achieved in order to conclude this proposal:
51+
1. Deletion strategy `AllAtOnce` as default value - deletes all applications at once as the current behavior of deletion.
52+
2. Deletion strategy `Reverse` lets applications be deleted in the reverse order of the steps configured in RollingSync strategy.
53+
54+
### Non-Goals
55+
56+
custom deletion strategy - this will be a separate goal if there is enough demand for it.
57+
58+
## Proposal
59+
60+
Ability to provide configuration related to the deletion/removal process when progressive sync is used. Implementation detail provides
61+
two options of introducing this field in ApplicationSet. The following use cases assumes Option 1 for the yaml file examples.
62+
63+
### Use cases
64+
65+
Add a list of detailed use cases this enhancement intends to take care of.
66+
67+
#### AllAtOnce deletionStrategy:
68+
```yaml
69+
apiVersion: argoproj.io/v1alpha1
70+
kind: ApplicationSet
71+
metadata:
72+
name: pricelist
73+
namespace: argocd
74+
spec:
75+
generators:
76+
- list:
77+
elements:
78+
- srv: config
79+
path: applicationsets/rollingsync/apps/pricelist-config
80+
- srv: db
81+
path: applicationsets/rollingsync/apps/pricelist-db
82+
- srv: frontend
83+
path: applicationsets/rollingsync/apps/pricelist-frontend
84+
strategy:
85+
type: RollingSync
86+
rollingSync:
87+
steps:
88+
- matchExpressions:
89+
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
90+
operator: In
91+
values:
92+
- config
93+
- matchExpressions:
94+
- key: pricelist-component
95+
operator: In
96+
values:
97+
- db
98+
- matchExpressions:
99+
- key: pricelist-component
100+
operator: In
101+
values:
102+
- frontend
103+
### Deletion configuration ###
104+
deletionOrder: AllAtOnce # available options to be AllAtOnce/Reverse (maybe custom as well)
105+
### Deletion configuration ###
106+
template:
107+
metadata:
108+
name: 'pricelist-{{srv}}'
109+
labels:
110+
pricelist-component: '{{srv}}'
111+
spec:
112+
project: default
113+
syncPolicy:
114+
automated:
115+
prune: true
116+
selfHeal: true
117+
retry:
118+
limit: 5
119+
backoff:
120+
duration: 5s
121+
maxDuration: 3m0s
122+
factor: 2
123+
source:
124+
repoURL: https://github.com/christianh814/gitops-examples
125+
targetRevision: main
126+
path: '{{path}}'
127+
destination:
128+
server: https://kubernetes.default.svc
129+
namespace: pricelist
130+
```
131+
132+
#### Reverse deletionStrategy:
133+
```yaml
134+
apiVersion: argoproj.io/v1alpha1
135+
kind: ApplicationSet
136+
metadata:
137+
name: pricelist
138+
namespace: argocd
139+
spec:
140+
generators:
141+
- list:
142+
elements:
143+
- srv: config
144+
path: applicationsets/rollingsync/apps/pricelist-config
145+
- srv: db
146+
path: applicationsets/rollingsync/apps/pricelist-db
147+
- srv: frontend
148+
path: applicationsets/rollingsync/apps/pricelist-frontend
149+
strategy:
150+
type: RollingSync
151+
rollingSync:
152+
steps:
153+
- matchExpressions:
154+
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
155+
operator: In
156+
values:
157+
- config
158+
- matchExpressions:
159+
- key: pricelist-component
160+
operator: In
161+
values:
162+
- db
163+
- matchExpressions:
164+
- key: pricelist-component
165+
operator: In
166+
values:
167+
- frontend
168+
### Deletion configuration ###
169+
deletionOrder: Reverse # available options to be AllAtOnce/Reverse (maybe custom as well)
170+
### Deletion configuration ###
171+
template:
172+
metadata:
173+
name: 'pricelist-{{srv}}'
174+
labels:
175+
pricelist-component: '{{srv}}'
176+
spec:
177+
project: default
178+
syncPolicy:
179+
automated:
180+
prune: true
181+
selfHeal: true
182+
retry:
183+
limit: 5
184+
backoff:
185+
duration: 5s
186+
maxDuration: 3m0s
187+
factor: 2
188+
source:
189+
repoURL: https://github.com/christianh814/gitops-examples
190+
targetRevision: main
191+
path: '{{path}}'
192+
destination:
193+
server: https://kubernetes.default.svc
194+
namespace: pricelist
195+
```
196+
#### If custom deletionStrategy:
197+
```yaml
198+
apiVersion: argoproj.io/v1alpha1
199+
kind: ApplicationSet
200+
metadata:
201+
name: pricelist
202+
namespace: argocd
203+
spec:
204+
generators:
205+
- list:
206+
elements:
207+
- srv: config
208+
path: applicationsets/rollingsync/apps/pricelist-config
209+
- srv: db
210+
path: applicationsets/rollingsync/apps/pricelist-db
211+
- srv: frontend
212+
path: applicationsets/rollingsync/apps/pricelist-frontend
213+
strategy:
214+
type: RollingSync
215+
rollingSync:
216+
steps:
217+
- matchExpressions:
218+
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
219+
operator: In
220+
values:
221+
- config
222+
- matchExpressions:
223+
- key: pricelist-component
224+
operator: In
225+
values:
226+
- db
227+
- matchExpressions:
228+
- key: pricelist-component
229+
operator: In
230+
values:
231+
- frontend
232+
### Deletion configuration ###
233+
deletionOrder: Custom # available options to be default/reverse/custom
234+
deletionSync:
235+
steps:
236+
- matchExpressions:
237+
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
238+
operator: In
239+
values:
240+
- config
241+
- matchExpressions:
242+
- key: pricelist-component
243+
operator: In
244+
values:
245+
- frontend
246+
- matchExpressions:
247+
- key: pricelist-component
248+
operator: In
249+
values:
250+
- db
251+
### Deletion configuration ###
252+
template:
253+
metadata:
254+
name: 'pricelist-{{srv}}'
255+
labels:
256+
pricelist-component: '{{srv}}'
257+
spec:
258+
project: default
259+
syncPolicy:
260+
automated:
261+
prune: true
262+
selfHeal: true
263+
retry:
264+
limit: 5
265+
backoff:
266+
duration: 5s
267+
maxDuration: 3m0s
268+
factor: 2
269+
source:
270+
repoURL: https://github.com/christianh814/gitops-examples
271+
targetRevision: main
272+
path: '{{path}}'
273+
destination:
274+
server: https://kubernetes.default.svc
275+
namespace: pricelist
276+
```
277+
278+
### Implementation Details/Notes/Constraints [optional]
279+
280+
There should be a check that correlates the deletionStrategy to ApplicationSet strategy. For example can only select reverse
281+
if rollingSync lists out an order of application deployment, otherwise should error out.
282+
283+
It was decided to have this field within strategy (which is a field associated with progressiveSync)
284+
285+
To be introduced in ApplicationSetStrategy as follows:
286+
```yaml
287+
type ApplicationSetStrategy struct {
288+
Type string `json:"type,omitempty" protobuf:"bytes,1,opt,name=type"`
289+
RollingSync *ApplicationSetRolloutStrategy `json:"rollingSync,omitempty" protobuf:"bytes,2,opt,name=rollingSync"`
290+
// RollingUpdate *ApplicationSetRolloutStrategy `json:"rollingUpdate,omitempty" protobuf:"bytes,3,opt,name=rollingUpdate"`
291+
// Add DeletionSync Strategy here
292+
DeletionOrder string `json:"deletionOrder,omitempty" protobuf:"bytes,4,opt,name=deletionOrder"` // takes value AllAtOnce/Reverse
293+
}
294+
295+
```
296+
297+
Looked at the following names for this field:
298+
1. DeletionSyncType
299+
2. DeletionSyncStrategy
300+
301+
But decided on having DeletionOrder for the following reasons:
302+
1. simpler to understand - Order is straightforward and thus sets expectation to user
303+
2. Since it's nested within `strategy`, suffix of strategy isn't needed.
304+
3. Leaving room for when/if it scales to have custom deletion strategy. i.e
305+
```yaml
306+
type ApplicationSetStrategy struct {
307+
Type string `json:"type,omitempty" protobuf:"bytes,1,opt,name=type"`
308+
RollingSync *ApplicationSetRolloutStrategy `json:"rollingSync,omitempty" protobuf:"bytes,2,opt,name=rollingSync"`
309+
// Add DeletionSync Strategy here
310+
DeletionOrder string `json:"deletionOrder,omitempty" protobuf:"bytes,3,opt,name=deletionOrder"` // takes value AllAtOnce/Reverse/Custom
311+
DeletionSync *ApplicationSetRolloutStrategy `json:"deletionSync,omitempty" protobuf:"bytes,4,opt,name=deletionSync"`
312+
}
313+
```
314+
315+
### Detailed examples
316+
Already covered in Use cases
317+
318+
### Security Considerations
319+
320+
Since no additional roles or privileges are needed to be able to delete deployed applications in a specific order,
321+
so no impact on the security aspects of Argo CD workloads.
322+
323+
324+
### Risks and Mitigations
325+
326+
No immediate Risks to consider
327+
328+
329+
### Upgrade / Downgrade Strategy
330+
Introducing new fields to the ApplicationSet CRD, however, no existing fields are being changed.
331+
This means that a new ApplicationSet version is unnecessary, and upgrading to the new spec with added fields will be a clean operation.
332+
333+
Downgrading could risk users receiving K8s API errors if they continue to try to apply the deletionStrategy field to a downgraded version of the ApplicationSet resource.
334+
Downgrading the controller while keeping the upgraded version of the CRD should cleanly downgrade/revert the behavior of the controller to the previous version without requiring users to adjust their existing ApplicationSet specs.
335+
336+
337+
## Drawbacks
338+
Slight increase in Argo CD code base complexity
339+
340+
## Alternatives
341+
TBD

0 commit comments

Comments
 (0)