|
| 1 | +--- |
| 2 | +date: 2023-11-17 |
| 3 | +title: Argo CD Config Management Plugins in Validated Patterns |
| 4 | +summary: Validated Patterns now support sidecar configmanagement plugins in ArgoCD |
| 5 | +author: Martin Jackson |
| 6 | +blog_tags: |
| 7 | +- openshift-platform-plus |
| 8 | +- devsecops |
| 9 | +- devops |
| 10 | +- patterns |
| 11 | +- pipelines |
| 12 | +- gitops |
| 13 | +aliases: /2023/11/17/argocd-cmps/ |
| 14 | +--- |
| 15 | + |
| 16 | +# Argo CD Configuration Management Plugins and the Validated Patterns Framework |
| 17 | + |
| 18 | +## Problem |
| 19 | + |
| 20 | +Argo CD has a number of mechanisms for facilitating Kubernetes application deployments besides applying raw manifests. |
| 21 | +The most prominent mechanisms it uses are Kustomize (which is built into kubectl now) and Helm (which is an external tool still). If the user has additional needs for manifest generation that cannot be met by either of these tools, Argo CD |
| 22 | +provides a mechanism called Configuration Management Plugins that allow for editing the manifest stream either in |
| 23 | +addition to or in lieu of Helm or Kustomize. This mechanism allows, for example, using both Helm and Kustomize on the |
| 24 | +same template files and/or bases at the same time. If the user needs a custom tool, such as [PolicyGen](https://cloud.redhat.com/blog/generating-governance-policies-using-kustomize-and-gitops) to be involved in generating Kubernetes |
| 25 | +manifests, this feature enables its use. Similarly, another use for this feature is to enable the |
| 26 | +[Argo CD Vault Plugin](https://github.com/argoproj-labs/argocd-vault-plugin), which works by substituting specific tags |
| 27 | +in manifests. This allows users to avoid storing secrets directly in git repositories, which is one of the key needs |
| 28 | +of an operational GitOps strategy. |
| 29 | + |
| 30 | +## Implementation |
| 31 | + |
| 32 | +The implementation in the Validated Patterns framework is meant to conform to the mechanism described [here](https://argo-cd.readthedocs.io/en/stable/operator-manual/config-management-plugins/) upstream. Note that the plugin configuration |
| 33 | +actually must live inside the container - either "baked in" to the sidecar image, or injected via configmap. The |
| 34 | +framework supports both options. |
| 35 | + |
| 36 | +Previously, the Validated Patterns `clusterGroup` chart would create three plugins using the CMP 1.0 framework. Only one |
| 37 | +of these was ever used (to the best of our knowledge), `helm-with-kustomize` in the [Industrial Edge](https://github.com/validatedpatterns/industrial-edge) pattern. As of this publication, the kustomize integration is no longer necessary - |
| 38 | +the code was refactored to operate directly on helm value files instead of creating dynamic kustomize patches. |
| 39 | + |
| 40 | +In the `clusterGroup` chart (which is the heart of the Validated Patterns framework), there is a new key, `argoCD`, |
| 41 | +that can optionally be used to implement an arbitrary number of CMP 2.0-style plugins. |
| 42 | + |
| 43 | +For example: |
| 44 | + |
| 45 | +```yaml |
| 46 | + argoCD: |
| 47 | + initContainers: [] |
| 48 | + configManagementPlugins: |
| 49 | + - name: helm-with-kustomize |
| 50 | + image: quay.io/hybridcloudpatterns/utility-container:latest |
| 51 | + imagePullPolicy: Always |
| 52 | + pluginArgs: |
| 53 | + - '--loglevel=debug' |
| 54 | + pluginConfig: | |
| 55 | + apiVersion: argoproj.io/v1alpha1 |
| 56 | + kind: ConfigManagementPlugin |
| 57 | + metadata: |
| 58 | + name: helm-with-kustomize |
| 59 | + spec: |
| 60 | + preserveFileMode: true |
| 61 | + init: |
| 62 | + command: ["/bin/sh", "-c"] |
| 63 | + args: ["helm dependency build"] |
| 64 | + generate: |
| 65 | + command: ["/bin/bash", "-c"] |
| 66 | + args: ["helm template . --name-template ${ARGOCD_APP_NAME:0:52} |
| 67 | + -f $(git rev-parse --show-toplevel)/values-global.yaml |
| 68 | + -f $(git rev-parse --show-toplevel)/values-{{ .Values.clusterGroup.name }}.yaml |
| 69 | + --set global.repoURL=$ARGOCD_APP_SOURCE_REPO_URL |
| 70 | + --set global.targetRevision=$ARGOCD_APP_SOURCE_TARGET_REVISION |
| 71 | + --set global.namespace=$ARGOCD_APP_NAMESPACE |
| 72 | + --set global.pattern={{ .Values.global.pattern }} |
| 73 | + --set global.clusterDomain={{ .Values.global.clusterDomain }} |
| 74 | + --set global.hubClusterDomain={{ .Values.global.hubClusterDomain }} |
| 75 | + --set global.localClusterDomain={{ coalesce .Values.global.localClusterDomain .Values.global.hubClusterDomain }} |
| 76 | + --set clusterGroup.name={{ .Values.clusterGroup.name }} |
| 77 | + --post-renderer ./kustomize"] |
| 78 | +``` |
| 79 | +
|
| 80 | +`initContainers` is an array of initContainers that will be added to the repo-server pod. In most cases you do not need |
| 81 | +to do this. (By default, an init container in the repo-server pod will copy the argocd binary into /var to run as the |
| 82 | +cmp server for the container. This behavior will happen even if you specify nothing here, which is the default. Since |
| 83 | +the argocd kind supports this, so do we.) |
| 84 | + |
| 85 | +`configManagementPlugins` is an array. Each element will add one sidecar plugin to the GitOps repo-server pod the |
| 86 | +clusterGroup chart controls. In the `argoCD` instance it primarily adds elements to the `sidecarContainers` property. |
| 87 | + |
| 88 | +The `name` element is the name of the plugin - this is how applications can specifically request that Argo CD/GitOps |
| 89 | +process the manifests. This name is also used to compose a configmap name if the user specifies the pluginConfig string. |
| 90 | + |
| 91 | +The `image` element is the image the sidecar will use. The repo-server default initContainer will copy the argocd server |
| 92 | +into the image; the user must supply any external binaries though. |
| 93 | + |
| 94 | +The `imagePullPolicy` element is optional. It defaults to `Always` if not specified. |
| 95 | + |
| 96 | +The `pluginArgs` element is optional, and is an array. If omitted, it does not have a default. It can be used to turn |
| 97 | +up the debug level of the cmp-server process inside the container. |
| 98 | + |
| 99 | +The `pluginConfig` element is a string, and is optional. If specified, it will be passed through the Helm `tpl` |
| 100 | +function, so any recognized Helm variables or functions will be rendered. The chart will arrange for this string to |
| 101 | +be injected into the sidecar as `plugin.yaml` via configmap. While it is possible to bake this into the sidecar, changes |
| 102 | +to the plugin.yaml would require the sidecar image to be rebuilt and redeployed, and the repo-server pod restarted. It |
| 103 | +is a documented method in the upstream documentation, so the framework allows it. |
| 104 | + |
| 105 | +Please note that the `preserveFileMode` setting in the example plugin config is not yet supported in Argo CD 2.6/GitOps |
| 106 | +Operator 1.8, but is in Argo CD 2.8/GitOps Operator 1.10. The main use for this property is to call executables inside |
| 107 | +the repository as post-renderers (as this example does). Please be aware that there are security concerns associated |
| 108 | +with doing this. The suggested practice is to ship any executable programs (including shell scripts, Python scripts |
| 109 | +etc.) as part of the sidecar image. |
| 110 | + |
| 111 | +## History |
| 112 | + |
| 113 | +### How CMPs came into the Validated Patterns Framework |
| 114 | + |
| 115 | +In the beginning, the Validated Patterns framework had not yet developed its preference (though not, as occasionally |
| 116 | +reported, an insistence) for Helm, and most of the existing gitops repositories were based on kustomize. The first |
| 117 | +pattern implemented with the framework was [industrial-edge](https://github.com/validatedpatterns/industrial-edge). |
| 118 | +This was based on the [MANUela](https://github.com/sa-mw-dach/manuela) demo, which was completely based on kustomize. |
| 119 | + |
| 120 | +We developed the Validated Patterns framework, to some degree, around what the industrial-edge pattern needed. One of |
| 121 | +the things we wanted to do was to find ways to allow the framework to be used to instantiate a demo without requiring |
| 122 | +the user to configure things that could be automatically discovered from the environment. So - the user has to |
| 123 | +configure their own credentials for connecting to git forges and container registries; but the domain the OpenShift |
| 124 | +cluster that will be running the demo can be discovered, so rather than requiring that to be configured, we provided a |
| 125 | +mechanism that extracted that information and stored it as a Helm variable. Meanwhile, the components of industrial-edge |
| 126 | +that used this information had very opinionated kustomize-based deployment mechanisms and workflows to update them. |
| 127 | +We did not want to change this mechanism at the time, so it was better for us to work out how to apply Helm templating |
| 128 | +on top of a set of of manifests that kustmomize had already rendered. The CMP 1.0 framework was suitable for this, and |
| 129 | +fairly straightforward to use, so we did. However, we did not, at that time, put any thought into parameterizing the |
| 130 | +use of config management plugins; making too radical a change to how the repo server worked would have difficult, and |
| 131 | +would have required injecting a new (and unsupported) image into a product; not something to be undertaken lightly. |
| 132 | +Finally, it was unclear that there would be significant demand for such a feature in the framework. |
| 133 | + |
| 134 | +### Questions that arose around CMPs in the Validated Patterns Framework |
| 135 | + |
| 136 | +Of course, there is some common wisdom about making assumptions in situations like this. Two major factors caused us to |
| 137 | +revisit the question of config management plugins in the framework. First, one of our prospective users clearly had an |
| 138 | +architectural need of the framework that was best met using config management plugins; and upstream, Argo CD had come up |
| 139 | +with an entirely new mechanism for implementing CMPs using sidecars. This took the question of rebuilding or |
| 140 | +substituting the repo-server image off the table; but required some changes in the framework to accomodate the new |
| 141 | +mechanism. Secondly, we learned that the existing plugin framework had been deprecated and was at risk of being removed. It was actually removed upstream in Argo CD 2.9. |
| 142 | + |
| 143 | +Now that the framework supports user-specified sidecar plugins, we would love to hear your feedback. Does our adoption |
| 144 | +of CMP 2.0 meet your needs? Please engage with us in our [upstream issue tracker](https://github.com/validatedpatterns/common/issues). |
0 commit comments