Sysctl Support for Docker Swarm Cluster for the first time in Docker 19.03.0 Pre-Release

Estimated Reading Time: 7 minutes

Docker CE 19.03.0 Beta 1 went public 2 week back. It was the first release which arrived with sysctl support for Docker Swarm Mode for the first time. This is definitely a great news for popular communities like Elastic Stack, Redis etc. as they rely on tuning the kernel parameter to get rid of memory exceptions. For example, Elasticsearch uses a mmapfs directory by default to store its indices. The default operating system limits on mmap counts is likely to be too low, which may result in out of memory exceptions, hence one need to  increase the limits everytime using sysctl tool. Great to see that Docker Inc. acknowledged the fact that kernel tuning is required sometimes and provides explicit support under Docker 19.03.0 Pre-Release. Great Job !

Wait..Do I really need sysctl?

Say, you have deployed your application on Docker Swarm. it’s pretty simple and it’s working great. Your application is growing day by day and now you just need to scale it. How are you going to do it? The simple answer is: docker service scale app=<number of tasks>.Surely, it is possible today but your containers can quickly hit kernel limits. One of the most popular kernel parameter is net.core.somaxconn. This parameter represents the maximum number of connections that can be queued for acceptance. The default value on Linux is 128, which is rather low.

The Linux kernel is flexible, and you can even modify the way it works on the fly by dynamically changing some of its parameters, thanks to the sysctl command. The sysctl programs allow to limit system-wide resource use. This can help a lot in system administration, e.g. when a user starts too many processes and therefore makes the system unresponsive for other users. Sysctl basically provides an interface that allows you to examine and change several hundred kernel parameters in Linux or BSD. Changes take effect immediately, and there’s even a way to make them persist after a reboot. By using sysctl judiciously, you can optimize your box without having to recompile the kernel and get the results immediately.

Please note that Not all sysctls are namespaced as of Docker 19.03.0 CE Pre-Release. Docker does not support changing sysctls inside of a container that also modify the host system.

Docker does support setting namespaced kernel parameters at runtime & runc honors this. Have a look:

$ docker run --runtime=runc --sysctl net.ipv4.ip_forward=1 -it alpine sh
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
bdf0201b3a05: Pull complete 
Digest: sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913
Status: Downloaded newer image for alpine:latest
/ # sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
/ # 

It is important to note that sysctl support is not new to Docker. The support for sysctl in Docker Compose all started during compose file format v2.1.

For example, to set Kernel parameters in the container, you can use either an array or a dictionary.

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

Under this blog post, I will showcase how to use sysctl under 2-Node Docker Swarm Cluster. Let us get started –

Installing a Node with Docker 19.03.0 Beta 1 Test Build on Ubuntu 18.10

Method:I

Downloading the static binary archive. Go to https://download.docker.com/linux/static/stable/ (or change stable to nightly or test), choose your hardware platform, and download the .tgz file relating to the version of Docker CE you want to install.

Captain'sBay==>wget https://download.docker.com/linux/static/test/x86_64/docker-19.03.0-beta1.tgz
--2019-04-10 09:20:01--  https://download.docker.com/linux/static/test/x86_64/docker-19.03.0-beta1.tgz
Resolving download.docker.com (download.docker.com)... 54.230.75.15, 54.230.75.117, 54.230.75.202, ...
Connecting to download.docker.com (download.docker.com)|54.230.75.15|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 62701372 (60M) [application/x-tar]
Saving to: ‘docker-19.03.0-beta1.tgz’
docker-19.03.0-beta1.tgz  100%[=====================================>]  59.80M  10.7MB/s    in 7.1s    
2019-04-10 09:20:09 (8.38 MB/s) - ‘docker-19.03.0-beta1.tgz’ saved [62701372/62701372]
Extract the archive
You can use the tar utility. The dockerd and docker binaries are extracted.

Extract the tar file

Captain'sBay==>tar xzvf docker-19.03.0-beta1.tgz 
docker/
docker/ctr
docker/containerd-shim
docker/dockerd
docker/docker-proxy
docker/runc
docker/containerd
docker/docker-init
docker/docker
Captain'sBay==>

Move the binaries to executable path

Move the binaries to a directory on your executable path It could be such as /usr/bin/. If you skip this step, you must provide the path to the executable when you invoke docker or dockerd commands.

Captain'sBay==>sudo cp -rf docker/* /usr/local/bin/

Start the Docker daemon:

$ sudo dockerd &
Client: Docker Engine - Community
 Version:           19.03.0-beta1
 API version:       1.40
 Go version:        go1.12.1
 Git commit:        62240a9
 Built:             Thu Apr  4 19:15:07 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.0-beta1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.1
  Git commit:       62240a9
  Built:            Thu Apr  4 19:22:34 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.5
  GitCommit:        bb71b10fd8f58240ca47fbb579b9d1028eea7c84
 runc:
  Version:          1.0.0-rc6+dev
  GitCommit:        2b18fe1d885ee5083ef9f0838fee39b62d653e30
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
Captain'sBay==>

Testing with hello-world

Captain'sBay==>sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest
INFO[2019-04-10T09:26:23.338596029Z] shim containerd-shim started                  address="/containerd-shim/m
oby/5b23a7045ca683d888c9d1026451af743b7bf4005c6b8dd92b9e95e125e68134/shim.sock" debug=false pid=2953
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/
For more examples and ideas, visit:
 https://docs.docker.com/get-started/
## Verifying the new `docker context` command

Verifying Docker version

root@DebianBuster:~# docker version
Client:
 Version:           19.03.0-beta1
 API version:       1.40
 Go version:        go1.11.5
 Git commit:        62240a9
 Built:             Thu Apr  4 19:18:53 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.0-beta1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.11.5
  Git commit:       62240a9
  Built:            Thu Apr  4 19:17:35 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.5
  GitCommit:        bb71b10fd8f58240ca47fbb579b9d1028eea7c84
 runc:
  Version:          1.0.0-rc6+dev
  GitCommit:        2b18fe1d885ee5083ef9f0838fee39b62d653e30
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
root@DebianBuster:~#

Creating a 2-Node Docker Swarm Mode Cluster

swarm-node-1:~$ sudo docker swarm init --advertise-addr 10.140.0.6 --listen-addr 10.140.0
.6:2377
Swarm initialized: current node (c78wm1g99q1a1g2sxiuawqyps) is now a manager.
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-1bc88158q1v4b4gdof8k0u532bxzdvrgxfztwgj2r443337mja-cmhuu258lu0327
e32l0g4pl47 10.140.0.6:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Run the below command on worker node:

swarm-node2:~$ sudo docker swarm join --token SWMTKN-1-1bc88158q1v4b4gdof8k0u532bxzdvrgxf
ztwgj2r443337mja-cmhuu258lu0327e32l0g4pl47 10.140.0.6:2377
This node joined a swarm as a worker.

Listing the Swarm Mode CLuster

$ sudo docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
      ENGINE VERSION
rf3xns913p4tlprmu98z2o8hi     swarm-node2         Ready               Active                            
      19.03.0-beta1
isbcijzlrft3ahpbzhgipwr9a *   swarm-node-1        Ready               Active              Leader        
      19.03.0-beta1

Running Multi-service Docker Compose for Redis

Redis is an open source, in-memory data structure store, used as a database, cache and message broker. Redis Commander is an application that allows users to explore a Redis instance through a browser. Let us look at the below Docker compose file for Redis as well as Redis Commander shown below:

version: '3'
services:
  redis:
    hostname: redis
    image: redis

  redis-commander:
    hostname: redis-commander
    image: rediscommander/redis-commander:latest
    restart: always
    environment:
    - REDIS_HOSTS=local:redis:6379
    ports:
    - "8081:8081"

Ensure that Docker Compose is installed on your system using the below commands:

curl -L https://github.com/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Run the below command to bring up Redis application running on Docker Swarm Mode:

sudo docker stack deploy -c docker-compose.yml myapp

$ sudo docker stack deploy -c docker-compose.yml myapp
Ignoring unsupported options: restart
Creating network myapp_default
Creating service myapp_redis-commander
Creating service myapp_redis

Verifying if the services are up and running:

~$ sudo docker stack ls
NAME                SERVICES            ORCHESTRATOR
myapp               2                   Swarm

~$ sudo docker service ls
ID                  NAME                    MODE                REPLICAS            IMAGE               
                    PORTS
ucakpqi7ozg1        myapp_redis             replicated          1/1                 redis:latest        
                    
fxor8v90a4m0        myapp_redis-commander   replicated          0/1                 rediscommander/redis
-commander:latest   *:8081->8081/tcp

Checking the service logs:


$ docker service logs -f myapp3_redis
myapp3_redis.1.7jpnbigi8kek@manager1    | 1:C 17 Apr 2019 06:26:08.006 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
myapp3_redis.1.7jpnbigi8kek@manager1    | 1:C 17 Apr 2019 06:26:08.006 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1, just started
myapp3_redis.1.7jpnbigi8kek@manager1    | 1:C 17 Apr 2019 06:26:08.006 # Warning: no config file specified, using the default config. In order to specify a configfile use redis-server /path/to/redis.conf
myapp3_redis.1.7jpnbigi8kek@manager1    | 1:M 17 Apr 2019 06:26:08.009 * Running mode=standalone, port=6379.
myapp3_redis.1.7jpnbigi8kek@manager1    | 1:M 17 Apr 2019 06:26:08.009 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

As you see above, there is a warning around /proc/sys/net/core/somaxconn lower value set to 128.

Building Docker Compose File using Sysctl parameter

Let us try to build a new Docker compose file with sysctl parameter specified:

Copy the below content and save it as a docker-compose.yml file.

version: '3'
services:
  redis:
    hostname: redis
    image: redis
  sysctls:
    net.core.somaxconn: 1024
  redis-commander:
    image: rediscommander/redis-commander:latest
    restart: always
    environment:
    - REDIS_HOSTS=local:redis:6379
    ports:
    - "8081:8081"

Running Your Redis application

$ sudo docker stack deploy -c docker-compose.yml myapp
Ignoring unsupported options: restart
Creating network myapp_default
Creating service myapp_redis
Creating service myapp_redis-commander

$ sudo docker service ls
ID                  NAME                    MODE                REPLICAS            IMAGE               
                    PORTS
2oxhaychob7s        myapp_redis             replicated          1/1                 redis:latest        
                    
pjdwti7hkg1q        myapp_redis-commander   replicated          1/1                 rediscommander/redis
-commander:latest   *:80->8081/tcp

Verifying the Redis service logs

$ sudo docker service logs -f myapp_redis
myapp_redis.1.mp57syo3okka@swarm-node-1    | 1:C 17 Apr 2019 06:59:44.510 # oO0OoO0OoO0Oo Redis is start
ing oO0OoO0OoO0Oo
myapp_redis.1.mp57syo3okka@swarm-node-1    | 1:C 17 Apr 2019 06:59:44.510 # Redis version=5.0.4, bits=64
, commit=00000000, modified=0, pid=1, just started
myapp_redis.1.mp57syo3okka@swarm-node-1    | 1:M 17 Apr 2019 06:59:44.511 * Running mode=standalone, port=6379.

You can see that the warning around /proc/sys/net/core/somaxconn is no longer being displayed which shows that the sysctls parameter has really worked.

In my next blog post, I will talk around rootless Docker and how to get it tested. Stay tuned !

Docker 19.03.0 Pre-Release: Fast Context Switching, Rootless Docker, Sysctl support for Swarm Services

Estimated Reading Time: 9 minutes

Last week Docker Community Edition 19.03.0 Beta 1 was announced and release notes went public here.Under this release, there were numerous exciting features which were introduced for the first time. Some of the notable features include – fast context switching, rootless docker, sysctl support for Swarm services, device support for Microsoft Windows.

Not only this, there were numerous enhancement around Docker Swarm, Docker Engine API, networking, Docker client, security & Buildkit. Below are the list of features and direct links to GitHub.

Let’s talk about Context Switching..

A context is essentially the configuration that you use to access a particular cluster. Say, for example, in my particular case, I have 4 different clusters – mix of Swarm and Kubernetes running locally and remotely. Assume that I have a default cluster running on my Desktop machine , 2 node Swarm Cluster running on Google Cloud Platform, 5-Node Cluster running on Play with Docker playground and a single-node Kubernetes cluster running on Minikube and that I need to access pretty regularly. Using docker context CLI I can easily switch from one cluster(which could be my development cluster) to test to production cluster in seconds.

Under this blog post, I will focus on fast context switching feature which was introduced for the first time. Let’s get started:

Tested Infrastructure:

  • A Node with Docker 19.03.0 Beta1 installed on Ubuntu 18.10
  • 2 Docker Swarm Node Cluster(swarm-node1 and swarm-node2) setup on installed on Ubuntu 18.10
  • 5-Node Swarm Cluster running on Play with Docker Platform
  • Create 3 Node Kubernetes Cluster using GKE

Installing a Node with Docker 19.03.0 Beta 1 Test Build on Ubuntu 18.10

Method:I

Downloading the static binary archive. Go to https://download.docker.com/linux/static/stable/ (or change stable to nightly or test), choose your hardware platform, and download the .tgz file relating to the version of Docker CE you want to install.

Captain'sBay==>wget https://download.docker.com/linux/static/test/x86_64/docker-19.03.0-beta1.tgz
--2019-04-10 09:20:01--  https://download.docker.com/linux/static/test/x86_64/docker-19.03.0-beta1.tgz
Resolving download.docker.com (download.docker.com)... 54.230.75.15, 54.230.75.117, 54.230.75.202, ...
Connecting to download.docker.com (download.docker.com)|54.230.75.15|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 62701372 (60M) [application/x-tar]
Saving to: ‘docker-19.03.0-beta1.tgz’
docker-19.03.0-beta1.tgz  100%[=====================================>]  59.80M  10.7MB/s    in 7.1s    
2019-04-10 09:20:09 (8.38 MB/s) - ‘docker-19.03.0-beta1.tgz’ saved [62701372/62701372]
Extract the archive
You can use the tar utility. The dockerd and docker binaries are extracted.

Extract the tar file

Captain'sBay==>tar xzvf docker-19.03.0-beta1.tgz 
docker/
docker/ctr
docker/containerd-shim
docker/dockerd
docker/docker-proxy
docker/runc
docker/containerd
docker/docker-init
docker/docker
Captain'sBay==>

Move the binaries to executable path

Move the binaries to a directory on your executable path It could be such as /usr/bin/. If you skip this step, you must provide the path to the executable when you invoke docker or dockerd commands.

Captain'sBay==>sudo cp -rf docker/* /usr/local/bin/

Start the Docker daemon:

