Docker Swarm: Difference between revisions

From Wildsong
Jump to navigationJump to search
Brian Wilson (talk | contribs)
mNo edit summary
Brian Wilson (talk | contribs)
mNo edit summary
Line 1: Line 1:
Docker Swarm is an orchestrator and so is Kubernetes.  
Docker Swarm is an orchestrator for Docker containers and so is Kubernetes.
Today I spend an hour examining [[Kubernetes]] and it just adds more complexity that I don't need.


[[Kubernetes]] is breathing down my neck too and today I am thinking, "What the hell, go for it! Why NOT run a single node with Kubernetes?"
== Initialization ==
I spent an hour looking at it and it just adds more complexity.


Some day I will spin up some IoT and Edge nodes for buzzword compliance but for now it's just one node. [[Bellman]]
Here is the command to turn Bellman into a Docker Swarm Manager and a Node.
 
The command made me pick an ethernet address, because Bellman has more than one.
Note, it made me pick an ethernet address, this is Bellman's primary internet interface.
This is Bellman's primary internet interface.


  bellman> '''docker swarm init --advertise-addr 192.168.123.2'''
  bellman> '''docker swarm init --advertise-addr 192.168.123.2'''
Line 17: Line 17:
  To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
  To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.


I can add a node on another machine using that token. I won't be doing this today. It would look like this.
I can add more nodes on other machines using that token. I won't be doing this today. It would look like this.


  '''tern>''' docker swarm join --token SWMTKN-1-5b81dywl9xkis6769fxnsvjahfy361w2kxkz69nc35bz3nxt6s-43jxeopl6inw8xur1vpcl23w7 192.168.123.2:2377
  '''tern>''' docker swarm join --token SWMTKN-1-5b81dywl9xkis6769fxnsvjahfy361w2kxkz69nc35bz3nxt6s-43jxeopl6inw8xur1vpcl23w7 192.168.123.2:2377
Line 26: Line 26:
  isk0jocx0rb37yonoafstyvoj *  bellman            Ready              Active              Leader              19.03.5
  isk0jocx0rb37yonoafstyvoj *  bellman            Ready              Active              Leader              19.03.5
  vjbx2h8n8280ecib2btzkwcxw    tern                Ready              Active                                  18.09.1
  vjbx2h8n8280ecib2btzkwcxw    tern                Ready              Active                                  18.09.1
=== Create a network ===


  bellman> '''docker network create -d overlay --attachable testing'''
  bellman> '''docker network create -d overlay --attachable testing'''
Line 32: Line 34:
The "attachable" option is for containers not yet running in swarm. I will need that soon, when I run bash in Debian for tests.
The "attachable" option is for containers not yet running in swarm. I will need that soon, when I run bash in Debian for tests.


Now ordinarily I'd use Docker Compose to start a reverse proxy (my favorite today is Varnish).
== Spinning up my first Swarm-managed container ==


Before worrying about Varnish though I will spin up simple web server on just the one existing node.
To try things out I will spin up 4 copies of a simple web server.
If I add tern it will spread them over the two nodes. I want it to use that "testing" network.
When I add Tern it will spread them over the two nodes. I want it to use that "testing" network.


  docker service create --name web --replicas 4 -p 80:80 --network testing --detach nginx:latest
  docker service create --name web --replicas 4 -p 80:80 --network testing --detach nginx:latest


Now I have 4 copies of nginx running. I can see that they were published on port 80 but that's inside the funny swarm network, how to see them? They are on localhost, I can do this "curl http://localhost". I can get the id (or just use the name "web")  
Now I have 4 copies of nginx running. They were published on port 80 but that's inside the funny swarm network, how to see them?  
and then kill them off,
Well, they are also exposed directly on the host when I used the -p "publish" option. I can do "curl http://localhost".  
I can get the id (or just use the name "web") and then kill them off,


  docker service ls
  docker service ls
Line 46: Line 49:
  curl http://localhost
  curl http://localhost


When I do the "curl" with the nginx replicas shut down, I can see the page served by Varnish (still running in Compose), it's the Home Assistant instance.
When I do "curl" with the nginx replicas shut down, I see the page served by Varnish (still running in Compose), it's showing me the Home Assistant instance.
So I guess '''the swarm takes precedence over whatever is running in Compose'''.  
So I guess '''the swarm takes precedence over whatever is running in Compose'''.  
'''This bit me when I accidentally masked Psono by putting the test for nginx on port 81. That's where I run Psono.'''  
'''This bit me when I accidentally masked Psono by putting the test for nginx on port 81. That's where I run Psono.'''  


