What is Blackbeard?
Blackbeard is a namespace manager for Kubernetes. 👍 It helps you to develop and test with Kubernetes using namespaces.
Kubernetes namespaces provide an easy way to isolate your components, your development environment, or your staging environment.
Blackbeard helps you to deploy your Kubernetes manifests on multiple namespaces, making each of them running a different version of your microservices. You may use it to manage development environment (one namespace per developer) or for testing purpose (one namespace for each feature to test before deploying in production).
Purpose
When working in a quite large team or, in a quite large project, have you ever experienced difficulties to test multiple features at the same time?
Usually, teams have 2 alternatives :
- Stack “features to test” in a queue and wait for the staging environment to be available;
- Try more or less successfully to create and maintain an “on demand” staging environment system, where each environment is dedicated to test a specified feature.
Blackbeard helps you to create ephemeral environments where you can test a set of features before pushing in production.
It also provide a very simple workflow, making things easier if you plan to run automated end-to-end testing.
How it works?
Playbooks
Blackbeard use playbooks to manage namespaces. A playbook is a collection of kubernetes manifest describing your stack, written as templates. A playbook also require a default.json
, providing the default values to apply to the templates.
Playbooks are created as files laid out in a particular directory tree.
Getting started
The following section describe how to quickly start to work with Blackbeard.
A full example, using 2 applications (an API and a front web app), is available on github. Have a look at it and try it on a local Kubernetes, for example (using docker-or-desktop or mini-kube).
Installation
Recommanded
The simplest way of installing Blackbeard is to use the installation script :
curl -sf https://raw.githubusercontent.com/Meetic/blackbeard/master/install.sh | sh
Manually
Download your preferred flavor from the releases page and install manually.
Using Go Get
Note : this method requires Go 1.9+ and dep.
go get github.com/Meetic/blackbeard
cd $GOPATH/src/github.com/Meetic/blackbeard
make build
Usage
Blackbeard provide a CLI interface in addition to a REST API. This way, you can use it either to run automated tests in a CI pipeline or plug your own UI for manuel deployment purpose.
Blackbeard requires kubectl
to be installed and configured to work.
Creating a new isolated env
blackbeard create -n my-feature
This command actually create a namespace and generate a JSON configuration file containing default values. This file, called an inventory
, is where you may update the values to apply specifically to your new namespace (such as microservice version)
Applying changes
blackbeard apply -n my-feature
This command apply your kubernetes manifest (modified by the values you have put in the generated inventory
previously) to your newly created namespace
Getting services endpoint / ports
blackbeard get services -n my-feature
This step will prompt a list of exposed services in the namespace. If you need to connect to a database in order to test data insertion, it is where you will find useful info.
Getting back to previous state
blackbeard delete -n my-feature
Delete all generated files and delete the namespace.
Workflow
Working with Blackbeard actually means working with a playbook
. Blackbeard manage Kubernetes namespaces based on a playbook.
First thing, is to create your own playbook. Once done, you have 2 ways to manage your namespaces using blackbeard :
- Using CLI
- Using the REST API
CLI
Blackbeard provide a set of CLI command.
CLI usage may be use for different purpose.
Locally, for developers, it is useful for managing multiple namespace either to develop a microservice calling other applications running a specified version, or to test the entire stack using specified version of multiple services in the stack.
In a CI/CD pipeline, for automated end-to-end testing.
Create a new env
cd {your playbook}
blackbeard create -n {namespace name}
- create a Kubernetes namespace;
- generate a
inventory
file for the newly created namespace; - generate a set of yml
manifest
based on the playbooktemplates
.
Update values & apply changes
cd {your playbook}/inventories
## edit the inventory file you want to update
cd ..
blackbeard apply -n {namespace name}
- apply values defined in the
inventory
file to the playbooktemplates
; - update the yml
manifest
using the newly updated values from theinventory
file; - run a
kubectl apply
command and apply changes in the manifest to the namespace.
List namespaces
blackbeard get namespaces
- prompt a list of available Kubernetes namespace;
for each namespace :
- indicate if the namespace is managed by a local
inventory
or not. - indicate the status of the namespace (aka : percentage of pods in a “running” state)
Exemple :
Namespace Phase Status Managed
backend Active 100% false
john Active 73% true
default Active 0% false
kevin Active 73% false
team1 Active 73% true
Get useful informations about services
blackbeard get services -n my-feature
- prompt a list of exposed services
Exposed services are Kubernetes services exposed using NodePort
or http services exposed via Ingress
Get Help
Usage:
blackbeard [command]
Available Commands:
apply Apply a given inventory to the associated namespace
create Create a namespace and generated a dedicated inventory.
delete Delete a namespace
get Show informations about a given namespace.
help Help about any command
reset Reset a namespace based on the template files and the default inventory.
serve Launch the blackbeard server
Flags:
--config string config file (default is $HOME/.blackbeard.yaml)
--dir string Use the specified dir as root path to execute commands. Default is the current dir.
-h, --help help for blackbeard
Use "blackbeard [command] --help" for more information about a command.
HTTP
Blackbeard also provide a web server and a websocket server exposing a REST api.
You can launch the Blackbeard server using the command :
blackbeard serve --help
Usage:
blackbeard serve [flags]
Flags:
--cors Enable cors
-h, --help help for serve
Global Flags:
--config string config file (default is $HOME/.blackbeard.yaml)
--dir string Use the specified dir as root path to execute commands. Default is the current dir.
The REST api documentation is written following the OpenAPI specifications.
This documentation is available in an HTML format, using Swagger UI.
Playbooks
Blackbeard uses Playbooks
to manage technical stack deployments across multiple namespaces.
A Playbook is organized as a collection of files inside of a directory. Inside of this directory, Blackbeard will expect a structure that matches this:
- A
templates
directory, containing Kubernetes manifests, written as templates. Those are typical configuration files for K8s (yaml). - A
defaults.json
file, defining the default values to apply (to the manifest templates) - An
inventories
directory that will contains the future inventories (One per namespace). The content of this directory should not be versioned. Inventories are variance of thedefaults.json
file. - A
configs
directory that will contains the future manifests files (one sub-dir per namespace). The content of this directory should not be versioned as well. Manifests are generated by applying theinventory
values to thetemplate
By default, Blackbeard will try to use the current directory as a Playbook. You can also specify a default playbook using a configuration file.
Thus, a Playbook made for an application called “MyApp” will look like :
MyApp
├── README.md
├── configs #Directory containing generated manifest for each inventory
│ ├── john #john is a namespace
│ │ ├── api.yml #Kubernetes manifest containing deployments and services for the api app.
│ │ └── front.yml #Kubernetes manifest containing deployments and services for the front-end app.
│ └── awesome-feature-to-test #awesome-feature-to-test is a namespace
│ ├── api.yml
│ └── front.yml
├── defaults.json #Default inventory file
├── inventories #Directory containing inventories for each namespace
│ ├── john_inventory.json #inventory for john namespace
│ └── awesome-feature-to-test_inventory.json #inventory for awesome-feature-to-test namespace
└── templates #Directory containing the Kubernetes manifest templates
├── api.yml.tpl
└── front.yml.tpl
On this example, you can see the stack contains an API and a front-end application and is deployed on 2 namespaces :
- One called john is used by john for development purpose
- One called awesome-feature-to-test is used for testing a feature on an isolated
Templates
Playbooks expect templates
and a default inventory.
Templates are very simple. The only constraints are :
- Templates must contains a valid Kubernetes manifest (yaml)
- Template files must have a
.tpl
extension
Example : api.yml.tpl
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: api
spec:
replicas: 1
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: myCompany/MyApp:{{.Values.api.version}}
args: ["-Xms{{.Values.api.memoryLimit}}", "-Xmx{{.Values.api.memoryLimit}}", "-Dconfig.resource=config.conf"]
imagePullPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
name: api
spec:
selector:
app: api
ports:
- protocol: TCP
port: 8080
Under the hood, Blackbeard use Go templating system.
Blackbeard compile templates using the content of the inventory file. Thus, two variables are available inside the template :
.Values
: contains a json object.Namespace
: contains a string
Inventories
An inventory is a file containing a json object. This object is made available inside the templates by Blackbeard.
The only constraints on an inventory json object are :
- An inventory must contains a
namespace
key, containing a string. The string value must be the name of the namespace the inventory is associated to; - An inventory must contains a
values
key. This key may contains whatever you want. - An inventory file must be located in the
inventories
directory - An inventory file must be named after the template :
{{namespace}}_inventory.json
Example : john_inventory.json
{
"namespace": "john",
"values": {
"api": {
"version": "1.2.0",
"memoryLimit": "128m"
},
"front": {
"version": "1.2.1"
}
}
}
Inventories are generated from the defaults.json
file. Blackeard copy the defaults.json
file content, create a inventory for the given namespace (located in the inventories
directory), past the content default values and change the namespace
key value with the corresponding namespace
defaults.json
The defaults.json
file is the default inventory. It contains defaults values to apply on the templates. Blackbeard uses it to generated per namespace inventory.
The only constraint on the default.json
file is :
- Must contains a
namespace
key, containing the value “default”.
Example : defaults.json
{
"namespace": "default",
"values": {
"api": {
"version": "1.0.0",
"memoryLimit": "128m"
},
"front": {
"version": "1.0.0"
}
}
}