$ sudo dockerd &
Client: Docker Engine - Community
 Version:           19.03.0-beta1
 API version:       1.40
 Go version:        go1.12.1
 Git commit:        62240a9
 Built:             Thu Apr  4 19:15:07 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.0-beta1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.1
  Git commit:       62240a9
  Built:            Thu Apr  4 19:22:34 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.5
  GitCommit:        bb71b10fd8f58240ca47fbb579b9d1028eea7c84
 runc:
  Version:          1.0.0-rc6+dev
  GitCommit:        2b18fe1d885ee5083ef9f0838fee39b62d653e30
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
Captain'sBay==>

Testing with hello-world

Captain'sBay==>sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest
INFO[2019-04-10T09:26:23.338596029Z] shim containerd-shim started                  address="/containerd-shim/m
oby/5b23a7045ca683d888c9d1026451af743b7bf4005c6b8dd92b9e95e125e68134/shim.sock" debug=false pid=2953
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/
For more examples and ideas, visit:
 https://docs.docker.com/get-started/
## Verifying the new `docker context` command

Method:II

If you have less time and want a single liner command to handle this, check this out –


root@DebianBuster:~# curl https://get.docker.com | CHANNEL=test sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 13063  100 13063    0     0   2305      0  0:00:05  0:00:05 --:--:--  2971
# Executing docker install script, commit: 2f4ae48
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=amd64] https://download.docker.com/linux/debian buster test" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ [ -n  ]
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sh -c docker version
Client:
 Version:           19.03.0-beta1
 API version:       1.40
 Go version:        go1.11.5
 Git commit:        62240a9
 Built:             Thu Apr  4 19:18:53 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.0-beta1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.11.5
  Git commit:       62240a9
  Built:            Thu Apr  4 19:17:35 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.5
  GitCommit:        bb71b10fd8f58240ca47fbb579b9d1028eea7c84
 runc:
  Version:          1.0.0-rc6+dev
  GitCommit:        2b18fe1d885ee5083ef9f0838fee39b62d653e30
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker your-user

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
         containers which can be used to obtain root privileges on the
         docker host.
         Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
         for more information.
root@DebianBuster:~#

Verifying Docker version

root@DebianBuster:~# docker version
Client:
 Version:           19.03.0-beta1
 API version:       1.40
 Go version:        go1.11.5
 Git commit:        62240a9
 Built:             Thu Apr  4 19:18:53 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.0-beta1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.11.5
  Git commit:       62240a9
  Built:            Thu Apr  4 19:17:35 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.5
  GitCommit:        bb71b10fd8f58240ca47fbb579b9d1028eea7c84
 runc:
  Version:          1.0.0-rc6+dev
  GitCommit:        2b18fe1d885ee5083ef9f0838fee39b62d653e30
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
root@DebianBuster:~#

Verifying docker context CLI

$ sudo docker context --help
Usage:  docker context COMMAND
Manage contexts
Commands:
  create      Create a context
  export      Export a context to a tar or kubeconfig file
  import      Import a context from a tar file
  inspect     Display detailed information on one or more contexts
  ls          List contexts
  rm          Remove one or more contexts
  update      Update a context
  use         Set the current docker context
Run 'docker context COMMAND --help' for more information on a command.

Creating a 2 Node Swarm Cluster

Install Docker 19.03.0 Beta 1 on both the nodes(using the same method discussed above). You can use GCP Free Tier account to create 2-Node Swarm Cluster.

Configuring remote access with systemd unit file

Use the command sudo systemctl edit docker.service to open an override file for docker.service in a text editor.

Add or modify the following lines, substituting your own values.

Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://10.140.0.6:2375

Save the file.

Reload the systemctl configuration

$ sudo systemctl daemon-reload Restart Docker.
$ sudo systemctl restart docker.service

Repeat it for other nodes which you are planning to include for building Swarm Mode cluster.

swarm-node-1:~$ sudo docker swarm init --advertise-addr 10.140.0.6 --listen-addr 10.140.0
.6:2377
Swarm initialized: current node (c78wm1g99q1a1g2sxiuawqyps) is now a manager.
To add a worker to this swarm, run the following command:
    docker swarm join --token SWMTKN-1-1bc88158q1v4b4gdof8k0u532bxzdvrgxfztwgj2r443337mja-cmhuu258lu0327
e32l0g4pl47 10.140.0.6:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Run the below command on worker node:

swarm-node2:~$ sudo docker swarm join --token SWMTKN-1-1bc88158q1v4b4gdof8k0u532bxzdvrgxf
ztwgj2r443337mja-cmhuu258lu0327e32l0g4pl47 10.140.0.6:2377
This node joined a swarm as a worker.

Listing the Swarm Mode CLuster

root@swarm-node-1:~# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
0v5r9xmpbxzqpy72u41ihfck0     swarm-node2         Ready               Active                                  19.03.0-beta1
xwmay5i48xxbzlp7is7a3uord *   swarm-node-1        Ready               Active              Leader              19.03.0-beta1

Switching the Context

Listing the Context

node-1:~$ sudo docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES E
NDPOINT   ORCHESTRATOR
default *           Current DOCKER_HOST based configuration   unix:///var/run/docker.sock               
         swarm

Adding the new Context

docker context create --docker host=tcp://10.140.0.6:2375 swarm-context1

Using the new context for Swarm

docker context use swarm-context1

Listing the Swarm Mode Cluster

 sudo docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES E
NDPOINT   ORCHESTRATOR
default             Current DOCKER_HOST based configuration   unix:///var/run/docker.sock               
         swarm
swarm-context1 *                                              tcp://10.140.0.6:2375             
 sudo docker context ls --format '{{json .}}' | jq .
{
  "Current": true,
  "Description": "Current DOCKER_HOST based configuration",
  "DockerEndpoint": "unix:///var/run/docker.sock",
  "KubernetesEndpoint": "",
  "Name": "default",
  "StackOrchestrator": "swarm"
}
{
  "Current": false,
  "Description": "",
  "DockerEndpoint": "tcp://10.140.0.6:2375",
  "KubernetesEndpoint": "",
  "Name": "swarm-context1",
  "StackOrchestrator": ""
}
$ sudo docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
      ENGINE VERSION
xwmay5i48xxbzlp7is7a3uord *   swarm-node-1        Ready               Active              Leader        
      19.03.0-beta1
$ sudo docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
0v5r9xmpbxzqpy72u41ihfck0     swarm-node2         Ready               Active                                  19.03.0-beta1
xwmay5i48xxbzlp7is7a3uord *   swarm-node-1        Ready               Active              Leader              19.03.0-beta1
tanvirkour1985@sys1:~$ 

Context Switching to remotely running Play with Docker(PWD) Platform

This is one of the most exciting part of this blog. I simply love PWD platform as I find it perfect playground for test driving Docker Swarm cluster. Just a click and you get 5-Node Docker Swarm Cluster in just 5 seconds.

Just click on 3-Manager and 2 workers and you get 5-Node Docker Swarm cluster for FREE.

Let us try to access this PWD cluster using docker context CLI.

Say, by default we have just 1 context for local Docker Host.

[:)Captain'sBay=>sudo docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT                 ORCHESTRATOR
default *           Current DOCKER_HOST based configuration   unix:///var/run/docker.sock   https://127.0.0.1:16443 (default)   swarm
swarm-context1                                                tcp://10.140.0.6:2375                                             

Let us go ahead and add PWD context. As shown below, you need to pick up the FQDN name but remember to remove “@” and replace it with “.”(dot)

[:)Captain'sBay=>sudo docker context create --docker host=tcp://ip172-18-0-5-biosq9o6chi000as1470.direct.labs.play-with-docker.com:2375 pwd-clu
ster1
pwd-cluster1
Successfully created context "pwd-cluster1"

This creates a context by name “pwd-cluster1”. You can verify it by listing out the current contexts available.

[:)Captain'sBay=>sudo docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT                                                                 K
UBERNETES ENDPOINT                 ORCHESTRATOR
default *           Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                                                     h
ttps://127.0.0.1:16443 (default)   swarm
pwd-cluster1                                                  tcp://ip172-18-0-5-biosq9o6chi000as1470.direct.labs.play-with-docker.com:2375    
                                   
swarm-context1                                                tcp://10.140.0.6:2375                                                            
                                   
[:)Captain'sBay=>

Let us switch to pwd-cluster1 by simply typing docker context use CLI.

[:)Captain'sBay=>sudo docker context use pwd-cluster1
pwd-cluster1
Current context is now "pwd-cluster1"

Listing out the context and verifying if it points to right PWD cluster.

[:)Captain'sBay=>sudo docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
wnrz5fks5drzs9agkyl8z3ffi *   manager1            Ready               Active              Leader              18.09.4
dcweon0icoolfs3kirj0p3qgg     manager2            Ready               Active              Reachable           18.09.4
f78bkvfbzot2jkr2n6cen7240     manager3            Ready               Active              Reachable           18.09.4
xla6nb5ql5i6pkjruyxpc1hzk     worker1             Ready               Active                                  18.09.4
45nk1t94ympplgaasiryunwvk     worker2             Ready               Active                                  18.09.4
[:)Captain'sBay=>

In my next blog post, I will showcase how to switch to Kubernetes cluster running on Minikube and GKE using compose on Kubernetes.

If you are a beginner and looking out to build your career in Docker | Kubernetes | Cloud, do visit DockerLabs. Join our community by clicking here. Thank You.

Meet K3s – A Lightweight Kubernetes Distribution for Raspberry Pi Cluster

Estimated Reading Time: 9 minutes

To implement a microservice architecture and a multi-cloud strategy, Kubernetes today has become a key enabling technology. The bedrock of Kubernetes remains the orchestration and management of Linux containers, to create a powerful distributed system for deploying applications across a hybrid cloud environment. Said that, Kubernetes has become the de-facto standard container orchestration framework for cloud-native deployments. Development teams have turned to Kubernetes to support their migration to new microservices architectures and a DevOps culture for continuous integration and continuous deployment.

Why Docker & Kubernetes on IoT devices?

Today many organizations are going through a digital transformation process. Digital transformation is the integration of digital technology into almost all areas of a business, fundamentally changing how you operate and deliver value to customers. It’s basically a cultural change.  The common goal for all these organization is to change how they connect with their customers, suppliers and partners. These organizations are taking advantage of innovations offered by technologies such as IoT platforms, big data analytics, or machine learning to modernize their enterprise IT and OT systems. They realize that the complexity of development and deployment of new digital products require new development processes. Consequently, they turn to agile development and infrastructure tools such as Kubernetes.

At the same time, that there has been a major increase in the demand for Kubernetes outside the datacenter. Kubernetes is pushing out of the data center into stores and factories. DevOps teams do find Kubernetes quite interesting as it provides predictable operations and a cloud-like provisioning experience on just about any infrastructure.

Docker containers & Kubernetes are an excellent choice for deploying complex software to the Edge. The reasons are listed below:

  • Containers are awesome
  • Consistent across a wide variety of Infrastructure
  • Capable of standalone or clustered operations
  • Easy to upgrade and/or replace containers
  • Support for different infrastructure configs(storage,CPU etc.)
  • Strong Ecosystem(Monitoring, logging, CI, management etc.)

Introducing K3s – A Stripped Down version of Kubernetes

K3s is a brand new distribution of Kubernetes that is designed for teams that need to deploy applications quickly and reliably to resource-constrained environments. K3s is a Certified Kubernetes distribution designed for production workloads in unattended, resource-constrained, remote locations or inside IoT appliances.

K3s is lightweight certified K8s distribution built for production operations. It is just 40MB binary with 512MB memory consumption. It is based on a single process w/t integrated K8s master, Kubelet and containerd. It includes SQLite in addition to etcd. Simultaneously released for x86_64, ARM64 and ARMv7. It is an open Source project, not yet Rancher product. It is wrapped in a simple package that reduces the dependencies and steps needed to run a production Kubernetes cluster. Packaged as a single binary, k3s makes installation and upgrade as simple as copying a file. TLS certificates are automatically generated to ensure that all communication is secure by default.

k3s bundles the Kubernetes components (kube-apiserver, kube-controller-manager, kube-scheduler, kubelet, kube-proxy) into combined processes that are presented as a simple server and agent model. Running k3s server will start the Kubernetes server and automatically register the local host as an agent. This will create a one node Kubernetes cluster. To add more nodes to the cluster just run k3s agent --server ${URL} --token ${TOKEN} on another host and it will join the cluster. It’s really that simple to set up a Kubernetes cluster with k3s.

Minimum System Requirements

  • Linux 3.10+
  • 512 MB of ram per server
  • 75 MB of ram per node
  • 200 MB of disk space
  • x86_64, ARMv7, ARM64

Under this blog post, I will showcase how to get started with K3s on 2-Node Raspberry Pi’s cluster.

Prerequisite:

Hardware:

  1. Raspberry Pi 3 ( You can order it from Amazon in case you are in India for 2590 INR)
  2. Micro-SD card reader ( I got it from here )
  3. Any Windows/Linux/MacOS
  4. HDMI cable ( I used the HDMI cable of my plasma TV)
  5. Internet Connectivity(WiFi/Broadband/Tethering using Mobile) – to download Docker 18.09.0 package
  6. Keyboard & mouse connected to Pi’s USB ports

Software:

  1. SD-Formatter – to format microSD card (in case of Windows Laptop)
  2. Win32DiskImager(in case you have Windows OS running on your laptop) – to burn Raspbian format directly into microSD card.(No need to extract XZ using any tool). You can use Etcher tool if you are using macbook.

Steps to Flash Raspbian OS on Pi Boxes:

  1. Format the microSD card using SD Formatter as shown below:
4

2. Download Raspbian OS from here and use Win32 imager(in case you are on Windows OS  running on your laptop) to burn it on microSD card.

3. Insert the microSD card into your Pi box. Now connect the HDMI cable  from one end of Pi’s HDMI slot to your TV or display unit and mobile charger(recommended 5.1V@1.5A).

4. Let the Raspbian OS boot up on your Pi box. It takes hardly 2 minutes for OS to come up.

5. Configure WiFi via GUI. All you need is to input the right password for your WiFi.

6. The default username is “pi” and password is “raspberry”. You can use this credentials to login into the Pi system.

7. You can use “FindPI” Android application to search for IP address if you don’t want to look out for Keyboard or mouse to search for the right IP address.

Enable SSH to perform remote login

To login via your laptop, you need to allow SSH service running. You can verify IP address command via ifconfig command.

[Captains-Bay]🚩 >  ssh pi@192.168.1.5
pi@192.168.1.5's password:
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb 26 12:30:00 2019 from 192.168.1.4
pi@raspberrypi:~ $ sudo su
root@raspberrypi:/home/pi# cd

Verifying Raspbian OS Version

root@raspberrypi:~# cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
root@raspberrypi:~#
</code></pre>

