Skip to content

Latest commit

 

History

History
247 lines (234 loc) · 10.4 KB

File metadata and controls

247 lines (234 loc) · 10.4 KB

Java EE Application on Docker Swarm Cluster

Docker Swarm solves one of the fundamental limitations of Docker where the containers could only run on a single Docker host. Docker Swarm is native clustering for Docker. It turns a pool of Docker hosts into a single, virtual host.

swarm1
Figure 1. Key Components of Docker Swarm

Swarm Manager: Docker Swarm has a Master or Manager, that is a pre-defined Docker Host, and is a single point for all administration. Currently only a single instance of manager is allowed in the cluster. This is a SPOF for high availability architectures and additional managers will be allowed in a future version of Swarm with #598. TODO: ADD LINK.

Swarm Nodes: The containers are deployed on Nodes that are additional Docker Hosts. Each Swarm Node must be accessible by the manager, each node must listen to the same network interface (TCP port). Each node runs a node agent that registers the referenced Docker daemon, monitors it, and updates the discovery backend with the node’s status. The containers run on a node.

Scheduler Strategy: Different scheduler strategies (binpack'', spread'' (default), and ``random'') can be applied to pick the best node to run your container. The default strategy optimizes the node for least number of running containers. There are multiple kinds of filters, such as constraints and affinity. This should allow for a decent scheduling algorithm.

Node Discovery Service: By default, Swarm uses hosted discovery service, based on Docker Hub, using tokens to discover nodes that are part of a cluster. However etcd, consul, and zookeeper can be also be used for service discovery as well. This is particularly useful if there is no access to Internet, or you are running the setup in a closed network. A new discovery backend can be created as explained here. It would be useful to have the hosted Discovery Service inside the firewall and #660 will discuss this.

Standard Docker API: Docker Swarm serves the standard Docker API and thus any tool that talks to a single Docker host will seamlessly scale to multiple hosts now. That means if you were using shell scripts using Docker CLI to configure multiple Docker hosts, the same CLI would can now talk to Swarm cluster and Docker Swarm will then act as proxy and run it on the cluster.

