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.