Organize and reuse components in a ksonnet app


Modules are a group of components within a namespace. When generating a Kubernetes manifest, ksonnet offers a way to selectively choose which components to use without creating a new ksonnet application. Modules also offer a way to organize components as a ksonnet application grows larger.

ksonnet module overview diagram

0. Prerequisites

Before we begin, ensure that:

  • You are using ksonnet 0.12 or above. Some features of modules may not be implemented prior to this version.
  • You have read the concepts. This document relies on an understanding of ksonnet terminology such as environments and components.

1. Creating a module

A module can be created with the ks module create <name> syntax. Each module contains params.libsonnet that allows setting params for components within that module.

$ ks module create a

// Resulting component directory structure
├── a
│   └── params.libsonnet
└── params.libsonnet

2. Nested module

Creating a nested module is possible through dot notation by ks module <parent>.<child>. This creates a nested structure with parameters for each module. This sets up an organizational hierarchy to help manage applications with many components.

$ ks module create a.b

// Example of a nested module
├── a
│   ├── b
│   │   └── params.libsonnet
│   └── params.libsonnet
└── params.libsonnet

3. Directory Structure

Listing all available modules show a root module as / that refers to components/ in the ksonnet application.

Modules are shown by their directory name in components/. Nested modules are shown with the full path with . separating each level. Notice that a and a.b are two separate modules.

$ ks module list

Generate components in a module

When a component is generated, it will be added by default to the components/ directory. The --module flag allows specifying a specific location for the component. We will generate a component to a module that does not exist yet.

$ ks pkg install incubator/nginx
$ ks generate nginx-simple nginx --module c
INFO Writing component at '/path/to/app/components/c/nginx.jsonnet'

// Generated component in a module
├── a
│   ├── b
│   │   └── params.libsonnet
│   └── params.libsonnet
├── c
│   ├── nginx.jsonnet
│   └── params.libsonnet
└── params.libsonnet
Note: If the specified module in the flag does not currently exist, a new module will be created with the component.

View components

Although a component was added to a module, running ks component list will only show components in the root module. Pass the --module flag to list components for a given module.

$ ks component list --module c

4. Patterns for usage

There are multiple levels of configurations within ksonnet:

  • context - using manifests from an environment across multiple clusters
  • environments - using parameters to adjust components
  • modules - selecting components for a given environment

Each set of modules used to generate a manifest should have a separate environment. An environment can have targets to be more specific about which modules (and by extension components) to use. The example below will show how to set an environment target with Redis and nginx components.

Then the nginx component is reused in new environment with a parameter to change the namespace.

Target environments

By default, ksonnet will only use the components within the root module. In app.yaml under the default environment, ksonnet will add multiple targets passed from the --module flags. A target refers to the name of a module.

A Redis component is generated inside an existing module. Then the environment targets are updated with our modules of interest.

$ ks pkg install incubator/redis
$ ks generate redis-stateless redis --module a.b
$ ks env targets default --module c --module a.b

Running ks show default will show a manifest using components from those two modules. In the example above, the manifest will use nginx.jsonnet and redis.jsonnet.

Usage in multiple environments

The nginx component can be reused in a different environment. Set a param using dot notation with the module followed by component name as shown below:

$ ks env create dev
$ ks param set c.nginx namespace dev --env dev
INFO setting environment component                 component-name=c.nginx 

Listing all the params in module c shows the namespace unchanged from the default value. By setting to the module and dev environment, the namespace is updated with the new value.

$ ks param list --module c
========= =====     =====
nginx     name      "nginx"
nginx     namespace "default"

$ ks param list --module c --env dev
========= =====     =====
nginx     name      "nginx"
nginx     namespace "dev"

If we previewed the manifest with ks show dev, the output will use only the nginx component from the c module with the param set for the dev environment. This example shows how ksonnet offers many options to increase modularity within configurations and even handle cases where configurations are distinctively used in a single environment.

Last updated on: September 4, 2018