Enable container features in Kernel

Edit /boot/cmdline.txt on both the Raspberry Pi nodes and add the following to the end of the line:

cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory

Reboot the devices.

Installing K3s

root@raspberrypi:~# curl -sfL https://get.k3s.io | sh -
[INFO]  Finding latest release
[INFO]  Using v0.2.0 as release
[INFO]  Downloading hash https://github.com/rancher/k3s/releases/download/v0.2.0/sha256sum-arm.txt
[INFO]  Downloading binary https://github.com/rancher/k3s/releases/download/v0.2.0/k3s-armhf
^Croot@raspberrypi:~# wget https://github.com/rancher/k3s/releases/download/v0.2.0/k3s-mhf && \
>   chmod +x k3s-armhf && \
>   sudo mv k3s-armhf /usr/local/bin/k3s
--2019-03-28 22:47:22--  https://github.com/rancher/k3s/releases/download/v0.2.0/k3s-armhf
Resolving github.com (github.com)... 192.30.253.112, 192.30.253.113
Connecting to github.com (github.com)|192.30.253.112|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/135516270/4010d900-41db-11e9-9992-cc2248364eac?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20190328%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190328T171725Z&X-Amz-Expires=300&X-Amz-Signature=75c5a361f0219d443dfa0754250c852257f1b8512e54094da0bcc6fbb92327cc&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dk3s-armhf&response-content-type=application%2Foctet-stream [following]
--2019-03-28 22:47:25--  https://github-production-release-asset-2e65be.s3.amazonaws.com/135516270/4010d900-41db-11e9-9992-cc2248364eac?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20190328%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190328T171725Z&X-Amz-Expires=300&X-Amz-Signature=75c5a361f0219d443dfa0754250c852257f1b8512e54094da0bcc6fbb92327cc&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dk3s-armhf&response-content-type=application%2Foctet-stream
Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.0.56
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.0.56|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 34684224 (33M) [application/octet-stream]
Saving to: ‘k3s-armhf’

k3s-armhf             100%[========================>]  33.08M  93.1KB/s    in 8m 1s

2019-03-28 22:55:28 (70.4 KB/s) - ‘k3s-armhf’ saved [34684224/34684224]

Boostrapping Your K3s Server

root@raspberrypi:~# sudo k3s server
INFO[2019-03-29T10:52:06.995054811+05:30] Starting k3s v0.2.0 (2771ae1)
INFO[2019-03-29T10:52:07.082595332+05:30] Running kube-apiserver --watch-cache=false --cert-dir /var/lib/rancher/k3s/server/tls/temporary-certs --allow-privileged=true --authorization-mode Node,RBAC --service-account-signing-key-file /var/lib/rancher/k3s/server/tls/service.key --service-cluster-ip-range 10.43.0.0/16 --advertise-port 6445 --advertise-address 127.0.0.1 --insecure-port 0 --secure-port 6444 --bind-address 127.0.0.1 --tls-cert-file /var/lib/rancher/k3s/server/tls/localhost.crt --tls-private-key-file /var/lib/rancher/k3s/server/tls/localhost.key --service-account-key-file /var/lib/rancher/k3s/server/tls/service.key --service-account-issuer k3s --api-audiences unknown --basic-auth-file /var/lib/rancher/k3s/server/cred/passwd --kubelet-client-certificate /var/lib/rancher/k3s/server/tls/token-node.crt --kubelet-client-key /var/lib/rancher/k3s/server/tls/token-node.key
INFO[2019-03-29T10:52:08.094785384+05:30] Running kube-scheduler --kubeconfig /var/lib/rancher/k3s/server/cred/kubeconfig-system.yaml --port 10251 --address 127.0.0.1 --secure-port 0 --leader-elect=false
INFO[2019-03-29T10:52:08.105366477+05:30] Running kube-controller-manager --kubeconfig /var/lib/rancher/k3s/server/cred/kubeconfig-system.yaml --service-account-private-key-file /var/lib/rancher/k3s/server/tls/service.key --allocate-node-cidrs --cluster-cidr 10.42.0.0/16 --root-ca-file /var/lib/rancher/k3s/server/tls/token-ca.crt --port 10252 --address 127.0.0.1 --secure-port 0 --leader-elect=false
Flag --address has been deprecated, see --bind-address instead.
INFO[2019-03-29T10:52:10.410557414+05:30] Listening on :6443
INFO[2019-03-29T10:52:10.519075956+05:30] Node token is available at /var/lib/rancher/k3s/server/node-token
INFO[2019-03-29T10:52:10.519226216+05:30] To join node to cluster: k3s agent -s https://192.168.43.134:6443 -t ${NODE_TOKEN}
INFO[2019-03-29T10:52:10.543022102+05:30] Writing manifest: /var/lib/rancher/k3s/server/manifests/coredns.yaml
INFO[2019-03-29T10:52:10.548766216+05:30] Writing manifest: /var/lib/rancher/k3s/server/manifests/traefik.yaml

I encountered the below error message while running K3s server for the first time.


INFO[2019-04-04T15:52:44.710450122+05:30] Waiting for containerd startup: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: Error while dialing dial unix /run/k3s/containerd/containerd.sock: connect: connection refused"
containerd: exit status 1

You can fix it by editing /etc/hosts and adding the right entry for your Pis boxes

127.0.0.1       raspberrypi-node3

By now, you should be able to get k3s nodes listed.

root@raspberrypi:~# sudo k3s kubectl get node -o wide
NAME          STATUS   ROLES    AGE     VERSION         INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION   CONTAINER-RUNTIME
raspberrypi   Ready    <none>   2m13s   v1.13.4-k3s.1   192.168.43.134   <none>        Raspbian GNU/Linux 9 (stretch)   4.14.98-v7+      containerd://1.2.4+unknown

Listing K3s Nodes

root@raspberrypi:~# k3s kubectl get nodes
NAME          STATUS   ROLES    AGE     VERSION
raspberrypi   Ready    <none>   2m26s   v1.13.4-k3s.1

Listing K3s Pods

root@raspberrypi:~# k3s kubectl get po
No resources found.
root@raspberrypi:~# k3s kubectl get po,svc,deploy
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.43.0.1    <none>        443/TCP   11h
root@raspberrypi:~#

containerd and Docker

k3s by default uses containerd. If you want to use it with Docker, all you just need to run the agent with the --docker flag

 k3s agent -s ${SERVER_URL} -t ${NODE_TOKEN} --docker &

Running Nginx Pods

To launch a pod using the container image nginx and exposing a HTTP API on port 80, execute:

root@raspberrypi:~# k3s kubectl run mynginx --image=nginx --replicas=3 --port=80
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/mynginx created

Listing the Nginx Pods

You can now see that the pod is running:

root@raspberrypi:~# k3s kubectl get po
NAME                       READY   STATUS    RESTARTS   AGE
mynginx-84b8d48d44-ggpcp   1/1     Running   0          119s
mynginx-84b8d48d44-hkdg8   1/1     Running   0          119s
mynginx-84b8d48d44-n4r6q   1/1     Running   0          119s

Exposing the Deployment

Create a Service object that exposes the deployment:


root@raspberrypi:~# k3s kubectl expose deployment mynginx --port 80
service/mynginx exposed

Verifying the endpoints controller for Pods

The below command verifies if endpoints controller has found the correct Pods for your Service:

root@raspberrypi:~# k3s kubectl get endpoints mynginx
NAME      ENDPOINTS                                   AGE
mynginx   10.42.0.10:80,10.42.0.11:80,10.42.0.12:80   17s

Testing if Nginx application is up & running:


root@raspberrypi:~# curl 10.42.0.10:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Adding a new Node to K3s Cluster


To add more nodes to the cluster just run k3s agent --server ${URL} --token ${TOKEN} on another host and it will join the cluster. It’s really that simple to set up a Kubernetes cluster with k3s.

To test drive K3s on multi-node cluster, first you will need to copy the token which is stored on the below location:

root@raspberrypi:~# cat /var/lib/rancher/k3s/server/node-token
K108b8e370b380bea959e8017abea3e540d1113f55df2c3f303ae771dc73fc67aa3::node:42e3dfc68ee27cf7cbdae5e4c8ac91b2
root@raspberrypi:~#

Create a variable NODETOKEN with token ID and then pass it directly with k3s agent command as shown below:

root@pi-node1:~# NODETOKEN=K108b8e370b380bea959e8017abea3e540d1113f55df2c3f303ae771dc73fc67aa3::node:42e3dfc68ee27cf7cbdae5e4c8ac91b2
root@pi-node1:~# k3s agent --server https://192.168.1.5:6443 --token ${NODETOKEN}
INFO[2019-04-04T23:09:16.804457435+05:30] Starting k3s agent v0.3.0 (9a1a1ec)
INFO[2019-04-04T23:09:19.563259194+05:30] Logging containerd to /var/lib/rancher/k3s/agent/containerd/containerd.log
INFO[2019-04-04T23:09:19.563629400+05:30] Running containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/containerd
INFO[2019-04-04T23:09:19.613809334+05:30] Connecting to wss://192.168.1.5:6443/v1-k3s/connect
INFO[2019-04-04T23:09:19.614108395+05:30] Connecting to proxy                           url="wss://192.168.1.5:6443/v1-k3s/connect"
FATA[2019-04-04T23:09:19.907450499+05:30] Failed to start tls listener: listen tcp 127.0.0.1:6445: bind: address already in use
root@pi-node1:~# pkill -9 k3s
root@pi-node1:~# k3s agent --server https://192.168.1.5:6443 --token ${NODETOKEN}
INFO[2019-04-04T23:09:45.843235117+05:30] Starting k3s agent v0.3.0 (9a1a1ec)
INFO[2019-04-04T23:09:48.272160155+05:30] Logging containerd to /var/lib/rancher/k3s/agent/containerd/containerd.log
INFO[2019-04-04T23:09:48.272542392+05:30] Running containerd -c /var/lib/rancher/k3s/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/k3s/agent/containerd
/run/k3s/containerd/containerd.sock: connect: connection refused"
INFO[2019-04-04T23:09:49.321863688+05:30] Waiting for containerd startup: rpc error: code = Unknown desc = server is not initialized yet
INFO[2019-04-04T23:09:50.347628159+05:30] Connecting to wss://192.168.1.5:6443/v1-k3s/connect

Listing the k3s Nodes

root@raspberrypi:~# k3s kubectl get nodes
NAME       STATUS   ROLES    AGE    VERSION
pi-node1   Ready    <none>   118s   v1.13.5-k3s.1
pi-node2   Ready    <none>   108m   v1.13.5-k3s.1

Setting up Nginx

As shown earlier, we will go ahead and test Nginx application on top of K3s cluster nodes

root@raspberrypi:~# k3s kubectl run mynginx --image=nginx --replicas=3 --port=80
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/mynginx created

Verifying the endpoints controller for Pods

root@raspberrypi:~# k3s kubectl expose deployment mynginx --port 80
service/mynginx exposed

Test driving Kubernetes Dashboard

root@node1:/home/pi# k3s kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/aio/deploy/recommended/kubernetes-dashboard.yaml
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
serviceaccount/kubernetes-dashboard created
role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created
root@node1:/home/pi#

We require kubectl proxy to get it accessible on our Web browser. This command creates a proxy server or application-level gateway between localhost and the Kubernetes API Server. It also allows serving static content over specified HTTP path. All incoming data enters through one port and gets forwarded to the remote kubernetes API Server port, except for the path matching the static content path.

root@node1:/home/pi# k3s kubectl proxy
Starting to serve on 127.0.0.1:8001

By now, you should be able to access Dashboard via 8001 port on your Raspberry Pi system browser.

Cleaning up

kubectl delete --all pods
pod "mynginx-84b8d48d44-9ghrl" deleted
pod "mynginx-84b8d48d44-bczsv" deleted
pod "mynginx-84b8d48d44-qqk9p" deleted

Hope you find this blog useful. In my future blog post, I will be talking about K3s Internals in detail.

References:

Docker Birthday #6: “Show-And-Tell” Event in Bangalore

Estimated Reading Time: 8 minutes

Docker’s Birthday Celebration is not just about cakes, food and party. It’s actually a global tradition that is near and dear to our heart because it gives each one of us an opportunity to express our gratitude to our huge community of contributors. The goal of this global celebration is to welcome every single Docker community users who are keen to understand and adopt this technology and influence others to grow this amazing community.

This year, celebrations all over the world took place during March 18-31, 2019 at across 75 Users groups events worldwide. Interestingly, Docker Inc. came up with really good idea of “Show-And-Tell: How do you Docker?” theme this time. Docker User Groups all over the world hosted local birthday show-and-tell celebrations. Each speaker got chance for 15-20 minutes of stage time to present how they’ve been using Docker. Every single speaker who presented their work got a Docker Birthday #6 T-shirt and have the opportunity to submit their Docker Birthday Show-and-tell to present at DockerCon. We celebrated Docker’s 6th Birthday in Bangalore at DellEMC Office, Mahadevapura on 30th March. Around 100+ audience participated for this Meetup event out of which 70% of the audience were beginners.

An Early Preparation..

Planning for Docker Birthday #6 celebration all started during the early first week of February. First of all, I came up with Docker Bangalore Meetup event page as to keep Community aware of upcoming “Show-And-Tell” event.

Soon after posting this event, my Google Forms got flooded with project stories. Received 30+ entries on the first 2 weeks which was just amazing. Out of overall 60 projects, I found 10 of the projects really powerful and hence started working with individuals to come up with better way to present it on the stage. In parallel, I placed an early order for a Birthday banner, Birthday stickers, T-shirts(Men & Women) for speakers, T-shirts(Men & Women) for the audience. Thanks to Docker, Inc for shipping it to Bangalore on-time.

Let’s talk about #7 Cool Projects…

After 3-4 week of continuous interaction, I finalized the list of 7 projects which looked really promising. In case you missed out this event, here is the short brief around each of these project work –

Project #1: Box-Exec

Akshit Grover, student of ACM VIT Student Chapter was one among the young engineer who came up with cool project idea titled “Box-Exec”.

Box Execute is an npm package to compile/run codes (like C,CPP, Python) in a virtualized environment, Here virtualized environment used is a docker container. This packages is built to ease the task of running a code against test cases as done by websites used to practice algorithmic coding. It supports automatic CPU time sharing configuration between containers and load balancing between multiple containers allocated for same language.

The project is hosted under Github Repo: https://github.com/akshitgrover/box-exec

Project #2: Flipper

Shivam Yaduka, 3rd Year student of ACM VIT Student Chapter was the next speaker on stage who talked about his super cool project idea titled “Flipper – Build, Ship & Navigate”.

