Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Image ModifiedImage ModifiedImage Modified

Panel
titleColor#FFF
titleBGColor#2A7886
titleContinguts

Table of Contents
maxLevel2

 

 

Balanceig transparent amb Docker Swarm, Compose i Consul

Crearem un cluster de docker-engine i instanciarem allà els nostres contenidors docker. A més configurarem un servei balancejat d'alta disponibilitat escalable.

Docker Swarm: Ens permet crear un cluster docker. El node master rebrà i distribuirà els contenidors als nodes secundaris on s'executaran.

Consul: Ens proporcionarà el servei de discover dels nous nodes i serveis que afegim al clúster swarm.

Registrator: Aquest servei monitoritzarà la informació com ara IP i PORT de cada servei activat als hosts i ho guardarà al consul.

Docker Compose: Ens permet configurar i crear grups de contenidors.

 

Requeriments previs

  • Docker Engine: Ens permet crear els contenidors, gestionar-los i instanciar-los
  • Docker Machine: Ens permet crear i gestionar les maquines virtuals
  • Driver Docker Machine Opennebula: Ens permet utilitzar el docker-machine al cloud de l'OpenNebula
  • Podem escalar el servei ofert per un contenir augmentar o disminuint el nombre de contenidors.

    En la següent imatge es mostren un seguit eines d'DevOps cobreix tot el cicle de vida de les aplicacions, en el tutorial ens centrarem en la part del desplegament fent servir la plataforma OpenNebula juntament amb Docker Swarm, Docker Compose i el servei de Consul.

    Image Added

    Requeriments previs

    • Docker Engine: Ens permet crear els contenidors, gestionar-los i instanciar-los
    • Docker Machine: Ens permet crear i gestionar les maquines virtuals
    • Driver Docker Machine Opennebula: Ens permet utilitzar el docker-machine al cloud de l'OpenNebula
    • Docker Compose

    Instal·lar el requeriments:

    • Per a poder implementar el docker swarm cluster amb l'OpenNebula hem d'instalar el Docker Engine, Docker Machine i el Driver Docker Machine Opennebula.
    Docker Compose

    Instal·lar el requeriments:

    • Per a poder implementar el docker swarm cluster amb l'OpenNebula hem d'instalar el Docker Engine, Docker Machine i el Driver Docker Machine Opennebula.
      Aquí està el manual de com fer-ho: DOCKER-1 Docker Machine OpenNebula Driver

    • Per instal·lar Docker Compose:

      Code Block
      language
      languagebash
      themeRDarkbash
      sudo -i
      curl -L https://github.com/docker/compose/releases/download/1.76.0-rc12/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
      chmod +x /usr/local/bin/docker-compose 
      exit

    Consul

    Disposarem d'una maquina virtual que ens proporcionarà el servei de discover amb consul

    Creem una màquina virtual a l'OpenNebula anomenada consul i deprés executem un contenidor docker de consul dins d'ella.

    Code Block
    languagebash
    themeRDarklanguagebash
    docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id [boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] consul
    docker $(docker-machine config consul) run -d -p "8500:8500" -h "consul" progrium/consul -server -bootstrap 

    Docker Swarm

    Diposarem dos tipus de màquines virtuals amb swarm:

    • Swarm-master: Aquesta màquina amb swarm serà l'encarregada de distribuir les instàncies dels contenidors als diferents nodes que tinguem al clúster.
    • Swarm-node: Aquesta o aquestes màquines seran les que executaran els contenidors docker.

    Swarm-master

    Creem la màquina virtual del swarm-master:

    Code Block
    language
    languageperl
    themeRDarkperl
    export CONSUL_IP=$(docker-machine ip consul)
    docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id  [boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] --swarm --swarm-master --swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376" swarm-master

    Swarm-node

     Creem la màquina virtual del swarm-node:

    Code Block
    languageperl
    themeRDark
    languageperl
    docker-machine create -d opennebula --opennebula-network-id [network_id] --opennebula-image-id [boot2docker_image_id] --opennebula-b2d-size [volatile_disk_size] --swarm --swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376" swarm-node-1

    Podem crear els nodes que vulguem. Només hem de canviar el nom de la màquina virtual 

    Desplegar contenidors Registrator

    Un cop hem creat el master i els diferents nodes, instanciarem els contenidors amb registrator a tot ells:
     . Utilitzarem la image de gliderlabs/registrator

    Necessitem tenir un servei Registrator corrent en cada host per monitoritzar tots el serveis que corre cada host. 

    Code Block
    languageperl
    themeRDark
    Code Block
    themeRDark
    languageperl
    export MASTER_IP=$(docker-machine ip swarm-master)
    export NODE_IP=$(docker-machine ip swarm-node-1)
    
    eval $(docker-machine env --swarm swarm-master)
    docker run -d --name=registrator -h ${MASTER_IP} --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator:latest consul://${CONSUL_IP}:8500
    
    eval $(docker-machine env swarm-node-1)
    docker run -d --name=registrator -h ${NODE_IP} --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator:latest consul://${CONSUL_IP}:8500
     

    Load Balancer

    Ara hem d'implementar un balancejador de càrrega que pugui distribuir les peticions per les diferents instàncies del servei. Com augmentarem i disminuirem les instàncies del servei, necessitem que el balancejador de càrrega s'actualitzi automàticament.

    Utilitzarem nginx per al load balancer i consul-template per la configuració del nginx.

    default.ctmpl

    Primer de tot, necessitem crear un template per a la configuració del nginx. Consul-template automàticament omplirà aquest fitxer amb la informació referent al servei instanciat i crea crearà la configuració pel nginx.

     

    El fitxer default.ctmpl ha de ser així:

    Code Block
    languageperl
    themeRDark
    languageperl
    {{$app := env "APP_NAME"}}
    
    upstream {{printf $app}} {
        least_conn;
        {{range service $app}}
        server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;{{end}}
    }
    
    server {
        listen 80 default;
    
        location / {
            proxy_pass http://{{printf $app}};
        }
    }

    start.sh

    Necessitem un script que actui com a entry point per a questa imatge docker.  

    El fixer start.sh ha de ser aixi:

    Code Block
    themeRDark
    languageperl
    #!/bin/bash
    service nginx start
    consul-template -consul=$CONSUL_URL -template="/templates/default.ctmpl:/etc/nginx/conf.d/default.conf:service nginx reload"

     Dockerfile  

    Code Block
    themeRDark
    languageperl
    FROM nginx:latest
    
    RUN apt-get update \
      && apt-get install -y unzip
    
    ADD files/start.sh /bin/start.sh
    RUN chmod +x /bin/start.sh
    ADD files/default.ctmpl /templates/default.ctmpl
    
    ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip /usr/bin/
    RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin
    
    EXPOSE 80
    ENTRYPOINT ["/bin/start.sh"]

    Docker Compose

    Fitxer docker-compose.yml
    Code Block
    themeRDark
    languageperl
    version: '2'
    services:
      lb:
        build: .
        container_name: lb
        ports:
          - "80:80"
        environment:
          - APP_NAME=[Nom_del_servei]
          - CONSUL_URL=${CONSUL_IP}:8500
        depends_on:
          - web
        networks:
          - front-tier
      web:
        image: nginx 
        ports:
          - "[Port_del_servei]"
        environment:
          - SERVICE_NAME=[Nom_del_servei]
        networks:
          - front-tier
    networks:
      front-tier:
        driver: overlay

     

    Code Block
    themeRDark
    languageperl
    docker-compose stop; docker-compose rm -f
    docker-compose up -d

     

    Code Block
    themeRDark
    languageperl
    docker-compose scale web=3
    Per a més informació : https://botleg.com/stories/load-balancing-with-docker-swarm/

    Crearem la variable app amb el valor de la variable d'entorn APP_NAME (definida més endavant al fitxer docker-compose.yml). També crearem un upstream amb el nom de la variable app. La linia least_conn fa que nginx encamini el traffic cap a l'instancia amb menys connexions.

    Per cada instancia del servei corrent crearem una linia amb l'adreça del node on s'executa ({{.Address}}) i el port per on està escoltant ({{.Port}}).

    Finalment està la zona de configuració del servidor. Aqui definim el port d'escolta del load balancer i creare una reverse proxy a l'upstream que hem creat.

    start.sh

    Necessitem un script que actui com a entry point per a questa imatge docker.  

    El fixer start.sh ha de ser aixi:

    Code Block
    languageperl
    themeRDark
    #!/bin/bash
    service nginx start
    consul-template -consul=$CONSUL_URL -template="/templates/default.ctmpl:/etc/nginx/conf.d/default.conf:service nginx reload"

    Aquest script engega primer el servei nginx. Després engega consul-template passant-li dos paràmetres:

    • -consul: Li passem la variable d'entorn $CONSURL_URL definida al docker-compose.yml
    • -template: Li passem 3 paràmetres: el path on està el template que hem creat anteriorment (dins del contenidor), el path on es guardarà el fitxer de configuració generat i la comanda que s'executarà un cop es generi una nova configuració.

    El consul-template crearà un nou fitxer de configuració cada cop que un servei s'engegui o s'aturi. La informació sobre aquests serveis es recollida per el servei registrator de cada node swarm i es emmagatzemada en el consul.


    Note
    El fitxers start.sh i default.ctmpl els guardarem en un directori anomenat "files". En el directori pare hi guardarem els fitxers Dockerfile i docker-compose.yml

    Dockerfile  


    Code Block
    languageperl
    themeRDark
    FROM nginx:latest
    
    RUN apt-get update \
      && apt-get install -y unzip
    
    ADD files/start.sh /bin/start.sh
    RUN chmod +x /bin/start.sh
    ADD files/default.ctmpl /templates/default.ctmpl
    
    ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip /usr/bin/
    RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin
    
    EXPOSE 80
    ENTRYPOINT ["/bin/start.sh"]

    Aquest Dockerfile utilitza nginx com a imatge base i instal·la consul-template damunt. Després copia l'script start.sh i el template default.ctmpl (que abans hem creat) dins del contenidor. Finalment exposa el port 80 i defineix el script start.sh com a entry point de la imatge.

    Docker Compose

    Docker Compose ens permet escriure la configuració que volem que tinguin els contenidors a desplegar. Utilitzarem Docker Compose File version 2, que ens permet definir la configuració referent a la xarxa, volums, ports, variables d'entorn.

    Per saber més sobre la versió 2 del fitxer de docker-compose, vés aqui.

    docker-compose.yml

    Exemple de docker-compose.yml

    Code Block
    languageperl
    themeRDark
    version: '2'
    services:
      lb:
        build: .
        container_name: lb
        ports:
          - "80:80"
        environment:
          - APP_NAME=[Nom_del_servei]
          - CONSUL_URL=${CONSUL_IP}:8500
        depends_on:
          - web
        networks:
          - front-tier
      web:
        image: [imatge_docker] 
        ports:
          - "[Port_del_servei]"
        environment:
          - SERVICE_NAME=[Nom_del_servei]
        networks:
          - front-tier
    networks:
      front-tier:
        driver: overlay

    Gestionar Docker Compose

    Per arrencar tots el serveis executem el següent.

    Per a veure els detalls dels serveis corrent podem utilitzar la comanda docker-compose ps

    Code Block
    languageperl
    themeRDark
    eval $(docker-machine env -swarm swarm-master)
    docker-compose up -d
    docker-compose ps

     Per parar i eliminar els serveis que estan corrent actualment:

    Code Block
    languageperl
    themeRDark
    docker-compose stop; docker-compose rm -f

    Ara mateix només tenim una instància del servei. Si volem augmentar o disminuir

    Code Block
    languageperl
    themeRDark
    docker-compose scale [nom servei]=[nombre d'instancies]


    Per a més informació : https://botleg.com/stories/load-balancing-with-docker-swarm/

    Exemple d'ús

     Volem crear un cluster de docker i crear un servei web balancejat amb nginx i escalable amb docker Compose.

    Actualment disposeu de dues imatges, ja precreades amb el Docker Engine instal·lat que podeu fer servir:

    • Creem les màquines virtuals de consul, swarm-master i un swarm-node:

    Code Block
    languagebash
    themeEmacs
    docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name boot2docker --opennebula-b2d-size 10240 consul
    docker $(docker-machine config consul) run -d -p "8500:8500" -h "consul" progrium/consul -server -bootstrap
    export CONSUL_IP=$(docker-machine ip consul)
    docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name boot2docker --opennebula-b2d-size 10240 --swarm --swarm-master --swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376" swarm-master
    docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name boot2docker --opennebula-b2d-size 10240 --swarm --swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376" swarm-node-1
         --opennebula-b2d-size 10240: Creem discos volàtils de 10GB

     

    Warning

    On $NETWORK_ID, serà l'ID de la xarxa on crearem el clúster. 

     

    Image Added

     

    • Despleguem Registrator a tots els nodes

      Code Block
      languagebash
      themeEmacs
      export MASTER_IP=$(docker-machine ip swarm-master)
      export NODE_IP=$(docker-machine ip swarm-node-1)
      
      eval $(docker-machine env --swarm swarm-master)
      docker run -d --name=registrator -h ${MASTER_IP} --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator:latest consul://${CONSUL_IP}:8500
      
      eval $(docker-machine env swarm-node-1)
      docker run -d --name=registrator -h ${NODE_IP} --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator:latest consul://${CONSUL_IP}:8500
    • Creem els fitxers de configuració necessaris

    files/default.ctmpl

    Code Block
    languageperl
    themeRDark
    {{$app := env "APP_NAME"}}
    
    upstream {{printf $app}} {
        least_conn;
        {{range service $app}}
        server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;{{end}}
    }
    
    server {
        listen 80 default;
    
        location / {
            proxy_pass http://{{printf $app}};
        }
    }

    files/start.sh

    Code Block
    languageperl
    themeRDark
    #!/bin/bash
    service nginx start
    consul-template -consul=$CONSUL_URL -template="/templates/default.ctmpl:/etc/nginx/conf.d/default.conf:service nginx reload"

    Dockerfile

    Code Block
    languageperl
    themeRDark
    FROM nginx:latest
    
    RUN apt-get update \
      && apt-get install -y unzip
    
    ADD files/start.sh /bin/start.sh
    RUN chmod +x /bin/start.sh
    ADD files/default.ctmpl /templates/default.ctmpl
    
    ADD https://releases.hashicorp.com/consul-template/0.12.2/consul-template_0.12.2_linux_amd64.zip /usr/bin/
    RUN unzip /usr/bin/consul-template_0.12.2_linux_amd64.zip -d /usr/local/bin
    
    EXPOSE 80
    ENTRYPOINT ["/bin/start.sh"]

    docker-compose.yml

    Code Block
    languageperl
    themeRDark
    version: '2'
    services:
      lb:
        build: .
        container_name: lb
        ports:
          - "80:80"
        environment:
          - APP_NAME=web_nginx
          - CONSUL_URL=${CONSUL_IP}:8500
        depends_on:
          - web
      web:
        image: nginx
        ports:
          - "80"
        environment:
          - SERVICE_NAME=web_nginx
    networks:
      default:
        driver: overlay

     

    • Activem el servei


      Des del directori on tenim el docker-compose.yml, executem:
    Code Block
    languageperl
    themeRDark

    Exemple d'ús

    Actualment disposeu de dues imatges, ja precreades amb el Docker Engine instal·lat que podeu fer servir:

    Crear el clúster swarm:

    • Creem les màquines virtuals de consul, swarm-master i un swarm-node amb discs volàtils de 10 GB amb les comandes:

      Code Block
      themeEmacs
      languagebash
      docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name boot2docker --opennebula-b2d-size 10240 consul
      docker $(docker-machine config consul) run -d -p "8500:8500" -h "consul" progrium/consul -server -bootstrap
      CONSUL_IP=$(docker-machine ip consul)
      docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name boot2docker --opennebula-b2d-size 10240 --swarm --swarm-master --swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376" swarm-master
      docker-machine create -d opennebula --opennebula-network-id $NETWORK_ID --opennebula-image-name boot2docker --opennebula-b2d-size 10240 --swarm --swarm-discovery="consul://$CONSUL_IP:8500" --engine-opt cluster-store=consul://$CONSUL_IP:8500 --engine-opt cluster-advertise="eth0:2376" swarm-node-01
      Warning

      On $NETWORK_ID, serà l'ID de la xarxa on crearem el clúster. 

       

      Després d'executar les comandes podem observar com s'han creat les màquines virtuals al panell de l'OpenNebula o utilitzant docker-machine:

       

      Image Removed

       

      Image Removed

       

    Connectem al docker-swarm i comprovem la informació del cluster:

    Code BlockthemeEmacslanguagebash
    eval $(docker-machine env 
    -
    -
    swarm
    swarm
    -master) docker infoImage Removed

     

    Creem la xarxa interna del clúster swarm i visualitzem les interfícies virtuals creades:

    Code Block
    themeEmacs
    languagebash
    docker network create --driver overlay --subnet=10.0.1.0/24 overlay_net
    docker network ls
    Image Removed

     

  • Ja tenim el clúster swarm configurat i corrent.

  • Executar contenidors docker al clúster creat:

    Ara podem començar a fer servir docker sobre el clúster que acabem de crear:

    Utilitzarem un contenidor nginx, per exemple

    Code Block
    themeEmacs
    languagebash
    docker pull nginx
    docker run --name mynginx -d -p 80:80 nginx

    Image Removed

    Podem comprovar com el contenidor s'està executant en un node del clúster:
    Image Removed
    Per accedir al servei del contenidor hem de posar la direcció IP del node del clúster al navegador
    Image Removed
     swarm-master)
    docker-compose up -d
    docker-compose ps

    Image Added

     

    Image Added

    • Augmentar o disminuir les instancies del servei


      Per augmentar o disminuir les instàncies del servei utilitzem la següent comanda

    Code Block
    languageperl
    themeRDark
    docker-compose scale web=4

    Image Added

    Amb aquest comanda augmentarem en 4 les instàncies desplegades del servei web.

    El nom que indiquem ha de ser en nom que hem indicar en el fitxer docker-compose.yml. Nosaltres el fitxer docker-compose.yml hem indicat que el nom del servei era web.

    Executem docker-compose ps per saber com estan les instancies. Hem esborrat les IP. Aqui es veurien com les instancies estan repartides pel diferents nodes del cluster swarm.

    Image Added 

    • Accedir al servei

       
      Hem d'accedir amb la IP del load balancer (lb)

    Image Added

    • Aturar i/o esborrar el serveis


    Code Block
    languageperl
    themeRDark
    docker-compose stop; docker-compose rm -f