Skip to main content

Customising Podspecs - A Guide on Plugins

While Rig provides Capsules as an abstraction that suits most usecases, you might find youself wanting that last little bit of control to fit your service definition perfectly. This is where Plugins come in. For more information on plugins, check out the Operator Setup guide, and the catalog for built-in plugins.

Customising Podspecs

In this guide, we will use an array of plugins to inject secrets from an init container. Furthermore, we will make this injection conditional based on the presence of a specific annotation on the capsule.

Prerequisites

  • A running Rig platform
  • The Rig CLI installed

Create a new capsule

First we need to create the capsule that we are going to work on:

rig deploy my-capsule -i nginx

Build the secret docker-image

We need a docker image with the secrets that we want to inject. This image should have the secrets in a file at /my/secrets/file.

FROM alpine
WORKDIR /my/secrets
RUN echo "my-secret" > file

If you wish to use this particular image, it is available at picklerig/top-secret:latest.

Configure the plugins.

For this to work, we need 3 components:

  • A plugin that creates an empty volume shared by the main container and the init container. For this we will use the object-template plugin.
  • A plugin that creates the init-container. For this we will naturally use the init-container plugin.
  • A plugin that mounts the shared volume in the main container. For this, we will again use the object-template plugin.

We configure these plugins in the operator-config. As the plugins are configured on operator-level, they will run for all capsules that are reconciled by that operator, which in turn means that they are cluster specific.

Helm values - Operator
config:
pipeline:
steps:
- plugins:
# Set up the secret volume.
- plugin: rigdev.object_template
config: |
group: apps
kind: Deployment
object: |
spec:
template:
spec:
volumes:
- name: secrets-volume
emptyDir: { }

# Start and copy secrets into the volume.
- plugin: rigdev.init_container
config: |
# The container to inject.
container:
name: secrets-init
# Replace this with your docker image.
image: picklerig/top-secret:latest
command:
- sh
args:
- -c
- "cp /my/secrets/file /secrets/"
volumeMounts:
- mountPath: /secrets/
name: secrets-volume

# Add the volume to the main container
- plugin: rigdev.object_template
config: |
group: apps
kind: Deployment
object: |
spec:
template:
spec:
containers:
- name: {{ .capsule.metadata.name }}
volumeMounts:
- mountPath: /secrets/
name: secrets-volume

These three plugins are now configured to run in sequence for each capsule that is reconciled by the operator.

Conditional injection

What if we only want to inject the secrets in some capsules? We can use the match field in the operator-config to filter which capsules the plugins are run for. In this case, we are going to match on the precense of an annotation inject-secrets: "".

Helm values - Operator
config:
pipeline:
steps:
- match:
annotations:
- inject-secrets: ""
- plugins:
...

This also means, that we have to add the annotation to the capsule in the previous step:

rig deploy my-capsule --set-annotation inject-secrets=""

Verify the result

To verify that the plugins are working as expected, we can view the secrets in the main container:

rig capsule instance exec my-capsule my-capsule-55d66dd45f-sfljf -- cat secrets/file