How to deploy distributed h2o flow cluster with docker?

南楼画角 提交于 2019-12-11 05:08:46

问题


I'm able to deploy a h2o cluster with ec2 instances and having the private ip in the flatfile. Doing the same with docker works but I can't figure out what to enter into the flatfile so they can create the cluster. Private IP the container is running on is not working


回答1:


Can the containers ping each others ip?

When launching h2o are you forcing the interface to use the container ip? java -jar h2o.jar -flatfile flatfile -ip -port

Are these docker containers when run exposing the port 54321 to each other? docker run -it -p 54321:54321




回答2:


As of the current version of H2O (3.18.0.8) what you can do is:

1) Put the list of EC2 instance private IP and port in the flatfile:

private-ip-1:54321
private-ip-2:54321
private-ip-3:54321

private-ip-1 should be in the standard four octet a.b.c.d network address form.

2) provide the --network host option to docker run:

docker run --network host [... rest of run command ...]


If you don't do this, what I think is happening is that each local H2O instance gets confused trying to figure out which node in the flatfile is itself. Since none of the local interfaces match what's in the flatfile, the cluster formation doesn't work for whatever reason.

I would actually consider this a bug.




回答3:


Ultimately, the solution for running H2O in docker may be to use a network plugin like weave, because weave can use multicasting (unlike docker overlay).

But I managed to hack together a solution for running H2O in docker swarm on an overlay network and a flatfile. The issue with running in swarm is that docker assigns each H2O instance two IP addresses: one resolvable as the stack_service and the other seen as $HOSTNAME from within the instance. H2O needs to use the $HOSTNAME IP, but it is difficult to determine this IP in advance for the flatfile. So instead, pass a config file with the stack_service names and then change them to IP addresses using a script before launching H2O in each instance.

So, for example, use a docker-compose file that defines three services:

services:
  h2o_worker1:
    image: [h2o image]
    configs:
      - source: flatfile
        target: /flatfile
    deploy:
      placement:
        constraints:
          - node.hostname == [node1]
    ... 
  h2o_worker2:
    image: [h2o image]
    configs:
      - source: flatfile
        target: /flatfile
    deploy:
      placement:
        constraints:
          - node.hostname == [node1]
    ... 
  h2o_worker3:
    image: [h2o image]
    configs:
      - source: flatfile
        target: /flatfile
    deploy:
      placement:
        constraints:
          - node.hostname == [node1]
    ... 

##### Configs #####
configs:
  flatfile:
    file: flatfile

Where ... is other docker compose parameters you need to enter, and [] represents things you need to define for your setup.

Now create a flatfile based on the service names that will be imported by the config:

h2o_worker1:54321
h2o_worker2:54321
h2o_worker3:54321

Obviously, change the ports if necessary. Then use an entrypoint script to lookup each service name's IP, and then add 1 to get the $HOSTNAME IP for each service. I just use sleep here to make sure all the services have started so that the IP lookup works. Docker always appears to assign the two IPS per service sequentially, but YMMV. As I said, this is a hack and probably not a great production-level solution. My entrypoint script looks something like this:

echo "Moving flatfile to ${H2O_HOME}"
cp /flatfile ${H2O_HOME}

sleep 60
echo "Replacing hostnames in flatfile with IP addresses."
grep -o -P '.*(?=:)' ${H2O_HOME}/flatfile > ${H2O_HOME}/hostnames
grep -o -P '(?<=:).*' ${H2O_HOME}/flatfile > ${H2O_HOME}/ports
dig +short $(cat ${H2O_HOME}/hostnames) > ${H2O_HOME}/hostnames_ip
cat ${H2O_HOME}/hostnames_ip | awk -F"." '{printf "%d.%d.%d.%d\n", $1, $2, $3, $4 + 1}' > ${H2O_HOME}/new_ips
paste -d ":" ${H2O_HOME}/new_ips ${H2O_HOME}/ports > ${H2O_HOME}/new_flatfile

echo "Starting H2O..."
bash -c "java -Xmx${H2O_NODE_MEMORY:-1g} -jar ${H2O_HOME}/h2o.jar -flatfile ${H2O_HOME}/new_flatfile"

The key here is using dig to retrieve the IP addresses for each service host, and then incrementing by one to get the secondary address that we need to pass to H2O. Note I define an environment variable in my Dockerfile so I can vary the node memory in the docker compose file. You don't need to do that. And the Dockerfile also sets a variable for the install location for H2O, to simplify things.

This lets me deploy the containers using docker swarm, and H2O in fact finds all the nodes correctly. Because H2O does not permit additions or deletions of nodes after the initial setup, it is not a big deal (at least for me) to define most of this in advance. That said, I may yet try to move to weave or another network plugin that avoids some of these issues.



来源:https://stackoverflow.com/questions/49907249/how-to-deploy-distributed-h2o-flow-cluster-with-docker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!