Skip to content

Commit

Permalink
inits MkDocs
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Hausenblas <hausenbl@amazon.com>
  • Loading branch information
mhausenblas committed Feb 21, 2020
1 parent 7a3c5a5 commit 9eddb46
Show file tree
Hide file tree
Showing 14 changed files with 333 additions and 0 deletions.
58 changes: 58 additions & 0 deletions docs/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
In the following we discuss the UX concepts of `kubed-sh` and review its architecture.


## UX concepts

In `kubed-sh` we're using terms as follows:

- **Cluster**: a collection of Kubernetes control plane (master) and node (worker) [components](https://kubernetes.io/docs/concepts/overview/components/); can be local (`kind` for example) or remote such as an EKS cluster.
- **Context**: when working with [multiple clusters](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) the context helps to pinpoint where exactly operations happen. Technically, a context defines the execution target and is a tuple in the form of: `<name,cluster,authinfo,namespace>`
- **Environment**: a `kubed-sh`-specific concept describing the current set of resources you're operating on; it is part of a context. Note that environment is an extension of the (*nix local shell) concept of an environment into a set of clusters, located in exactly one Kubernetes namespace. For example, an environment has a list of environment variables and can be used for fine-grained execution control (scripting, project isolation).

### Environments

In `kubed-sh` you can always tell the execution target by looking at the prompt. The general format of the prompt is as follows:

```
[environment@context::namespace]
```

For example:

```
[example.com@kind::demo]
```

Above means you're currently in the `example.com` environment, using the `minikube` context with the `default` namespace.

Here are the rules:

- If no environment is explicitly created, the global environment is used. The prompt then changes to `[context::namespace]`. This is the default at startup.
- The context can be changed by issuing the built-in `use` command.
- The environment can be changed by issuing the built in `env` command.
- If the environment name (`$ENV`) is a FQDN and you launch a long-running (background) process called `theapp` then the resulting underlying service will be exposed to the outside world at `$ENV/theapp`.

### Launching programs

`kubed-sh` follows two simple rules that mimic the behaviour you're used to from a local shell:

1. If a launch command via a binary or a script with an interpreted environment (initially: support for Node.js, Python, and Ruby) ends with an `&`, this causes the creation of a deployment and a service (name equals the name of the binary or script); this is good for any long-running app, effectively executing in the background.
1. If the launch command doesn't end in an `&` then a pod is created; this is good for one-shot batch or interactive apps.

Further, `kubed-sh` supports environment variables to define and overwrite behavior such as the images used, exposed service port, runtime features like hot-reload, etc.


## Architecture

The system architecture of `kubed-sh` looks as follows:

![kubed-sh system architecture](img/kubed-sh-arch.png)

In a nutshell, `kubed-sh` uses `kubectl` to launch and control binaries and scripts for you. It is multi-cluster and context aware and supports some local commands (such as `cd`, `ls`, `cat`) as well as a number of cluster commands, for example `ps`, `kill` or `curl`.


First and foremost `kubed-sh` depends on `kubectl` for all cluster operations. That is, all remote operations in the cluster essentially cause shelling out to `kubectl`. You can see what `kubectl` commands `kubed-sh` executes when you execute the `debug` built-in command.

To provide the shell interaction we're using the REPL package [chzyer/readline](https://github.com/chzyer/readline), offering autocomplete, search (`CTRL+R`) and other standard operations such as `CTRL+L` for clearing the screen.

`kubed-sh` is stateless, meaning that any kind of state—such as environment membership, phases or app components—is entirely stored in Kubernetes, using labels and annotations.
27 changes: 27 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
!!! question "Question"
For whom is `kubed-sh`? When to use it?

!!! quote "Answer"
I suppose it's mainly useful in a prototyping, development, or testing phase, although for low-level interactions you might find it handy in prod environments as well since it provides an interactive, context-aware version of `kubectl`. See also [use cases](../usecases/).


!!! question "Question"
How is `kubed-sh` pronounced?

!!! quote "Answer"
Glad you asked. Well, I pronounce it /ku:bˈdæʃ/ as in 'kube dash' ;)

