App Bundles

Overview

The App Bundle is a Helm Chart that instead of providing a regular resources, that normally represents an application, it provides App CRs, optionally accompanied by ConfigMaps and Secrets. In other words, it is a way to represent a group of apps as a single app, to the user and to the system. Check out the public docs if you look for a more detailed explanation.

The App Bundle usage is currently well established in the company.

For example, for CAPI it has been decided to deploy default apps in this way, see ADR. By bundling a group of default apps we make the installation simpler and also means we can retire the Release CRD used in vintage clusters. Hence, a default-apps-PROVIDER app bundle will exist for each CAPI provider.

Another example is grouping apps by the topic, creating specialized bundles, like for example the security-pack app.

Naming Convention

It has been decided for App Bundles to carry the -bundle prefix in order to distinguish them from regular apps, see the PDR.

Note, as you may notice the security-pack referenced in this doc, for whatever reason, is not compliant with these rules yet, do not be suggested by it and please stick to the PDR demands.

What may seem as another exception are default-apps-PROVIDER apps. These however are subject to a bit different rules, as being used in a different ways than usual apps, no matter bundled or not. See the reasoning behind these apps in the previous paragraph.

Creating a new App Bundle

It’s recommended to base new App Bundles on the SOTA (State of the Art) App Bundle.

For default apps this is default-apps-openstack and the app should be published to the cluster-catalog.

For other bundles this is security-pack.

Note, app bundle beyond its fancy name is nothing more than a regular Helm Chart. Whatever the Helm offers for Charts creation can be used when creating a bundle. Some demands are however posed on the configuration, yet not by the bundle construction, but by the way how App Platform works. Find more about in the next paragraphs.

Installing an App Bundle

The installation process for bundles can be found in the public docs. Go there to understand:

  • the components the installation involves
  • the configurational demands by these components

Child Apps

The child apps are templated via the App Bundles helm chart. These examples are taken from the security-pack Helm chart.

# values.yaml
apps:
  falco:
    appName: falco
    chartName: falco-app
    catalog: giantswarm
    enabled: true
    namespace: security-pack
    version: 0.3.2

Each child app should have the giantswarm.io/managed-by label set to the name of the parent app e.g. default-apps-openstack. This identifies the parent app CR and means the install is not blocked by app-admission-controller.

giantswarm.io/managed-by: {{ .Release.Name | quote }}

For CAPI the child app CRs should be created in the org namespace and have a cluster name prefix e.g. dev01-coredns.

For vintage clusters the child app CRs should be created in the cluster namespace and should not have the cluster name prefix.

This can be done via a template helper.

# templates/_helpers.tpl
{{/*
When apps are created in the org namespace add a cluster prefix.
*/}}
{{- define "app.name" -}}
{{- if ne .cluster .ns -}}
{{- printf "%s-%s" .cluster .app -}}
{{- else -}}
{{- .app -}}
{{- end -}}
{{- end -}}

# templates/apps.yaml
{{- $appName := include "app.name" (dict "app" .appName "cluster" $.Values.clusterName "ns" $.Release.Namespace) }}

User Values

Each child app in the bundle needs to be configurable. This is done via the values.yaml of the app bundle’s Helm Chart which needs to pass values to the child apps.

This relies heavily on Helm templating so care needs to be taken and ideally there should be test coverage for this. Find an example of such values.yaml below.

userConfig:
  trivy:
    configMap:
      values: |
        trivy:
          networkPolicy:
            enabled: true        

GitOps Support

There is a problem with using GitOps and managed apps in general, affecting the bundles as well. The user values are passed via the values key of either a ConfigMap or a Secret, and must be a single block of YAML. This prevents using bases and overrides in Flux. This is because kustomize cannot patch strings.

The proposal in RFC#29 is to use both .spec.config and .spec.userConfig and the values will be merged by app-operator.

apiVersion: application.giantswarm.io/v1alpha1
kind: App
metadata:
  name: something
  namespace: org-some
spec:
  config:
    configMap:
      name: flux01-default-apps-config
      namespace: org-some
  userConfig:
    configMap:
      name: flux01-userconfig
      namespace: org-some

This approach has been adapted and explained in our GitOps Template repository, that represents our GitOps offering.