Bootstrapping docker deamon - docker

In the official Kubernetes multinode Docker guide , it is mentioned that you need to another Docker instance:
A bootstrap Docker instance which is used to start etcd and flanneld, on which the Kubernetes components depend
So what is a bootstrap instance and how do you make sure that keeps running on restarts ?

The documentation gives a detailed explanation as to the purpose of the bootstrap instance of Docker:
This guide uses a pattern of running two instances of the Docker
daemon: 1) A bootstrap Docker instance which is used to start etcd and
flanneld, on which the Kubernetes components depend 2) A main Docker
instance which is used for the Kubernetes infrastructure and user’s
scheduled containers
This pattern is necessary because the flannel daemon is responsible
for setting up and managing the network that interconnects all of the
Docker containers created by Kubernetes. To achieve this, it must run
outside of the main Docker daemon. However, it is still useful to use
containers for deployment and management, so we create a simpler
bootstrap daemon to achieve this.
In summary the special bootstrap docker daemon runs the bits that kubernetes depends on, freeing up the the normal docker daemon to be managed by kubernetes. This is a trick that leverages the fact that both etcd and flanneld can be run as containers. Alternatively one would have to set them up locally as services.
As for ensuring the bootstrapping docker daemon survives a restart, the answer lies within the code. Here's where it's being called when running the master.sh script.
https://github.com/kubernetes/kube-deploy/blob/master/docker-multinode/master.sh#L36
https://github.com/kubernetes/kube-deploy/blob/master/docker-multinode/docker-bootstrap.sh#L20
So the code attempts to setup a service for the extra docker daemon process.

Related

Should we use supervisors to keep processes running in Docker containers?

I'm using Docker to run a java REST service in a container. If I were outside of a container then I might use a process manager/supervisor to ensures that the java service restarts if it encounters a strange one-off error. I see some posts about using supervisord inside of containers but it seems like they're focused mostly on running multiple services, rather than just keeping one up.
What is the common way of managing services that run in containers? Should I just be using some built in Docker stuff on the container itself rather than trying to include a process manager?
You should not use a process supervisor inside your Docker container for a single-service container. Using a process supervisor effectively hides the health of your service, making it more difficult to detect when you have a problem.
You should rely on your container orchestration layer (which may be Docker itself, or a higher level tool like Docker Swarm or Kubernetes) to restart the container if the service fails.
With Docker (or Docker Swarm), this means setting a restart policy on the container.

difference between docker service and docker container

I can create a docker container by command
docker run <<image_name>>
I can create a service by command
docker service create <<image_name>>
What is the difference between these two in behaviour?
When would I need to create a service over container?
docker service command in a docker swarm replaces the docker run. docker run has been built for single host solutions. Its whole idea is to focus on local containers on the system it is talking to. Whereas in a cluster the individual containers are irrelevant. We simply use swarm services to manage the multiple containers in a cluster. Swarm will orchestrate the containers of the services for us.
docker service create is mainly to be used in docker swarm mode. docker run does not have the concept of scaling up/down. With docker service create you can specify the number of replicas to be created using the --replicas command. This will create and manage multiple replicas of a containers in many different nodes. There are several such options for managing multiple containers using docker service create and other commands under docker service ...
One more note: docker services are for container orchestration systems(swarm). It has built in facility for failure recovery. ie. it recreates a container on failure. docker runwould never recreate a container if it fails. When the docker service commands are used we are not directly asking to perform action like "create a single container", rather we are saying to the orchestration system to "put this job in your queue and when you can get to it perform that action on the swarm". This means it has rollback facilities, failure mitigation and lots of intelligence built in.
You need to consider using docker service create when in swarm mode and docker run when not in swarm mode. You can lookup on docker swarms to understand docker services.
There is no real difference. In the official documentation you can read "Services are really just containers in production".
Services can be declared in "docker-compose.yml" and can be started from it. Once started, they will run as containers.
It is just a common way to name parts of your stack.

Docker swarm get deployment status