Flipper is a Docker playground which allows users to run Docker-in-Docker-In-Docker commands ~ all on a web browser in a matter of seconds. It gives the experience of having a free RHEL Virtual Machine in browser, where you can build and run Docker containers.

Highlights:

  • Flipper uses Python as a backend scripting language
  • Flipper uses Python-CGI in order to interact through a Web server with a client running a Web browser.
  • It uses HTML/CSS as a Front-end language.
  • It can be hosted on your Laptop flawlessly

I got chance to interlock with Shivam during my Docker session in VIT Campus where we discussed around this idea. I liked the idea and suggested him to talk around it in the upcoming Birthday Meetup. In his own words…

“…. I use Docker to provide Cloud Virtualization services like Software-As-A-Service(SaaS) and Container-As-A-Service(CaaS). The Hybrid Cloud is made and deployed on my own workstation, No commercial platforms have been used. In SaaS, whenever a user launches a particular software, in the background a docker shell is created with the particular software installed in it and the user gets to access the service. In CaaS, if a user wants a quick Linux terminal, all he need is to click on the start button after he enters his username and a random number. A docker shell is created in the background and is displayed on the browser itself. So the user can quickly do his tasks. I have used Ansible to execute docker commands but a major portion of SaaS and CaaS is done on python36 and python-cgi to integrate front-end and back-end…”

His project is hosted on GITHUB and you can access it via
https://github.com/yshivam/Flipper

Project #3: GigaHex

Shad Amez from Expedia was next to present his amazingly cool project rightly titled “Gigahex – SandBox for Big Data Developers”

He started his talk around the challenges around existing Sandbox tools like VirtualBox, bloated Docker images for Big Data applications. He claimed a smaller footprint, low CPU & system Overhead and automation with his promising “GigaHex” platform.

He is yet to launch his cool project in Q2 this year. You can expect much more at https://launcher.gigahex.com/

Project #4: Z10N : Device simulation at scale using Docker Swarm

Hemanth Gaikwad, Validation Architect from DellEMC, headed over to the stage to talk around his active project titled ” Z10N : Device simulation at scale using Docker Swarm “.


Hemanth initiated his presentation talking about the existing challenges in delivering products to the customer on time with high quality. He stated that the major challenge is to develop and test as thoroughly and efficiently as we can, given our time and resource constraints. Essentially a company needs improved quality and reduced software lifecycle time to be able to survive in the competitive software landscape and reap the benefits of being early to market with high quality software features. Hardware availability happens to be scarce which results in design, development and tests getting pushed right. Products are developed and tested under non-scaled environments for just a few finite states, again impacting quality. Reduced quality would inherently further increase the costs and efforts.

An in-house tool called “Z10N” (pronounced zee-on) can help create real world lab environment with thousands of hardware devices at the fraction of cost for physical devices. Z10N would help the organization to:

  • Cut through the massive costs/efforts
  • Reduce vendor/hardware dependency
  • Enable rapid prototyping
  • Drastically simplify design & validation of complex sensor states/error conditions
  • Seamlessly design & develop products, execute automation & non-functional tests at will without worrying about the hardware availability Learn how you could simulate/emulate a hardware device and create thousands of clones for the same in just a few minutes with 99% reduction in expenditure.

He claimed that Z10N is already helping make better, faster products and with its capabilities it’s surely getting you the “Power to do more”.

Project #5: JAAS :
Distributed WorkLoad Testing using Containers

Next, Vishnu Murty, Senior Principal Engineer from DellEMC delivered a talk around “JAAS” – DellEMC in-house project for distributed workload testing using Docker containers.

Vishnu initiated his talk around challenges with existing Loading testing tools for various workloads like FTP, Web, Database, Mail etc. He stated that Load testing tools available in market comes with its own challenges like Cost, Learning Curve and Workloads Support. To cope with these challenges, he started looking at possible solution and hence JAAS (JMeter As A Service) was born. JAAS uses Containers and open source tools to deliver servers validation efforts.

Tech Stack behind JAAS:

  • Containers and Docker SWARM: For auto deploying of JMeter Apps, we use Docker containers. We use Docker SWARM service for creating Virtual JMETER Users for Generating the Load.
  • JMeter: Performance/Load testing framework from Apache, has been widely accepted as a Performance/Load testing tool for multiple applications.
  • Python: Python responsible for communicating across all individual components (Docker SWARM and ELK Stack) using Rest API.
  • ELK Stack: We store all logs, beats Data, JMeter results in Elastic Search. Visualize in Kibana.

His talk has been selected for Containerday happening June 24-26 at Hamburg https://www.containerdays.io/ . Don’t miss out his talk if you get chance to attend this conference.

Project #6: Comparative Study of Hadoop over VMs Vs Docker containers

Shivankit Bagla was our next young speaker who talked about his recent International Journal of Applied Engineering Research document https://www.ripublication.com/ijaer18/ijaerv13n6_166.pdf and his talk was titled around “Comparative study of Hadoop over VM Vs Docker containers.

He talked about his project which was a comparative study of the performance of Hadoop cluster in a containerised environment Vs virtual machine. He demonstrated on how running a Hadoop cluster in a Docker environment actually increases the performance of a Hadoop cluster and decreases the time taken by Hadoop system to perform certain actions.

Project #7: Turn Your Raspberry Pi into CCTV Surveillance Camera using Docker Containers

I presented my recent experiment around Docker containers on Raspberry Pi cluster showcasing how to turn Raspberry Pi into CCTV Camera using a single Docker container. I couldn’t get much time to demonstrate due to time constraint but I would suggest you to check out my detailed blog post around it via
http://collabnix.com/turn-your-raspberry-pi-into-low-cost-cctv-surveillance-camerawith-night-vision-in-5-minutes-using-docker/




Special thanks to the below list of individuals who provided support to make this event successful –

  • Shad Amez, Expedia
  • Akshit Grover, VIT
  • Shivam Yaduka, VIT
  • Shavitha Pareek, DellEMC
  • Vishnu Murty, DellEMC
  • Hemanth Gaikwad, DellEMC
  • Vineeth Abhraham, DellEMC
  • Shivankit Bagla, Acceletrade

Below are the list of topics as well as slides links for all the above listed project ideas:

TopicPresentation
GigaHex – Sandbox Environment for Big Data Application by Shad Amez, ExpediaSlides
Box-Exec – by Akshit Grover, VITSlides
Device Simulation at Scale using Docker Swarm by Hemanth Gaikwad, DellEMC
Distributed WorkLoad Testing Using Docker Containers by Visnu Murty, DellEMC
Flipper – Tiny Cloud on Browser using Docker by Shivam Yaduka, VITSlides
Comparative Study of Hadoop over Virtual Machine Vs Docker Containers by Shivankit BaglaSlides

References:

5 Minutes to Kubernetes Dashboard running on Docker Desktop for Windows 2.0.0.3

Estimated Reading Time: 6 minutes



If you want to get started with Kubernetes on your Laptop running Windows 10, Docker Desktop for Windows CE is the quickest way. Docker Desktop is the preferred choice for millions of developers that are building containerized applications for couple of reasons. The major reasons being –

  • 1-click installation and setup of a complete Docker development environment for Windows
  • Integrated tools including the Docker command lineDocker Compose and kubectl command line
  • Ability to start/stop with a single click
  • In-built Single Node Kubernetes Cluster

Docker Desktop is an easy-to-install application for your Mac or Windows environment that enables you to start coding and containerizing in minutes. Docker Desktop includes everything you need to build, test and ship containerized applications right from your machine.

Today Docker Desktop for Windows comes in two flavour – Docker Desktop Community & Docker Desktop Enterprise. You can download these editions via the below link:

Please note that you will need license file for Docker Desktop Enterprise to be installed on your Windows Laptop. Also, you will need to remove Docker Desktop Community Edition before you go ahead and install Enterprise release.


Docker Desktop Enterprise takes Docker Desktop Community, formerly known as Docker for Windows and Docker for Mac, a step further with simplified enterprise application development and maintenance. With Docker Desktop Enterprise, IT organizations can ensure developers are working with the same version of Docker Desktop Enterprise and can easily distribute Docker Desktop Enterprise to large teams using a number of third-party endpoint management applications. With the Docker Desktop Enterprise graphical user interface (GUI), developers are no longer required to work with lower-level Docker commands and can auto-generate Docker artifacts

Installing Docker Desktop for Windows 2.0.0.3 Platform

Let us started with a simple installation of Docker Desktop Community Release. Open https://hub.docker.com/editions/community/docker-ce-desktop-windows and click on “Login to Download” page to download and install Docker Desktop for Windows. Once you install Docker Desktop, you can see “whale” icon appear in the below taskbar(as shown below):

Checking Docker Version

There are two ways to verify Docker version – one through UI and other via CLI. To verify it via CLI, all you need is to run docker version to check the basic details of your deployment. You should see “Windows” listed as the operating system for the Docker client and the Docker Engine:

Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:31 2019
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     true
 Kubernetes:
  Version:          v1.10.11
  StackAPI:         v1beta2
PS C:\Users\Ajeet_Raina>

The OS/Arch field tells you the operating system and CPU architecture you’re using. Docker is cross-platform, so you can manage Windows Docker servers from a Linux client and vice-versa, using the same docker commands.

Open up Whale icon which you see in the taskbar menu and browse through “Settings”. Click on Kubernetes and select the options shown below to bring up Kubernetes cluster.

Based on your internet speed, you need to wait for single node kubernetes cluster to come up. Once the UI shows “Kubernetes is running”, you should be good to go ahead and perform the below commands.

Verify the Kubectl

PS C:\WINDOWS\system32> kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4
b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:38:32Z", GoVersion:"go1.9.3", Compiler:"gc", Plat
md64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4
b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:25:46Z", GoVersion:"go1.9.3", Compiler:"gc", Plat
64"}
PS C:\WINDOWS\system32>



Setting up Kubernetes Dashboard

Dashboard is a web-based Kubernetes user interface. You can use Dashboard to deploy containerized applications to a Kubernetes cluster, troubleshoot your containerized application, and manage the cluster resources. You can use Dashboard to get an overview of applications running on your cluster, as well as for creating or modifying individual Kubernetes resources (such as Deployments, Jobs, DaemonSets, etc). For example, you can scale a Deployment, initiate a rolling update, restart a pod or deploy new applications using a deploy wizard.

Dashboard also provides information on the state of Kubernetes resources in your cluster and on any errors that may have occurred.

Let us go ahead and test drive Kubernetes dashboard in just 2 minutes.

PS C:\Users\Ajeet_Raina> kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
secret "kubernetes-dashboard-certs" created
serviceaccount "kubernetes-dashboard" created
role.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
deployment.apps "kubernetes-dashboard" created
service "kubernetes-dashboard" created
PS C:\Users\Ajeet_Raina>

You can access Dashboard using the kubectl command-line tool by running the following command:

PS C:\Users\Ajeet_Raina> kubectl proxy
Starting to serve on 127.0.0.1:8001

Go to http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ on Browser and you will get the below output:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "no endpoints available for service \"kubernetes-dashboard\"",
  "reason": "ServiceUnavailable",
  "code": 503
}
curl http://localhost:8001/api

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "192.168.65.3:6443"
    }
  ]
}
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/",
    "/apis/admissionregistration.k8s.io",
    "/apis/admissionregistration.k8s.io/v1beta1",
    "/apis/apiextensions.k8s.io",
    "/apis/apiextensions.k8s.io/v1beta1",
    "/apis/apiregistration.k8s.io",
    "/apis/apiregistration.k8s.io/v1",
    "/apis/apiregistration.k8s.io/v1beta1",
    "/apis/apps",
    "/apis/apps/v1",
    "/apis/apps/v1beta1",
    "/apis/apps/v1beta2",
    "/apis/authentication.k8s.io",
    "/apis/authentication.k8s.io/v1",
    "/apis/authentication.k8s.io/v1beta1",
    "/apis/authorization.k8s.io",
    "/apis/authorization.k8s.io/v1",
    "/apis/authorization.k8s.io/v1beta1",
    "/apis/autoscaling",
    "/apis/autoscaling/v1",
    "/apis/autoscaling/v2beta1",
    "/apis/batch",
    "/apis/batch/v1",
    "/apis/batch/v1beta1",
    "/apis/certificates.k8s.io",
    "/apis/certificates.k8s.io/v1beta1",
    "/apis/compose.docker.com",
    "/apis/compose.docker.com/v1beta1",
    "/apis/compose.docker.com/v1beta2",
    "/apis/events.k8s.io",
    "/apis/events.k8s.io/v1beta1",
    "/apis/extensions",
    "/apis/extensions/v1beta1",
    "/apis/networking.k8s.io",
    "/apis/networking.k8s.io/v1",
    "/apis/policy",
    "/apis/policy/v1beta1",
    "/apis/rbac.authorization.k8s.io",
    "/apis/rbac.authorization.k8s.io/v1",
    "/apis/rbac.authorization.k8s.io/v1beta1",
    "/apis/storage.k8s.io",
    "/apis/storage.k8s.io/v1",
    "/apis/storage.k8s.io/v1beta1",
    "/healthz",
    "/healthz/autoregister-completion",
    "/healthz/etcd",
    "/healthz/ping",
    "/healthz/poststarthook/apiservice-openapi-controller",
    "/healthz/poststarthook/apiservice-registration-controller",
    "/healthz/poststarthook/apiservice-status-available-controller",
    "/healthz/poststarthook/bootstrap-controller",
    "/healthz/poststarthook/ca-registration",
    "/healthz/poststarthook/generic-apiserver-start-informers",
    "/healthz/poststarthook/kube-apiserver-autoregistration",
    "/healthz/poststarthook/rbac/bootstrap-roles",
    "/healthz/poststarthook/start-apiextensions-controllers",
    "/healthz/poststarthook/start-apiextensions-informers",
    "/healthz/poststarthook/start-kube-aggregator-informers",
    "/healthz/poststarthook/start-kube-apiserver-informers",
    "/logs",
    "/metrics",
    "/openapi/v2",
    "/swagger-2.0.0.json",
    "/swagger-2.0.0.pb-v1",
    "/swagger-2.0.0.pb-v1.gz",
    "/swagger.json",
    "/swaggerapi",
    "/version"
  ]
}

Wait, where is the dashboard?

Browse to http://:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ and this shall open up kubeconfig page as shown below:

Run the below command to set token:

PS C:\Users\Ajeet_Raina\Desktop> $TOKEN=((kubectl -n kube-system describe secret default | Select-String "token:") -split " +")[1]

PS C:\Users\Ajeet_Raina\Desktop> kubectl config set-credentials docker-for-desktop --token="${TOKEN}"



Click on Kubeconfig and select the “config” file under C:\Users<Username>.kube\config

That’s it. You should be able to access Kubernetes Dashboard as shown below:

You can view the nodes details under Dashboard:

