StormForge Kustomize export

Automate committing patches to Git and deploying through CI

For infrastructure workflows fully automated by a CI pipeline and Kustomize, an alternative option for deployment of recommended resource settings may be to incorporate StormForge’s recommendations into the CI pipeline.

Because Kustomizations (kustomization.yaml files) often serve as the entrypoint for application definitions in tools like Flux CD, tying into Kustomize is frequently the easiest way to automate resource settings if an organization wants or needs to do that during the CI/CD process, rather than managing these settings with a controller.

This approach uses the StormForge CLI to pull StormForge patches and then formats them into a Kustomize Component, which can then be included by a Kustomization.

Example

Consider the following Kustomization, which includes an Nginx application and a Podinfo application. The Kustomization also references a Component in the ./stormforge directory.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../base/podinfo
  - ../base/nginx
patches:
  - path: podinfo-values.yaml
    target:
      kind: HelmRelease

components:
  - ./stormforge

The stormforge component is generated by a command such as the one shown below. The core of the command is an invocation of the Stormforge CLI, which fetches recommendations as patches for a provided scope. Scope selection options include cluster, namespace, labels, and others.

#!/bin/bash
cat <<EOF > ./stormforge/kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component

patches:
$(stormforge get recommendations \
  --cluster CLUSTER \
  --namespace NAMESPACE \
  --patches \
  | yq '.workload.namespace as $ns
        | [ .patches[]
            | .patch.metadata += {"namespace": $ns}
            | {"target": {
                 "kind": .patch.kind,
                 "name": .patch.metadata.name,
                 "namespace": $ns },
               "patch": (.patch | toyaml)}]')
EOF

The resulting Component file might look like this:

---
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component

patches:
- target:
    kind: Deployment
    name: nginx-deployment
    namespace: nginx
  patch: |
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      annotations:
        kubernetes.io/change-cause: Optimize Live (XXXXXXXXXX)
        stormforge.io/last-updated: "202X-XX-XXT00:39:50Z"
        stormforge.io/recommendation-url: https://api.stormforge.io/...
      name: nginx-deployment
      namespace: nginx
    spec:
      template:
        spec:
          containers:
            - name: nginx
              resources:
                requests:
                  cpu: 11m
                  memory: 166Mi    
- target:
    kind: Deployment
    name: redis
    namespace: cache-app
  patch: |
    ...    

The patches list includes patches for every workload in the scope provided to the stormforge get recommendations command. If the target resource is present in the Kustomization, its recommended resource requests patch will be applied to it.

Patches generated in this way match exactly what the applier would do on-cluster, if on-cluster management of resources was being performed.

Last modified September 3, 2024