Releases & States

Kerbi's state management system lets you store the values it computes during $ kerbi template or $ kerbi values, and then retrieve those values again. Kerbi uses a ConfigMap, Secret, or database in your cluster to store the data.

To build an intuitive understanding of state management, see the Walkthrough.

Kubernetes Workflow

Conceptual Workflow

Your goal as a developer using variable-based templating in a modern CD pipeline should be to achieve the following workflow:

  1. Template a new manifest using new values merged onto the last set of values you used

  2. Try applying that new manifest to the Kubernetes cluster

  3. If the apply worked:

    1. Store the values you just used to generate this manifest for next time

  4. Otherwise:

    1. Stop everything, ping devs, etc...

Helm Workflow

Helm does this for you in one line with:

$ helm install foo . \
    --set pod.image=v2

This is great, but there are some downsides, namely that you are delegating the most critical command in Kubernetes - kubectl apply - to another tool.

Kerbi Workflow

Kerbi, on the other hand, is designed to never run critical operations like kubectl apply on your behalf. So with Kerbi, you can implement conceptual workflow as follows:

$ kerbi template foo . \
    --set pod.image=v2 \
    --read-state @latest \
    --write-state @new-candidate \
    > manifest.yaml

$ kubectl apply --dry-run=server -f manifest.yaml \
  && kerbi state promote @candidate
  && kubectl apply -f manifest.yaml

Running kubectl apply with --dry=run-server will yield a status code of "0" if all resources were accepted, and "1" otherwise. Therefore, the statement that comes after the && only gets evaluated if Kubernetes accepted all our resources - what we wanted.

What is a State?

A state is a record that stores the values (aka variables) that were computed during a $ kerbi template operation, provided a --write state [TAG] flag is passed.

State records have the following attributes:

  • tag - its unique name, which can be anything

  • revision - the semantic version number of your project (see guide)

  • message any human readable note, or perhaps a git commit id

  • values the final values computed by template or values show

  • default_values the final default values computed by template or values show

  • created_at an ISO8601 timestamp

You can easily inspect any state with the CLI:

$ kerbi state show antelope @latest

--------------------------------------------
 TAG              1.0.0
--------------------------------------------
 RELEASE          antelope
--------------------------------------------
 REVISION         1.0.0
--------------------------------------------
 MESSAGE
--------------------------------------------
 CREATED_AT       2022-04-12 14:43:24 +0100
--------------------------------------------
 VALUES           pod.image: centos          
                  service.type: ClusterIP
--------------------------------------------
 DEFAULT_VALUES   pod.image: nginx          
                  service.type: ClusterIP
--------------------------------------------
 OVERRIDDEN_KEYS  pod.image
--------------------------------------------

What is a Release?

A release is a collection of states. Conceptually, a release also means "one instance of the app".

Name, Namespace, and Resource Name

In a world where a Kubernetes namespace was a reliable boundary for an application's perimeter, we (and probably Helm) would just use namespaces. But this is unfortunately not the case.

A release is identified by its name and its namespace. Unless you pass --namespace [NAME], its namespace will automatically be set to its name. Let's build an intuition:

$ kerbi release init antelope
namespaces/antelope: Created
configmaps/antelope/kerbi-antelope-db: Created

$ kerbi release init zebra --namespace antelope
namespaces/antelope: Already existed
configmaps/antelope/kerbi-zebra-db: Created

$ kerbi release init antelope --namespace default
namespaces/default: Already existed
configmaps/default/kerbi-antelope-db: Created

Referring to Releases

When you run a command like $ kerbi template [RELEASE_NAME], Kerbi will look for a ConfigMap called kerbi-[RELEASE_NAME]-db in the namespace [RELEASE_NAME].

If you pass an explicit namespace, e.g $ kerbi template [RELEASE_NAME] --namespace [NAMESPACE] then it will look for the ConfigMap in the namespace [NAMESPACE].

Remember you can easily figure out what's where with:

$ kerbi release list
NAME      BACKEND    NAMESPACE  RESOURCE           STATES  LATEST
antelope   ConfigMap  antelope   kerbi-antelope-db  0
zebra      ConfigMap  antelope   kerbi-zebra-db     0
antelope   ConfigMap  default    kerbi-antelope-db  0

Subtle Difference with Helm

Release names and namespaces are confusing. If you're used to Helm, it's important to highlight the difference. Illustrative pseudocode:

# HOW KERBI DOES IT
release_name = read('release_name')
namespace = release_name || read('namespace')

# HOW HELM DOES IT
release_name = read('release_name')
namespace = read(namespace) || 'default'

Configuration

State management backends

Kerbi can store the compiled values data in a ConfigMap, a Secret, or an arbitrary database. **** You can set this behavior either with a flag e.g --backend ConfigMap or in the global Kerbi config e.g $ kerbi config set state-backend: Secret.

Only ConfigMap currently works

Secret and database are not yet finished.

If you use a ConfigMap or Secret, you'll need to give Kerbi access your cluster. The examples below show the three different ways to do that.

To use this auth mode:

$ kerbi config set k8s-auth-type kube-config

If you have a ~/.kube/config.yaml on your machine, then this should work without any further configuration. The following settings are available:

$ kerbi config set kube-config-path /path/to/your/kube/config
$ kerbi config set kube-config-context <e.g gke-stagging-cluster>

Note that each configuration above can also be passed as a flag in any state touching operation, e.g $ kerbi template --k8s-auth-type in-cluster.

State Tag Substitutions

We can feed the CLI special expressions instead of literals tag. When Kerbi encounters a special keyword, formatted as @<keyword>, it will attempt to resolve it to a literal tag name. Depending on the keyword, the resolved tag may or may not refer to an existing state tag.

The @latest keyword

Resolves to the tag of the newest _non_-candidate state (as given by created_at). Behavior is the same during read and write operations.

Example: $ kerbi state show zebra @latest

The @candidate keyword

Resolves to the tag of the newest candidate state (as given by created_at). Behavior is the same during read and write operations.

Example: $ kerbi state retag zebra @candidate 1.2.3

The @new-candidate keyword

Resolves to a random, free (not yet taken by existing states) tag with a candidate status prefix. Only works for write operations.

Example: $ kerbi values show -f v2.yaml --write-state @new-candidate. The name of the new state in this case resolved to "[cand]-purple-purse"

The @random keyword

Resolves to a random, free (not yet taken by existing states) tag without a candidate status prefix. Only works for write operations.

Example: $ kerbi values show -f v2.yaml --write-state @random. The name of the new state in this case resolved to "spiky-goose"

Candidate Status

States have a "candidate" flag to make it possible to implement the conceptual workflow described in the first section. In short, you want a state to be in candidate mode until you know it has been successfully applied to the cluster.

Designation

To make Kerbi as simple as possible, there is no special attribute to designate candidacy, only a special prefix [cand]-. So any state that begins with [cand]- is treated as a candidate. Conversely, if you want to promote a state to non-candidate and rename it in one go, just:

$ kerbi state retag @candidate <a-new-name>

Creation

Because the

Promoting and Pruning

To promote a state and keep its name, run:

$ kerbi state promote @candidate

You can also delete all candidate states with one command:

$ kerbi state prune-candidates 

Last updated