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