I skipped the "--network testing" parameter and everything still worked. I think maybe that's just so I can attach more services later?? Here's a test. This looks the way I expected.
I also tried skipping the "--network testing" parameter and everything still worked. Creating a separate network allows me to isolate
containers, just like with Docker and Docker Compose. For example, there is no reason for my Home Assistant and Pihole containers to
know about each other.


  docker run -it --rm --network testing debian:bullseye bash
  docker run -it --rm --network testing debian:bullseye bash
Line 69: Line 73:
The standard nginx page is returned from curl both times, so I know it's hitting a replica and running under the name "web", which is what I assigned.
The standard nginx page is returned from curl both times, so I know it's hitting a replica and running under the name "web", which is what I assigned.
Inside the container I can see my local LAN too, for example from the Debian instance I can "curl http://bellman.wildsong.biz:8123/" and get the Home Assistant page.
Inside the container I can see my local LAN too, for example from the Debian instance I can "curl http://bellman.wildsong.biz:8123/" and get the Home Assistant page.
So far, easy easy.
So far, all this is easy.
 
== That healthcheck thing ==


It's not too soon to think about it. ;-)
== Healthcheck ==


With nginx I can create my own Docker image and build the healthcheck right into the image.
With nginx I can create my own Docker image and bake the healthcheck right into the Docker image.
 
I know "curl" is not the best way to do this. https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/ but for now it's what I am using!   
Yes, I know "curl" is not the answer. https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/ but for now it's what I am using!   


In my Dockerfile, I have this  
In my Dockerfile, I have this  
Line 90: Line 91:
  01a3f36f7580  wildsong/nginx:latest      "/docker-entrypoint.…"  About a minute ago  Up About a minute (healthy)  80/tcp  web.1.ssssfmwmwp8je7g1dnsabevew
  01a3f36f7580  wildsong/nginx:latest      "/docker-entrypoint.…"  About a minute ago  Up About a minute (healthy)  80/tcp  web.1.ssssfmwmwp8je7g1dnsabevew


When I create the service, I will get a warning because I have not pushed that image (wildsong/nginx) to a registry, but it still works because I am running only one node for now. When I do "docker ps" I can see that the container is marked as "healthy".
When I create the service, I will get a warning because I have not pushed that image (wildsong/nginx) to a registry,  
 
but it still works because I am running only one node for now.  
When I do "docker ps" I can see that the container is marked as "healthy".


The service is bound to the IP address I created with the "docker swarm init" command. So I can hit it with the localhost address or the one I specified, with nginx, pointing a browser at http://192.168.123.2/ works.
The service is bound to the IP address I created with the "docker swarm init" command. So I can hit it with the localhost address or the one I specified, with nginx, pointing a browser at http://192.168.123.2/ works.
Line 100: Line 102:


== Replicas 0, Problems 1 ==
== Replicas 0, Problems 1 ==
Earlier in my testing regimen I was encountering creating a stack and having lots of services running but showing "Replicas 0/1". This means, nothing running. When I searched for the containers with "docker ps", there was nothing.


I kept going and got past this. When I figure out in 5 minutes what I did wrong I will write it up here. But that is what 0/1 means: nothing running for that service.
Earlier in my testing regimen I was encountering creating a stack
and having lots of services running but showing "Replicas 0/1".
This means, nothing running. When I searched for the containers with "docker ps", there was nothing.
I kept going and got past this. When I figure out in 5 minutes what I did wrong I will  
write it up here. But that is what 0/1 means: nothing running for that service.


== Services migration ==
== Service migration plan ==


I want to move the services I normally use on Bellman into the Swarm.
I want to move the services I normally use on Bellman into the Swarm.

Revision as of 22:29, 21 April 2023

Docker Swarm is an orchestrator for Docker containers and so is Kubernetes. Today I spend an hour examining Kubernetes and it just adds more complexity that I don't need.

Initialization

Here is the command to turn Bellman into a Docker Swarm Manager and a Node. The command made me pick an ethernet address, because Bellman has more than one. This is Bellman's primary internet interface.

bellman> docker swarm init --advertise-addr 192.168.123.2
Swarm initialized: current node (isk0jocx0rb37yonoafstyvoj) is now a manager.

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

   docker swarm join --token SWMTKN-1-5b81dywl9xkis6769fxnsvjahfy361w2kxkz69nc35bz3nxt6s-43jxeopl6inw8xur1vpcl23w7 192.168.123.2:2377

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

I can add more nodes on other machines using that token. I won't be doing this today. It would look like this.

tern> docker swarm join --token SWMTKN-1-5b81dywl9xkis6769fxnsvjahfy361w2kxkz69nc35bz3nxt6s-43jxeopl6inw8xur1vpcl23w7 192.168.123.2:2377
This node joined a swarm as a worker.
bellman> docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE  VERSION
isk0jocx0rb37yonoafstyvoj *   bellman             Ready               Active              Leader              19.03.5
vjbx2h8n8280ecib2btzkwcxw     tern                Ready               Active                                  18.09.1

