github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/docs/operating/docker-swarm/README.md (about)

     1  # Docker Swarm and IronFunctions
     2  
     3  How to run IronFunction as a scheduler on top of Docker Standalone Swarm cluster.
     4  
     5  ## Quick installation
     6  
     7  *Prerequisite 1: Make sure you have a working Docker 1.12+ Standalone Swarm cluster in place, you can build one by following the instructions at [Docker's website](https://docs.docker.com/swarm/).*
     8  
     9  *Prerequisite 2: It assumes that your running environment is already configured to use Swarm's master scheduler.*
    10  
    11  This is a step-by-step procedure to execute IronFunction on top of Docker Swarm cluster. It works by having IronFunction daemon started through Swarm's master, and there enqueueing tasks through Swarm API.
    12  
    13  ### Steps
    14  
    15  1. Start IronFunction in the Swarm Master. It expects all basic Docker environment variables to be present (DOCKER_TLS_VERIFY, DOCKER_HOST, DOCKER_CERT_PATH, DOCKER_MACHINE_NAME). The important part is that the working Swarm master environment must be passed to Functions daemon:
    16  ```ShellSession
    17  $ docker login # if you plan to use private images
    18  $ docker volume create --name functions-datafiles
    19  $ docker run -d --name functions \
    20          -p 8080:8080 \
    21          -e DOCKER_TLS_VERIFY \
    22          -e DOCKER_HOST \
    23          -e DOCKER_CERT_PATH="/docker-cert" \
    24          -e DOCKER_MACHINE_NAME \
    25          -v $DOCKER_CERT_PATH:/docker-cert \
    26          -v functions-datafiles:/app/data \
    27          iron/functions
    28  ```
    29  
    30  2. Once the daemon is started, check where it is listening for connections:
    31  
    32  ```ShellSession
    33  # docker info
    34  CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                                     NAMES
    35  5a0846e6a025        iron/functions       "/usr/local/bin/entry"   59 seconds ago      Up 58 seconds       2375/tcp, 10.0.0.1:8080->8080/tcp   swarm-agent-00/functions
    36  ````
    37  
    38  Note `10.0.0.1:8080` in `PORTS` column, this is where the service is listening. IronFunction will use Docker Swarm scheduler to deliver tasks to all nodes present in the cluster.
    39  
    40  3. Test the cluster:
    41  
    42  ```ShellSession
    43  $ export IRON_FUNCTION=$(docker port functions | cut -d ' ' -f3)
    44  
    45  $ curl -H "Content-Type: application/json" -X POST -d '{ "app": { "name":"myapp" } }' http://$IRON_FUNCTION/v1/apps
    46  {"message":"App successfully created","app":{"name":"myapp","config":null}}
    47  
    48  $ curl -H "Content-Type: application/json" -X POST -d '{ "route": { "type": "sync", "path":"/hello-sync", "image":"iron/hello" } }' http://$IRON_FUNCTION/v1/apps/myapp/routes
    49  {"message":"Route successfully created","route":{"app_name":"myapp","path":"/hello-sync","image":"iron/hello","memory":128,"type":"sync","config":null}}
    50  
    51  $ curl -H "Content-Type: application/json" -X POST -d '{ "name":"Johnny" }' http://$IRON_FUNCTION/r/myapp/hello-sync
    52  Hello Johnny!
    53  ```
    54  
    55  ## Production installation
    56  
    57  *Prerequisite 1: Make sure you have a working Docker Standalone Swarm cluster with multi-node network mode in place, you can build one by following the instructions at [Docker's website](https://docs.docker.com/swarm/). The instructions to build a multi-host network can be found at [Docker's engine manual](https://docs.docker.com/engine/userguide/networking/get-started-overlay/#overlay-networking-with-an-external-key-value-store).*
    58  
    59  *Prerequisite 2: It assumes that your running environment is already configured to use Swarm's master scheduler.*
    60  
    61  This is a step-by-step procedure to execute IronFunction on top of Docker Swarm cluster. It works by having IronFunction daemon started through Swarm's master, however the tasks are executed on each host locally. In production, database and message queue must be external to IronFunction execution, this guarantees robustness of the service against failures.
    62  
    63  We strongly recommend you deploy your own HA Redis and PostgreSQL clusters. Otherwise, you can follow the instructions below and have them set in single nodes.
    64  
    65  ### Groundwork
    66  
    67  Although we're assuming you already have your Docker Swarm installed and configured, these `docker-machine` calls are instructive regarding some configuration details:
    68  ```bash
    69  #!/bin/bash
    70  
    71  # Note how every host points to an external etcd both for swarm discovery (--swarm-discovery) as much as network configuration (--engine-opt=cluster-store=)
    72  docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery etcd://$ETCD_HOST:2379/swarm --engine-opt="cluster-store=etcd://$ETCD_HOST:2379/network" --engine-opt="cluster-advertise=eth1:2376" swarm-manager;
    73  
    74  # Set aside one host for DB activities
    75  docker-machine create -d virtualbox --engine-label use=db --swarm --swarm-discovery etcd://$ETCD_HOST:2379/swarm --engine-opt="cluster-store=etcd://$ETCD_HOST:2379/network" --engine-opt="cluster-advertise=eth1:2376" swarm-db;
    76  
    77  # The rest is a horizontally scalable set of hosts for IronFunction
    78  docker-machine create -d virtualbox --engine-label use=worker --swarm --swarm-discovery etcd://$ETCD_HOST:2379/swarm --engine-opt="cluster-store=etcd://$ETCD_HOST:2379/network" --engine-opt="cluster-advertise=eth1:2376" swarm-worker-00;
    79  docker-machine create -d virtualbox --engine-label use=worker --swarm --swarm-discovery etcd://$ETCD_HOST:2379/swarm --engine-opt="cluster-store=etcd://$ETCD_HOST:2379/network" --engine-opt="cluster-advertise=eth1:2376" swarm-worker-01
    80  ```
    81  
    82  ### Steps
    83  
    84  If you using externally deployed Redis and PostgreSQL cluster, you may skip to step 4.
    85  
    86  1. Build a multi-host network for IronFunction:
    87  ```ShellSession
    88  $ docker network create --driver overlay --subnet=10.0.9.0/24 functions-network
    89  ````
    90  
    91  2. Setup Redis as message queue service:
    92  ```ShellSession
    93  $ docker create -e constraint:use==db --network=functions-network -v /data --name redis-data redis /bin/true;
    94  $ docker run -d -e constraint:use==db --network=functions-network --volumes-from redis-data --name functions-redis redis;
    95  ````
    96  
    97  3. Setup PostgreSQL as datastore:
    98  ```ShellSession
    99  $ docker create -e constraint:use==db --network=functions-network -v /var/lib/postgresql/data --name postgresql-data postgres /bin/true;
   100  $ docker run -d -e constraint:use==db --network=functions-network --volumes-from postgresql-data --name functions-postgres -e POSTGRES_PASSWORD=mysecretpassword postgres
   101  ```
   102  
   103  4. Start IronFunctions:
   104  ```ShellSession
   105  $ docker run -d --name functions-00 \
   106          -l functions \
   107          -e constraint:use==worker \
   108          --network=functions-network \
   109          -p 8080:8080 \
   110          -v /var/run/docker.sock:/var/run/docker.sock \
   111          -e 'MQ_URL=redis://functions-redis' \
   112          -e 'DB_URL=postgres://postgres:mysecretpassword@functions-postgres/?sslmode=disable' \
   113          iron/functions
   114  ```
   115  
   116  5. Load Balancer:
   117  
   118  ```ShellSession
   119  $ export BACKENDS=$(docker ps --filter label=functions --format="{{ .ID }}" | xargs docker inspect | jq -r '.[].NetworkSettings.Ports["8080/tcp"][] | .HostIp + ":" + .HostPort' | paste -d, -s -)
   120  
   121  $ docker run -d --name functions-lb -p 80:80 -e BACKENDS noqcks/haproxy
   122  
   123  $ export IRON_FUNCTION=$(docker port functions-lb | cut -d ' ' -f3)
   124  
   125  $ curl -H "Content-Type: application/json" -X POST -d '{ "app": { "name":"myapp" } }' http://$IRON_FUNCTION/v1/apps
   126  {"message":"App successfully created","app":{"name":"myapp","config":null}}
   127  
   128  $ curl -H "Content-Type: application/json" -X POST -d '{ "route": { "type": "sync", "path":"/hello-sync", "image":"iron/hello" } }' http://$IRON_FUNCTION/v1/apps/myapp/routes
   129  {"message":"Route successfully created","route":{"app_name":"myapp","path":"/hello-sync","image":"iron/hello","memory":128,"type":"sync","config":null}}
   130  
   131  $ curl -H "Content-Type: application/json" -X POST -d '{ "name":"Johnny" }' http://$IRON_FUNCTION/r/myapp/hello-sync
   132  Hello Johnny!
   133  ```