Viewing the Namespace:

You can get quick view of roles by clicking on “Roles” on the left side of the UI:

Viewing the Storage Classes:

Viewing the services:

Further Readings:

Turn Your Raspberry Pi into Low-cost CCTV Surveillance Camera(with Night Vision) in 5 Minutes using Docker

Estimated Reading Time: 9 minutes

Last week I purchased Raspberry PI Infrared IR Night Vision Surveillance Camera Module 500W Webcam. This webcam features 5MP with OmniVision 5647 sensor which is in fixed focus mode. The high-definition 5MP camera delivers outstanding photos but can also shoot video, ideal for drones or a CCTV project. The camera overcomes the disadvantages offered by our other Raspberry Pi Cameras as it has provision for night surveillance too.

It cost me 1190 bucks (INR) and took just 3-4 day time to arrive. This Raspberry Pi Camera Module is a custom designed add-on for Raspberry Pi. It attaches to Raspberry Pi by way of one of the two small sockets on the board upper surface. This interface uses the dedicated CSI interface, which was designed especially for interfacing to cameras. The CSI bus is capable of extremely high data rates, and it exclusively carries pixel data.

Under this blog post, I will showcase how to install the latest Docker 18.09.0 on Raspberry Pi. I will test drive BuildKit on top of this credit-card sized device and finally showcase how to turn this small Pi into low-cost HD surveillance camera using a single Docker Image.

Pre-requisite:

Hardware:

  1. Raspberry Pi 3 ( You can order it from Amazon in case you are in India for 2590 INR)
  2. Micro-SD card reader ( I got it from here )
  3. Any Windows/Linux/MacOS
  4. HDMI cable ( I used the HDMI cable of my plasma TV)
  5. Internet Connectivity(WiFi/Broadband/Tethering using Mobile) – to download Docker 18.09.0 package
  6. Keyboard & mouse connected to Pi’s USB ports

Software:

  1. SD-Formatter – to format microSD card (in case of Windows Laptop)
  2. Win32DiskImager(in case you have Windows OS running on your laptop) – to burn Raspbian format directly into microSD card.(No need to extract XZ using any tool). You can use Etcher tool if you are using macbook.

Steps to Flash Raspbian OS on Pi Box:

  1. Format the microSD card using SD Formatter as shown below:
4

2. Download Raspbian OS from here and use Win32 imager(in case you are on Windows OS  running on your laptop) to burn it on microSD card.

3. Insert the microSD card into your Pi box. Now connect the HDMI cable  from one end of Pi’s HDMI slot to your TV or display unit and mobile charger(recommended 5.1V@1.5A).

4. Let the Raspbian OS boot up on your Pi box. It takes hardly 2 minutes for OS to come up.

5. Configure WiFi via GUI. All you need is to input the right password for your WiFi.

6. The default username is “pi” and password is “raspberry”. You can use this credentials to login into the Pi system.

7. You can use “FindPI” Android application to search for IP address if you don’t want to look out for Keyboard or mouse to search for the right IP address.

Enable SSH to perform remote login

To login via your laptop, you need to allow SSH service running. You can verify IP address command via ifconfig command.

[Captains-Bay]🚩 >  ssh pi@192.168.1.5
pi@192.168.1.5's password:
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb 26 12:30:00 2019 from 192.168.1.4
pi@raspberrypi:~ $ sudo su
root@raspberrypi:/home/pi# cd

Verifying Raspbian OS Version

root@raspberrypi:~# cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
root@raspberrypi:~#

Installing Docker 18.09

root@raspberrypi:~# curl -sSL https://get.docker.com/ | sh
# Executing docker install script, commit: 40b1b76
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sh -c curl -fsSL "https://download.docker.com/linux/raspbian/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sh -c echo "deb [arch=armhf] https://download.docker.com/linux/raspbian stretch edge" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sh -c docker version
Client:
 Version:           18.09.0
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        4d60db4
 Built:             Wed Nov  7 00:57:21 2018
 OS/Arch:           linux/arm
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.0
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       4d60db4
  Built:            Wed Nov  7 00:17:57 2018
  OS/Arch:          linux/arm
  Experimental:     false
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker your-user

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
         containers which can be used to obtain root privileges on the
         docker host.
         Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
         for more information.

** DOCKER ENGINE - ENTERPRISE **

If you’re ready for production workloads, Docker Engine - Enterprise also includes:

  * SLA-backed technical support
  * Extended lifecycle maintenance policy for patches and hotfixes
  * Access to certified ecosystem content

** Learn more at https://dockr.ly/engine2 **

ACTIVATE your own engine to Docker Engine - Enterprise using:

  sudo docker engine activate

Verifying Docker Version

root@raspberrypi:~# docker version
Client:
 Version:           18.09.0
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        4d60db4
 Built:             Wed Nov  7 00:57:21 2018
 OS/Arch:           linux/arm
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.0
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       4d60db4
  Built:            Wed Nov  7 00:17:57 2018
  OS/Arch:          linux/arm
  Experimental:     false
root@raspberrypi:~#

Test Drive Nginx App on Pi Box

root@raspberrypi:~# docker run -d -p 80:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
9c38b5a8a4d5: Pull complete
1c9b1b3e1e0d: Pull complete
258951b5612f: Pull complete
Digest: sha256:dd2d0ac3fff2f007d99e033b64854be0941e19a2ad51f174d9240dda20d9f534
Status: Downloaded newer image for nginx:latest
d812bf50d136b0f78353f0a0c763b6b08ecc5e7ce706bac8bd660cdd723e0fcd
root@raspberrypi:~#
root@raspberrypi:~# curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@raspberrypi:~#
root@raspberrypi:~# docker info
Containers: 1
 Running: 1
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 18.09.0
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 9754871865f7fe2f4e74d43e2fc7ccd237edcbce
runc version: 09c8266bf2fcf9519a651b04ae54c967b9ab86ec
init version: fec3683
Security Options:
 seccomp
  Profile: default
Kernel Version: 4.14.98-v7+
Operating System: Raspbian GNU/Linux 9 (stretch)
OSType: linux
Architecture: armv7l
CPUs: 4
Total Memory: 927.2MiB
Name: raspberrypi
ID: FEUI:RVU6:AWPZ:6P22:TSLT:FDJC:CBIB:D2NU:AQEQ:IHVH:HFRY:HYWF
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
Product License: Community Engine

WARNING: No memory limit support
WARNING: No swap limit support
WARNING: No kernel memory limit support
WARNING: No oom kill disable support
WARNING: No cpu cfs quota support
WARNING: No cpu cfs period support

BuildKit on Raspberry Pi

root@raspberrypi:~# export DOCKER_BUILDKIT=1
root@raspberrypi:~# git clone https://github.com/ajeetraina/hellowhale
Cloning into 'hellowhale'...
remote: Enumerating objects: 28, done.
remote: Total 28 (delta 0), reused 0 (delta 0), pack-reused 28
Unpacking objects: 100% (28/28), done.
root@raspberrypi:~# cd hellowhale/
root@raspberrypi:~/hellowhale# ls
Dockerfile  html  README.md  wrapper.sh
root@raspberrypi:~/hellowhale# docker build -t ajeetraina/hellowhalecom .
[+] Building 7.9s (5/8)                                                         
 => [internal] load build definition from Dockerfile                       0.1s
 => => transferring dockerfile: 129B                                       0.0s
 => [internal] load .dockerignore                                          0.2s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for docker.io/library/nginx:latest            0.0s
 => [1/3] FROM docker.io/library/nginx:latest                              0.0s
 => => resolve docker.io/library/nginx:latest                              0.0s
 => [internal] helper image for file operations                            0.1s
 => => resolve docker.io/docker/dockerfile-copy:v0.1.9@sha256:e8f159d3f00  7.5s
 => => sha256:b13ecc473b58ad8d80fba73ae6de690f6fcbe341bdaca42 736B / 736B  0.0s
 => => sha256:fabe16b757ee155dfd7210795199962d1b35e22b3437d06 767B / 767B  0.0s
 => [internal] load build context                                          0.1s
 => => transferring context: 34.39kB                                       0.0s

root@raspberrypi:~/hellowhale# time docker build -t ajeetraina/hellowhale .
[+] Building 0.4s (9/9) FINISHED                                                
 => [internal] load build definition from Dockerfile                       0.1s
 => => transferring dockerfile: 31B                                        0.0s
 => [internal] load .dockerignore                                          0.1s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for docker.io/library/nginx:latest            0.0s
 => [internal] helper image for file operations                            0.0s
 => [1/3] FROM docker.io/library/nginx:latest                              0.0s
 => [internal] load build context                                          0.0s
 => => transferring context: 317B                                          0.0s
 => CACHED [2/3] COPY wrapper.sh /                                         0.0s
 => CACHED [3/3] COPY html /usr/share/nginx/html                           0.0s
 => exporting to image                                                     0.1s
 => => exporting layers                                                    0.0s
 => => writing image sha256:5aee990f7e24e7c0f486ed01b4c1f8696ff307f836af1  0.0s
 => => naming to docker.io/ajeetraina/hellowhale                           0.0s

real	0m0.615s
user	0m0.204s
sys	0m0.082s

Verifying Dockerd

root@raspberrypi:~/hellowhale# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: e
   Active: active (running) since Tue 2019-02-26 13:01:04 IST; 38min ago
     Docs: https://docs.docker.com
 Main PID: 2437 (dockerd)
      CPU: 1min 46.174s
   CGroup: /system.slice/docker.service
           ├─2437 /usr/bin/dockerd -H unix://
           ├─2705 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8
           └─4186 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8

Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.400368104+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.402012958+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.402634316+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.403005881+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.408358205+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.810154786+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.810334839+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.811462659+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.811768546+0
Feb 26 13:37:07 raspberrypi dockerd[2437]: time="2019-02-26T13:37:07.402282796+0

Verifying if armv7 hello-world image is available or not

docker run --rm mplatform/mquery hello-world
Unable to find image 'mplatform/mquery:latest' locally
latest: Pulling from mplatform/mquery
db6020507de3: Pull complete
5107afd39b7f: Pull complete
Digest: sha256:e15189e3d6fbcee8a6ad2ef04c1ec80420ab0fdcf0d70408c0e914af80dfb107
Status: Downloaded newer image for mplatform/mquery:latest
Image: hello-world
 * Manifest List: Yes
 * Supported platforms:
   - linux/amd64
   - linux/arm/v5
   - linux/arm/v7
   - linux/arm64
   - linux/386
   - linux/ppc64le
   - linux/s390x
   - windows/amd64:10.0.14393.2551
   - windows/amd64:10.0.16299.846
   - windows/amd64:10.0.17134.469
   - windows/amd64:10.0.17763.194

Verifying hellowhale Image

root@raspberrypi:~# docker run --rm mplatform/mquery ajeetraina/hellowhale
Image: ajeetraina/hellowhale
 * Manifest List: No
 * Supports: amd64/linux

Verifying Prometheus Image

root@raspberrypi:~# docker run --rm mplatform/mquery rycus86/prometheus
Image: rycus86/prometheus
 * Manifest List: Yes
 * Supported platforms:
   - linux/amd64
   - linux/arm/v7
   - linux/arm64

Running Low-cost HD surveillance Camera system using Docker Container

We have reached finally to the interesting topic of this blog post. Now we are going to run a Docker container which runs CCTV surveillance software – all with a single-liner CLI.

Cloning the Repository:

$ git clone https://github.com/collabnix/docker-cctv-raspbian
$ cd docker-cctv-raspbian

Building the Docker Image

docker build -t collabnix/docker-cctv-raspbian .

Configuring Camera Interface

Before you execute run.sh, you need to configure Camera Interface by running the below command:

# raspi-config

It will open up command-line UI window, choose Interfacing , select Camera and enable it. Save and exit the CLI window.

Running the Docker container

Before you execute run.sh, you will need to load the required driver “bcm2835-v412” to make your camera module work. If you miss this step, you will end up seeing a blank screen even though the application comes up without any issue.

root@raspberrypi:~/rpi-motion# sudo modprobe bcm2835-v4l2
 root@raspberrypi:~/rpi-motion# ls
$sh run.sh

That’s it. Browse over to http://192.168.1.5:8082(either using Win Laptop or macbook) to open up CCTV cam which initiates the video streaming instantly. Cool, isn’t it?

I recorded this specific video for almost 1/2 hour to keep track of what “Spikey” – My Little Cocatail have been spending time in the weekend. It was cool to share this to my kid.

To summarize – Docker containers can make it really easy to turn your Pi box into HD surveillance camera in just few minutes. In my future blog post, I will bring up more exciting use cases around Docker and Pi. Stay tuned !

Test Drive 5 Cool Linux Applications on Docker Desktop for Windows Platform

Estimated Reading Time: 6 minutes

Docker Desktop for Windows 2.0.0.3 Release is available. This release comes with Docker Engine 18.09.2, Compose v1.23.2 & Kubernetes v1.10.11. One of the most anticipating feature introduced with this release is around the process isolation feature on Windows 10 for the first time. Process-isolation containers were already possible on Windows Server, but for the first time they are now also available on the regular Windows 10 of your laptop. One need to install the Docker Desktop Edge version 2.0.1.0 or newer to get benefit of process isolation feature. Please remember that Docker Engine should be at version 18.09.1 or higher.You must select a Windows base image from Dockerhub that matches the kernel of your host’s Windows version.

Can I run Linux-based application on Docker Desktop?

Yes, it is possible today. With Docker Desktop for Windows, it is possible to run Linux containers on Windows. All you need to do is to simply click on “Switch to Linux Containers” option under Preference Pane UI and start building and running Linux-based application. That’s it.

Under this blog post, I will be demonstrating Top 5 cool Linux based applications to run on Docker Desktop for Windows 2.0.0.3 platform.

  • Running NGINX Application on Docker Desktop
  • Running Your Own customized Web application on Docker Desktop
  • Building a Single Node Docker Swarm Cluster
  • Running Docker Swarm Visualizer Tool on Docker Desktop
  • Running WordPress Application on a single Node Swarm Cluster
  • Running Elastic Stack Application on Docker Desktop

Installing Docker Desktop for Windows 2.0.0.3 Platform

Let us started with a simple installation of Docker Desktop. Open https://hub.docker.com/editions/community/docker-ce-desktop-windows and click on “Login to Download” page to download and install Docker Desktop for Windows. Once you install Docker Desktop, you can see “whale” icon appear in the below taskbar(as shown below):

Checking Docker Version

There are two ways to verify Docker version – one through UI and other via CLI. To verify it via CLI, all you need is to run docker version to check the basic details of your deployment. You should see “Windows” listed as the operating system for the Docker client and the Docker Engine:

Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:31 2019
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     true
 Kubernetes:
  Version:          v1.10.11
  StackAPI:         Unknown
