The kubit operator is a Kubernetes controller that can render and apply jsonnet templates based on the kubecfg jsonnet tooling/framework.
kubit aims to decouple of the persona of who builds a package vs who installs it.
In the current landscape, the choice of the templating engine is heavily influenced by what is the current tool your users are more comfortable with.
For example, if you think your users are going to prefer using helm to install the package, you're likely to pick helm as your templating language.
But it doesn't have to be this way. What if the tool used to install the package is decoupled from the the choice of the tool used to build the package?
By using kubit as the package installation method, the choice of helm, kustomize, or anything else becomes obselete as it installs packages from generic OCI bundles, a simple tarball containing manifests detailing how to install the package.
This means that the installation experience is decoupled from the language of choice for packaging the application, it is simply handed to kubit and abstracted away, performing the necessary installation steps.
kubectl apply -k 'https://github.com/kubecfg/kubit//kustomize/global?ref=v0.0.22'The Kubernetes controller is the main way to use kubit.
(popular on macos, but also available on linux)
brew install kubecfg/kubit/kubitDirect install from sources:
cargo install --git https://github.com/kubecfg/kubit/ --tag v0.0.22The CLI is an optional tool that provides helpers and alternative ways to install and inspect packages.
- Install the kubit operator once
- Apply a CR that references a package OCI artifact
Example foo.yaml CR:
apiVersion: kubecfg.dev/v1alpha1
kind: AppInstance
metadata:
name: foo
namespace: myns
spec:
package:
image: ghcr.io/kubecfg/demo:v0.1.0
apiVersion: demo/v1alpha1
spec:
bar: bazSuch a CR can be applied using standard Kubernetes tooling such as kubectl, or ArgoCD:
kubectl apply -f foo.yamlThe controller will continuously attempt to reconcile the desired state of the application instance
and update the outcome of the reconciliation in the status field of the AppInstance custom resource.
You can observe the status field of the AppInstance resource using standard Kubernetes tooling such as:
kubectl get -f foo.yaml -o json | jq .statusTIP: render logs in more readable format with:
kubectl get -f foo.yaml -o json | jq -r '.status.lastLogs|to_entries[] | "\(.key): \(.value)"'The kubecfg pack command can be used to take a jsonnet file and all its dependencies and push them
all together as a bundle into an OCI artifact.
kubecfg pack ghcr.io/kubecfg/demo:v0.1.0 demo.jsonnetYou can run the same logic that the kubit controller does when rendering and applying a template by running
the kubit CLI tool from your laptop:
kubit local apply foo.yamlkubit is just a relatively thin wrapper on top of kubecfg.
For increased compatibility, it uses the kubectl apply operation to apply the manifests using more standard
tooling, rather than the kubecfg integrated Kubernetes API.
You can preview the actual commands that kubit will run with:
kubit local apply foo.yaml --dry-run=scriptOther interesting options are --dry-run=render and --dry-run=diff which will respectively just render the YAML without applying it
and rendering + diffing the manifests against a running application. This can be useful to preview effects of changes in the spec or
between versions of a package.
If you do not wish to install later versions of kubectl and kubecfg onto your system, you can specify the --docker flag to have the
dependencies run as Docker containers instead.
Sometimes you'd like to try out some jsonnet code before you package it up and publish to your OCI registry:
kubit local apply foo.yaml --dry-run=diff --package-image file://$HOME/my-project/my-main.jsonnetBy default kubit runs in its own kubit namespace. This is not always desired, so kubit also supports running in a specified namespace.
This has a few advantages:
kubitonly requires aRoleandRoleBindingwhen running in a single namespace and does not require theCRD- In companies/environments where namespaces are limited,
kubitcan run alongside the app without needing a second namespace
To use kubit in single namespace mode, install the single-namespace flavor of the kustomize package into a specific namespace:
kubectl apply -k 'https://github.com/kubecfg/kubit//kustomize/single-namespace?ref=v0.0.22' -n <my-application-namespace>
This instance of kubit is then configured by creating a ConfigMap named app-instance with the data field containing a key app-instance with the yaml
version of the AppInstance.
Example for how to create this ConfigMap:
kubectl create configmap -n mycoolapp app-instance --from-file=app-instance=example-kubit-testing.yaml
Create Kubernetes resources:
kubectl apply -k ./kustomize/localThe manifests in ./kustomize/local are like ./kustomize/global but don't spawn the kubit controller.
Build and run the controller locally:
cargo run -- --as system:serviceaccount:kubit:kubitIf you already installed kubit (e.g. with kubectl apply -k ./kustomize/global) in your test cluster but you still want to quickly run the locally built kubit controller without uninstalling the in-cluster controller you can pause an appinstance and run the local controller with --only-paused:
kubectl patch -f foo.yaml --patch '{"spec":{"pause": true}}' --type mergeThen you can run the controller locally and have it process only the resource you paused:
cargo run -- --as system:serviceaccount:kubit:kubit --only-pausedTo unpause the resource:
kubectl patch -f foo.yaml --patch '{"spec":{"pause": false}}' --type merge