github.com/oam-dev/kubevela@v1.9.11/design/vela-core/app_deployment.md (about) 1 # Multi-Version, Multi-Cluster Application Deployment Design 2 3 ## Background 4 5 Currently Vela supports Application CRD which templates the low level resources and exposes high level parameters to users. But that's not enough. It requires a couple of standard techniques to deploy an application in production: 6 7 1. **Rolling upgrade** (aka rollout): To continuously deploy apps requires to rollout in a safe manner which usually involves step by step rollout batches and analysis. 8 2. **Traffic shifting**: When rolling upgrade an app, it needs to split the traffic onto both the old and new revisions to verify the new version while preserving service availability. 9 3. **Multi-cluster**: Modern application infrastructure involves multiple clusters to ensure high availability and maximize service throughput. 10 11 ## Proposal 12 13 This issue proposes to add a new ApplicationDeployment CRD to satisfy the above requirements. 14 15 ```yaml 16 kind: ApplicationDeployment 17 name: example-app-deploy 18 spec: 19 traffic: 20 hosts: 21 - example-app.example.com 22 http: 23 - match: 24 - uri: 25 prefix: "/web" 26 weightedTargets: 27 - revisionName: example-app-v1 28 componentName: testsvc 29 port: 80 30 weight: 50 31 - revisionName: example-app-v2 32 componentName: testsvc 33 port: 80 34 weight: 50 35 36 appRevisions: 37 - # Name of the AppRevision. 38 # Each modification to Application would generate a new AppRevision. 39 revisionName: example-app-v1 40 41 # Cluster specific workload placement config 42 placement: 43 - clusterSelector: 44 # You can select Clusters by name or labels. 45 # If multiple clusters is selected, one will be picked via a unique hashing algorithm. 46 labels: 47 usage: production 48 name: prod-cluster-1 49 50 distribution: 51 replicas: 5 52 53 - # If no clusterSelector is given, it will use the same cluster as this CR 54 distribution: 55 replicas: 5 56 57 - revisionName: example-app-v2 58 placement: 59 - clusterSelector: 60 labels: 61 usage: production 62 name: prod-cluster-1 63 distribution: 64 replicas: 5 65 - distribution: 66 replicas: 5 67 ``` 68 69 In above proposal, the `placementStrategies` part requires a Cluster CRD that are proposed as below: 70 71 ```yaml 72 kind: Cluster 73 metadata: 74 name: prod-cluster-1 75 labels: 76 usage: production 77 spec: 78 kubeconfigSecretRef: 79 name: kubeconfig-cluster-1 80 ``` 81 82 ## Technical details 83 84 Here are some ideas how we can implement the above API. 85 86 First of all, we will add a new AppDeployment controller to do the reconcile logic. For each feature they are implemented as follows: 87 88 ### 1. Rollout 89 90 In the following example, we are assuming the app has deployed v1 now and is upgrading to v2. Here are the workflow: 91 92 - User modifies Application to trigger revision change. 93 - Add annotation `app.oam.dev/rollout-template=true` to create a new revision instead of replace existing one. 94 - User gets the names of the v1 and v2 AppRevision to complete AppDeployment spec. 95 - User applies AppDeployment which includes both the v1 and v2 revisions. 96 - The AppDeployment controller will calculate the diff between previous and current AppDeployment specs. The diff consists of three parts: 97 - Del: the revisions that existed before and do not exist in the new spec. They should be scaled to 0 and removed. 98 - Mod: The revisions that still exist but needs to be changed. 99 - Add: The revisions that did not exist before and will be deployed fresh new. 100 - After the diff calculation, the AppDeployment controller will execute the plan as follows: 101 - Handle Del: remove revisions. 102 - Handle Add/Mod: handle distribution, handle scaling. A special case is in current cluster no need to do distribution. 103 104 ### 2. Traffic 105 106 We will make sure the spec works for the following environments: 107 108 - K8s ingress + service (traffic split percentages determined by replica number) 109 - Istio service mesh 110 111 Here is the workflow with Istio: 112 113 - User applies AppDeployment to split traffic between v1 and v2 each 50% 114 - The AppDeployment controller will create VirtualService object: 115 116 ```yaml 117 apiVersion: networking.istio.io/v1alpha3 118 kind: VirtualService 119 spec: 120 hosts: 121 - example-app.example.com 122 http: 123 - match: 124 - uri: 125 prefix: "/web" 126 127 route: 128 - destination: 129 host: example-app-v1 130 weight: 50 131 - destination: 132 host: example-app-v2 133 weight: 50 134 ``` 135 136 > Note: The service name is a convention which could be inferred from the app name. 137 138 Here is the workflow with Ingress: 139 140 - User applies AppDeployment to split traffic between v1 and v2, but didn't and shouldn't specify `weight`. 141 - The AppDeployment controller will create/update Ingress object: 142 143 ```yaml 144 apiVersion: networking.k8s.io/v1 145 kind: Ingress 146 spec: 147 rules: 148 - http: 149 paths: 150 - path: /v1 151 pathType: prefix 152 backend: 153 service: 154 name: example-app-v1 155 port: 156 number: 80 157 158 - path: /v2 159 pathType: prefix 160 backend: 161 service: 162 name: example-app-v2 163 port: 164 number: 80 165 ``` 166 167 ### 3. Multi Cluster 168 169 We will implement the logic inside the AppDeployment controller itself. 170 171 Here is the workflow: 172 173 - User applies AppDeployment with `placement` of each revision. 174 - The AppDeployment controller will select the clusters, get their credentials. 175 Then deployed specified number of replicas to that cluster. 176 177 ## Considerations 178 179 - The current rollout strategy is to do scaling up/down directly. We should support strategy to rolling-upgrade old to new versions. To simplify the calculation of rolling plan, we can restrict that only one revision is reduced and another newer revision is increased. 180 - Build multi-stage rollout strategies like [argo-progressive-rollout](https://github.com/Skyscanner/argocd-progressive-rollout/) 181 - AppDeployment could adopt native k8s workloads (e.g. Deployment, Statefulset) in the future.