Rekube
Rekube is a toolkit for Kubernetes configuration management.
The main components of the project are:
- Kubernetes API: The entire Kubernetes API is exposed as a ReasonML library.
- Configuration DSL: A custom PPX (preprocessor extension) can be used to write Kubernetes declarations using a JSON-like syntax with type annotations.
- YAML-to-Reason converter: A convenient CLI utility can be used to translate existing YAML files into typed ReasonML declarations.
Note: This project is currently unstable and unreleased.
Quickstart
To install rekube in an esy project, add the following dependency to your package.json
file:
"dependencies": {
"rekube": "github:rizo/rekube#a7c4d09"
}
If you are using opam, run: opam install
rekube
.
In your dune project add the following dependencies to your dune
file:
(executable
(name Infra)
(public_name gen-infra)
(libraries rekube console.lib)
(preprocess (pps rekube.ppx)))
Finally, describe your configuration in a file called Infra.re
and execute it to generate the raw JSON files.
$ esy gen-infra
Kubernetes API
The full API can be explored from the Rekube.Kubernetes
module.
Here are some popular APIs:
Rekube.Kubernetes.Definitions.Api.Core.V1
Rekube.Kubernetes.Definitions.Api.Apps.V1
Rekube.Kubernetes.Definitions.Api.Autoscaling.V1
Rekube.Kubernetes.Definitions.Apimachinery.Pkg.Api.Resource
Configuration DSL
Writing declarative configuration that represents an application is the main way to describe deployments and resources in Kubernetes. The standard format used for configuration in the Kubernetes ecosystem is YAML. Although it is a very terse and human-friendly format, it lacks compositional and validation properties that would help it scale for large clusters.
Avoiding unnecessary boilerplate and repetition is important for lowering maintenance effort in any non-trivial distributed system. The configuration DSL in rekube achieves exactly that by building directly on top of the official Kubernetes API and relying on excellent modularity and safety properties of ReasonML.
Example
Here is a small example of a node.js app defined using the rekube DSL:
open Kubernetes.Definitions.Api.Apps.V1;
open Kubernetes.Definitions.Api.Core.V1;
let name = "my-app";
let deployment = (~replicas=1, ~namespace) => {
let metadata = Meta {
"name": name,
"namespace": namespace,
"labels": [("app", name)]
};
Deployment {
"metadata": metadata,
"spec": Deployment_spec {
"replicas": replicas,
"template": Pod_template_spec {
"metadata": metadata,
"spec": Pod_spec {
"containers": [
Container {
"name": name,
"image": "gcr.io/hello-minikube-zero-install/hello-node",
"ports": [Port { "name": "app", "container_port": 8080 }],
"resources": Resources {
"requests": [("cpu", "100m"), ("memory", "500Mi")],
"limits": [("cpu", "500m"), ("memory", "1Gi")]
},
}
]
}
}
}
}
}
The deployment object is defined as a function that accepts a namespace and the number of replicas. It can be instantiated multiple times and used, for example, in different Kubernetes clusters.
Syntax Extension
The PPX (preprocessor extension) works by translating all expressions that start with a constructor and are followed by a JSON object to function calls in the Kubernetes API. The following example describes the mapping:
Object {"key1": value1, "key2": value2}
==>
Object.make(~key1=value1, ~key2=value2)()
Note: The extra ()
is needed to avoid partial application of the labeled arguments with default values.
The full power of ReasonML can be used in this configuration. Variables can be declared, common definitions can be grouped into modules, standard library functions can be used, etc.
Troubleshooting
Here is a list of common issues and suggested solutions:
Error: Unbound module Foo
– this indicates that after the translation, the moduleFoo
in the function applicationFoo.make
could not be found. Make sure the module is accessible in the current scope.Error: Unbound constructor Foo
– this might happen if you are using unquoted object keys (e.g.Foo { x: 42 }
). The syntax extension will only work with quoted keys.Error: Syntax error: '}' expected
– this might happen if you are mixing quoted and unquoted object keys (e.g.Foo { x: 42, "y": 2 }
). The syntax extension will only work with quoted keys.Error: The function applied to this argument has type ?foo:t -> x. This argument cannot be applied with label ~bar
– the key "bar" does not belong to the object. The mentioned type will list all available keys.Error: Object literal without annotation
– configuration objects require a module annotation. Without the annotation the syntax translation will not work.Error: This expression has type foo:string -> X.t but an expression was expected of type X.t
– This type error indicates that theX.make
was not fully applied. You need to provide the value for the required keyfoo
.
YAML-to-Reason converter
To facilitate the transition from existing Kubernetes configuration, rekube provides a CLI tool called rekube-conv
that will convert any valid YAML manifest file to the ReasonML configuration DSL described above. As part of this process it will validate and infer the types of all the objects.
$ esy rekube-conv my-deployment.yaml