PS C:\Users\Ajeet_Raina>

The OS/Arch field tells you the operating system and CPU architecture you’re using. Docker is cross-platform, so you can manage Windows Docker servers from a Linux client and vice-versa, using the same docker commands.

Running Your First NGINX application

Let us start with “Hello World” example of web application to test drive our first application. Run the below command to bring up NGINX app which runs on port 80 on your laptop system.

PS C:\Users\Ajeet_Raina> docker run -d -p 80:80 nginx
567450d768e42e521bf3cec945d07bc3f796b6c5503d971881f5169e30a73215

That’s it. Open up your favourite browser and be ready to see NGINX default page instantly. Cool…isn’t it?

Running Your First Nginx based Docker Container

Under this example, I will showcase how to bring up your customized webpage. All you need to do is bring up your 2nd webpage to run on available port 81 as shown below:

PS C:\Users\Ajeet_Raina> docker run -d -p 81:80 ajeetraina/hellowhale
33e673c86f63990cdac2c155bc6bfe20a7b7809b82434908bc38517ae029d0e8

You can refer to https://github.com/ajeetraina/hellowhale to see how I built up this webpage in detail.

Building up Docker Swarm Cluster

Docker Swarm Mode is supported on Docker Desktop for Windows Platform. Let us first initiate Docker Swarm Mode and see how WordPress application can be deployed on this cluster.

PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress> docker swarm init
Swarm initialized: current node (29g3oqgz89f9g7gyicgq8h1o2) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-1gz58w1cgci63er4dhl6rkhhg29umkkt373ic85hpb3ywvtvqg-4ersf0a9dz00ime4xy
168.65.3:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress>

Verifying Single Node Cluster

PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress> docker node ls
ID                            HOSTNAME                STATUS              AVAILABILITY        MANAGER STATUS      ENGINE
 VERSION
29g3oqgz89f9g7gyicgq8h1o2 *   linuxkit-00155d1fffe2   Ready               Active              Leader              18.09.
2

Running Docker Swarm Visualizer

Let us try running Swarm Visualizer for Docker Swarm by using the below docker-compose file:

version: "3"
services:

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    stop_grace_period: 1m30s
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    deploy:
      placement:
        constraints: [node.role == manager]

All you need is to run the “docker-compose up -d” command to bring up visualizer tool as shown below:

Running WordPress Application on Docker Desktop running Swarm Mode Cluster

Let us first stop the last 2 containers which listen on port 80 and 81 and then follow the below command to bring up WordPress App.

Go ahead and clone the repository for “stack.yml” file under https://github.com/collabnix/dockerlabs/blob/master/beginners/install/windows/docker-desktop-for-windows/wordpress/stack.yml

Run the below command to bring up WordPress Application on Docker Swarm Mode Cluster.

PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress\example1> docker stack deploy --orchestrator=swarm -c stack.yml myapp10
.yml myapp10
Ignoring unsupported options: restart

Creating network myapp10_default
Creating service myapp10_db
Creating service myapp10_wordpress
PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress\example1>

Verifying the Stack

PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress\example1> docker stack --orchestrator=swarm ls
NAME                SERVICES            ORCHESTRATOR
myapp10             2                   Swarm
PS C:\Users\Ajeet_Raina\docker101\play-with-docker\wordpress\example1>

Hence, you can bring up Linux based WordPress application in just 1 minute.

Setting up Elastic Stack on Docker Desktop

We need to perform few of configuration changes related to Docker for Windows before we proceed with setting up ELK stack. First we need to enable share drives for ELK stack to work. Docker for Windows provides you a simplified approach to enable this feature. Click on Whale Icon > Shared Drives > Select “C:” local drive which will be made available to your Docker containers which run ELK Stack.

Once you select and click on “Apply” it will restart Docker as well as Kubernetes(if enabled earlier). This should be good enough for OpenUSM to work smoothly.

Cloning the ELK Repository

git clone https://github.com/collabnix/openusm

cd openusm/logging/

Setting up ELK Stack

Docker for Windows is a development platform and comes with docker-compose installed by default. All you need is to run the below command to bring up ELK stack… Awesome, Isn’t it?

docker-compose up -d

You can verify if ELK has come up or not by running the below command as shown:

Open up http://127.0.0.1:5601 to access Kibana UI as shown below:

Hope you found this blog really helpful. In my future posts, I will demonstrate 5 cool Windows based applications running on Docker Desktop Platform.

Top 5 Features of Docker Engine v18.09.1 That You Shouldn’t Miss Out

Estimated Reading Time: 11 minutes

Docker Engine v18.09.1 went GA last month. It was made available for both the Community and Enterprise users. Docker Enterprise is a superset of all the features in Docker Community Edition. It incorporates defect fixes that you can use in environments where new features cannot be adopted as quickly for consistency and compatibility reasons.

New in 18.09 is an aligned release model for Docker Engine – Community and Docker Engine – Enterprise. The new versioning scheme is YY.MM.x where x is an incrementing patch version. They will ship concurrently with the same x patch version based on the same code base.

[Updated – 2/15/2019]:Security fixes for Docker Engine – Enterprise and Docker Engine – Community

  • Update runc to address a critical vulnerability that allows specially-crafted containers to gain administrative privileges on the host. CVE-2019-5736
  • Ubuntu 14.04 customers using a 3.13 kernel will need to upgrade to a supported Ubuntu 4.x kernel

Docker Engine v18.09.1 comes with dozens of new features, improvements and bug fixes. Let us go through the list of Top features which you should be aware of while you upgrade to Docker 18.09.1 release.

  • Docker Engine v18.09.1 comes with containerd v1.2.2
  • BuildKit 0.3.3 is Available & is out of experimental mode
  • Support for Compose on Kubernetes
  • Exposing Product Info under docker info command
  • Process isolation on Windows 10 for the first time
  • Support for remote connections using SSH
  • Support for SSH agent socket forwarder
  • Support for “registry-mirrors” and “insecure-registries” when using BuildKit
  • Support for build-time secrets using a --secret flag when using BuildKit
  • Support for docker build –pull … when using BuildKit

Docker Engine v18.09.1 comes with containerd 1.2.2 version

Docker Engine v18.09.2 release for CE and EE both is shipped with containerd 1.2.2 version. In Docker versions prior to 18.09, containerd was managed by the Docker engine daemon. In Docker Engine 18.09, containerd is managed by systemd.

Let us try installing the latest Docker 18.09.2 on a fresh Ubuntu 18.10 VM and try verifying the containerd version.

sudo curl -sSL https://get.docker.com/ | sh
# Executing docker install script, commit: 26dda3d
+ sudo -E sh -c apt-get update -qq >/dev/null
+ sudo -E sh -c apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sudo -E sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sudo -E sh -c echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu cosmic edge" > /etc/apt/sources.list.d/docker.list
+ sudo -E sh -c apt-get update -qq >/dev/null
+ sudo -E sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ sudo -E sh -c docker version
Client:
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.6
 Git commit:        6247962
 Built:             Sun Feb 10 04:13:46 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 03:42:13 2019
  OS/Arch:          linux/amd64
  Experimental:     false
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:

  sudo usermod -aG docker robertsingh181

Remember that you will have to log out and back in for this to take effect!

WARNING: Adding a user to the "docker" group will grant the ability to run
         containers which can be used to obtain root privileges on the
         docker host.
         Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
         for more information.
@collabnix:~$ sudo usermod -aG docker robertsingh181

Verifying Docker Version

$sudo docker version
Client:
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.6
 Git commit:        6247962
 Built:             Sun Feb 10 04:13:46 2019
 OS/Arch:           linux/amd64
 Experimental:      false
Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 03:42:13 2019
  OS/Arch:          linux/amd64
  Experimental:     false

Please Note: The client and container runtime are now in separate packages from the daemon in Docker Engine 18.09. Users should install and update all three packages at the same time to get the latest patch releases.

For example, on Ubuntu: sudo apt install docker-ce docker-ce-cli containerd.io.

$ sudo dpkg --list | grep container
ii  containerd.io                  1.2.2-3                             amd64        An open and reliable container runtime
ii  docker-ce                      5:18.09.2~3-0~ubuntu-cosmic         amd64        Docker: the open-source application container engine
ii  docker-ce-cli                  5:18.09.2~3-0~ubuntu-cosmic         amd64        Docker CLI: the open-source application container engine

Verifying Containerd Version

$ sudo containerd --help
NAME:
 containerd - 
                  __        _                     __
_________  ____  / /_____ _(_)___  ___  _________/ /
/ ___/ __ \/ __ \/ __/ __ `/ / __ \/ _ \/ ___/ __  /
/ /__/ /_/ / / / / /_/ /_/ / / / / /  __/ /  / /_/ /
\___/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/   \__,_/
high performance container runtime
USAGE:
 containerd [global options] command [command options] [arguments...]
VERSION:
 1.2.2
COMMANDS:
   config    information on the containerd config
   publish   binary to publish events to containerd
   oci-hook  provides a base for OCI runtime hooks to allow arguments to be injected.
   help, h   Shows a list of commands or help for one command
GLOBAL OPTIONS:
 --config value, -c value     path to the configuration file (default: "/etc/containerd/config.toml")
 --log-level value, -l value  set the logging level [trace, debug, info, warn, error, fatal, panic]
 --address value, -a value    address for containerd's GRPC server
 --root value                 containerd root directory
 --state value                containerd state directory
 --help, -h                   show help
 --version, -v                print the version
$ sudo ctr version
Client:
Version:  1.2.2
Revision: 9754871865f7fe2f4e74d43e2fc7ccd237edcbce
Server:
Version:  1.2.2
Revision: 9754871865f7fe2f4e74d43e2fc7ccd237edcbce

Since containerd is managed by systemd under v18.09.1 release, any custom configuration to the docker.service systemd configuration which changes mount settings (for example, MountFlags=slave) breaks interactions between the Docker Engine daemon and containerd, and you will not be able to start containers. Run the following command to get the current value of the MountFlags property for the docker.service:

sudo systemctl show --property=MountFlags docker.service
MountFlags=

Update your configuration if this command prints a non-empty value for MountFlags, and restart the docker service.

BuildKit 0.3.3 is Available & is out of experimental mode

BuildKit is a new project under the Moby umbrella for building and packaging software using containers. It is a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner. Docker 18.09.0 is the first release with buildkit support. With this latest release, you can now run Buildkit without experimental mode enabled. Buildkit can now be configured with an option in daemon.json too.

The docker build is a Docker integrated tool for building images using Dockerfile. It requires Docker daemon to be running. It’s similar to docker run command but some features are intentionally removed for security reasons like no volumes(docker run -v, docker run --mount) and no privileged mode(`docker run –privileged). Buildkit is meant to become the next generation backend implementation for docker build command and github.com/docker/docker/builder package. This doesn’t mean any changes to Dockerfile format as buildkit draws a boundary between build backends and frontends. Dockerfile would be one of the frontend implementations. When invoked from the Docker CLI buildkit would be capable of exposing clients context directory as a source and use Docker containers as a worker. The snapshots would be backed by Docker’s layer store(containerD snapshot drivers). End results from the builder would be exported to docker images.

What problems does BuildKit solve for us?

If you look at Dockerfile, we are reading all commands in Dockerfile from start to the end one by one until we reach to the end.Modifying a single line always invalidates the caches of the subsequent lines. For example: N-th line is assumed to be always dependent on (N-1)th line

FROM debian
EXPOSE 80
RUN apt update && apt install git

As shown above, modifying the 2nd line(EXPOSE 80) always invalidates the apt cache due to false dependency. A user need to arrange the instructions carefully for efficient caching. This brings inefficient caching problem.

Not only this, inaccessible to private assets is another major problem with traditional Dockerfile. There is no safe way to access private assets(eg. Git Repos, S3) from build containers. Hence, copying credentials using COPY can leak the credentials accidently.Buildkit solves the above problems by using DAG-style low level language called LLB.

The main areas BuildKit improves on the current experience are performance, storage management, and extensibility. From the performance side, a significant update is a new fully concurrent build graph solver. It can run build steps in parallel when possible and optimize out commands that don’t have an impact on the final result. We have also optimized the access to the local source files. By tracking only the updates made to these files between repeated build invocations, there is no need to wait for local files to be read or uploaded before the work can begin.

Let us compare docker build Vs Buildkit and see how Buildkit builds the Docker image a more faster than traditional approach.

$ git clone https://github.com/ajeetraina/hellowhale
Cloning into 'hellowhale'...
remote: Enumerating objects: 28, done.
remote: Total 28 (delta 0), reused 0 (delta 0), pack-reused 28
Unpacking objects: 100% (28/28), done.
~$ cd hellowhale/
~$ ls
Dockerfile  README.md  html  wrapper.sh
:~/hellowhale$ time docker build -t ajeetraina/hellowhale .
Sending build context to Docker daemon  153.1kB
Step 1/4 : FROM nginx:latest
latest: Pulling from library/nginx
6ae821421a7d: Pull complete 
da4474e5966c: Pull complete 
eb2aec2b9c9f: Pull complete 
Digest: sha256:dd2d0ac3fff2f007d99e033b64854be0941e19a2ad51f174d9240dda20d9f534
Status: Downloaded newer image for nginx:latest
 ---> f09fe80eb0e7
Step 2/4 : COPY wrapper.sh /
 ---> 10d671c6cf08
Step 3/4 : COPY html /usr/share/nginx/html
 ---> 3e8a09f56168
Step 4/4 : CMD ["./wrapper.sh"]
 ---> Running in b1f24992f9e5
Removing intermediate container b1f24992f9e5
 ---> 9dae85ca0867
Successfully built 9dae85ca0867
Successfully tagged ajeetraina/hellowhale:latest
real    0m6.359s
user    0m0.035s
sys     0m0.022s

Let’s build it with buildkit:

 time docker build -t ajeetraina/hellowhale .
