Skip to content
Snippets Groups Projects
Commit fcfac85c authored by Jessica Yao's avatar Jessica Yao
Browse files

concept reference docs

parent 7223254e
No related branches found
No related tags found
No related merge requests found
## Concepts
# Concept Reference
The ksonnet framework is centered around a couple of key concepts.
The ksonnet framework is centered around a couple of key concepts and terms. This reference gives a brief explanation of each. To get a more tangible sense of how these concepts tie together, see the Tutorial (WIP, link pending).
* Ksonnet
* [Application](#application)
* [Environment](#environment)
* [Component](#component)
* [Prototype](#prototype)
* [Parameter](#parameter)
* [Part](#part)
* [Package](#package)
* [Registry](#registry)
* Related
* [Manifest](#manifest)
* [Jsonnet](#jsonnet)
The following diagram shows how the ksonnet framework works holistically:
![ksonnet overview diagram](/docs/img/ksonnet_overview.svg)
---
### Application
TODO
A ksonnet application represents a well-structured directory of Kubernetes [manifests](#manifests). This directory is autogenerated by [`ksonnet init`](docs/cli-reference/ksonnet_init.md). These manifests typically tie together in some way—for example, they might collectively define a web service like the following:
<p align="center">
<img alt="ksonnet application diagram" src="/docs/img/guestbook_app.svg" height="250px">
</p>
---
### Environment
TODO
An environment consists of four elements, some of which can be pulled from your current [kubeconfig context](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#context):
| What | Example | Description | How is this tracked? |
| ---------- | ------------- | ------------- | ---------- |
| (1) *Name* | dev | A string used to identify a particular environment. Must be unique within a ksonnet app. | A directory under `environments/` (e.g. `environments/dev/`). <br><br>**A name with slashes results in a hierarchical file structure**. For example, `us-west/staging` creates `environments/us-west/staging/`.|
| (2) *Server* | https://cluster-name-with-hash.us-west-2.elb.amazonaws.com | The address and port of a Kubernetes API server. In other words, identifies a unique cluster. | Inside `environments/<env-name>/spec.json` |
| (3) *Namespace* | dev | Specifically, a [Kubernetes namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/). | Inside `environments/<env-name>/spec.json` |
| (4) *Kubernetes API version* | version:v1.7.1 | The version of your cluster's Kubernetes API server, defaults to v1.7.0. | Used to generate appropriate files in `environments/<env-name>/.metadata/` based on the specified version of the Kubernetes OpenAPI spec |
ksonnet allows you to deploy any particular *application* to **multiple** environments. Below is a visualization of two environments that represent different namespaces on the same cluster:
![ksonnet environment diagram](/docs/img/environment.svg)
If you're wondering why you might deploy a common set of manifests to different environments, here are some potential use cases:
* Release Management (*dev* vs *test* vs *prod*)
* Multi-AZ (*us-west-2* vs *us-east-1*)
* Multi-cloud (*AWS* vs *GCP* vs *Azure*)
---
### Component
TODO
A ksonnet *application* can be broken down into a series of discrete components:
<p align="center">
<img alt="ksonnet component diagram" src="/docs/img/component.svg" height="150px">
</p>
Components can be as simple as a single Kubernetes resource (e.g. a Deployment) or as complex as a complete logging stack (e.g. EFK). More concretely, a component corresponds to a Kubernetes manifest in `components/`. There are two ways to add this manifest:
* Typically, **you autogenerate it** with the [`ks generate`](docs/cli-reference/ks_generate.md) command. In this case, the manifest is expressed in a language called [Jsonnet](#jsonnet).
* Alternatively, you can **manually drop in** a file. In this case, your manifest can be any one of YAML, JSON, or Jsonnet. Because all three languages are supported, this approach allows you to introduce ksonnet to existing codebases without significant rewrites.
How does the autogeneration process work? When you use `ks generate`, the component is generated from a *prototype*. The distinction between a component and a prototype is a bit subtle. If you are familiar with object oriented programming, you can roughly think of a prototype as a "class", and a component as its instantiation:
<p align="center">
<img alt="component class analogy" src="/docs/img/component_and_prototype.svg" height="180px">
</p>
All of the component files in an *app* can be deployed to a specified *environment* using [`ks apply`](docs/cli-reference/ks_apply.md).
---
### Prototype
TODO
Prototypes are often used as the basis for components; they are the reason that `ks generate` allows you to quickly move from a blank app to multiple complete manifests.
By itself, a prototype is a pre-written but incomplete manifest:
<p align="center">
<img alt="prototype diagram" src="/docs/img/prototype.svg" height="170px">
</p>
Why is this useful? Prototypes allow you to avoid copying and pasting boilerplate code, and to focus on the parts of your configuration that are specific to your app. Specifically, during `ks generate`, you can specify certain command-line *parameters* to "fill-in-the-blanks" of a prototype and output a complete manifest into the `components/` directory:
![prototype parameter component diagram](/docs/img/prototype_and_parameters.svg)
Out of the box, ksonnet comes with some system prototypes (like `io.ksonnet.pkg.deployment-exposed-with-service`) that you can explore with the various [`ks prototype`](docs/cli-reference/ks_prototype.md) commands. See [*package*](#package) for information on downloading or sharing additional prototypes.
---
### Parameter
TODO
Parameters allow you to customize your prototypes—both at the time of their creation, and after the fact. You can use the various [`ks param`](docs/cli-reference/ks_param.md) commands to view or modify current parameters. Params can be set globally or per-environment.
Under the hood, the `ks param` commands update a couple of local [*Jsonnet*](#jsonnet) files, so that you always have a version-controllable representation of what you `ks apply` onto your Kubernetes cluster. These are structured as follows:
* **App params** (`components/params.libsonnet`) — treated like defaults
* (Optional) **Global params**
* Manually specified by editing the Jsonnet
* Used to make a variable accessible to multiple components (e.g. if the number of Redis and nginx replicas are related)
* **Component-specific params**
* e.g. 80 for `deployment-example.port`
* Populated from `ks generate`
* **Per-environment params** (`environments/<env-name>/params.libsonnet`) — override app params, similar to inheritance
* **Component-specific params** only
For example, you can use params to ensure that you have 3 Redis replicas in your *prod* environment and 1 in *dev*, because prod needs to handle higher traffic.
---
### Part
TODO
Prototypes often come in sets, where each prototype offers a slightly different "flavor" of a common base (e.g. `redis-persistent` and `redis-stateless` are two possible ways of deploying a Redis datastore).
Given that ksonnet is designed around modularity, a common pattern is to refactor most of the shared prototype code into a single *parts* library. This might look something like the following:
```
{
parts:: {
deployment:: {
persistent(...)::
...,
nonPersistent(...)::
...,
base(...)::
...,
},
networkPolicy:: {
allowExternal(...)::
...,
denyExternal(...)::
...,
},
...
}
}
```
Once a library like this is established, different parts like `redis.parts.deployment.persistent` can be mixed and matched to produce new prototypes. Intuitively, this looks a bit like the following:
![parts diagram](/docs/img/parts.svg)
*NOTE: Parts do not have to be 1:1 with Kubernetes API resources like Deployments. This is just a relatively intuitive way to organize them.*
Prototypes that are distributed via ksonnet *packages* typically adhere to the pattern described above.
---
### Package
TODO
A package contains:
* **A set of related *prototypes*** (e.g. `redis-persistent`, `redis-stateless`)
* **Associated helper libraries** that define the prototype *parts* (e.g. `redis.libsonnet`)
Packages allow you to easily distribute and reuse code in any ksonnet *application*, using the various [`ks pkg`](docs/cli-reference/ks_pkg.md) commands. The CLI writes package code into the `vendor/` directory.
To be recognized and imported by ksonnet, packages need to follow a specific schema. See the annotated file tree below, as an example:
```
.
├── README.md // Human-readable description of the package
├── parts.yaml // Provides metadata about the package
├── prototypes // Can be imported and used to generate components
│ ├── redis-all-features.jsonnet
│ ├── redis-persistent.jsonnet
│ └── redis-stateless.jsonnet
└── redis.libsonnet // Helper library, includes prototype parts
```
`parts.yaml` metadata is used to populate the output of the [`ks prototype describe`](docs/cli-reference/ks_prototype_describe.md) command. The official packages in [`ksonnet/parts/incubator`](https://github.com/ksonnet/parts/tree/master/incubator) also use `parts.yaml` to autogenerate `README.md` documentation.
You can take a look at the [nginx](https://github.com/ksonnet/parts/tree/master/incubator/nginx) and [Redis](https://github.com/ksonnet/parts/tree/master/incubator/redis) packages as additional examples.
---
### Registry
TODO
Registries are essentially repositories for *packages*. (We mean registry here in the same sense that there are registries for container images). Registries are identified by a `registry.yaml` in their root that declares a list of packages.
The ability to add new registries is under development. In the meantime, ksonnet allows you do download *packages* from the [`ksonnet/parts/incubator`](https://github.com/ksonnet/parts/tree/master/incubator) registry.
Use the various [`ks registry`](docs/cli-reference/ks_registry.md) commands to see what packages are available.
---
### Manifest
When you’re trying to run code on a Kubernetes cluster, there’s a relatively clean separation between:
* "What you run" (your code, containerized in an image)
* "How you run it" (YAML or JSON manifests)
The "how"—your YAML and JSON manifests—declare the API resources that your code uses to actually run ON Kubernetes. Example resources include Pods and Deployments.
One of ksonnet's key features is that it allows you to write more concise manifests, using a language called *Jsonnet*.
---
### Jsonnet
ksonnet uses [Jsonnet](http://jsonnet.org/) to express all of your `components/` manifests (and associated configuration files, like `components/params.libsonnet`).
Jsonnet is a data templating language—for simplicity, think of it as a fancier version of JSON, one that supports features like [variables](http://jsonnet.org/docs/tutorial.html#locals) and [object concatenation](http://jsonnet.org/docs/tutorial.html#oo). If you've ever had to copy and paste large chunks of YAML or JSON manifests, Jsonnet avoids this problem!
You can see how much more concise it is by comparing the same manifest, written in two different languages:
![jsonnet vs yaml](/docs/img/jsonnet_vs_yaml.png)
(Note that we've omitted Jsonnet's `import` lines in this example).
Jsonnet is also JSON-compatible, meaning that you can drop parts of your legacy manifests into your ksonnet manifests, without having to rewrite them all at once.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
docs/img/jsonnet_vs_yaml.png

69.2 KiB

This diff is collapsed.
kubecfg @ 2169ce8b
Subproject commit 2169ce8baf09ef5403f4d5e6eb0e4f1c65df88a9
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment