Kapitan — Inventory explained

D. Heinrich
Kapitan Blog
Published in
3 min readFeb 16, 2021

--

In this post I’d like to explain my view of the inventory/classes and inventory/targets and give a few examples.

If you need a little introduction you can read my previous post “Kapitan — rise and shine” and you can also follow along with the whole Kapitan blog.

With this post I’d like to explain my view on Kapitan’s “inventory section” and how I understand and use them.

Overview

Here you can see the overall components.

NOTE:

In the following I only explain how I use Kapitan! It’s built to have the flexibility to fit your needs. So you may find my way not to fit for your use case. I would appreciate when you share them in the comment section.

Inventory

inventory/classes

Classes are the “most” generic form for an application/micro services. With its default parameters.

I’d like to organise them in folders, so I for example have a “database” folder where I place my generic PostgreSQL and MySQL layout.

When defining a service, we may or may not need certain “default” parameters. In my case I’d like to use image postgres:10 as default and have a backup.interval of every 6 hours as well as a given storage class longhorn which I usually have installed.

With all that given I set the following values as my “default” parameters:

NOTE: The following two code blocks are the same file.

$ cat inventory/classes/database/postgres.yml
parameters:
postgres:
image: postgres:${postgres:version}
version: "10"
backup:
interval: "0 */6 * * *"
size: 10Gi
component: database
users:
postgres:
password: ?{plain:targets/${target_name}/postgres-password||randomstr|base64}
persistence:
storageclass: "longhorn"
accessModes: ["ReadWriteOnce"]
size: 10Gi
[...]

I even let create the postgres.users.postgres.passwordsecret by Kapitan, if its not pre-existing using:

?{plain:targets/${target_name}/postgres-password||randomstr|base64}

But more on that in another post…

These parameters can now be referenced into the components section of Kapitan like so:

$ cat inventory/classes/database/postgres.yml
[...]
#
# Components / Parts
#
components:
postgres:
type: statefulset
image: ${postgres:image}
labels:
app.kubernetes.io/version: ${postgres:version}
app.kubernetes.io/component: ${postgres:component}
service:
type: ClusterIP
ports:
tcp:
service_port: ${database:port}
env:
POSTGRES_PASSWORD: ${postgres:users:postgres:password}
POSTGRES_USER: ${database:user}
POSTGRES_DB: ${database:name}
volume_mounts:
pgdata:
mountPath: /var/lib/postgresql/data/
subPath: pgdata
volume_claims:
pgdata:
spec:
accessModes: ${postgres:persistence:accessModes}
storageClassName: ${postgres:persistence:storageclass}
resources:
requests:
storage: ${postgres:persistence:size}

As you can see above, I linked all my “default” parameters into the component where I need it. Its similar to a json/yaml path.

inventory/targets

The targets are a combination of the available classes, overrides of parameters and additional compile tasks for Kapitan.
Also targets can hold informations about a full deployment (for example Nginx + microservices + database + backup job).

The references under “classes” are directly inside inventory/classes.

So in the following example Kapitan expects me to have the following files:

  • inventory/classes/common.yml
  • inventory/classes/database/postgres.yml
  • inventory/classes/database/postgres-backup.yml
  • inventory/classes/gitea/gitea.yml
  • templates/docs/global/<one or multiple templates>.md.j2
$ cat inventory/targets/gitea/gitea.yml
classes:
- common
- database.postgres
- database.postgres-backup
- gitea.gitea
parameters:
target_name: gitea
domain: <my domain>

components:
gitea:
service:
type: NodePort
kapitan:
compile:
- output_path: .
input_type: jinja2
input_paths:
- templates/docs/global/

I also set a target_name here gitea . This can also be target_name: gitea-dev or something similar.
When for example I specified the service in the components section of a class to be type: ClusterIP but for a certain use case I need to have it as NodePort I can simply override it by setting parameters.components.gitea.service.type inside the target file.
With parameters.kapitan.compile I also have the ability to add additional documentation for a project or a stage.

So if I’d like to have a multistage environment I can think of using the following:

for a Dev environment

$ cat inventory/targets/gitea/gitea-dev.yml
classes:
- common
- database.postgres
- database.postgres-backup
- gitea.gitea
parameters:
target_name: gitea-dev
domain: <my dev domain>
[...]

for a QS environment

$ cat inventory/targets/gitea/gitea-qs.yml
classes:
- common
- database.postgres
- database.postgres-backup
- gitea.gitea
parameters:
target_name: gitea-qs
domain: <my qs domain>
[...]

I’m also able to use specific compilations for a particular target.

As always, check the Kapitan-reference repository for more detailed examples.

Cheers

Sources:

--

--

D. Heinrich
Kapitan Blog

Working as a Head of Infrastructure at Flower Labs.