[+] Building 1.7s (9/9) FINISHED                                                                                                                                                 
 => [internal] load build definition from Dockerfile                                                                                                                        0.1s
 => => transferring dockerfile: 135B                                                                                                                                        0.0s
 => [internal] load .dockerignore                                                                                                                                           0.0s
 => => transferring context: 2B                                                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/nginx:latest                                                                                                             0.0s
 => [internal] helper image for file operations                                                                                                                             0.4s
 => => resolve docker.io/docker/dockerfile-copy:v0.1.9@sha256:e8f159d3f00786604b93c675ee2783f8dc194bb565e61ca5788f6a6e9d304061                                              0.7s
 => => sha256:e8f159d3f00786604b93c675ee2783f8dc194bb565e61ca5788f6a6e9d304061 2.03kB / 2.03kB                                                                              0.0s
 => => sha256:a546a4352bcaa6512f885d24fef3d9819e70551b98535ed1995e4b567ac6d05b 736B / 736B                                                                                  0.0s
 => => sha256:494e63343c3f0d392e7af8d718979262baec9496a23e97ad110d62b9c90d6182 766B / 766B                                                                                  0.0s
 => => sha256:df3b4bed1f63b36992540a09e0d10bd3f9d0b082d50810313841d745d7cce368 898.21kB / 898.21kB                                                                          0.2s
 => => sha256:f7b6696c3fee7264ec4486cebe146a6a98aa8d1e46747843107ff473aada8d56 861.00kB / 861.00kB                                                                          0.2s
 => => extracting sha256:df3b4bed1f63b36992540a09e0d10bd3f9d0b082d50810313841d745d7cce368                                                                                   0.1s
 => => extracting sha256:f7b6696c3fee7264ec4486cebe146a6a98aa8d1e46747843107ff473aada8d56                                                                                   0.1s
 => [1/3] FROM docker.io/library/nginx:latest                                                                                                                               0.0s
 => => resolve docker.io/library/nginx:latest                                                                                                                               0.0s
 => [internal] load build context                                                                                                                                           0.0s
 => => transferring context: 34.39kB                                                                                                                                        0.0s
 => [2/3] COPY wrapper.sh /                                                                                                                                                 0.2s
 => [3/3] COPY html /usr/share/nginx/html                                                                                                                                   0.2s
 => exporting to image                                                                                                                                                      0.1s
 => => exporting layers                                                                                                                                                     0.0s
 => => writing image sha256:db60ac4c90d7412b8c9f9382711f0d97a9ad9d4a33c05200aa36dc4c935c8cb3                                                                                0.0s
 => => naming to docker.io/ajeetraina/hellowhale                                                                                                                            0.0s
real    0m1.732s
user    0m0.042s
sys     0m0.019s
~/hellowhale$

Buildkit took just 0m1.732sec compared to 0m6.359sec taken by traditional docker build method.

Below are the list of dozens of enhancements which comes around Buildkit and I shall be discussing these in details in my upcoming blog posts:

Support for Compose on Kubernetes

Compose on Kubernetes allows you to deploy Docker Compose files onto a Kubernetes cluster. Compose on Kubernetes comes installed on Docker Desktop and Docker Enterprise. On Docker Desktop you will need to activate Kubernetes in the settings to use Compose on Kubernetes.

Check out my last 2 blogs which talks about how Compose on Kubernetes work for Play with Kubernetes & Minikube.

Docker v18.09.1 now exposes Product Info under docker info command

Under Docker v18.09.1 it is now possible to verify if it is an enterprise or community product as shown below:

Process isolation on Windows 10 for the first time

Process-isolation containers were already possible on Windows Server, but for the first time they are now also available on the regular Windows 10 of your laptop. Windows 10–1809 (“October 2018 Update”) + Docker engine 18.09.1 + the Windows 1809 base images from Dockerhub are the first combination that allows you to run “real” Windows containers on Windows 10, without the need of Hyper-v virtualization.

One need to install the Docker Desktop   Edge version 2.0.1.0 or newer. Please remember that Docker Engine should be at version 18.09.1 or higher.You must select a Windows base image from Dockerhub that matches the kernel of your host’s Windows version. For Windows 10–1809, that’s the :1809version/tag of nanoserverservercore and windows (or any higher-level image, that builds up on one of these).

Let us run a test container in process-isolation mode by adding the parameter --isolation=process :

docker run --isolation=process mcr.microsoft.com/windows/nanoserver:1809 cmd.exe /c ping 127.0.0.

In case you’re on Windows 10 Build 1706 and try to run the below command, it won’t work as expected. One need to be running atleast 1809 build for smooth operation.

Support for remote connections using SSH

Docker Engine v18.09 offers the possibility for a Docker client to communicate with a remote daemon via ssh. The Docker client communicates usually with the daemon either locally, via the unix socket /var/run/docker.sock, or over a network via a tcp socket. With Docker 18.09.1 you can now SSH to remote Docker host and execute docker CLI flawlessly.

This new connection method between client and engine allows for simple and shared SSH configuration which is far more common and more easily administered that the prior custom CA/certs solution via the docker cli, it is easily done by setting the env var DOCKER_HOST=ssh://hostname or directly on the docker command using the -H parameter as in

docker -H ssh://hostname info
$ docker -H ssh://ajeetraina@10.94.26.28 run -ti ubuntu echo “hello”
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
6cf436f81810: Pull complete 
987088a85b96: Pull complete 
b4624b3efe06: Pull complete 
d42beb8ded59: Pull complete 
Digest: sha256:7a47ccc3bbe8a451b500d2b53104868b46d60ee8f5

Please note that you might need to configure SSH key based login and run an SSH agent so you only need to enter a passphrase once. Especially if you are on cloud platform you will need SSH passphrase to allow this command to work as it directly doesn’t allow SSH from one cloud instance to another.

Below are further details of features which I am planning to discuss in my upcoming blog posts:

  • Added --chown flag support for ADD and COPY commands on Windows moby/moby#35521
  • Added docker engine subcommand to manage the lifecycle of a Docker Engine running as a privileged container on top of containerd, and to allow upgrades to Docker Engine Enterprise docker/cli#1260

A Bonus..

Please note that the client and container runtime are now in separate packages from the daemon in Docker Engine 18.09. Users should install and update all three packages at the same time to get the latest patch releases. For example, on Ubuntu:sudo apt install docker-ce docker-ce-cli containerd.io.

Hope you found this blog informative. In case of any query, feel free to drop me a message or join me at DockerLabs

Building Data Persistent & Datacenter Asset Reporting Capability with Racktables running inside Docker container

Estimated Reading Time: 5 minutes

Let’s talk about Docker inside the datacenter..

If you are a datacenter administrator and still scouring through a spreadsheet of “unallocated” IP addresses, tracking asset and service tag of your individual computer hardware systems, maintaining quite complex documentation of the racks, devices, links and network resources you have in control etc., you definitely need a robust asset management tool. Racktables is one of the most popular and lightweight tool which you can rely upon.

Racktables is a smart and robust solution for datacenter and server room asset management. It helps document hardware assets, network addresses, space in racks, networks configuration and much much more!

With RackTables you can:

  • Have a list of all devices you’ve got
  • Have a list of all racks and enclosures
  • Mount the devices into the racks
  • Maintain physical ports of the devices and links between them
  • Manage IP addresses, assign them to the devices and group them into networks
  • Document your NAT rules
  • Integrate Nagios, Cacti, Munin, Zabbix etc. as plugin directly into UI
  • Describe your loadbalancing policy and store loadbalancing configuration
  • Attach files to various objects in the system
  • Create users, assign permissions and allow or deny any actions they can do
  • Label everything and even everyone with flexible tagging system

Shown below is the screenshot of Racktables elements which comprises of Rackspace, Objects, IPv4 & IPv6 space, Virtual Respources, Logs, Configuration settings, IP SLB, 820.1Q, Patches & Cables.

My Image

Shown below is the reporting plugin which we are going to integrate into Racktables all using Docker containers. In case you’re new, Plugins provide the ability to add functionality to RackTables and, in some cases, override existing behavior. See the racktables-contribs repository for user-submitted plugins.

My Image

Racktables is a great tool based on LAMP stack. Sometimes it becomes cumbersome to install & manage this tool as you can expect great deal of dependencies around its packages for various distros of Linux.

If you visit https://www.freelists.org/list/racktables-users , you will notice numerous issues faced by first time Lab admins to build this platform with desired plugins and manage them. To simplify this, I started looking out how to build high persistent Racktables tool along with plugins integration & reporting capabilities.

Here’s a 2 min guide to setup Racktables along with its effective plugins inside Docker container:

Tested Infrastructure

PlatformNumber of InstanceReading Time
Ubuntu 18.04 VM15 min

Pre-requisite

  • Install Ubuntu 18.04 VM either on VM or Bare Metal system
  • Install Docker & Docker Compose

Install Docker

curl -sSL https://get.docker.com/ | sh

Install Docker Compose

curl -L https://github.com/docker/compose/releases/download/1.24.0-rc1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Clone this Repository

git clone https://github.com/collabnix/racktables-docker
cd racktables-docker

Install Docker

curl -sSL https://get.docker.com/ | sh

[Optional]Configuring DNS for your Docker container(in case you’re behind the firewall)

Edit daemon.json file and restart the docker daemon using “systemctl restart docker” command:

 cat /etc/docker/daemon.json
{
"dns": ["8.8.8.8"]
}

Bring up Racktables Services using Docker Compose

All you need is a Dockerfile & Docker compose file which brings up microservices together to build up Racktables tool. Under Dockerfile, you can add plugins of your choice. Under this example, I have added Reporting plugin so as to generate reports like who is the owner of the specific HW parts, how many number of specific types of components are present and so on..

The Content of Dockerfile look like

# vim: set ft=dockerfile:
FROM alpine:3.6
# Author with no obligation to maintain
MAINTAINER Ajeet Singh Raina ajeetraina@gmail.com>

ENV DBHOST="mariadb" \
    DBNAME="racktables" \
    DBUSER="racktables" \
    DBPASS=""

COPY entrypoint.sh /entrypoint.sh
RUN apk update
RUN apk --no-cache add \
    ca-certificates \
    curl \
    php5-bcmath \
    php5-curl \
    php5-fpm \
    php5-gd \
    php5-json \
    php5-ldap \
    php5-pcntl \
    php5-pdo_mysql \
    php5-snmp \
    && chmod +x /entrypoint.sh \
    && curl -sSLo /racktables.tar.gz 'https://github.com/RackTables/racktables/archive/RackTables-0.21.1.tar.gz' \
    && mkdir /opt \
    && tar -xz -C /opt -f /racktables.tar.gz \
    && mv /opt/racktables-RackTables-0.21.1 /opt/racktables \
    && rm -f /racktables.tar.gz \
    && sed -i \
    -e 's|^listen =.*$|listen = 9000|' \
    -e 's|^;daemonize =.*$|daemonize = no|' \
    /etc/php5/php-fpm.conf

# Adding Plugins for Racktable Reports

