github.com/argoproj/argo-cd/v2@v2.10.5/docs/proposals/config-management-plugin-v2.md (about)

     1  ---
     2  title: Config-Management-Plugin-Enhancement
     3  authors:
     4    - "@kshamajain99" # Authors' github accounts here.
     5  sponsors:
     6    - TBD        # List all intereste parties here.
     7  reviewers:
     8    - TBD
     9  approvers:
    10    - TBD
    11  
    12  creation-date: 2021-03-29
    13  last-updated: 2021-03-29
    14  ---
    15  
    16  # Config Management Plugin Enhancement
    17  
    18  We want to enhance config management plugin in order to improve Argo CD operator and end-user experience 
    19  for using additional tools such as cdk8s, Tanka, jkcfg, QBEC, Dhall, pulumi, etc. 
    20  
    21  ## Summary
    22  
    23  Currently, Argo CD provides first-class support for Helm, Kustomize and Jsonnet/YAML. The support includes:
    24  - Bundled binaries (maintainers periodically upgrade binaries)
    25  - An ability to override parameters using UI/CLI
    26  - The applications are discovered in Git repository and auto-suggested during application creation in UI
    27  - Performance optimizations. Argo CD "knows" when it is safe to generate manifests concurrently and takes advantage of it.
    28  
    29  We want to enhance the configuration management plugin so that it can provide similar first-class support for additional 
    30  tools such as cdk8s, Tanka, jkcfg, QBEC, Dhall, pulumi, etc.
    31  
    32  ## Motivation
    33  
    34  The config management plugin feature should be improved to provide the same level of user experience as 
    35  for the natively supported tools to the additional tools such as  cdk8s, Tanka, jkcfg, QBEC, Dhall, pulumi, etc., 
    36  including Argo CD operators as well as end-user experience.
    37  
    38  ### Goals
    39  
    40  The goals for config management plugin enhancement are,
    41  
    42  #### Improve Installation Experience
    43  The current Config Management plugin installation experience requires two changes:
    44  - An entry in configManagementPlugins in the Argo CD configmap (i.e.  argocd-cm)
    45  - Either an init container with a volume mount that adds a new binary into Argo CD repo server pod, or a rebuild of the argocd image, which contains the necessary tooling
    46  
    47  The problem with this approach is that the process is error-prone, manual, and requires learning from each and every Argo CD administrator. 
    48  
    49  The goal is to make additional tools easily accessible for installation to Argo CD operators.
    50  
    51  #### Provide Discovery (Auto-selection of Tool)
    52  For Argo CD’s natively supported config management plugins (Helm, Kustomize, Jsonnet), Argo CD auto-detects 
    53  and selects the appropriate tool given only the path in the Git repository. 
    54  This selection is based on the recognition of well-known files in the directory (e.g. Chart.yaml, kustomization.yaml, etc...). 
    55  
    56  Currently, unlike natively supported tools, when a plugin is used, a user needs to explicitly specify the plugin 
    57  that should be used to render the manifests. As part of the improvements to config management plugins, 
    58  
    59  We want to provide the same ability to auto-select the plugin based on recognized files in the path of the git repository.
    60  
    61  #### Parameters support in UI/CLI
    62  Currently, configuration management plugins allow specifying only a list of environment variables via UI/CLI. 
    63  
    64  We want to extend its functionality to provide a similar experience as for existing natively supported tools 
    65  to additional config management tools. 
    66  
    67  ### Non-Goals
    68  
    69  * We aren't planning on changing the existing support for native plugins as of now. 
    70  
    71  ## Proposal
    72  
    73  We have drafted the solution to the problem statement as **running configuration management plugin tools as sidecar in the argocd-repo-server**. 
    74  
    75  All it means that Argo CD Config Management Plugin 2.0 will be,
    76  - A user-supplied container image with all the necessary tooling installed in it. 
    77  - It will run as a sidecar in the repo server deployment and will have shared access to the git repositories.
    78  - It will contain a CMP YAML specification file describing how to render manifests.
    79  - Its entrypoint will be a lightweight CMP API server that receives requests by the main repo-server to render manifests, 
    80  based on the CMP specification file.
    81  
    82  This mechanism will provide the following benefits over the existing solution,
    83  - Plugin owners control their execution environment, packaging whatever dependent binaries required.
    84  - An  Argo CD user who wants to use additional config management tools does not have to go through the hassle of building 
    85  a customized argocd-repo-server in order to install required dependencies. 
    86  - The plugin image will be running in a container separate from the main repo-server.
    87  
    88  ### Use cases
    89  
    90  * UC1: As an Argo CD user, I would like to use first-class support provided for additional tools to generate and manage deployable kubernetes manifests
    91  * UC2: As an Argo CD operator, I want to have smooth experience while installing additional tools such as  cdk8s, Tanka, jkcfg, QBEC, Dhall, pulumi, etc.
    92  * UC3: As a plugin owner, I want to have some control over the execution environment as I want to package whatever dependent binaries required. 
    93  
    94  ### Implementation Details
    95  
    96  Config Management Plugin v2.0 implementation and experience will be as,
    97  
    98  #### Installation
    99  
   100  To install a plugin, an operator will simply patch argocd-repo-server to run config management plugin container as a sidecar, 
   101  with argocd-cmp-server as it’s entrypoint. Operator can use either off-the-shelf or custom built plugin image as sidecar image. 
   102  
   103  ```bash
   104  # A plugin is a container image which runs as a sidecar, with the execution environment
   105  # necessary to render manifests. To install a plugin, 
   106  containers:
   107  - name: cdk8s
   108    command: [/var/run/argocd/argocd-cmp-server]
   109    image: docker.ui/cdk8s/cdk8s:latest
   110    volumeMounts:
   111    - mountPath: /var/run/argocd
   112      name: var-files
   113  ```
   114  
   115  The argocd-cmp-server binary will be populated inside the plugin container via an init container in the argocd-repo-server, 
   116  which will pre-populate a volume shared between plugins and the repo-server.
   117  
   118  ```bash
   119  # An init container will copy the argocd static binary into the shared volume
   120  # so that the CMP server can become the entrypoint
   121  initContainers:
   122  - command:
   123    - cp
   124    - -n
   125    - /usr/local/bin/argocd
   126    - /var/run/argocd/argocd-cmp-server
   127    image: quay.io/argoproj/argocd:latest
   128    name: copyutil
   129    volumeMounts:
   130    - mountPath: /var/run/argocd
   131      name: var-files
   132   
   133  # var-files is a shared volume between repo-server and cmp-server which holds:
   134  # 1) socket files that repo-server uses to communicate to each plugin
   135  # 2) git repositories cloned by repo-server
   136  volumes:
   137  - emptyDir: {}
   138    name: var-files
   139  ```
   140  
   141  #### Configuration
   142  
   143  Plugins will be configured via a ConfigManagementPlugin manifest located inside the plugin container, placed at a 
   144  well-known location (e.g. /home/argocd/plugins/plugin.yaml). Argo CD is agnostic to the mechanism of how the plugin.yaml would be placed, 
   145  but various options can be used on how to place this file, including: 
   146  - Baking the file into the plugin image as part of docker build
   147  - Volume mapping the file through a configmap.
   148  
   149  Note that, while the ConfigManagementPlugin looks like a Kubernetes object, it is not actually a custom resource. 
   150  It only follows kubernetes-style spec conventions.
   151  
   152  ```bash
   153  # metadata file is in the root and shell executor knows about it
   154  apiVersion: argoproj.io/v1alpha1
   155  kind: ConfigManagementPlugin
   156  metadata:
   157    name: cdk8s
   158  spec:
   159    version: v1.0
   160    init:
   161      command: [cdk8s, init]
   162    generate:
   163      command: [sh, -c, "cdk8s synth && cat dist/*.yaml"]
   164    discovery:
   165      find:
   166      - command: [find . -name main.ts]
   167        glob: "**/*/main.ts"
   168      check:
   169      - command: [-f ./main.ts]
   170        glob: "main.ts"
   171  ```
   172  
   173  #### Config Management Plugin API Server (cmp-server)
   174  The Config Management Plugin API Server (cmp-server) will be a new Argo CD component whose sole responsibility will be 
   175  to execute `generate` commands inside the plugin environment (the sidecar container), at the request of the repo-server.
   176  
   177  The cmp-server will expose the following APIs to the repo-server,
   178  
   179  - GenerateManifests(path) - returns YAML output using plugin tooling
   180  - IsSupported(path) - returns whether or not the given path is supported by the plugin
   181  
   182  At startup, cmp-server looks at the /home/argocd/cmp-server/plugin.yaml ConfigManagementPlugin specification file to understand how to perform the requests.
   183  
   184  #### Registration & Communication
   185  The repo-server needs to understand what all plugins are available to render manifests. To do this, the cmp-server 
   186  sidecars will register themselves as available plugins to the argocd-repo-server by populating named socket files in the 
   187  shared volume between repo-server and cmp-server. e.g.:
   188  
   189  ```bash
   190  /home/argocd/plugins/
   191                          cdk8s.sock
   192                          jkcfg.sock
   193                          pulumi.sock
   194  ```
   195  
   196  The name of the socket file will indicate the plugin name. To discover the available plugins, the repo-server will list 
   197  the shared plugins directory to discover the available plugins.
   198  
   199  To communicate with a plugin, the repo-server will simply need to connect to the socket and make gRPC calls against the 
   200  cmp-server listening on the other side. 
   201  
   202  #### Discovery (Auto-selection of Tool)
   203  
   204  - The plugin discovery will run in the main repo-server container.
   205  - Argo CD repo-server lists the shared plugins directory and runs `discover` command from the specification file, 
   206  whichever plugin provides a positive response first will be selected.
   207  
   208  #### Versioning
   209  There will be one sidecar container per version. Hence, for two different versions users will have to configure two different sidecars.
   210  
   211  ### Security Considerations
   212  
   213  The use of the plugin as sidecars separate from the repo-server is already a security improvement over the current v1.8 
   214  config management plugin mechanism, since the plugin tooling will no longer have access to the files of the argocd-repo-server image. 
   215  However additional improvements can be made to increase security.
   216  
   217  ### Risks and Mitigations
   218  
   219  One issue is that currently when repositories are cloned, the repo is cloned using the same UID of the repo-server user, 
   220  and so all repository files are created using that UID. This means that a command which executes in the git repository path, 
   221  could traverse upwards and see/write files which are outside of the repository tree.
   222  
   223  One proposal to prevent out-of-tree access to files, is that each git repository could be cloned with unique UIDs, 
   224  different from the repo-server’s UID. When the cmp-server executes the tooling command to generate manifests, 
   225  the command could be executed using the UID of the git repository files. e.g.:
   226  
   227  ```
   228  cmd := exec.Command(command, args...)
   229  cmd.SysProcAttr = &syscall.SysProcAttr{}
   230  cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid}
   231  ```
   232  
   233  This would ensure that the command could not read or write anything out-of-tree from the repository directory.
   234  
   235  ### Upgrade / Downgrade Strategy
   236  
   237  The argocd-repo-server manifest will change in order to populate the argocd-cmp-server binary inside the plugin container 
   238  via an init container.
   239  
   240  ```bash
   241  # An init container will copy the argocd static binary into the shared volume
   242  # so that the CMP server can become the entrypoint
   243  initContainers:
   244  - command:
   245    - cp
   246    - -n
   247    - /usr/local/bin/argocd
   248    - /var/run/argocd/argocd-cmp-server
   249    image: quay.io/argoproj/argocd:latest
   250    name: copyutil
   251    volumeMounts:
   252    - mountPath: /var/run/argocd
   253      name: var-files
   254   
   255  # var-files is a shared volume between repo-server and cmp-server which holds:
   256  # 1) socket files that repo-server uses to communicate to each plugin
   257  # 2) git repositories cloned by repo-server
   258  volumes:
   259  - emptyDir: {}
   260    name: var-files
   261  ```
   262    
   263  After upgrading to CMP v2, an Argo CD operator will have to make following changes,
   264  
   265  * In order to install a plugin, an Argo CD operator will simply have to patch argocd-repo-server 
   266  to run config management plugin container as a sidecar, with argocd-cmp-server as it’s entrypoint:
   267  
   268  ```bash
   269  # A plugin is a container image which runs as a sidecar, with the execution environment
   270  # necessary to render manifests. To install a plugin, 
   271  containers:
   272  - name: cdk8s
   273    command: [/var/run/argocd/argocd-cmp-server]
   274    image: docker.ui/cdk8s/cdk8s:latest
   275    volumeMounts:
   276    - mountPath: /var/run/argocd
   277      name: var-files
   278  ```
   279  
   280  * Plugins will be configured via a ConfigManagementPlugin manifest located inside the plugin container, placed at a 
   281  well-known location (e.g. /plugin.yaml). Argo CD is agnostic to the mechanism of how the plugin.yaml would be placed, 
   282  but various options can be used on how to place this file, including: 
   283      - Baking the file into the plugin image as part of docker build
   284      - Volume mapping the file through a configmap.
   285  (For more details please refer to [implementation details](#configuration))
   286  
   287  ## Drawbacks
   288  
   289  There aren't any major drawbacks to this proposal. Also, the advantages supersede the minor learning curve of the new way of managing plugins.
   290  
   291  However following are few minor drawbacks,
   292  
   293  * With addition of plugin.yaml, there will be more yamls to manage
   294  * Operators need to be aware of the modified Kubernetes manifests in the subsequent version.
   295  * The format of the CMP manifest is a new "contract" that would need to adhere the usual Argo CD compatibility promises in future.
   296  
   297  
   298  ## Alternatives
   299  
   300  1. ConfigManagementPlugin as CRD. Have a CR which the human operator creates:
   301  
   302  ```bash
   303  apiVersion: argoproj.io/v1alpha1
   304  kind: ConfigManagementPlugin
   305  metadata:
   306    name: cdk8s
   307  spec:
   308    name: cdk8s
   309    image: docker.ui/cdk8s/cdk8s:latest
   310    version: v1.0
   311    init:
   312      command: [cdk8s, init]
   313    generate:
   314      command: [sh, -c, "cdk8s synth && cat dist/*.yaml"]
   315    discovery:
   316      find:
   317      - command: [find . -name main.ts]
   318        glob: "**/*/main.ts"
   319      check:
   320      - command: [-f ./main.ts]
   321        glob: "main.ts"
   322  ```
   323  2. Something magically patches the relevant manifest to add the sidecar.