Concepts

Flights

Overview

Flights in Yoke are analogous to Charts in Helm. A Chart is a collection of templates packaged as one referencable entity. Similarly, in Yoke, Flights refer to both the code that describes Kubernetes resources and the packaged WebAssembly (wasm) asset representing the executable.

At its core, a Flight is a piece of software that generates Kubernetes resources. In that way, even a Helm Chart is a subset of Flights (Refer to Helm Compatibility for more information). This allows us to view Flights at two levels: High and Low Altitude Flights (High-Level vs Low-Level).

High-Altitude Flights

High-Level Flights are the programs / runtimes / compiled wasm executables that generate the Kubernetes Package Instance for deployment.

Low-Altitude Flights

Low-Level Flights are the building blocks of the software. These are most likely represented as functions that take inputs and return Kubernetes resources. They can be shared via their language's ecosystems: npm, go modules, cargo, gems, and so on.

Flight Dependencies

Flights are programs that output a list or arbitrary kubernetes resources to be applied as a singular release. There are two types of resources that are not considered to be part of the release but dependencies of the release: Namespaces and Custom Resource Definitions.

When your flight contains a custom resource, it can be useful to specify the custom resource defintion to ensure that the cluster will be able to accept your resource. This is more practical than doing it in two staged releases, the prior where we install dependencies, and the latter where we install our desired resources.

However this poses problems:

To solve these issues, yoke considers Namespaces and CRDs to be dependencies of the Flight, and does not consider them part of the Flight's resources to be tracked in the revision history. By default, no action is performed and dependencies are simply ignored. When running the takeoff command, we can specify which dependencies we want to apply via the --create-namespaces and --create-crds flags.

yoke takeoff --create-namespaces --create-crds foo example.wasm.gz

Why Wasm?

Yoke's goal is to enable software engineers to write packages for Kubernetes as code. The issue is that code is not easy to package, and code itself is useless without its runtime or compiler. Yoke would need to be able to get the appropriate runtime or compiler for any language, and moreover, it would need to get those dependencies compiled for the correct architecture and OS as where Yoke is running. This would be an enormous task.

This leaves us with two options: either accept arbitrary input as packages or find a common target that many languages support. Yoke chooses both options.

Arbitrary Input

The former allows us to support any runtime, even those that do not compile to wasm. This allows us to write Flights in our beloved dynamic languages:

# Deploy a Flight defined in Python
python3 app.py | yoke takeoff my-release

# Or in Javascript
node app.js | yoke takeoff my-release

# Or in Ruby
ruby app.rb | yoke takeoff my-release

# Or directly from a file
yoke takeoff my-release < resources.yaml

However, it comes with serious drawbacks:

Using Wasm

With wasm, we can solve all our problems, including the two mentioned above:

Wasm being sandboxed is a big deal for us. It eliminates side-effects such as IO and makes our programs predictable. It buys us a measure of security too, given that should a supply chain attack happen in the dependencies of your programs, an attacker would not have direct access to your filesystem, the network, or ultimately your K8s cluster.

Example:

GOOS=wasip1 GOARCH=wasm go build -o main.wasm ./my-flight
yoke takeoff my-release ./main.wasm