kude

module
v0.0.1-beta07 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2022 License: Apache-2.0

README ΒΆ

kude

Maintainer GoVersion GoDoc GoReportCard codecov

Kude (Kubernetes Deployment) is a tool for deploying Kubernetes applications. It stands on the shoulders of giants such as kustomize, kpt and helm, but unifies them to one coherent model, while drawing the best features into one cohesive tool.

πŸ‘‰ Yeah yeah, just take me to an example, I can figure it out!

Kude is built as a pipeline, which starts by reading a set of resources, processing them by invoking a chain of functions (more on that below), and producing an output of resources; those can be the same resources, usually enriched in some way, and potentially new resources as well.

Each such "pipeline" is called a Kude Package - basically a directory with a kude.yaml file that describes the process and optionally an additional set of Kubernetes manifests used by that pipeline. Kude packages can also include external resources - local or remote. Those resources (referred to in the kude.yaml file) can be simple Kubernetes manifests, Helm charts, or even other Kude packages. All of those can be either local or remote.

The pipeline functions are where the magic happens - each function receives the set of resources read so far, and is responsible for doing some kind of manipulation - either enriching them, or producing new ones. The function's output will be provided as input to the next function, and so forth. What makes Kude so extensible is the fact that each function is a Docker image! This allows anyone to write Kude functions using any tool, language or method one wants!

High level features
  • Package inheritance & composition
    • Similar to Kustomize's overlay concept
    • Supports:
      • Local files
      • Git repositories
      • Remote directory/file URLs
      • Other Kude packages (local & remote)
      • More!
  • Name hashes for ConfigMap and Secret resources
    • This is a useful feature introduced in kustomize, where the name of a ConfigMap or Secret is suffixed with a hash (computed from its contents). Other resources referencing that ConfigMap or Secret are updaed to correctly reference the hashed-name.
    • By doing this, whenever the contents of such ConfigMap or Secret are changed, their hash suffix (and hence their name) would change as well, resulting in a reload of the dependent pods.
  • Extensible!
    • Kude packages are a pipeline of functions
    • Each function is just a Docker image adhering to a very (very!) simple contract (see below)
    • You can use any Kude function you want, and you can even write your own!
  • Team player!
    • Can work with existing technologies such as Helm, Kustomize (coming soon!) and Kpt (coming soon!)
    • Works with kubectl easily - just run kude | kubectl apply -f - to deploy!
  • Growing functions catalog

Status

This is currently alpha, with some features still in development, and not full test coverage. We're on it! πŸ’ͺ

Example

Given this directory structure:

└── my-kude-package
    β”œβ”€β”€ kude.yaml
    β”œβ”€β”€ deployment.yaml
    └── service.yaml

The kude.yaml contains:

apiVersion: kude.kfirs.com/v1alpha2
kind: Pipeline
resources:
  # Define two local input resources:
  - deployment.yaml
  - service.yaml
steps:
  # Define just one function to process resources
  # It will add an annotation to each resource
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: purpose
      value: kude-example

The deployment.yaml contains:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: super-microservice
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: super-microservice
  template:
    metadata:
      labels:
        app.kubernetes.io/name: super-microservice
    spec:
      containers:
        - image: "examples/super-microservice:v1"
          name: microservice
          ports:
            - containerPort: 8080

The service.yaml contains:

apiVersion: v1
kind: Service
metadata:
  name: super-microservice
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app.kubernetes.io/name: test

Run kude to generate the following resources:

/home/test/my-kude-package: $ kude build

Expect the following output (notice the annotations for each resource):

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    purpose: kude-example # <-- ANNOTATED!
  name: super-microservice
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: super-microservice
  template:
    metadata:
      labels:
        app.kubernetes.io/name: super-microservice
    spec:
      containers:
        - image: "examples/super-microservice:v1"
          name: microservice
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    purpose: kude-example # <-- ANNOTATED!
  name: super-microservice
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080
  selector:
    app.kubernetes.io/name: test

Configuration

Targeting

Often in a pipeline, you would want a function to only apply its effects to a subset of the resources. For example, to add an Ingress annotation only to Ingress objects. This can be done like so:

apiVersion: kude.kfirs.com/v1alpha2
kind: Pipeline
resources:
  ...
steps:
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: foo1
      value: bar1
      includes:
        - apiVersion: v1 # <-- only apply to objects in this API group
          kind: Secret  # <-- and only apply to objects of type Secret
      excludes:
        - name: guarded-secret # <-- but do not annotate any object named "guarded-secret" 
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: foo2
      value: bar2
      includes:
        - apiVersion: v1 # <-- only apply to objects in this API group
          kind: Secret  # <-- and only apply to objects of type Secret
          name: my-secret # <-- and only apply to objects with this name 
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: foo3
      value: bar3
      includes:
        - apiVersion: v1 # <-- only apply to objects in this API group
          kind: Secret  # <-- and only apply to objects of type Secret
          name: my-secret # <-- and only apply to objects with this name 
          namespace: my-namespace # <-- and only in this namespace
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: foo4
      value: bar4
      includes:
        - apiVersion: v1 # <-- only apply to objects in this API group
          kind: Secret  # <-- and only apply to objects of type Secret
          name: my-secret # <-- and only apply to objects with this name 
          namespace: my-namespace # <-- and only in this namespace
          labelSelector: app=my-app # <-- and only to objects with label 'app' equaling 'my-app'

Each one of the properties in the includes array is optional, but at least one of them must be specified. The format for the excludes array is the same as for includes, and also requires at least one of the properties to be specified.

Targeting will only match objects that match at least one of the filters in the includes array, and do not match any of the filters in the excludes array. If the includes array is empty, all objects will be matched (but the excludes array will still be applied). If the excludes array is empty, only objects in the includes array will be matched (or all, if the includes array is empty as well).

Mounting local files

Some function configuration values might need to come from local files, rather than hard-coded into the pipelines. This can be useful for reusing the same values across multiple functions or even multiple packages, as well as for providing secrets.

Luckily Kude makes this super easy! Here's how:

apiVersion: kude.kfirs.com/v1alpha2
kind: Pipeline
resources:
  ...
steps:
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: purpose1
      path: purpose.txt
    mounts:
      - purpose.txt # <-- local file called "purpose.txt" will be mounted to the function as "/workspace/purpose.txt"
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: purpose2
      path: a-file
    mounts:
      - purpose.txt:a-file # <-- local file called "purpose.txt" will be mounted to the function as "/workspace/a-file"
  - image: ghcr.io/arikkfir/kude/functions/annotate
    config:
      name: purpose3
      path: /tmp/my-file
    mounts:
      - purpose.txt:/tmp/my-file # <-- local file called "purpose.txt" will be mounted to the function as "/tmp/my-file"

Kude Functions

The following functions are available:

  • annotate - Annotate Kubernetes resources with metadata
  • create-configmap - Generate a Kubernetes ConfigMap
  • create-namespace - Generate a Kubernetes namespace
  • create-secret - Generate a Kubernetes Secret
  • helm - Invoke Helm for any purpose (mainly used for helm template ... command)
  • label - Label Kubernetes resources
  • set-namespace - Set namespace for resources.
  • yq - Patch resources using yq

Writing Kude Functions

Until we document this, please see the functions source code.

Contributing

We welcome any contributions from the community - help us out! Have a look at our contribution guide for more information on how to get started on sending your first PR.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL