Lambda-kube is a Clojure library for building inputs for Kubernetes.
Add lambdakube as a dependency to your project.clj
, and
(preferably), lein-auto as
a plugin.
:require
the namespace:
(:require [lambdakube.core :as lk]
[lambdakube.util :as lku]
[clojure.java.io :as io])
Define a module function, defining the different parts of the system.
;; A module function takes an injector ($) as parameter, and adds rules to it.
(defn module [$]
(-> $
;; A rule defines a resource (:frontend) and dependencies ([:num-fe-replicas]).
(lk/rule :frontend [:backend-master :backend-slave :num-fe-replicas]
(fn [master slave num-replicas]
;; We start with an empty pod.
(-> (lk/pod :frontend {:app :guesbook
:tier :frontend})
;; We add a container, specifying a name, image and environments.
(lk/add-container :php-redis "gcr.io/google-samples/gb-frontend:v4"
(lk/add-env {} {:GET_HOST_FROM :env
:REDIS_MASTER_SERVICE_HOST (:hostname master)
:REDIS_SLAVE_SERVICE_HOST (:hostname slave)}))
;; We load three files from resources and mount them to the container
(lk/add-files-to-container :php-redis :new-gb-fe-files "/var/www/html"
(map-resources ["index.html" "controllers.js" "guestbook.php"]))
;; Wait for the master and slave to come up
(lku/wait-for-service-port master :redis)
(lku/wait-for-service-port slave :redis)
;; Then we wrap the pod with a deployment, specifying the number of replicas.
(lk/deployment num-replicas)
;; Finally, we expose port 80 using a NodePort service.
(lk/expose-cluster-ip :frontend (lk/port :php-redis :web 80 80)))))))
Define configuration.
(def config
{:num-fe-replicas 3})
Define a -main
function.
(defn -main []
(-> (lk/injector)
module
lk/standard-descs
(lk/get-deployable config)
lk/to-yaml
(lk/kube-apply (io/file "guestbook.yaml"))))
Run it:
$ lein auto run
It will create a YAML file (my-app.yaml
) and call kubectl apply
on
it. Then it will remain to watch your source files for changes, and
when changed, will re-apply automatically.
A complete example can be found here.
Kubernetes is great. With Kubernetes, the imperative notion of installing software becomes a thing of the past, while the declarative notion of describing how software is to be installed becomes the way it is done. A declarative definition allows us, developers, to specify just how we want our software installed, and to have it under source control, so that we can install it once and again, exactly the same way.
To allow us to do so, Kubernetes defines a declarative language -- a language of API Objects. Today, these API objects are either written by hands, typically in YAML format, or rendered using Go templates that come as part of a Helm chart.
While the language provided by Kubernetes exposes its entire API, providing developers access to all its wealth, this language does not provide one important thing -- abstraction.
In programming languages, abstraction mechanisms allow developers define new concepts, and then use them (and reuse them) in different contexts. Functions, for example, provide a powerful abstraction mechanism in which some computation is given a name, allowing it to be reused in different contexts, with different parameters.
Kubernetes allows us to define objects such as Pods, Deployments and ConfigMaps. These are the building blocks provided by Kubernetes. But it doesn't give you a mechanism to create your own blocks. This is Lambda-Kube comes into the picture.
Lambda-Kube is a Clojure library. It contains functions, most of which are purely-functional (have no side-effects). These functions allow developers to build objects in the Kubernetes object language. These objects can then be handed to Kubernetes, to turn them into a running system.
Clojure is very good in making functions, and especially pure functions, compose. Unlike the Kubernetes object language, in which object definitions are often big, allowing many options, Lambda-Kube functions are designed to be simple, but are designed to compose well, following the Unix Philosophy.
Lambda-Kube provides a collection of functions that represent the major Kubernetes objects and some patterns regarding them, but users are encouraged to extend this library with their own functions, adding functionality Lambda-Kube does not address.
Well, yes and no.
No, because Helm is considered a "package manager for Kubernetes", while Lambda-Kube is a library for building Kubernetes objects. However, by generating Kubernetes objects, Lambda-Kube provides an alternative to Helm's use of Go templates. Here is why we believe this alternative is better.
Additionally, it allows users to write reusable Clojure libraries that describe the deployment of services. As such, they can play the role charts play in Helm. Clojure already has a few good package managers (e.g., Leiningen and Boot), which can install such libraries on demand. This makes them (and not Lambda-Kube itself), Helm-replacements.
Lambda-Kube is a Clojure library. Its core namespace contains three families of functions:
In addition, it has a utility namespace, which provides functions for common patters, and a testing framework, which facilitates the definition of integration tests.
Lambda-Kube takes follows a few best practices made to make the systems you build with it maintainable.
Lambda-Kube does not aspire to:
lein auto run
.Copyright © 2018 Boaz Rosenan
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation? These fine people already did:
Boaz Rosenan & Christian GruberEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close