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.