!!! question "Question"
Why another Kubernetes shell? There are already some, such as [cloudnativelabs/kube-shell](https://github.com/cloudnativelabs/kube-shell),
[errordeveloper/kubeplay](https://github.com/errordeveloper/kubeplay), and [c-bata/kube-prompt](https://github.com/c-bata/kube-prompt). Are they not cool or what?

!!! quote "Answer"
True, there is previous art, though these shells more or less aim at making `kubectl` interactive, exposing the commands such as `get` or `apply` to the user.

In a sense `kubed-sh` is more like [technosophos/kubeshell](https://github.com/technosophos/kubeshell), trying to provide an environment a typical *nix user is comfortable with. For example, rather than providing a `create` or `apply` command to run a program, the user would simply enter the name of the executable, as she would do, for example, in the bash shell. See also the [motivation](why.md).

!!! question "Question"
How does `kubed-sh` work?

!!! quote "Answer"
Good question. Essentially it's really just a glorified `kubectl` wrapper on steroids. See also the [architecture](../design/#architecture) section.
Binary file added docs/img/hotreload.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/introducing-kubed-sh.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/katacoda.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/kubed-sh-arch.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/launch-bin.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[![GitHub release](https://img.shields.io/github/release/mhausenblas/kubed-sh/all.svg)](https://github.com/mhausenblas/kubed-sh/releases/)
[![GitHub issues](https://img.shields.io/github/issues/mhausenblas/kubed-sh.svg)](https://github.com/mhausenblas/kubed-sh/issues)
[![Go Report Card](https://goreportcard.com/badge/github.com/mhausenblas/kubed-sh)](https://goreportcard.com/report/github.com/mhausenblas/kubed-sh)

Welcome to `kubed-sh`, the Kubernetes distributed shell for the casual cluster user. In a nutshell, `kubed-sh` lets you execute a program in a Kubernetes cluster without having to create a container image or learn new concepts. For example, let's say you have a Node.js script called [test.js](https://raw.githubusercontent.com/mhausenblas/kubed-sh/master/tc/node/test.js) and you want to launch it as a containerized app in your Kubernetes cluster, here's what you'd need to do in `kubed-sh`:

```
[minikube::default]$ node test.js &
[minikube::default]$ ps
DPID SOURCE URL
kubed-sh-1517679562543558000 test.js test
```

Looks familiar to what you do in your local shell? That's the point of `kubed-sh` :)

| [![Introducing kubed-sh](img/introducing-kubed-sh.png)](https://www.youtube.com/watch?v=gqi1-XLiq-o) | [![kubed-sh hot-reload feature demo](img/hotreload.png)](https://www.useloom.com/share/441a97fd48ae46da8d786194f93968f6) |
|:--------------------------------:|:------------------------------------------:|
| *Introducing kubed-sh (5 min)* | *kubed-sh hot-reload feature demo (3 min)* |

In addition to launching (Linux ELF) binaries directly, the following interpreted environments are currently supported:

- When you enter `node script.js`, a Node.js (default version: 12) environment is provided and `script.js` is executed.
- When you enter `python script.py`, a Python (default version: 3.6) environment is provided and the `script.py` is executed.
- When you enter `ruby script.rb`, a Ruby (default version: 2.5) environment is provided and the `script.rb` is executed.

Note that `kubed-sh` is a proper shell environment. This means you can expect features such as auto-complete of built-in commands, history operations (`CTRL+R`), or clearing the screen (`CTRL+L`) to work as per usual.
21 changes: 21 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
To use `kubed-sh` you must meet two prerequisites:

1. `kubectl` must be [installed](https://kubernetes.io/docs/tasks/tools/install-kubectl/), tested with client version up to and included `1.17`.
1. Access to a Kubernetes cluster must be configured, tested with up to `1.14`.

To verify your setup, you can use the following two steps:

- If you execute `ls ~/.kube/config > /dev/null && echo $?` and you see a `0` as a result, you're good, and further
- If you execute `kubectl config get-contexts | wc -l` and see a number greater than `0`, then that's super dope.

Now, download the [latest binary](https://github.com/mhausenblas/kubed-sh/releases/latest) for Linux and macOS.

For example, to install `kubed-sh` from binary on macOS you could do the following:

```sh
curl -L https://github.com/mhausenblas/kubed-sh/releases/latest/download/kubed-sh_darwin_amd64.tar.gz \
-o kubed-sh.tar.gz && \
tar xvzf kubed-sh.tar.gz kubed-sh && \
mv kubed-sh /usr/local/bin && \
rm kubed-sh*
```
30 changes: 30 additions & 0 deletions docs/motivation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
While Kubernetes is a very powerful, flexible, and extensible environment to run applications, it can also be quite overwhelming, especially for casual users. This effectively means there's a barrier to entry for developers.

Three issues motivated me to write `kubed-sh` in the first place: 1. the number of Kubernetes primitives one needs to learn in order to use it, 2. lack of
interactivity of existing tools, and 3. the need to build/push/pull container images.

You can read more about this topic in [As We May Kube](https://itnext.io/as-we-may-kube-293b30c0a365) or have a quick look here:


## Learning curve: primitives

Kubernetes introduces a number of [primitives](https://kubernetes.io/docs/concepts/) such as pods, deployments, and services. These form the building blocks for the applications you deploy and run. Now, without having at least a basic familiarity with the workloads, networking, and storage concepts it's hard to figure when to use what and how to combine things.

Some platforms, such as OpenShift, help here by hiding certain complex primitives and making it easier for the casual user, however oftentimes certain resource types, such as pods or services still are present and the user needs to be knowledgeable around them, nevertheless.

When coming from single-machine operating system such as Linux, you're already familiar with certain primitives such as processes, files, and job management in the shell. Put in other words, in order to execute a, say, Python script, you only need to know how to type `python thescript.py`, without studying Linux kernel structures first.


## Lack of interactivity

For many folks the go-to tool for interacting with a Kubernetes cluster on the command line to date is still `kubectl`. While there are [number of tools available](https://abhishek-tiwari.com/10-open-source-tools-for-highly-effective-kubernetes-sre-and-ops-teams/) that make your life easier, not many are interactive and/or offer a fully functional shell environment.


## Container image build drag

In order to launch an application, you first need a container image that Kubernetes in turn can run, then. There are multiple options to create a container image, from using a [CI/CD pipeline](https://fabric8.io/guide/cdelivery.html) to specialized build processes such as [S2I](https://docs.openshift.org/latest/architecture/core_concepts/builds_and_image_streams.html#source-build) to local builds and manual pushes. One can also use off-the-shelf images, launch them and then use tools like [Telepresence](https://www.telepresence.io/) or [ksync](https://vapor-ware.github.io/ksync/) to transfer the application code into the running container. In any case, one has to deal with images, directly and explicitly. Wouldn't it be nice if that task
is automagically done for you?




125 changes: 125 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
Once you've `kubed-sh` installed, launch it and you should find yourself in an interactive shell:

```sh
$ kubed-sh
Note: It seems you're running kubed-sh in a non-Linux environment (detected: darwin),
so make sure the binaries you launch are Linux binaries in ELF format.
Detected Kubernetes client in version v1.17.2 and server in version v1.14.9-eks-c0eccc
[user@somecluster.eu-west-1.eksctl.io::demo]$
```
Above, you notice that on start-up `kubed-sh` will tell you which client and server version of Kubernetes it has detected and at any point in time you are able to tell in which context (`user@somecluster.eu-west-1.eksctl.io` here) and namespace (`demo` here) you're operating.

### Built-in commands

Supported built-in commands (see also `help`) are as follows:

```
cat (local):
output content of file to terminal
cd (local):
change working directory
curl (cluster):
execute a curl operation in the cluster
contexts (local):
list available Kubernetes contexts (cluster, namespace, user tuples)
echo (local):
print a value or environment variable
env (local):
list all environment variables currently defined
exit (local):
leave shell
help (local):
list built-in commands; use help command for more details
kill (cluster):
stop a distributed process
literally (local):
execute what follows as a kubectl command
note that you can also prefix a line with ` to achieve the same
ls (local):
lists content of directory
ps (cluster):
list all distributed (long-running) processes in current context
pwd (local):
print current working directory
sleep (local):
sleep for specified time interval (NOP)
use (local):
select a certain context to work with
```
### Modes
You can use `kubed-sh` either interactively or in script mode. In script mode, you provide `kubed-sh` a script file to interpret or make it executable (for example using `chmod 755 thescript` along with a [hashbang](https://en.wikipedia.org/wiki/Shebang_(Unix)) header). The following example illustrates using `kubed-sh` in script mode:
Imagine you have a script file called `test.kbdsh` with the following content:
```
#!/usr/bin/env kubed-sh
use user@somecluster.eu-west-1.eksctl.io
# This line is a comment that will be ignored
node ../thescript.js &
ps
```
Then, you can make it executable and execute it like so:
```
$ chmod 755 test.kbdsh
$ ./test.kbdsh
```
Alternatively you can provide a script via `stdin`:
```
$ cat tc/script.kbdsh | kubed-sh
```
… or as a command line argument:
```
$ kubed-sh tc/script.kbdsh
```
Note that all three ways shown above are equivalent.
### Environments
`kubed-sh` supports environments and within it variables—akin to what your local shell (bash, zsh, fish) does. There are some pre-defined environment variables which influence the creation of the cluster processes you create by either specifying a binary or interpreter and script:
- `BINARY_IMAGE` (default: `alpine:3.7`) … used for executing binaries
- `NODE_IMAGE` (default: `node:12-alpine`) … used for executing Node.js scripts
- `PYTHON_IMAGE` (default: `python:3.6-alpine3.7`) … used for executing Python scripts
- `RUBY_IMAGE` (default: `ruby:2.5-alpine3.7`) … used for executing Ruby scripts
- `SERVICE_PORT` (default: `80`) … used to expose long-running processes within the cluster
- `SERVICE_NAME` (default: `""`) … used to overwrite the URL for long-running processes within the cluster
- `HOTRELOAD` (default: `false`) … used for enabling a watch on local files to trigger automatic updates on modification (EXPERIMENTAL)
!!! tip
You can overwrite at any time any of the above environment variables to change the runtime behavior of the cluster processes you create. All changes are valid for the runtime of `kubed-sh`. That is, when you quit `kubed-sh` all pre-defined environment variables are reset to their default values.
Useful for scripting and advanced users: with the 0.5 release there are now four sub-commands to `env` (which itself simply lists the defined variables):
- `env list` … list all defined environments in current context
- `env create ENVNAME` … create a new environment called `ENVNAME`
- `env select ENVNAME` … make environment called `ENVNAME` the active one
- `env delete ENVNAME` … delete environment called `ENVNAME`
If no environment is selected, you are operating in the global environment.
See also the [design](http://kubed.sh/design) as well as [Issue #6](https://github.com/mhausenblas/kubed-sh/issues/6) for what environments are and how to work with them. Note that when you do an `env delete ENVNAME`, this environment is reaped and goes back into the global.
### Configuration
The following environment variables, defined in the parent shell (such as bash), influence the runtime behavior of `kubed-sh`. On start-up, `kubed-sh` evaluates these environment variables and enables or changes its behavior:
| env var | default | set for |
| -------------------:| ------- | ------- |
| `KUBEDSH_DEBUG` | `false` | print detailed messages for debug purposes |
| `KUBEDSH_NOPREPULL` | `false` | disable image pre-pull |
| `KUBECTL_BINARY` | `which kubectl` is used to determine the binary | if set, rather than using auto-discovery, use this binary for `kubectl` commands |
!!! tip
If you are in an environment such as EKS on Fargate or OpenShift Online where you can't create a DaemonSet, then simply launch `kubed-sh` with `$ KUBEDSH_NOPREPULL=true kubed-sh`
7 changes: 7 additions & 0 deletions docs/usecases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
If you have access to a [Kubernetes](https://kubernetes.io/) cluster and you have [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) installed, you're good to go. You might want to consider using `kubed-sh`, for example for:

- **Prototyping**—Let's say you quickly want to try out a Python script or, in the context of microservices, see how a Go program and a Node.js script play together.
- **Developing**—Imagine you're developing a program in Ruby and want to launch it in a Kubernetes cluster, without having to build an image and pushing it to a registry. In this case, the experimental hot-reload feature (using `HOTRELOAD=true`) is useful for you. Whenever you save the file locally, it gets updated in the Kubernetes cluster, if hot-reload is enabled.
- **Learning Kubernetes**—You're new to Kubernetes and want to learn how to interact with it? Tip: if you issue the `debug` command you can see which `kubectl` commands `kubed-sh` launches in the background.

Also, you may be interested in [my motivation](../motivation) for writing `kubed-sh`?
39 changes: 39 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
site_name: kubed.sh
site_description: 'A cloud native shell for Kubernetes'
site_author: 'Michael Hausenblas'
repo_name: 'mhausenblas/kubed-sh'
repo_url: 'https://github.com/mhausenblas/kubed-sh'
copyright: 'Copyright &copy; 2020 Amazon'
nav:
- Home: index.md
- Use Cases: usecases.md
- Installation: install.md
- Usage: usage.md
- FAQ: faq.md
- Background:
- Motivation: motivation.md
- Design: design.md
theme:
name: 'material'
logo:
icon: 'launch'
font:
text: 'Lato'
code: 'PT Mono'
palette:
primary: 'orange'
accent: 'blue'
highlightjs: true
hljs_languages:
- yaml
- json
- bash
markdown_extensions:
- toc:
permalink: true
- admonition
- codehilite:
linenums: true
- pymdownx.details
- pymdownx.superfences

0 comments on commit 9eddb46

Please sign in to comment.