Deploy Kubernetes with a Single Command Using Atomicapp

Modified under MIT license from Project Atomic blog article Deploy Kubernetes with a Single Command Using Atomicapp (source) and relicensed under CC BY SA 3.0 Unported

Kubernetes, the open source orchestration system for Docker containers, is a fast-moving project that can be somewhat complicated to install and configure, especially if you're just getting started with it.

For this document we're going to focus on getting installation down to a single command:

# atomic run jasonbrooks/kubernetes-atomicapp

The first part of the command, atomic, refers to the containerized application and system management tool that ships with all Atomic Hosts and that allows an image provider to specify how a container image expects to be run. This tool takes advantage of the support for adding custom metadata, through labels, that debuted in docker 1.6.0.

If you aren't using an Atomic Host, the atomic tool is available in the CentOS 7 repository. Issue a yum install atomic command to get one of your own.

You can read all about atomic in this post from Dan Walsh, but the short version is that labels allow image developers to fold their big-hairy-docker-run-commands into their Dockerfiles, and the atomic tool allows users to access these labels.

At the end of the command, we have atomicapp, which is a tool for packaging complex multi-container applications and services, along with their orchestration metadata, into a deployable container image. Atomicapp is a reference implementation of the Nulecule specification.

You can learn more about Nulecule from one of these fine blog posts, or read on as we create our own Atomic App.


Atomic Apps are pretty easy to build. The process consists of gathering up orchestration metadata from whichever providers you intend to support (atomicapp currently works with Kubernetes, Docker, and OpenShift), placing this metadata in the right directory structure, and filling out a Nulecule file with information about the images, parameters, and metadata you wish to use.

The Nulecule repository contains a project template that we can use for reference:

$ git clone
$ tree nulecule/spec/examples/
└── template
    ├── artifacts
    │   ├── provider1
    │   │   ├── pod.json
    │   │   └── service.json
    │   └── provider2
    │       └── file.json
    ├── Dockerfile
    └── Nulecule

For our Kubernetes app, we'll be using the Docker provider, with one metadata file for each of the three docker run commands we mentioned above:

$ mkdir -p nulecule/examples/kubernetes-atomicapp/artifacts/docker
$ echo "docker run --net=host -d /usr/local/bin/etcd --addr= --bind-addr= --data-dir=/var/etcd/data" > nulecule/examples/kubernetes-atomicapp/artifacts/docker/kube-etcd_run
$ echo "docker run --net=host -d -v /var/run/docker.sock:/var/run/docker.sock /hyperkube kubelet --api_servers=http://localhost:8080 --v=2 --address= --enable_server --hostname_override= --config=/etc/kubernetes/manifests" > nulecule/examples/kubernetes-atomicapp/artifacts/docker/kube-master_run
$ echo "docker run -d --net=host --privileged /hyperkube proxy --master= --v=2" > nulecule/examples/kubernetes-atomicapp/artifacts/docker/kube-svcproxy_run

Next, we need to customize our Nulecule file:

$ vi nulecule/examples/kubernetes-atomicapp/Nulecule

specversion: 0.0.2
id: kubernetes-atomicapp

  name: Kubernetes Atomic App
  appversion: 0.0.1
  description: Atomic app for deploying a local, dockerized kubernetes
  - name: kubernetes-atomicapp
        - file://artifacts/docker/kube-etcd_run
        - file://artifacts/docker/kube-master_run
        - file://artifacts/docker/kube-svcproxy_run

Next, we'll create an answers.conf file to ensure that docker is picked up as our default provider -- otherwise, atomicapp will default to kubernetes.

$ vi nulecule/examples/kubernetes-atomicapp/answers.conf

namespace = default
provider = docker

Finally we need a Dockerfile, which we can copy, mostly unchanged, from the Nulecule template. We need to modify the Nulecule providers label to list Docker as our provider, and add in the answer file we created above:

$ cp nulecule/spec/examples/template/Dockerfile nulecule/examples/kubernetes-atomicapp/
$ vi nulecule/examples/kubernetes-atomicapp/Dockerfile

FROM projectatomic/atomicapp:0.1.3


LABEL io.projectatomic.nulecule.specversion 0.0.2
LABEL io.projectatomic.nulecule.providers = "docker"

ADD /Nulecule /Dockerfile /answers.conf /application-entity/
ADD /artifacts /application-entity/artifacts

Now we can pack up our metadata, Nulecule file, and Dockerfile into an image:

# docker build -t YOURNAME/kubernetes-atomicapp nulecule/examples/kubernetes-atomicapp/.

You can now run your image, push it to a Docker registry to pull and run somewhere else, or you can just run this image already pushed to the Docker hub:

# atomic run jasonbrooks/kubernetes-atomicapp

NOTE: Running Kubernetes in this way involves providing a container with access to the Docker daemon on the host machine, which SELinux prevents, so you'll need to put SELinux into permissive mode (sudo setenforce 0) for this experiment.

CAUTION: Running a production (non-experiment) machine in permissive mode is a serious security risk and should be avoided.

From here, you can pick up with the original Kubernetes-on-Socker walkthrough, at the Test it out step.