github.com/oam-dev/kubevela@v1.9.11/design/vela-core/apply-once-only.md (about) 1 # Apply-Once-Only: Apply workload/trait only when spec is changed 2 3 - Owner: Yue Wang(@captainroy-hy), Jianbo Sun(@wonderflow) 4 - Date: 11/24/2020 5 - Status: Implemented 6 7 ## Intro 8 When an ApplicationConfiguration is deployed, 9 vela-core will create(apply) corresponding workload/trait instances and keep them stay align with the `spec` defined in ApplicationConfiguration through periodical reconciliation. 10 11 If we run vela-core with `--apply-once-only` flag enabled, vela-core will never apply the workload and trait instance after they are applied once. Even if they are changed by others (e.g., trait controller, workload controller,etc). 12 Since the create operation is the only one apply operation occurring on workload/trait, we call this mechanism as `Apply Once Only`. 13 14 ## A Motivational Example 15 Here is a scenario from production environment to demonstrate how `Apply Once Only` works. 16 17 ```yaml 18 apiVersion: core.oam.dev/v1alpha2 19 kind: ApplicationConfiguration 20 metadata: 21 name: example-appconfig 22 spec: 23 components: 24 - componentName: example-component 25 --- 26 apiVersion: core.oam.dev/v1alpha2 27 kind: Component 28 metadata: 29 name: example-component 30 spec: 31 workload: 32 apiVersion: apps/v1 33 kind: Deployment 34 spec: 35 ... 36 template: 37 spec: 38 containers: 39 - image: sample/app:1.0 40 name: sample-app 41 ``` 42 43 After deploying above ApplicationConfiguration, vela-core will create a Deployment with corresponding `PodTemplateSpec`. 44 45 In production env, it's possible to change the Deployment according to particular requirements, e.g., RolloutTrait, AutoscalerTrait,etc. 46 Currently, we just use `kubectl` to simulate workload is changed bypass changing the ApplicationConfiguration. 47 Below cmd changes `spec.template.spec.containers[0].image` of the Deployment from `sample/app:1.0` to `sample/app:2.0`. 48 ```shell 49 cat <<EOF | kubectl patch deployment example-deploy --patch 50 spec: 51 template: 52 spec: 53 containers: 54 - name: sample-app 55 image: sample/app:2.0 56 EOF 57 ``` 58 59 Above change will trigger recreate of Pods owned by the Deployment. 60 But vela-core will change it back to `sample/app:1.0` in the following reconciliation soon or late. 61 That's not what we expect in some scenarios. 62 63 Instead, we hope vela-core ignore reconciling the workload we changed and leave them as what they are now until we change the `spec` of their parent ApplicationConfiguration . 64 65 ## Goals 66 67 Add a startup parameter for vela-core controller to allow users choose whether to enable apply only once or not. 68 69 If enabled, workload/trait will be applied only one time for each resource generation (only when the corresponding appconfig/component is created or updated). 70 After workload/trait created/updated and aligned to the generation of appconfig, vela-core will not apply them EXCEPT below situations: 71 72 - The `spec` of ApplicationConfiguration is changed (new generation created) 73 - The revision of Component is changed 74 75 By default, the mechanism is disabled, vela-core will always reconcile and apply workload/trait periodically as usual. 76 77 ## Implementation 78 79 In each round of reconciliation, vela-core compares below Labels & Annotations of existing workload/trait with newly rendered ones before applying. 80 81 After deploying the ApplicationConfiguration in the motivational example, the Deployment created by vela-core will have such labels and annotations. 82 83 84 ```yaml 85 apiVersion: apps/v1 86 kind: Deployment 87 metadata: 88 annotations: 89 deployment.kubernetes.io/revision: "1" 90 app.oam.dev/generation: "1" 91 generation: 1 92 labels: 93 app.oam.dev/component: example-component 94 app.oam.dev/name: example-appconfig 95 app.oam.dev/resourceType: WORKLOAD 96 app.oam.dev/revision: example-component-v1 97 ... 98 ``` 99 100 - `annotations["app.oam.dev/generation"]:"1" ` refers to the generation of AppConfig 101 - `labels["app.oam.dev/revision"]:"example-component-v1" ` refers to the revision of Component 102 103 These crucial two are propogated from AppConfig and Component during reconciliation. 104 Any change applied to the Deployment directly has no impact on these labels and annotations, e.g., change the Deployment spec just like what we do in the [motivational example](#a-motivational-example). 105 If `--apply-once-only` is enabled, since no discrepancy is found on labels and annotations, 106 vela-core controller will ignore applying the Deployment and leave it as what it is at that moment. 107 108 By contrast, changes on AppConfig (changing `spec` creates new generation) and Component (updating Component creates new revision) will change the value of these labels and annotations. 109 For example, if we update the spec of AppConfig, newly rendered workload is supposed to contain such labels and annotations. 110 111 ```yaml 112 apiVersion: apps/v1 113 kind: Deployment 114 metadata: 115 annotations: 116 deployment.kubernetes.io/revision: "1" 117 app.oam.dev/generation: "2" # generation of AppConfig changed 118 generation: 1 119 labels: 120 app.oam.dev/component: example-component 121 app.oam.dev/name: example-appconfig 122 app.oam.dev/resourceType: WORKLOAD 123 app.oam.dev/revision: example-component-v1 124 ... 125 ``` 126 Since discrepancy is found, vela-core controller will apply(update) the Deployment with newly rendered one. 127 Thus, the changes we made to the Deployment before will also be eliminated. 128 129 The same mechanism also works for Trait as well as Workload. 130 131 ### Apply Once Only Force 132 133 Based on the same mechanism as `apply-once-only`, `apply-once-only-force` has a more strict method for apply only once. 134 135 It allows to skip re-creating a workload or trait that has already been DELETED from the cluster if its spec is not changed. 136 137 Besides the condition in `apply-once-only`, `apply-once-only-force` has one more condition: 138 139 - if the component revision not changed, the workload will not be applied. 140 141 ## Usage 142 143 Three available options are provided to a vela-core runtime setup flag named `apply-one-only`, referring to three modes: 144 145 - off - `apply-once-only` is disabled, this is the default option 146 - on - `apply-once-only` is enabled 147 - force - `apply-once-only-force` is enabled 148 149 You can set it through `helm` chart value `applyOnceOnly` which is "off" by default if omitted, for example 150 151 ```shell 152 helm install -n vela-system kubevela ./charts/vela-core --set applyOnceOnly=on 153 ``` 154 or 155 ``` 156 helm install -n vela-system kubevela ./charts/vela-core --set applyOnceOnly=force 157 ``` 158 159