RUN apk add git \
   && git clone https://github.com/collabnix/racktables-contribs \
   && cd racktables-contribs/extensions \
   && cp -r plugins/* /opt/racktables/plugins/

VOLUME /opt/racktables/wwwroot
EXPOSE 9000
ENTRYPOINT ["/entrypoint.sh"]
CMD ["/usr/bin/php-fpm5"]

The content of Docker Compose file look like this:

mariadb:
  image: mariadb
  environment:
  - MYSQL_DATABASE=racktables
  - MYSQL_USER=racktables
  - MYSQL_PASSWORD=password123
  - MYSQL_RANDOM_ROOT_PASSWORD=password123
  volumes:
  - ./db_data:/var/lib/mysql

racktables:
  build: .
  links:
  - mariadb
  environment:
  - DBHOST=mariadb
  - DBNAME=racktables
  - DBUSER=racktables
  - DBPASS=password123
nginx:
  image: nginx:stable-alpine
  links:
  - racktables
  volumes_from:
  - racktables
  volumes:
  - ./nginx.conf:/etc/nginx/nginx.conf
  ports:
  - 80:80

cd racktables-docker
docker-compose build
docker-compose up -d 

Accessing Racktables UI

Start by browsing to http://localhost/?module=installer&step=5

Please don’t forget to add /?module=installer&step=5 at the end of the URL. Click on “Next”, enter your new password. Login as “admin” and “your new password”. That’s it. Here you have ~ your new Racktables tool installed along with Reporting + Data persistent capabilities.

If you browse to Main Page > Reports section you will see “Custom”, “Server”, “Switches”, “Virtual Machines” getting added automatically as shown below:

My Image

Did we talk about data persistence?

Containers are ephemeral in nature. Depending upon your frequent changes, there could be chances that your container might go down anytime and your application become inaccessible. No worry…As data persistence capability is already implemented, you need not worry about loosing your data.

The below code under Docker compose takes care of this functionality:

mariadb:
  image: mariadb
  environment:
  - MYSQL_DATABASE=racktables
  - MYSQL_USER=racktables
  - MYSQL_PASSWORD=password123
  - MYSQL_RANDOM_ROOT_PASSWORD=password123
  volumes:
  - ./db_data:/var/lib/mysql

Hope you found this blog informative. If you are facing any issue, feel free to raise any issue under https://github.com/collabnix/racktables-docker.

In my future blog post, I will talk about additional monitoring plugins which can be integrated into Racktables using Docker containers.

References:

  • https://www.freelists.org/list/racktables-users
  • https://github.com/RackTables/racktables-contribs

Test Drive Compose on Kubernetes on Play with Kubernetes(PWK) Playground in 5 Minutes

Estimated Reading Time: 8 minutes

On the 2nd day of Dockercon, Docker Inc. open sourced Compose on Kubernetes project. This project provides a simple way to define cloud native applications with a higher-level abstraction, the Docker Compose file. Docker Compose is a tool for defining and running multi-container Docker applications is already used by millions of Docker users.Docker Enterprise Edition already had this capability enabled starting Compose File version 3.3 where one can use the same docker-compose.yml file for Swarm deployment as well as one can specify Kubernetes workloads whenever stack is deployed.

2 week back, I noticed a community ask for running Compose on Kubernetes on Play with Kubernetes Playground. To my interest, I started looking at how to simplify the solution so that it becomes easy for anyone who can set it up in no time. I forked the repository and begin to build a simple script and Makefile to get it up and running over PWK.

ICYMI.. Check out my recent blog post ~ “Compose on Kubernetes for Minikube”.

Under this blog post, we will see how Compose on Kubernetes can be enabled on top of Play with Kubernetes Platform with just 2 scripts . Let’s get started.

Open https://labs.play-with-k8s.com/ to access Kubernetes Playground.

Click on the Login button to authenticate with Docker Hub or GitHub ID.

Once you start the session, you will have your own lab environment.

Adding First Kubernetes Node

Click on “Add New Instance” on the left to build your first Kubernetes Cluster node. It automatically names it as “node1”. Each instance has Docker Community Edition (CE) and Kubeadm already pre-installed. This node will be treated as the master node for our cluster.

Bootstrapping the Master Node

Clone the Repository and run this script on your 1st instance

git clone https://github.com/collabnix/compose-on-kubernetes
cd compose-on-kubernetes/scripts/pwk/
sh bootstrap-pwk.sh

When you execute this script, as part of initialization, the kubeadm write several configuration files needed, setup RBAC and deployed Kubernetes control plane components (like kube-apiserver, kube-dns, kube-proxy, etcd, etc.). Control plane components are deployed as Docker containers.

Copy the above kubeadm join token command and save it for the next step. This command will be used to join other nodes to your cluster.

Adding Worker Nodes

Click on “Add New Node” to add a new worker node.

Checking the Cluster Status

[node1 ~]$ kubectl get nodes
NAME      STATUS     ROLES     AGE       VERSION
node1     Ready      master    18m       v1.11.3
node2     Ready      <none>    4m        v1.11.3
node3     Ready      <none>    39s       v1.11.3
node4     NotReady   <none>    22s       v1.11.3
node5     NotReady   <none>    4s        v1.11.3

[node1 ]$ kubectl get po
No resources found.
[node1 ]$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   1h

Executing the below script which setup Compose Namespace, etcd cluster & Compose controller all in a single shot


chmod +x prepare-pwk.sh
sh prepare-pwk.sh
[node1 pwk]$ sh prepare-pwk.sh
Creating Compose Namespace...
namespace/compose created
Installing Helm...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 21.6M  100 21.6M    0     0  25.3M      0 --:--:-- --:--:-- --:--:-- 25.4M
Preparing Helm
linux-amd64/
linux-amd64/tiller
linux-amd64/helm
linux-amd64/LICENSE
linux-amd64/README.md
Creating tiller under kube-system namespace...
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller-cluster-rule created
Creating /root/.helm
Creating /root/.helm/repository
Creating /root/.helm/repository/cache
Creating /root/.helm/repository/local
Creating /root/.helm/plugins
Creating /root/.helm/starters
Creating /root/.helm/cache/archive
Creating /root/.helm/repository/repositories.yaml
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com
Adding local repo with URL: http://127.0.0.1:8879/charts
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!
 Tiller is still coming up...Please Wait
NAME                             READY     STATUS    RESTARTS   AGE
coredns-78fcdf6894-699fx         1/1       Running   0          5m
coredns-78fcdf6894-trslx         1/1       Running   0          5m
etcd-node1                       1/1       Running   0          4m
kube-apiserver-node1             1/1       Running   0          4m
kube-controller-manager-node1    1/1       Running   0          4m
kube-proxy-5gskp                 1/1       Running   0          4m
kube-proxy-5hbkb                 1/1       Running   0          5m
kube-proxy-lcsnz                 1/1       Running   0          4m
kube-scheduler-node1             1/1       Running   0          4m
tiller-deploy-85744d9bfb-bjw2f   0/1       Running   0          15s
weave-net-9vt2s                  2/2       Running   1          4m
weave-net-k87d7                  2/2       Running   0          5m
weave-net-nmmt5                  2/2       Running   0          4m
NAME:   etcd-operator
LAST DEPLOYED: Mon Jan 21 14:27:50 2019
NAMESPACE: compose
STATUS: DEPLOYED

RESOURCES:
==> v1/ServiceAccount
NAME                                               SECRETS  AGE
etcd-operator-etcd-operator-etcd-backup-operator   1        4s
etcd-operator-etcd-operator-etcd-operator          1        4s
etcd-operator-etcd-operator-etcd-restore-operator  1        4s

==> v1beta1/ClusterRole
NAME                                       AGE
etcd-operator-etcd-operator-etcd-operator  4s

==> v1beta1/ClusterRoleBinding
NAME                                               AGE
etcd-operator-etcd-operator-etcd-backup-operator   4s
etcd-operator-etcd-operator-etcd-operator          3s
etcd-operator-etcd-operator-etcd-restore-operator  3s

==> v1/Service
NAME                   TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)    AGE
etcd-restore-operator  ClusterIP  10.108.89.92  <none>       19999/TCP  3s

==> v1beta2/Deployment
NAME                                               DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
etcd-operator-etcd-operator-etcd-backup-operator   1        1        1           0          3s
etcd-operator-etcd-operator-etcd-operator          1        1        1           0          3s
etcd-operator-etcd-operator-etcd-restore-operator  1        1        1           0          3s

==> v1/Pod(related)
NAME                                                             READY  STATUS             RESTARTS  AGE
etcd-operator-etcd-operator-etcd-backup-operator-56fd448cd897mk  0/1    ContainerCreating  0      2s
etcd-operator-etcd-operator-etcd-operator-c5b8b8f74-pttr2        0/1    ContainerCreating  0      2s
etcd-operator-etcd-operator-etcd-restore-operator-58587cdc9g4br  0/1    ContainerCreating  0      2s


NOTES:
1. etcd-operator deployed.
  If you would like to deploy an etcd-cluster set cluster.enabled to true in values.yaml
  Check the etcd-operator logs
    export POD=$(kubectl get pods -l app=etcd-operator-etcd-operator-etcd-operator --namespacecompose --output name)
    kubectl logs $POD --namespace=compose
Loaded plugins: fastestmirror, ovl
base                                                                    | 3.6 kB  00:00:00
docker-ce-stable                                                        | 3.5 kB  00:00:00
extras                                                                  | 3.4 kB  00:00:00
kubernetes/signature                                                    |  454 B  00:00:00
kubernetes/signature                                                    | 1.4 kB  00:00:10 !!!
updates                                                                 | 3.4 kB  00:00:00
(1/7): base/7/x86_64/group_gz                                           | 166 kB  00:00:00
(2/7): extras/7/x86_64/primary_db                                       | 156 kB  00:00:00
(3/7): base/7/x86_64/primary_db                                         | 6.0 MB  00:00:00
(4/7): updates/7/x86_64/primary_db                                      | 1.3 MB  00:00:00
(5/7): docker-ce-stable/x86_64/primary_db                               |  20 kB  00:00:00
(6/7): docker-ce-stable/x86_64/updateinfo                               |   55 B  00:00:01
(7/7): kubernetes/primary                                               |  42 kB  00:00:01
Determining fastest mirrors
 * base: mirror.nl.datapacket.com
 * extras: mirror.nl.datapacket.com
 * updates: mirror.denit.net
kubernetes                                                                             305/305
Resolving Dependencies
--> Running transaction check
---> Package wget.x86_64 0:1.14-18.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===============================================================================================
 Package            Arch                 Version                      Repository          Size
===============================================================================================
Installing:
 wget               x86_64               1.14-18.el7                  base               547 k

Transaction Summary
===============================================================================================
Install  1 Package

Total download size: 547 k
Installed size: 2.0 M
Downloading packages:
wget-1.14-18.el7.x86_64.rpm                                             | 547 kB  00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : wget-1.14-18.el7.x86_64                                                     1/1
install-info: No such file or directory for /usr/share/info/wget.info.gz
  Verifying  : wget-1.14-18.el7.x86_64                                                     1/1

Installed:
  wget.x86_64 0:1.14-18.el7

Complete!
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been upgraded to the current version.
Happy Helming!
etcdcluster.etcd.database.coreos.com/compose-etcd created
NAME                             READY     STATUS    RESTARTS   AGE
coredns-78fcdf6894-699fx         1/1       Running   0          6m
coredns-78fcdf6894-trslx         1/1       Running   0          6m
etcd-node1                       1/1       Running   0          5m
kube-apiserver-node1             1/1       Running   0          6m
kube-controller-manager-node1    1/1       Running   0          5m
kube-proxy-5gskp                 1/1       Running   0          6m
kube-proxy-5hbkb                 1/1       Running   0          6m
kube-proxy-lcsnz                 1/1       Running   0          5m
kube-scheduler-node1             1/1       Running   0          5m
tiller-deploy-85744d9bfb-bjw2f   1/1       Running   0          1m
weave-net-9vt2s                  2/2       Running   1          6m
weave-net-k87d7                  2/2       Running   0          6m
weave-net-nmmt5                  2/2       Running   0          5m
--2019-01-21 14:28:49--  https://github.com/docker/compose-on-kubernetes/releases/download/v0.4.18/installer-linux
Resolving github.com (github.com)... 140.82.118.3, 140.82.118.4
Connecting to github.com (github.com)|140.82.118.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/158560458/e9a86500-15b2-11e9-8620-1eec5bf160e3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20190121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190121T142850Z&X-Amz-Expires=300&X-Amz-Signature=bd4020beb0f68210e2a3cfa8ca8166dddcf1d1e4868737eb9ad83363cd39c660&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dinstaller-linux&response-content-type=application%2Foctet-stream [following]
--2019-01-21 14:28:50--  https://github-production-release-asset-2e65be.s3.amazonaws.com/158560458/e9a86500-15b2-11e9-8620-1eec5bf160e3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20190121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190121T142850Z&X-Amz-Expires=300&X-Amz-Signature=bd4020beb0f68210e2a3cfa8ca8166dddcf1d1e4868737eb9ad83363cd39c660&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dinstaller-linux&response-content-type=application%2Foctet-stream
Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.161.163
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.161.163|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 28376064 (27M) [application/octet-stream]
Saving to: 'installer-linux'

100%[=====================================================>] 28,376,064  15.9MB/s   in 1.7s

2019-01-21 14:28:52 (15.9 MB/s) - 'installer-linux' saved [28376064/28376064]

INFO[0000] Checking installation state
INFO[0000] Install image with tag "v0.4.18" in namespace "compose"
INFO[0000] Api server: image: "docker/kube-compose-api-server:v0.4.18", pullPolicy: "Always"
INFO[0001] Controller: image: "docker/kube-compose-controller:v0.4.18", pullPolicy: "Always"
failed to find a Stack API version
error: the server doesn't have a resource type "stacks"
[node1 pwk]$ sh prepare-pwk.sh
Creating Compose Namespace...
Installing Helm...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 21.6M  100 21.6M    0     0  14.9M      0  0:00:01  0:00:01 --:--:-- 14.9M
Preparing Helm
linux-amd64/
linux-amd64/tiller
linux-amd64/helm
linux-amd64/LICENSE
linux-amd64/README.md
Creating tiller under kube-system namespace...
clusterrolebindings.rbac.authorization.k8s.io "tiller-cluster-rule" already exists
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been upgraded to the current version.
Happy Helming!
 Tiller is still coming up...Please Wait
NAME                             READY     STATUS    RESTARTS   AGE
coredns-78fcdf6894-699fx         1/1       Running   0          7m
coredns-78fcdf6894-trslx         1/1       Running   0          7m
etcd-node1                       1/1       Running   0          6m
kube-apiserver-node1             1/1       Running   0          6m
kube-controller-manager-node1    1/1       Running   0          6m
kube-proxy-5gskp                 1/1       Running   0          6m
kube-proxy-5hbkb                 1/1       Running   0          7m
kube-proxy-lcsnz                 1/1       Running   0          6m
kube-scheduler-node1             1/1       Running   0          6m
tiller-deploy-85744d9bfb-bjw2f   1/1       Running   0          2m
weave-net-9vt2s                  2/2       Running   1          6m
weave-net-k87d7                  2/2       Running   0          7m
weave-net-nmmt5                  2/2       Running   0          6m
NAME            REVISION        UPDATED                         STATUS          CHART        APP VERSION     NAMESPACE
etcd-operator   1               Mon Jan 21 14:27:50 2019        DEPLOYED        etcd-operator-0.8.3    0.9.3           compose
Run: helm ls --all etcd-operator; to check the status of the release
Or run: helm del --purge etcd-operator; to delete it
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: mirror.nl.datapacket.com
 * extras: mirror.nl.datapacket.com
 * updates: mirror.denit.net
Package wget-1.14-18.el7.x86_64 already installed and latest version
Nothing to do
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been upgraded to the current version.
Happy Helming!
etcdcluster.etcd.database.coreos.com/compose-etcd unchanged
NAME                             READY     STATUS    RESTARTS   AGE
coredns-78fcdf6894-699fx         1/1       Running   0          7m
coredns-78fcdf6894-trslx         1/1       Running   0          7m
etcd-node1                       1/1       Running   0          6m
kube-apiserver-node1             1/1       Running   0          7m
kube-controller-manager-node1    1/1       Running   0          7m
kube-proxy-5gskp                 1/1       Running   0          7m
kube-proxy-5hbkb                 1/1       Running   0          7m
kube-proxy-lcsnz                 1/1       Running   0          6m
kube-scheduler-node1             1/1       Running   0          6m
tiller-deploy-85744d9bfb-bjw2f   1/1       Running   0          2m
weave-net-9vt2s                  2/2       Running   1          7m
weave-net-k87d7                  2/2       Running   0          7m
weave-net-nmmt5                  2/2       Running   0          6m
--2019-01-21 14:30:05--  https://github.com/docker/compose-on-kubernetes/releases/download/v0.4.18/installer-linux
Resolving github.com (github.com)... 140.82.118.3, 140.82.118.4
Connecting to github.com (github.com)|140.82.118.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/158560458/e9a86500-15b2-11e9-8620-1eec5bf160e3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20190121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190121T143006Z&X-Amz-Expires=300&X-Amz-Signature=53d5f390f91b968a53219512c18b696e1a085cbbd59cdb953ca95bea1aca4d60&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dinstaller-linux&response-content-type=application%2Foctet-stream [following]
--2019-01-21 14:30:06--  https://github-production-release-asset-2e65be.s3.amazonaws.com/158560458/e9a86500-15b2-11e9-8620-1eec5bf160e3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20190121%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190121T143006Z&X-Amz-Expires=300&X-Amz-Signature=53d5f390f91b968a53219512c18b696e1a085cbbd59cdb953ca95bea1aca4d60&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dinstaller-linux&response-content-type=application%2Foctet-stream
Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.233.59
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.233.59|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 28376064 (27M) [application/octet-stream]
Saving to: 'installer-linux.1'

100%[=====================================================>] 28,376,064  16.3MB/s   in 1.7s

2019-01-21 14:30:08 (16.3 MB/s) - 'installer-linux.1' saved [28376064/28376064]

INFO[0000] Checking installation state
INFO[0001] Compose version v0.4.18 is already installed in namespace "compose" with the same settings
compose.docker.com/v1beta1
compose.docker.com/v1beta2
Waiting for the stack to be stable and running...
db1: Pending            [pod status: 0/2 ready, 2/2 pending, 0/2 failed]
web1: Pending           [pod status: 0/3 ready, 3/3 pending, 0/3 failed]
db1: Ready              [pod status: 1/2 ready, 1/2 pending, 0/2 failed]
web1: Ready             [pod status: 1/3 ready, 2/3 pending, 0/3 failed]

Stack hellostack is stable and running

NAME         SERVICES   PORTS        STATUS                            CREATED AT
hellostack   2          web1: 8082   Progressing (Stack is starting)   2019-01-21T14:30:10Z

Verifying the Stack

[node1 pwk]$ kubectl get stack
NAME         SERVICES   PORTS        STATUS                         CREATED AT
hellostack   2          web1: 8082   Available (Stack is started)   2019-01-21T14:30:10Z

References:

  • https://github.com/docker/compose-on-kubernetes/issues/35
  • https://github.com/collabnix/compose-on-kubernetes/tree/master/scripts/pwk