There are lots of other concepts but these are the main ones.

  1. Create a Swarm cluster. The easiest way of using Swarm is, by using the official Docker image:

    docker run swarm create

    This command returns a <TOKEN> and is the unique cluster id. It will be used when creating master and nodes later. This cluster id is returned by the hosted discovery service on Docker Hub.

    Note
    Make sure to note this cluster id now as there is no means to list it later.
  2. Swarm is fully integrated with Docker Machine, and so is the easiest way to get started. Let’s create a Swarm Master next:

    docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token://<TOKEN> swarm-master

    Replace <TOKEN> with the cluster id obtained in the previous step.

    --swarm configures the machine with Swarm, --swarm-master configures the created machine to be Swarm master. Swarm master creation talks to the hosted service on Docker Hub and informs that a master is created in the cluster.

  3. Connect to this newly created master and find some more information about it:

    eval "$(docker-machine env swarm-master)"
    docker info
    Note
    If you’re on Windows, use the docker-machine env swarm-master command only and copy the output into an editor to replace all appearances of EXPORT with SET and issue the three commands at your command prompt, remove the quotes and all duplicate appearences of "/".

    This will show the output as:

    > docker info
    Containers: 2
    Images: 7
    Storage Driver: aufs
     Root Dir: /mnt/sda1/var/lib/docker/aufs
     Backing Filesystem: extfs
     Dirs: 11
     Dirperm1 Supported: true
    Execution Driver: native-0.2
    Kernel Version: 4.0.3-boot2docker
    Operating System: Boot2Docker 1.6.2 (TCL 5.4); master : 4534e65 - Wed May 13 21:24:28 UTC 2015
    CPUs: 1
    Total Memory: 998.1 MiB
    Name: swarm-master
    ID: USSA:35LS:WVRN:GKAZ:MLD4:XMQF:P7PL:VQ5D:7V4K:2QAH:5D2L:HC4K
    Debug mode (server): true
    Debug mode (client): false
    Fds: 24
    Goroutines: 37
    System Time: Wed Jun 10 03:40:00 UTC 2015
    EventsListeners: 1
    Init SHA1: 7f9c6798b022e64f04d2aff8c75cbf38a2779493
    Init Path: /usr/local/bin/docker
    Docker Root Dir: /mnt/sda1/var/lib/docker
    Username: arungupta
    Registry: [https://index.docker.io/v1/]
    Labels:
     provider=virtualbox
  4. Create Swarm nodes.

    docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-01

    Replace <TOKEN> with the cluster id obtained in the previous step.

    Node creation talks to the hosted service at Docker Hub and joins the previously created cluster. This is specified by --swarm-discovery token://…​ and specifying the cluster id obtained earlier.

  5. To make it a real cluster, let’s create a second node:

    docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-02

    Replace <TOKEN> with the cluster id obtained in the previous step.

  6. List all the nodes / Docker machines, that has been created so far.

    docker-machine ls

    This shows the output as:

    NAME            ACTIVE   DRIVER       STATE     URL                         SWARM
    lab                      virtualbox   Running   tcp://192.168.99.103:2376
    swarm-master    *        virtualbox   Running   tcp://192.168.99.107:2376   swarm-master (master)
    swarm-node-01            virtualbox   Running   tcp://192.168.99.108:2376   swarm-master
    swarm-node-02            virtualbox   Running   tcp://192.168.99.109:2376   swarm-master

    The machines that are part of the cluster have the cluster’s name in the SWARM column, blank otherwise. For example, lab'' is a standalone machine where as all other machines are part of the swarm-master'' cluster. The Swarm master is also identified by (master) in the SWARM column.

  7. Connect to the Swarm cluster and find some information about it:

    eval "$(docker-machine env --swarm swarm-master)"
    docker info

    This shows the output as:

    > docker info
    Containers: 4
    Strategy: spread
    Filters: affinity, health, constraint, port, dependency
    Nodes: 3
     swarm-master: 192.168.99.107:2376
      └ Containers: 2
      └ Reserved CPUs: 0 / 1
      └ Reserved Memory: 0 B / 1.023 GiB
     swarm-node-01: 192.168.99.108:2376
      └ Containers: 1
      └ Reserved CPUs: 0 / 1
      └ Reserved Memory: 0 B / 1.023 GiB
     swarm-node-02: 192.168.99.109:2376
      └ Containers: 1
      └ Reserved CPUs: 0 / 1
      └ Reserved Memory: 0 B / 1.023 GiB

    There are 3 nodes – one Swarm master and 2 Swarm nodes. There is a total of 4 containers running in this cluster – one Swarm agent on master and each node, and there is an additional swarm-agent-master running on the master. This can be verified by connecting to the master and listing all the containers:

  8. List nodes in the cluster with the following command:

    docker run swarm list token://<TOKEN>

    This shows the output as:

    > docker run swarm list token://b9d9da9198c0facbeeae302242fb65a5
    192.168.99.109:2376
    192.168.99.108:2376
    192.168.99.107:2376

The complete cluster is in place now, and we need to deploy the Java EE application to it.

Swarm takes care for the distribution of the deployments across the nodes. The only thing, we need to do is to deploy the application as already explained in [JavaEE7_Container_Linking].

  1. Start MySQL server as:

    docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql

    -e define environment variables that are read by the database at startup and allow us to access the database with this user and password.

  2. Start WildFly and deploy Java EE 7 application as:

    docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7

    This is using the Docker Container Linking explained earlier.

  3. Check the state of the cluster as:

    > docker info
    Containers: 7
    Strategy: spread
    Filters: affinity, health, constraint, port, dependency
    Nodes: 3
     swarm-master: 192.168.99.107:2376
      └ Containers: 2
      └ Reserved CPUs: 0 / 1
      └ Reserved Memory: 0 B / 1.023 GiB
     swarm-node-01: 192.168.99.108:2376
      └ Containers: 2
      └ Reserved CPUs: 0 / 1
      └ Reserved Memory: 0 B / 1.023 GiB
     swarm-node-02: 192.168.99.109:2376
      └ Containers: 3
      └ Reserved CPUs: 0 / 1
      └ Reserved Memory: 0 B / 1.023 GiB

    ``swarm-node-02'' is running three containers and so lets look at the list of containers running there:

    > eval "$(docker-machine env swarm-node-02)"
    > docker ps -a
    CONTAINER ID        IMAGE                                    COMMAND                CREATED              STATUS              PORTS                    NAMES
    f8022254703d        arungupta/wildfly-mysql-javaee7:latest   "/opt/jboss/wildfly/   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp   mywildfly
    7b6e9324c735        mysql:latest                             "/entrypoint.sh mysq   7 minutes ago        Up 7 minutes        0.0.0.0:3306->3306/tcp   mysqldb
    6ed4c35c943b        swarm:latest                             "/swarm join --addr    12 minutes ago       Up 12 minutes       2375/tcp                 swarm-agent
  4. Access the application as:

    curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employees

    to see the output as:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>