Skip to content

Release management

Overview

RMK uses Helmfile for the release management.

RMK uses a reduced set of the Helmfile commands without changing their behavior. The full list of commands can be found in the release category. Additionally, flags are provided for the commands, which allow extending capabilities and help during the command execution debug.

For example:

rmk release build
rmk release list
rmk release template --skip-context-switch --selector app=myapp1
rmk release sync --helmfile-log-level=debug --selector app=myapp1 
rmk release destroy 

The --skip-context-switch (-s) flag can be used with commands like rmk release template to skip switching to a Kubernetes cluster.

This is useful in situations where a cluster has not been provisioned yet, releases are being developed, but the user still wants to preview intermediate results, such as checking the templating of a release.

In a project repository, all the release values files are stored in the etc/<scope>/<env>/values/ directories. For example:

etc/deps/develop/values/
etc/rmk-test/staging/values/

The release values are inherited by the projects, e.g., the upstream project’s values (deps) are included into the downstream project’s values (rmk-test).

All releases.yaml files controlling which releases are enabled/disabled are stored in the etc/<scope>/<env>/ directories. For example:

etc/deps/develop/releases.yaml

Similar to the SOPS secrets files, the releases.yaml files are never inherited by the projects in contrast to the release values. Each project should have its own releases.yaml files for all deployed scopes and environments.

The release installation order is declared in helmfile.yaml.gotmpl file. For an example, see the cluster-deps Helmfile.

Running any of the commands in the release category will trigger the Helmfile’s dependency resolution mechanism (DAG). Additionally, RMK verifies that the current Kubernetes context matches the Git branch and environment, preventing releases from being synchronized to an unintended Kubernetes cluster (RMK will select a correct automatically).

Among the user-defined Helmfile selectors, the following labels are available by default:

  • name: Release name.
  • namespace: Release namespace.
  • chart: Chart name.

For example:

rmk release list --selector name=myapp1
rmk release sync --selector namespace=kube-system
rmk release destroy --selector chart=mychart1

Examples of usage

List of all available releases

rmk release list

Viewing a specific release YAML after the Helm values template rendering

rmk release template --selector app=myapp1

Synchronization of all releases

rmk release sync

Synchronization of a specific scope of the releases

rmk release sync --selector scope=deps

Synchronization of a specific release with passing the “–set” Helmfile argument

rmk release sync --selector app=myapp1 --helmfile-args="--set='values.key1=value1'"

Destroy all releases

rmk release destroy

Overriding release values for inherited upstream projects

It is possible to override any release value for the inherited upstream project repository. You can override any element separately in its YAML file.

For example, you have the following file in the cluster-deps upstream project, e.g. aws-cluster.yaml.gotmpl.

# ...

## The machine pools configurations
machinePools:
  app:
    enabled: false
    annotations: {}
    labels: {}
    managed:
      spec:
        # AdditionalTags is an optional set of tags to add to AWS resources managed by the AWS provider, in addition 
        # to the ones added by default.
        additionalTags: {}
        # DiskSize specifies the root disk size
        diskSize: 10
        # InstanceType specifies the AWS instance type
        instanceType: t3.medium
        # Labels specifies labels for the Kubernetes node objects
        labels:
          db: app
        # Scaling specifies scaling for the ASG behind this pool
        scaling:
          maxSize: 1
          minSize: 1
        # Taints specifies the taints to apply to the nodes of the machine pool
        taints:
          - effect: NoSchedule
            key: old-taint
            value: value1
        # ...
    # Number of desired machines.
    replicas: 1
    spec:
    # ...

# ...

Then, if you need to change the machinePools.app.* values in the develop environment of the rmk-test downstream project, e.g., to enable the app nodes and increase their count to 10, you do not need to copy the entire file. Instead, you can override only the specific values by repeating their YAML path.

Your override file will be minimalistic and contain only the necessary changes:

machinePools:
  app:
    enabled: true
    managed:
      spec:
        scaling:
          maxSize: 10
          minSize: 10
    replicas: 10

If you want to override the taints field, which is an array, the correct way to do this is to provide the whole array:

taints:
  # old taint
  - effect: NoSchedule
    key: old-taint
    value: value1
  # new taint
  - effect: PreferNoSchedule
    key: new-taint
    value: value2

You cannot override a subset of the array items:

taints:
  # incorrect
  - effect: NoSchedule
    key: new-taint
    value: value2

To check the final result, run the rmk release template command and see the final YAML.

Release update and integration into the CD pipeline

The rmk release update command automates the process of updating and delivering releases according to the version changes of artifacts, e.g., container images, following the GitOps methodology.

Since RMK is a binary file that can be downloaded and installed on any Unix-based operating system, it can be integrated with almost any CI/CD system: GitHub Actions, GitLab, Drone CI, Jenkins, etc.

Example of integration with GitHub Actions

Prerequisites:

Create the following workflow in your project repository at .github/workflows/release-update.yaml. An example content of the GitHub Actions’ workflow:

name: Release update

on:
  workflow_dispatch:
    inputs:
      image_repository_full_name:
        description: Image repository full name of application.
        required: true
      version:
        description: Current application version.
        required: true

jobs:
  release-update:
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout main repository
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
          fetch-depth: 0

      - name: Release update
        env:
          AWS_REGION: us-east-1
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          RMK_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN_REPO }}
          RMK_SLACK_WEBHOOK: ${{ secrets.RMK_SLACK_WEBHOOK }}
          RMK_SLACK_CHANNEL: project1-cd-notifications
          RMK_RELEASE_UPDATE_REPOSITORY: ${{ github.event.inputs.image_repository_full_name }}
          RMK_RELEASE_UPDATE_TAG: ${{ github.event.inputs.version }}
        run: |
          curl -sL "https://edenlabllc-rmk-tools-infra.s3.eu-north-1.amazonaws.com/rmk/s3-installer" | bash

          rmk config init --cluster-provider=aws --progress-bar=false --slack-notifications
          rmk release update --skip-ci --deploy

In this example, we have prepared a GitHub Action that expects two input parameters:

  • image_repository_full_name
  • version

As soon as a request with these parameters is sent to this action, RMK will be executed, first analyzing all the releases.yaml files to match the image_repository_full_name and will replace the tag field with the corresponding version if the versions differ. After that, it will automatically commit the changes to the current branch in the releases.yaml files where changes have been found. Then, it will synchronize the releases where the version changes were found.

An example of the releases.yaml file:

# ...
foo:
  enabled: true
  image:
    repository: 123456789012.dkr.ecr.us-east-1.amazonaws.com/app.foo
    tag: v0.1.0
bar:
  enabled: true
  image:
    repository: 123456789012.dkr.ecr.us-east-1.amazonaws.com/app.bar
    tag: v0.1.1
# ...

To fully automate code delivery in the CI pipeline, add a step that triggers the deployment after building and pushing the container image. This step should pass the full image repository name and tag via an API call using cURL or GitHub CLI. This ensures seamless deployment to the infrastructure environment.


Last update: February 17, 2025