Administración de Docker Swarm con Portainer

por | marzo 30, 2019

Portainer nos proporciona una GUI web desde la que administrar un clúster de Docker Swarm: operatividad de contenedores (parada, reinicio, etc…), gestión de stacks, servicios, plantillas de imágenes, volúmenes para persistencia de datos…

En mi entorno parto de 4 nodos, 2 de ellos master y otros dos workers. Los 4 están configurados para poder servir peticiones de mis contenedores:

[root@docker-master1 ~]# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
olw40ii82gslxgfjtmy5h2ncr *   docker-master1      Ready               Active              Leader              18.09.1
lvvjz6c4bfe4ez16kzkyuc31o     docker-master2      Ready               Active              Reachable           18.09.1
q8em4kafthkm1phkuuab48eau     docker-worker1      Ready               Active                                  18.09.1
hb4ylcxtchc6kevimak7wxr9e     docker-worker2      Ready               Active                                  18.09.1

También tengo una serie de servicios desplegados:

root@docker-master1 ~]# docker service ls
ID                  NAME                  MODE                REPLICAS            IMAGE                        PORTS
tpmlzwsun4xt        httpd_httpd           global              4/4                 httpd:2.4                    *:80->80/tcp, *:443->443/tcp
9040dr4bjqtf        jboss_jboss           global              4/4                 jboss/wildfly:latest         *:8080->8080/tcp, *:9990->9990/tcp
rhjjxlrqimj7        portainer_agent       global              4/4                 portainer/agent:latest       
rs5wrgflhmax        portainer_portainer   replicated          1/1                 portainer/portainer:latest   *:9000->9000/tcp
oxj7bf6e36kj        tomcat_tomcat         global              4/4                 tomcat:8.0                   *:8180->8080/tcp

Como se puede ver Portainer es un servicio más dentro del clúster. El servicio de administración se encuentra desplegado en modo réplica sólo en un nodo:

[root@docker-master1 ~]# docker service ps portainer_portainer 
ID                  NAME                    IMAGE                        NODE                DESIRED STATE       CURRENT STATE         ERROR               PORTS
u7zkwx0rq1tf        portainer_portainer.1   portainer/portainer:latest   docker-master1      Running             Running 3 hours ago                       

El agente está en los cuatro nodos.

[root@docker-master1 ~]# docker service ps portainer_agent 
ID                  NAME                                        IMAGE                    NODE                DESIRED STATE       CURRENT STATE         ERROR               PORTS
02s2mimzojgn        portainer_agent.q8em4kafthkm1phkuuab48eau   portainer/agent:latest   docker-worker1      Running             Running 3 hours ago                       
lhoewvvlc2zm        portainer_agent.olw40ii82gslxgfjtmy5h2ncr   portainer/agent:latest   docker-master1      Running             Running 3 hours ago                       
ldi3cj7kj7hb        portainer_agent.lvvjz6c4bfe4ez16kzkyuc31o   portainer/agent:latest   docker-master2      Running             Running 3 hours ago                       
p2sch9c3gqfd        portainer_agent.hb4ylcxtchc6kevimak7wxr9e   portainer/agent:latest   docker-worker2      Running             Running 3 hours ago        

La instalación de Portainer por tanto se puede realizar desplegándolo como un servicio más dentro de nuestro clúster:

[root@docker-master1 ~]# curl -L https://downloads.portainer.io/portainer-agent-stack.yml -o portainer-agent-stack.yml

Echando un vistazo al fichero de configuración del stack vemos que el agente se despliega en modo global para todo el clúster y el contenedor que contiene los servicios de administración se despliega en modo réplica:

version: '3.2'

services:
  agent:
    image: portainer/agent
    environment:
      # REQUIRED: Should be equal to the service name prefixed by "tasks." when
      # deployed inside an overlay network
      AGENT_CLUSTER_ADDR: tasks.agent
      # AGENT_PORT: 9001
      # LOG_LEVEL: debug
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    networks:
      - agent_network
    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

  portainer:
    image: portainer/portainer
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    ports:
      - "9000:9000"
    volumes:
      - portainer_data:/data
    networks:
      - agent_network
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]

networks:
  agent_network:
    driver: overlay
    attachable: true

volumes:
  portainer_data:
[text]

Desplegamos el stack:
[text]
[root@docker-master1 ~]# docker stack deploy --compose-file=portainer-agent-stack.yml portainer
Creating service portainer_portainer
Creating service portainer_agent

Una vez desplegado accedo a Portainer entrando en http://docker-master1:9000. La primera vez que conectemos tendremos que especificar un usuario administrador y su contraseña.

Dentro, podemos echar un vistazo global a nuestro clúster:

Los stacks podemos añadirlos directamente desde la interfaz:

Gestión de servicios, pudiendo actualizarlos, eliminarlos o escalar dentro del clúster:

Visión del clúster swarm:

En cuanto a las imágenes de docker, podemos hacer pull desde DockerHub, importarlas o crear nuestros ficheros Dockerfile con las especificaciones necesarias:

Gestión de volúmenes:

Como vemos Portainer es una herramienta bastante completa e intuitiva desde la que poder administrar nuestro clúster de Docker Swarm.

Tenéis el repositorio del proyecto en GitHub.