After running docker stack deploy to deploy some services to swarm is there a way to programmatically test if all containers started correctly?
The purpose would be to verify in a staging CI/CD pipeline that the containers are actually running and didn't fail on startup. Restart is disabled via restart_policy.
I was looking at docker stack services, is the replicas column useful for this purpose?
$ docker stack services --format "{{.ID}} {{.Replicas}}" my-stack-name
lxoksqmag0qb 0/1
ovqqnya8ato4 0/1
Yes, there are ways to do it, but it's manual and you'd have to be pretty comfortable with docker cli. Docker does not provide an easy built-in way to verify that docker stack deploy succeeded. There is an open issue about it.
Fortunately for us, community has created a few tools that implement docker's shortcomings in this regard. Some of the most notable ones:
https://github.com/issuu/sure-deploy
https://github.com/sudo-bmitch/docker-stack-wait
https://github.com/ubirak/docker-php
Issuu, authors of sure-deploy, have a very good article describing this issue.
Typically in CI/CD I see everyone using docker or docker-compose. A container runs the same in docker as it does docker swarm with respects to "does this container work by itself as intended".
That being said, if you still wanted to do integration testing in a multi-tier solution with swarm, you could do various things in automation. Note this would all be done on a single node swarm to make testing easier (docker events doesn't pull node events from all nodes, so tracking a single node is much easier for ci/cd):
Have something monitoring docker events, e.g. docker events -f service=<service-name> to ensure containers aren't dying.
always have healthchecks in your containers. They are the #1 way to ensure your app is healthy (at the container level) and you'll see them succeed or fail in docker events. You can put them in Dockerfiles, service create commands, and stack/compose files. Here's some great examples.
You could attach another container to the same network to test your services remotely 1-by-1 using tasks. with reverse DNS. This will avoid the VIP and let you talk to a specific replica(s).
You might get some stuff out of docker inspect <service-id or task-id>
Another solution might be to use docker service scale - it will not return until service is converged to specified amount of replicas or will timeout.
export STACK=devstack # swarm stack name
export SERVICE_APP=yourservice # service name
export SCALE_APP=2 # desired amount of replicas
docker stack deploy $STACK --with-registry-auth
docker service scale ${STACK}_${SERVICE_APP}=${SCALE_APP}
One drawback of that method is that you need to provide service names and their replica counts (but these can be extracted from compose spec file using jq).
Also, in my use case I had to specify timeout by prepending timeout command, i.e. timeout 60 docker service scale, because docker service scale was waiting its own timeout even if some containers failed, which could potentially slow down continuous delivery pipelines
References
Docker CLI: docker service scale
jq - command-line JSON processor
GNU Coreutils: timeout command
you can call this for every service. it returns when converged. (all ok)
docker service update STACK_SERVICENAME

Why does Docker have a daemon?

I recently discovered rkt, a competitor container runtime to Docker. It seems like rkt does not need a daemon. For me, rkt is like running any other command and it works easily with systemd (or other init systems).
This makes me wonder about the utility of Docker's daemon.
Why does Docker need a daemon ? What does the daemon provide that would not be possible without it ? Is its only goal to remove the need for an init system like systemd (as can be seen in the Rancher OS) ?
Docker was designed as a client/server application which allows you to have remote access to the docker API. This allows tools like the classic container based swarm that were effectively a reverse proxy to a cluster of docker hosts.
The daemon also provides a place for shared state. It's restarting containers according to their restart policy. But it's also managing networks and volumes that may be shared between multiple containers.
Lastly, with the introduction of swarm mode, the daemon is also the central location for these tools that would otherwise be run as their own daemons with tools like kubernetes.
If you need a daemon-less solution but otherwise like docker, then consider using runc which is the runtime environment that docker uses for each container by default.
This doesn't involve the init inside the container. If you need that, docker now includes an optional init that you can enable per container. And you've always had the option to include your own init, like tini, if you needed something to cleanup zombie processes.

sharing docker.sock or docker in docker (dind)

We're running a mesos cluster and jenkins for continuous integration workflow.
Jenkins is configured with the mesos plugin.
Previously we built our docker images in mesos containers. Now we are switching to docker containers for building our docker images.
I've been searching for the advantage of building our docker images inside a docker container with dind image like this one "dind-jenkins-slave" found on docker hub.
With dind you lose the caching opportunities when sharing the docker.sock of the host. And with dind you also have to push the privileged parameter.
What is the downside of just sharing the docker.sock of the host?
I'm using sharing docker.sock approach. The only downside which I see is security - you could do everything what you want with the host when you could run any docker containers. But if you trust people who create jobs or could control which docker containers with which options could be run from jenkins then giving access to main docker daemon is easy solution.
It depends on what you're doing, really. To get our jenkins jobs truly isolated so that we can run as many as we want in parallel, we switched to DinD. If you share the host socket you still only have a single docker daemon- port conflicts, pulling/pushing multiple images from separate jobs, and one job relying on an image or build that is also being messed with by another job are all issues.
To get around the caching issue, I create the dind container and leave it around. I run
docker start -a dindslave || docker run -v ${WORKSPACE}:/data my/dindimage jenkinscommands.sh
Then jenkins just writes its commands to jenkinscommands.sh and restarts the container every time. When you remove the container you remove your cache as well, and you don't share caches between jobs if that is something you want... but you don't have to think about jobs interfering with one another or making sure they are running on the same host.

Resources