Inject a sidecar using KubeMod

admission controller sidecar KubeMod

3 min read | by Jordi Prats

Using a webhook we can mutate Kubernetes objects when they are inserted to the cluster. But using a mutating operator can save us the trouble of having to actually code how the object needs to be patched

One of the options is using KubeMod, using a CRD we can configure the mutations we want to happen.

First we need to specify how to identify the object we want to mutate. On this example it will select all the Deployments with the label app=website

apiVersion: api.kubemod.io/v1beta1
kind: ModRule
metadata:
  name: website-deployment-mutations
spec:
  type: Patch
  match:
    - select: '$.kind'
      matchValue: Deployment

    - select: '$.metadata.labels.app'
      matchValue: 'website'

  patch:
    - op: add
      path: /metadata/labels/test
      value: kubemod

And then what we want to patch, for example, we can add a label as follows:

apiVersion: api.kubemod.io/v1beta1
kind: ModRule
metadata:
  name: website-label
spec:
  type: Patch
  match:
    - select: '$.kind'
      matchValue: Deployment

    - select: '$.metadata.labels.app'
      matchValue: 'website'

  patch:
    - op: add
      path: /metadata/labels/test
      value: kubemod

Once it is in place, we can now apply the yaml file to create this object. After this if we describe it we will be able to see how KubeMod have added the label automatically:

$ kubectl describe deploy ampa-website
Name:                   ampa-website
Namespace:              pet2cattle
CreationTimestamp:      Fri, 02 Jul 2021 13:16:22 +0200
Labels:                 app=website
                        app.kubernetes.io/managed-by=halyard
                        app.kubernetes.io/name=ampa
                        app.kubernetes.io/part-of=pet2cattle
                        app.kubernetes.io/version=1.20.8
                        test=kubemod

This mutating operator can be usefull to modify object that we don't have control over them. We could, for example, inject a sidecar

apiVersion: api.kubemod.io/v1beta1
kind: ModRule
metadata:
  name: website-sidecar
spec:
  type: Patch
  match:
    - select: '$.kind'
      matchValue: Deployment

    - select: '$.metadata.labels.app'
      matchValue: 'website'

    - select: '$.metadata.labels["app.kubernetes.io/name"]'
      matchValue: 'ampa'

    - select: '$.metadata.labels["kubemod.sidecar"]'
      matchValue: gitsync
      negate: true

  patch:

    - op: add
      path: /metadata/labels/kubemod.sidecar
      value: gitsync

    - op: add
      path: '/spec/template/spec/containers/-1'
      value: |-
        name: gitpull-daemon
        image: ampa/website:latest
        env:
          - name: 'GIT_SSH_COMMAND'
            value: 'ssh -i /var/website/keys/ssh.key  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
        command:
          - sh
          - '-xc'
          - 'cd /var/website; while true; do git pull; sleep 2m; done'

Set the resource limits:

apiVersion: api.kubemod.io/v1beta1
kind: ModRule
metadata:
  name: website-limits
spec:
  type: Patch
  match:
    - select: '$.kind'
      matchValue: Deployment

    - select: '$.metadata.labels.app'
      matchValue: 'website'

    - select: '$.metadata.labels["app.kubernetes.io/name"]'
      matchValues:
        - website
        - adminsite

  patch:
    - op: replace
      select: '$.spec.template.spec.containers[*].resources'
      path: '/spec/template/spec/containers/#0/resources'
      value: |-
        limits:
          cpu: "2"
          memory: 6000Mi
        requests:
          cpu: 500m
          memory: 5000Mi

Or update any setting, such a environment variable:

apiVersion: api.kubemod.io/v1beta1
kind: ModRule
metadata:
  name: website-jmx
spec:
  type: Patch
  match:
    - select: '$.kind'
      matchValue: Deployment

    - select: '$.metadata.labels.app'
      matchValue: 'website'

    - select: '$.metadata.labels["app.kubernetes.io/name"]'
      matchValues:
        - website
        - adminsite

    - select: '$.spec.template.spec.containers[*].env[*].value'
      matchValue: '-XX:MaxRAMPercentage=50.0'

  patch:
    - op: replace
      select: '$.spec.template.spec.containers[*].env[? @.name =~ "JAVA_OPTS"].value'
      path: '/spec/template/spec/containers/#0/env/#1/value'
      value: '-Xms15G -Xmx15G'

Posted on 27/09/2021