docs/proposals/deletion-strategy-progressive-sync.md
This proposal is building upon the ideas presented in https://github.com/argoproj/argo-cd/pull/14892 to introduce deletion strategy for progressive sync. While the original proposal laid the groundwork, this proposal extends to address some unanswered sections and changes implementation details.
Introduce a new functionality of ArgoCD ProgressiveSync that will allow users to configure order of deletion for applicationSet's deployed applications. The deletion strategies can be:
The original proposal mentions another strategy - custom wherein the user can provide a specific order of deletion.
Is such a usecase needed?
This feature can extend the application dependency from deployment to deletion as well. Ability to provide deletion order can complete the ProgressiveSync feature.
Current deletion/removal strategy which ArgoCD use works fine if there aren't any dependencies between the different applications. However, it does not work when there are dependencies between the applications. This was noticed when some kubernetes core services were deployed in specific order and to be removed in reverse order.
Following goals should be achieved in order to conclude this proposal:
AllAtOnce as default value - deletes all applications at once as the current behavior of deletion.Reverse lets applications be deleted in the reverse order of the steps configured in RollingSync strategy.custom deletion strategy - this will be a separate goal if there is enough demand for it.
Ability to provide configuration related to the deletion/removal process when progressive sync is used. Implementation detail provides two options of introducing this field in ApplicationSet. The following use cases assumes Option 1 for the yaml file examples.
Add a list of detailed use cases this enhancement intends to take care of.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pricelist
namespace: argocd
spec:
generators:
- list:
elements:
- srv: config
path: applicationsets/rollingsync/apps/pricelist-config
- srv: db
path: applicationsets/rollingsync/apps/pricelist-db
- srv: frontend
path: applicationsets/rollingsync/apps/pricelist-frontend
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
operator: In
values:
- config
- matchExpressions:
- key: pricelist-component
operator: In
values:
- db
- matchExpressions:
- key: pricelist-component
operator: In
values:
- frontend
### Deletion configuration ###
deletionOrder: AllAtOnce # available options to be AllAtOnce/Reverse (maybe custom as well)
### Deletion configuration ###
template:
metadata:
name: 'pricelist-{{srv}}'
labels:
pricelist-component: '{{srv}}'
spec:
project: default
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 5
backoff:
duration: 5s
maxDuration: 3m0s
factor: 2
source:
repoURL: https://github.com/christianh814/gitops-examples
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: pricelist
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pricelist
namespace: argocd
spec:
generators:
- list:
elements:
- srv: config
path: applicationsets/rollingsync/apps/pricelist-config
- srv: db
path: applicationsets/rollingsync/apps/pricelist-db
- srv: frontend
path: applicationsets/rollingsync/apps/pricelist-frontend
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
operator: In
values:
- config
- matchExpressions:
- key: pricelist-component
operator: In
values:
- db
- matchExpressions:
- key: pricelist-component
operator: In
values:
- frontend
### Deletion configuration ###
deletionOrder: Reverse # available options to be AllAtOnce/Reverse (maybe custom as well)
### Deletion configuration ###
template:
metadata:
name: 'pricelist-{{srv}}'
labels:
pricelist-component: '{{srv}}'
spec:
project: default
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 5
backoff:
duration: 5s
maxDuration: 3m0s
factor: 2
source:
repoURL: https://github.com/christianh814/gitops-examples
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: pricelist
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pricelist
namespace: argocd
spec:
generators:
- list:
elements:
- srv: config
path: applicationsets/rollingsync/apps/pricelist-config
- srv: db
path: applicationsets/rollingsync/apps/pricelist-db
- srv: frontend
path: applicationsets/rollingsync/apps/pricelist-frontend
strategy:
type: RollingSync
rollingSync:
steps:
- matchExpressions:
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
operator: In
values:
- config
- matchExpressions:
- key: pricelist-component
operator: In
values:
- db
- matchExpressions:
- key: pricelist-component
operator: In
values:
- frontend
### Deletion configuration ###
deletionOrder: Custom # available options to be default/reverse/custom
deletionSync:
steps:
- matchExpressions:
- key: pricelist-component # the "key" is based on the label (below as "pricelist-component: {{srv}}")
operator: In
values:
- config
- matchExpressions:
- key: pricelist-component
operator: In
values:
- frontend
- matchExpressions:
- key: pricelist-component
operator: In
values:
- db
### Deletion configuration ###
template:
metadata:
name: 'pricelist-{{srv}}'
labels:
pricelist-component: '{{srv}}'
spec:
project: default
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 5
backoff:
duration: 5s
maxDuration: 3m0s
factor: 2
source:
repoURL: https://github.com/christianh814/gitops-examples
targetRevision: main
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: pricelist
There should be a check that correlates the deletionStrategy to ApplicationSet strategy. For example can only select reverse if rollingSync lists out an order of application deployment, otherwise should error out.
It was decided to have this field within strategy (which is a field associated with progressiveSync)
To be introduced in ApplicationSetStrategy as follows:
type ApplicationSetStrategy struct {
Type string `json:"type,omitempty" protobuf:"bytes,1,opt,name=type"`
RollingSync *ApplicationSetRolloutStrategy `json:"rollingSync,omitempty" protobuf:"bytes,2,opt,name=rollingSync"`
// RollingUpdate *ApplicationSetRolloutStrategy `json:"rollingUpdate,omitempty" protobuf:"bytes,3,opt,name=rollingUpdate"`
// Add DeletionSync Strategy here
DeletionOrder string `json:"deletionOrder,omitempty" protobuf:"bytes,4,opt,name=deletionOrder"` // takes value AllAtOnce/Reverse
}
Looked at the following names for this field:
But decided on having DeletionOrder for the following reasons:
strategy, suffix of strategy isn't needed.type ApplicationSetStrategy struct {
Type string `json:"type,omitempty" protobuf:"bytes,1,opt,name=type"`
RollingSync *ApplicationSetRolloutStrategy `json:"rollingSync,omitempty" protobuf:"bytes,2,opt,name=rollingSync"`
// Add DeletionSync Strategy here
DeletionOrder string `json:"deletionOrder,omitempty" protobuf:"bytes,3,opt,name=deletionOrder"` // takes value AllAtOnce/Reverse/Custom
DeletionSync *ApplicationSetRolloutStrategy `json:"deletionSync,omitempty" protobuf:"bytes,4,opt,name=deletionSync"`
}
Already covered in Use cases
Since no additional roles or privileges are needed to be able to delete deployed applications in a specific order, so no impact on the security aspects of Argo CD workloads.
No immediate Risks to consider
Introducing new fields to the ApplicationSet CRD, however, no existing fields are being changed. This means that a new ApplicationSet version is unnecessary, and upgrading to the new spec with added fields will be a clean operation.
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. 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.
Slight increase in Argo CD code base complexity
TBD