By Heptio, Inc., 2017
kube.libsonnet
provides a simple alternative to writing
complex YAML for your Kubernetes configurations. It accomplishes
this goal by using the data templating language
Jsonnet to write against the
Kubernetes application API. This approach also makes it
easy to extend your configuration as your application scales up.
Other projects, such as Kompose,
OpenCompose, and compose2kube, simplify
the process of writing a Kubernetes configuration by creating a simpler
API that maps to the Kubernetes API. kube.libsonnet
instead simplifies
the work required to build and customize the Kubernetes API objects
themselves. This approach results in concise, modular configurations,
without losing any of the options and features of the original
Kubernetes API.
First, you need Jsonnet:
brew install jsonnet
Then, fork or clone this repository, and add the appropriate import statements for the library to your Jsonnet code. For example (from the tutorial):
local core = import "../../kube/core.libsonnet";
local kubeUtil = import "../../kube/util.libsonnet";
Let's start by converting the Kubernetes
nginx hello world tutorial to use kube.libsonnet
.
Here is the original YAML:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
And here is the equivalent implementation in Jsonnet with
kube.libsonnet
(see also source):
// hello.jsonnet; imports omitted
{
local nginxContainer =
container.Default("nginx", "nginx:1.7.9") +
container.NamedPort("http", 80),
"deployment.json": deployment.FromContainer("nginx-deployment", 2, nginxContainer),
}
Using the Jsonnet command line, we can easily generate a
deployment.json
file from the above, which can then be sent to the
cluster directly by kubectl
:
$ jsonnet hello.jsonnet -m . # Generates `deployment.json`.
$ kubectl create -f deployment.json # Dispatch to run on cluster.
This is nice, but sometimes the default Deployment
object is not
precisely what you want.
A core goal of kube.libsonnet
is to maintain the flexibility and
expressiveness of the original Kubernetes API objects. To give you
some idea of how easy it is to modify these objects, let's
change the deployment specification to use a rolling update strategy
and a custom selector (see also source). We use
kube.libsonnet
's mixins to make the changes.
// hello.jsonnet; imports omitted
{
local nginxContainer =
container.Default("nginx", "nginx:1.7.9") +
container.NamedPort("http", 80),
"deployment.json":
deployment.FromContainer("nginx-deployment", 2, nginxContainer) +
deployment.mixin.spec.RollingUpdateStrategy() +
deployment.mixin.spec.Selector({ "app": "nginx" }),
}
Here we customize the strategy
and selector
fields, but we
can use this method to customize any field in the Kubernetes-standard
Deployment Spec API object. In fact, as
the tutorial demonstrates, all kube.libsonnet
objects are customizable.
If you look at the generated YAML, you can see the customized API objects.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
strategy:
rollingUpdate:
maxSurge: 1,
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
See also the following resources:
- Tutorial. A more in-depth tutorial that explains the
core abstractions and tools exposed by
kube.libsonnet
. - gitlab.jsonnet and
gitlab.libsonnet. A real-world example
of a Kubernetes configuration written with
kube.libsonent
. The first file is the main entry point for Jsonnet. It compiles GitLab's deployments, services, etc., to JSON so thatkubectl
can pick them up. The second file contains the logic that defines each component. - Design document, (highly incomplete) Explains the goals and rationale behind the core design decisions.