Modular Kubernetes Programming— Part II

Sidhartha Mani
Koki
Published in
3 min readJan 31, 2018

This is a follow up post to the one published yesterday titled “Modular Kubernetes Programming”. If you aren’t familiar with modular Kubernetes resources, please read the previous article in this series before continuing.

The previous article talks about the advantages of dividing Kubernetes resources into modules, and showed the use of animport statement to import a module into another module.

This article dives into using theparams keyword in Koki Short.

The skin of a chameleon is nothing but a parameterized skin color changer. The parameter is obtained from the surroundings. (https://commons.wikimedia.org/w/index.php?curid=49366049)

Parametric Modules

Modules in Koki Short have been designed to be not just evolvable, but also configurable. This provides the maximum flexbility for users using this system.

Consider this Pod definition:

pod:
containers:
- env:
- from: metadata.namespace
key: POD_NAMESPACE
expose:
- admin-port: 8080
- driver-port: 28015
- cluster-port: 29015
image: gcr.io/google_containers/rethinkdb:1.16.0_1
name: rethinkdb
volume:
- mount: /data/rethinkdb_data
store: rethinkdb-storage
labels:
db: rethinkdb
role: admin

name: rethinkdb-admin
version: v1
volumes:
rethinkdb-storage: empty_dir

In Kubernetes, labels and annotations are used to decorate resources with custom metadata. Generally, labels are shared between different resources and are used to select resources of specific kinds.

For instance, if you wanted to front the pod defined above with a Service resource, then the service would “select” this pod by looking for all pods with a certain label.

Since labels are shared between various resources, their definitions should be created, updated and managed together. We already saw how a module system could be beneficial here. Let’s modularize the pod above to use labels from a module instead of repeating them in each file.

pod:
containers:
- env:
- from: metadata.namespace
key: POD_NAMESPACE
expose:
- admin-port: 8080
- driver-port: 28015
- cluster-port: 29015
image: gcr.io/google_containers/rethinkdb:1.16.0_1
name: rethinkdb
volume:
- mount: /data/rethinkdb_data
store: rethinkdb-storage
labels:
db: rethinkdb
role: admin

name: rethinkdb-admin
version: v1
volumes:
rethinkdb-storage: empty_dir

The text in bold is the module boundary. Let’s put everything within the boundary into a different module. Let’s name the module definition file rethink-labels-module.yaml, containing the data below:

labels:
db: rethinkdb
role: admin

Now, let’s update the original pod definition to use this module

imports:
- labels: ./rethink-labels-module.yaml

pod:
containers:
- env:
- from: metadata.namespace
key: POD_NAMESPACE
expose:
- admin-port: 8080
- driver-port: 28015
- cluster-port: 29015
image: gcr.io/google_containers/rethinkdb:1.16.0_1
name: rethinkdb
volume:
- mount: /data/rethinkdb_data
store: rethinkdb-storage
labels:
${labels}

name: rethinkdb-admin
version: v1
volumes:
rethinkdb-storage: empty_dir

The above module system works perfectly when the labels are used exactly as defined in the module file.

Let’s consider the scenario where the role defined in the labels module is not always admin. If you wish to specify the role as user in another resource, the params feature in Koki Short is the answer!

Theparams keyword is used to parameterize the imported module. This save significant amount of time, which would otherwise be required to rewrite the same configuration multiple times with minor changes. Let’s use params to change the role to user

params:
- role: "role of the rethinkdb service (admin|user)"
default: admin
labels:
db: rethinkdb
role: ${role}

When importing this module, the role can be parameterized

imports:
- labels: ./rethink-labels-module.yaml
params:
role: user

pod:
containers:
- env:
- from: metadata.namespace
key: POD_NAMESPACE
expose:
- admin-port: 8080
- driver-port: 28015
- cluster-port: 29015
image: gcr.io/google_containers/rethinkdb:1.16.0_1
name: rethinkdb
volume:
- mount: /data/rethinkdb_data
store: rethinkdb-storage
labels:
${labels}

name: rethinkdb-admin
version: v1
volumes:
rethinkdb-storage: empty_dir

Let’s expand the whole parameterized, modularized resource and see the final result.

$ short -k -f rethinkdb.yaml

The output looks like this

apiVersion: v1
kind: Pod
metadata:
labels:
db: rethinkdb
role: user
name: rethinkdb-admin
spec:
containers:
- env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: gcr.io/google_containers/rethinkdb:1.16.0_1
name: rethinkdb
ports:
- containerPort: 8080
name: admin-port
protocol: TCP
- containerPort: 28015
name: driver-port
protocol: TCP
- containerPort: 29015
name: cluster-port
protocol: TCP
resources: {}
volumeMounts:
- mountPath: /data/rethinkdb_data
mountPropagation: ""
name: rethinkdb-storage
volumes:
- emptyDir: {}
name: rethinkdb-storage

The role has been parameterized to be user.

Conclusion

This blog post sheds more light onto the param keyword in the module system. This powerful feature provide users with the flexibility needed for creating, reading, writing and managing Kubernetes manifests easily.

You can learn more about Short or download examples to play with. You can also try out the Chrome extension to translate live on your browser!

Stay tuned for more deep dives into Modular Kubernetes programming using Koki Short!

--

--