Skip to main content

Components

A component is a collection of Kubernetes manifests including all resources needed for an application, such as a Deployment, a Service or a Secret.

Folder Structure

A component should be placed in components/<name>.js or components/<name>/index.js.

.
└── components
├── foo
│ └── index.js
└── nginx.js

When you run kosko generate, Kosko will find all files or folders in components folder that matching the pattern set in components configuration (it is * by default, which means everything in components folder). You can add component names or patterns to the command to specify which components to generate.

# Use `components` in `kosko.toml`.
kosko generate

# Specify which components to generate
kosko generate nginx dev_*

Basic

Let's start with a basic component. In the following example, we will create a new file components/busybox.js that exports a Pod.

import { Pod } from "kubernetes-models/v1/Pod";

const pod = new Pod({
metadata: { name: "busybox" },
spec: {
containers: [{ name: "busybox", image: "busybox" }]
}
});

export default pod;

Then you can run kosko generate to print YAML.

kosko generate
# apiVersion: v1
# kind: Pod
# metadata:
# name: busybox
# spec:
# containers:
# - name: busybox
# image: busybox

At the first line, we import Pod class from kubernetes-models package. This is a separated package which is generated automatically from Kubernetes OpenAPI Specification. It provides type definitions and validation. You can import corresponding resources as below.

// Class
import { Kind } from "kubernetes-models/<apiVersion>/<kind>";

// Interface
import { IKind } from "kubernetes-models/<apiVersion>/<kind>";

Kind can be omitted from the import path if you want to import multiple resources at a time. Please note that this might have impact on the module loading speed.

import { Pod, Service } from "kubernetes-models/v1";

kubernetes-models also supports custom resource definitions (CRDs). You can see here for a full list of supported 3rd-party models.

import { Certificate } from "@kubernetes-models/cert-manager/cert-manager.io/v1/Certificate";

If the CRD package is not available yet, or you want to skip validation on certain manifests, Kosko also supports plain objects.

const pod = {
apiVersion: "v1",
kind: "Pod"
};

Export More Manifests

In the following example, we will create a file components/nginx.js that exports a Deployment and Service.

import { Deployment } from "kubernetes-models/apps/v1/Deployment";
import { Service } from "kubernetes-models/v1/Service";

const labels = { app: "nginx" };

const deployment = new Deployment({
metadata: { name: "nginx" },
spec: {
selector: {
matchLabels: labels
},
template: {
metadata: { labels },
spec: {
containers: [{ name: "nginx", image: "nginx" }]
}
}
}
});

const service = new Service({
metadata: { name: "nginx" },
spec: {
selector: labels,
ports: [{ port: 80 }]
}
});

export default [deployment, service];

At the last line, we replace the export value with an array. So when you run kosko generate, it will print YAML as below.

kosko generate
# ---
# apiVersion: apps/v1
# kind: Deployment
# (omitted)
# ---
# apiVersion: v1
# kind: Service
# (omitted)

Function

You can also export a function that returns an array of manifests.

export default function () {
return [new Deployment(), new Service()];
}

Async Function

export default async function () {
return [new Deployment(), new Service()];
}

Iterable

Besides array, objects which implements the iterable protocol, such as Set, Map or generator functions, are also supported.

// Set
export default new Set([new Deployment(), new Service()]);

// Generator function
function* gen() {
yield new Deployment();
yield new Service();
}

export default gen();

Async Iterable

// Async generator function
async function* gen() {
yield new Deployment();
yield new Service();
}

export default gen();

Nested Manifests

info

Available since v1.0.0.

All of the patterns we just mentioned above can be combined together. It is very useful for reusing manifests across components.

For example, we can create a function that returns a database as a resource, and use it later in components.

import { Deployment } from "kubernetes-models/apps/v1/Deployment";
import { Service } from "kubernetes-models/v1/Service";

function createDatabase(name: string) {
const metadata = { name: `${name}-db` };
return [new Deployment({ metadata }), new Service({ metadata })];
}

export default [
createDatabase("my-app"),
new Deployment({ metadata: { name: "my-app" } }),
new Service({ metadata: { name: "my-app" } })
];

All manifests in arrays and functions will be flattened. Below is YAML output.

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-db
---
apiVersion: v1
kind: Service
metadata:
name: my-app-db
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
---
apiVersion: v1
kind: Service
metadata:
name: my-app