Go to file
Nikolai Rodionov 4c725c3c55
Fix kustomize example
2024-02-07 11:06:37 +01:00
helmfile Init commit 2024-02-07 10:38:02 +01:00
kustomize Fix kustomize example 2024-02-07 11:06:37 +01:00
README.md Init commit 2024-02-07 10:38:02 +01:00
keys.txt Init commit 2024-02-07 10:38:02 +01:00

README.md

Helmfile vs Flux

First, I need to say that I'm not really good at Kustomize, and maybe everything can be done better.

Let's say we need to install Bitnami Postgres to 2 clusters using helm charts.

  • Passwords should be stored in git encrypted with SOPS
  • One database needs to be 10Gb in size, and another just 1Gb

With flux we're creating two manifests:

---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
  name: bitnami
  namespace: flux-system
spec:
  interval: 1m0s
  type: default
  url: https://charts.bitnami.com/bitnami
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  creationTimestamp: null
  name: postgresql
  namespace: flux-system
spec:
  chart:
    spec:
      chart: postgresql
      sourceRef:
        kind: HelmRepository
        name: bitnami
        namespace: flux-system
      version: 13.3.1
  install:
    crds: Create
    createNamespace: true
  interval: 1m0s
  releaseName: postgresql
  targetNamespace: database

With helmfile it's going to be this:

repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: postgresql
    chart: bitnami/postgresql
    version: 13.3.1
    namespace: database

So it's 30 lines of code against 8.

Then we need to add values. With flux we would add something like that to the manifest.

  valuesFrom:
  - kind: ConfigMap
    name: database-postgresql-values.postgresql.yaml
    valuesKey: database-postgresql-values.postgresql.yaml
  - kind: ConfigMap
    name: database-postgresql-values.spec.postgresql.yaml
    valuesKey: database-postgresql-values.spec.postgresql.yaml

Spec means special in that case

And we need to create 2 configmaps (or it can be just one, cause I wanted to reuse common values, but I think kustomize won't let me use the folder that is not in that kustomize context, so I'm not sure how)

And it's either 4 or 7 lines of code in addition

apiVersion: v1
data:
  database-postgresql-values.spec.postgresql.yaml: |
    persistence:
      size: 1Gi    
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: database-postgresql-values.spec.postgresql.yaml
  namespace: flux-system
---
apiVersion: v1
data:
  database-postgresql-values.postgresql.yaml: |
    architecture: standalone

    auth:
      database: postgres

    metrics:
      enabled: false    
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: database-postgresql-values.postgresql.yaml
  namespace: flux-system

In case it's just one configmap, it would be something like:

apiVersion: v1
data:
  database-postgresql-values.postgresql.yaml: |
    persistence:
      size: 1Gi
    architecture: standalone
    auth:
      database: postgres
    metrics:
      enabled: false    
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: database-postgresql-values.postgresql.yaml
  namespace: flux-system

So it's either about 25 or 15 lines of code. Also, it's not just you go to the chart's values and creates a values file, you need to create a whole configmap, so you either need to remember the whole CM spec,cmds to create it, or you need to find a reference somewhere to copy-paste.

Also, since it's just static manifests, names of configmaps and keys are not set once and reused. So it's error-prone configuration, especially when you can't just debug it, and you need to deploy it to spot a problem. Once you update a configmap name/key, you need not to forget to update the Release manifest.

With helmfile it's going to be something like that.

Add it to the helmfile:

    values:
      - ./values/common/values.postgresql.yaml
      - ./values/cluster-1/values.postgresql.yaml

And then values

---
architecture: standalone

auth:
  database: postgres

metrics:
  enabled: false
---
persistence:
  size: 1Gi

So, additional ~10 lines of code.

And the secret thingy

I'm pretty syre it can be done better, since I'm not good at Kustomize, so it might be a bad point.

How am I doing that?

I'm creating a Kubernetes secret where data is encrypted with Sops. To be honest I encrypt the whole secret, but it's just because I've screwed up the sops config part. But the idea is that there is a k8s secret with encrypted data. I won't count lines here, because probably it should be less that I have, approximately it's about 10 lines of code, because it's the whole manifest. And it has the same problem ConfigMap has, because it's a static manifest. but with my approach it's also required to have a secret-generator, that is decrypting secrets with the ksops plugin

---
apiVersion: viaduct.ai/v1
kind: ksops
metadata:
  name: shoebill-secret-gen
files:
  - src/secrets/database-postgresql-secrets.postgresql.yaml

And it's 6 additional lines + a system dependency (ksops). But I've been told that I don't have to do it this way, so it might be not required at all.

Helmfile:

    secrets:
      - ./values/{{ .Environment.Name}}/secrets.postgresql.yaml

So 2 lines are added to the helmfile, and a secret, that in unencrypted state is 4 lines of code

And already at this step it about 65 vs 24. for one chart in one cluster. With the helmfile you don't need to add k8s objects boilerplate around values, you just use them as they are defined in a chart, you don't need to use k8s object boilerplate code around release and repo. And you don't need to check names of secret/configmaps/keys, so they correspond in two static objects.

Now, let's add a second cluster:

Maybe if you use Kustomize with variables, you can avoid it, so I'm not sure

But probably, it would be just 1-to-1 copypaste of the first cluster with one line changed, so I'd expect to have 130 lines of code. And with helmfile I'd do it this way

---
environments:
  cluster-1:
  cluster-2:
---
repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: postgresql
    chart: bitnami/postgresql
    version: 13.3.1
    namespace: database
    values:
      - ./values/common/values.postgresql.yaml
      - ./values/{{ .Environment.Name }}/values.postgresql.yaml
    secrets:
      - ./values/{{ .Environment.Name}}/secrets.postgresql.yaml

So it's just about 4 lines of code added to the helmfile, and 3 added as new values, so 31 in total.

Then if you need to change something that is common for there tho clusters (helmchart version, or common values), with helmfile you'll need to update it once, and with flux you'll have to do it as many times, as you have clusters, since it's going to be copy-paste, it's boring and hence error-prone task.