Create a network

bellman> docker network create -d overlay --attachable testing
shaboxhgakqer14j1ve7zyysj

The "attachable" option is for containers not yet running in swarm. I will need that soon, when I run bash in Debian for tests.

Spinning up my first Swarm-managed container

To try things out I will spin up 4 copies of a simple web server. When I add Tern it will spread them over the two nodes. I want it to use that "testing" network.

docker service create --name web --replicas 4 -p 80:80 --network testing --detach nginx:latest

Now I have 4 copies of nginx running. They were published on port 80 but that's inside the funny swarm network, how to see them? Well, they are also exposed directly on the host when I used the -p "publish" option. I can do "curl http://localhost". I can get the id (or just use the name "web") and then kill them off,

docker service ls
docker service rm pmbrvm6wow7q
curl http://localhost

When I do "curl" with the nginx replicas shut down, I see the page served by Varnish (still running in Compose), it's showing me the Home Assistant instance. So I guess the swarm takes precedence over whatever is running in Compose. This bit me when I accidentally masked Psono by putting the test for nginx on port 81. That's where I run Psono.

I also tried skipping the "--network testing" parameter and everything still worked. Creating a separate network allows me to isolate containers, just like with Docker and Docker Compose. For example, there is no reason for my Home Assistant and Pihole containers to know about each other.

docker run -it --rm --network testing debian:bullseye bash
# apt update
# apt install -y bind9-dnsutils
# nslookup web
Server:         127.0.0.11
Address:        127.0.0.11#53

Non-authoritative answer:
Name:   web
Address: 10.0.1.27
# apt install -y curl
# curl http://10.0.1.27
# curl http://web/

The standard nginx page is returned from curl both times, so I know it's hitting a replica and running under the name "web", which is what I assigned. Inside the container I can see my local LAN too, for example from the Debian instance I can "curl http://bellman.wildsong.biz:8123/" and get the Home Assistant page. So far, all this is easy.

Healthcheck

With nginx I can create my own Docker image and bake the healthcheck right into the Docker image. I know "curl" is not the best way to do this. https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/ but for now it's what I am using!

In my Dockerfile, I have this

FROM nginx:latest
HEALTHCHECK CMD curl --fail http://localhost || exit 1
$ docker build -t wildsong/nginx .
$ docker service rm web
$ docker service create --name web --replicas 1 -p 80:80 --network testing --detach wildsong/nginx
$ docker ps | grep web
01a3f36f7580   wildsong/nginx:latest      "/docker-entrypoint.…"   About a minute ago   Up About a minute (healthy)   80/tcp   web.1.ssssfmwmwp8je7g1dnsabevew

When I create the service, I will get a warning because I have not pushed that image (wildsong/nginx) to a registry, but it still works because I am running only one node for now. When I do "docker ps" I can see that the container is marked as "healthy".

The service is bound to the IP address I created with the "docker swarm init" command. So I can hit it with the localhost address or the one I specified, with nginx, pointing a browser at http://192.168.123.2/ works.

I suspect this means Varnish will redirect traffic to it??? https://bellman.wildsong.biz/ should work if that's true. It does not, for some reason it's going to Home Assistant.

Okay. Some rule in Varnish was kicking in, not sure what, but I added Bellman support in there and now it's working as expected.

Replicas 0, Problems 1

Earlier in my testing regimen I was encountering creating a stack and having lots of services running but showing "Replicas 0/1". This means, nothing running. When I searched for the containers with "docker ps", there was nothing. I kept going and got past this. When I figure out in 5 minutes what I did wrong I will write it up here. But that is what 0/1 means: nothing running for that service.

Service migration plan

I want to move the services I normally use on Bellman into the Swarm.

  1. Varnish (and hitch)
  2. Pihole
  3. Psono (Including PostgreSQL)
  4. Home Assistant (Including Mosquitto)
  5. Unifi
  6. Logitech Media Server

Psono has to be accessible from the Internet but none of the others do; some things are in Varnish but really currently only for testing.

I see a copy of mysql, I wonder who that belongs to.

Also running today I have pgadmin and rocketchat, both of which I can shelve for now.

Before I can proceed, I need persistent data, and I need to deal with these issues.

  • Special case #1 for Home Assistant, I need a connection to a USB device (the radio for Zigbee and ZWave)
  • Special case #2, for Pihole I need to watch the network.

I think this means leaving both of these in a plain old Docker Compose set up for now.

Persistence: How do volumes work in a swarm?

Bring in Compose

By that I mean I want to deploy a stack of containers using a docker-compose.yml file as the configuration. So far I have not needed it, if I start just one container per project then "docker service" commands are fine.