0

I'm in the process of rolling out a High Availability docker swarm setup across multiple data centers, but I have a bit of a high-level question about configuration differentiation.

Say I have a single docker service, called worker, and a HA master-master SQL database between data centers dc-a and dc-b. At the moment, worker will use the same config, regardless of if it's being run on dc-a or dc-b.

Is there any way of differentiating the internal worker configuration or docker image, so if that if worker is deployed to dc-a, it runs config-a, and if deployed to dc-b, it runs config-b?

The end goal is to always target the database that is local to the current data center. I know it's possible to use different datacenter DNS entries to guide database connections to the local machine, but it'd be more flexible if we could use an entirely separate config/image depending on where the worker is deployed.

Is this possible with docker swarm?

Shookit
  • 103
  • 2

1 Answers1

1

The closest you can get is use a template in the service definition but that doesn't let you use node or engine labels. What you can get from that is {{.Node.Hostname}} which maps to the hostname. That string can be used in an environment variable definition or volume mount.

You'll either need to have your entrypoint parse that value to know where to point based on that hostname variable, or a directory of hostnames in the volume mount to load data specific to that hostname. The environment variable is easier and more flexible as you add more hosts, but assumes your hostname includes something that can point to which datacenter you are running inside.

For more details on using templates with a service definition, see the docs on service create: https://docs.docker.com/engine/reference/commandline/service_create/#create-services-using-templates


If this was me, I'd probably opt for an easier configuration of two separate services with similar configs, differing by maybe a single environment variable. Then use a node label constraint to run each service on only nodes in one data center or the other. You can use yaml anchors/aliases to copy between the services, e.g.:

version: '3.4'

services:
  app-east: &app-service
    image: app-image:${app_tag:-latest}
    deploy:
      replicas: 2
      placement:
        constraints:
        - 'node.labels.region==east'
    environment:
      DB: 'db-east'
      other_var: 'common value'
  app-west:
    <<: *app-service
    deploy:
      placement:
        constraints:
        - 'node.labels.region==west'
    environment:
      DB: 'db-west'

I've honestly never used yaml anchors and aliases that many layers up, and only changing one array entry, so you may find that you need to be a little more granular with their usage. That said, the end result of the above should be 4 containers, 2 in east, and another 2 in west, with the difference of a single DB environment variable.

BMitch
  • 5,966
  • 1
  • 25
  • 32
  • That's hugely helpful, thank you! In addition to workers like above, I also unfortunately have a cron-like service that regularly adds tasks for the workers to perform. I think DNS or virtual IPs might be the only way to work around that, as I can only have one instance of that running, regardless of DC. That said, the templating suggestion is great! – Shookit Apr 27 '18 at 11:51