top of page
Search
  • miguel19436

Primeros pasos Rundeck en Docker

Updated: Jul 20, 2020

Publicado por Luis Toledo, Programador Senior de Variacode Software


Siguiendo la serie de posts presentados por Reiner Acuña acerca de Rundeck: Primeros pasos con Rundeck y Conociendo más a fondo Rundeck, en el siguiente post se presentará como utilizar Rundeck en un ambiente basado en containers. Se profundizará desde cómo crear una instalación básica, hasta extenderla para crear instalaciones más completas.


Imagen de Rundeck en Docker

Rundeck posee una imagen oficial de docker que permite comenzar a utilizar el producto con un conjunto de configuraciones por defecto.


Existen distintas imágenes para Rundeck Open Source y Enterprise.


También es posible acceder a ejemplos útiles en el siguiente repositorio:


Es posible acceder a distintas ediciones de ambas imágenes, las cuales se diferencian por los tags en el nombre de la imagen (por ejemplo rundeck/rundeck:3.2.8-20200608). Siempre se recomienda usar la última versión disponible. También existe una versión de pruebas que tiene las últimas funcionalidades en desarrollo (SNAPSHOT).


Ejemplo básico de Rundeck


A continuación se presenta un ejemplo básico para iniciar Rundeck en docker. En este post se utilizará docker-compose por su capacidad para orquestar entornos de containers.


Recomendaciones para utilizar Rundeck en docker:


  • Usar una base de datos externa para contar con data persistente (no se recomienda trabajar con la base embebida salvo en casos de testing). La base de datos puede ser una base de datos existente o se puede montar con docker.

  • Almacenar los logs de ejecuciones en algún volumen compartido (como veremos más adelante esto también se puede realizar a través de otro servicio docker)

  • docker-compose.yaml


version: '3'
services:
 rundeck:
   image: rundeck/rundeck:SNAPSHOT
   container_name: rundeck-example
   ports:
     - '4444:4440'
   environment:
     RUNDECK_GRAILS_URL: 'http://localhost:4444'
     RUNDECK_DATABASE_DRIVER: com.mysql.jdbc.Driver
     RUNDECK_DATABASE_USERNAME: rundeck
     RUNDECK_DATABASE_PASSWORD: '${DB_PASSWORD}'
     RUNDECK_DATABASE_URL: 'jdbc:mysql://mysql/rundeck?autoReconnect=true&useSSL=false'

Donde:

  • ports: define el puerto donde se expondrá rundeck, por defecto Rundeck inicia en el puerto 4440. Se puede utilizar cualquier puerto para exponer el servicio con el host, pero se debe setear el puerto en RUNDECK_GRAILS_URL.

  • RUNDECK_GRAILS_URL: URL por la cual se puede acceder al servicio de rundeck. Para poder acceder a rundeck desde el host, se debe incluir el puerto con que se exponer el container (eg: http://localhost:4444)

  • RUNDECK_DATABASE_XXX: define los parámetros de conexión a la base de datos.


Para construir el container se deben ejecutar los siguientes comandos:


$ docker-compose build
$ docker-compose up
#(revisar si el container está corriendo)
$ docker-compose ps 
# (ver logs de rundeck)
docker-compose logs

Para ingresar a Rundeck debe utilizar el valor definido en RUNDECK_GRAILS_URL en el browser.


Extender imagen base


¿Por qué extender la imagen base de Rundeck?

  • Instalar software adicional

  • Copiar plugins/addons al container

  • agregar/modificar archivos de configuración

  • Crear certificados e importarlos en cacerts/truststore de java o Rundeck.

  • Cualquier otro archivo que se necesite copiar a la imagen

Como concepto general de docker, la imagen que se cree debe ser lo suficientemente “atómica” de tal forma de que no se necesite instalar nada extra una vez que el container sea iniciado. Es por esto que todos los archivos de configuración, software requeridos, etc, deben ser incorporados cuando la imagen se construye, y las configuraciones customizadas deben ser expuestas a través de variables de entorno.


¿Cómo extender la imagen?


  1. Crear un archivo Dockerfile que extienda de la imagen base de Rundeck

  2. Usar el Dockerfile en el docker-compose.yaml del proyecto


> Estructura de carpetas del ejemplo:


├── example1
│   ├── Dockerfile
│   └── docker-compose.yaml

> Dockerfile:


FROM rundeck/rundeck:SNAPSHOT 

USER root

# upgrade os
RUN apt-get -y update && \
   apt-get -y install \
   software-properties-common 
 
# install python
RUN apt-get -y install python3-pip && \
   pip3 install --upgrade pip

RUN password rundeck:rundeck

USER rundeck

En el ejemplo primero el Dockerfile extiende la imagen oficial de Rundeck (FROM rundeck/rundeck:SNAPSHOT), luego cambia a usuario root para realizar una serie de instalaciones de software, y finalmente vuelve al usuario Rundeck.


version: '3'
services:
 rundeck:
   build:
     context: .
   container_name: rundeck-single
   ports:
     - '4444:4440'
   environment:
     RUNDECK_GRAILS_URL: 'http://localhost:4444'
     RUNDECK_DATABASE_DRIVER: com.mysql.jdbc.Driver
     RUNDECK_DATABASE_USERNAME: rundeck
     RUNDECK_DATABASE_PASSWORD: '${DB_PASSWORD}'
     RUNDECK_DATABASE_URL: 'jdbc:mysql://mysql/rundeck?autoReconnect=true&useSSL=false'

En docker-compose ahora haremos referencia al Dockerfile, utilizado los atributos “build/context”. Al utilizar un punto en dicho valor, le decimos a docker que busque el Dockerfile en la misma carpeta. Si se trabaja con subfolders se debe indicar el nombre en dicha propiedad.


Sistema de templates de archivos de configuración


Rundeck utiliza un sistema de templates para construir los archivos de configuración basados en variables de entorno. A través de estos templates se generan archivos como rundeck-config.properties, framework.properties, log4j2.properties, etc, los cuales controlan los principales aspectos de configuración de Rundeck.


Los templates se generan usando el software REMCO.


Como se mencionó, existen casos en los cuales se necesita agregar configuraciones extras a los archivos principales de configuración de rundeck (rundeck-config.properties, framework.properties), o que se necesite crear algún otro archivo dinámico dependiente de variables de entorno del container. Por ejemplo, puede que sea necesario agregar configuraciones de algún plugin de Rundeck que no viene instalado por defecto o que se necesite modificar la contraseña por defecto del usuario admin en realm.properties.


Algunos ejemplos de templates existentes:


Cómo agregar un template

A continuación presentaré un ejemplo de cómo configurar un custom template.


Estructura de carpetas:


├── Dockerfile
├── README.md
├── docker-compose.yaml
└── remco
    ├── resources.d
    │   └── extra-rundeck-config.properties.toml
    └── templates
        └── extra-rundeck-config.properties

Lo primero para crear un custom tempate es definir la estructura de carpetas como se ve en el ejemplo: se debe crear una carpeta denominada remco, con dos carpetas dentro llamadas resource.d y templates.


Dentro de la carpeta resource.d se debe crear los archivos .toml que definen la ruta fuente y destino donde se copiaran los archivos de configuración. Un archivo .toml debe ser como el siguiente:


[[template]]
 src         = "${REMCO_TEMPLATE_DIR}/extra-rundeck-config.properties"
 dst         = "${REMCO_TMP_DIR}/rundeck-config/extra-rundeck-config.properties"
mode        = "0644"

Fuente (src) apunta a los archivos que se definirán en remco/tempates de la carpeta de nuestro proyecto.


Destinos (dst) apunta a las carpetas del container, las cuales pueden ser:


  • ${REMCO_TMP_DIR}/rundeck-config/nombrearchivotemplate.properties => si se define al path ${REMCO_TMP_DIR}/rundeck-config/ el archivo de configuración se fusionará con /home/rundeck/service/config/rundeck-config.properties de rundeck

  • ${REMCO_TMP_DIR}/framework/nombrearchivotemplate.properties => si se define al path ${REMCO_TMP_DIR}/framework/ el archivo de configuración se fusionará con /home/rundeck/etc/framework.properties.

  • Cualquier path , por ejemplo => /home/rundeck/etc/nombre.aclpolicy


Luego, el template definido en la fuente del archivo .toml puede contener reemplazo de variables como se ve en el siguiente ejemplo. Además, puede aceptar condicionales simples:


# remco/template/extra-rundeck-config.properties

rundeck.feature.pagedjoblist.enabled={{ getv("/rundeck/feature/pagedjoblist/enabled", "false") }}

{% if exists("/rundeck/security/ldap/bindpassword") -%}
rundeck.security.ldap.bindPassword={{ getv("/rundeck/security/ldap/bindpassword") }}
{% endif %}

Finalmente, las variables definidas en el template anterior se pueden especificar en docker-compose.yaml. Para esto se debe transformar el path en una formato de variable de entorno, por ejemplo:

  • /rundeck/feature/pagedjoblist/enabled => RUNDECK_FEATURE_PAGEDJOBLIST_ENABLED

  • /rundeck/security/ldap/bindpassword => RUNDECK_JAAS_LDAP_BINDPASSWORD


version: '3'
services:
 rundeck:
   build:
     context: .
   container_name: rundeck-single
   ports:
     - '4444:4440'
   environment:
     RUNDECK_GRAILS_URL: 'http://localhost:4444'
     RUNDECK_DATABASE_DRIVER: com.mysql.jdbc.Driver
     RUNDECK_DATABASE_USERNAME: rundeck
     RUNDECK_DATABASE_PASSWORD: '${DB_PASSWORD}'
     RUNDECK_DATABASE_URL: 'jdbc:mysql://mysql/rundeck?autoReconnect=true&useSSL=false'
     RUNDECK_FEATURE_PAGEDJOBLIST_ENABLED:true
     RUNDECK_JAAS_LDAP_BINDPASSWORD: “password123”

Pasar configuraciones de java a la instancia de Rundeck


A veces es necesario definir configuraciones de JAVA extras al container que levanta Rundeck (por ejemplo para habilitar el uso de ssl o configurar un módulo de login extra). Para esto se puede usar el atributo “command” de docker compose.


version: '3'
services:
 rundeck:
   image: rundeck/rundeck:SNAPSHOT
   container_name: rundeck-single
   command: '-Dloginmodule.conf.name=jaas-loginmodule-reloaded.conf -Dloginmodule.name=rundeck'
   ports:
     - '4444:4440'
   environment:
     RUNDECK_GRAILS_URL: 'http://localhost:4444'
     RUNDECK_DATABASE_DRIVER: com.mysql.jdbc.Driver
     RUNDECK_DATABASE_USERNAME: rundeck
     RUNDECK_DATABASE_PASSWORD: '${DB_PASSWORD}'
     RUNDECK_DATABASE_URL: 'jdbc:mysql://mysql/rundeck?autoReconnect=true&useSSL=false'

Ejemplo de Rundeck completo


A continuación se mostrará un ejemplo completo de Rundeck interactuando con otros servicios en docker, como una base de datos y servicio de storage. La estructura de carpeta es la siguiente:


├── Dockerfile
├── .env
├── data
│   └── realm.properties
├── docker-compose.yaml
├── lib
│   ├── generate-ssl.sh
│   └── keytool_input
├── plugins
│   └── README.md
└── remco
    ├── resources.d
    │   ├── custom-framework.properties.toml
    │   ├── jaas-loginmodule-hotreload.conf.toml
    │   └── plugin-rundeck-config.properties.toml
    └── templates
        ├── custom-framework.properties
        ├── jaas-loginmodule-hotreload.conf
        └── plugin-rundeck-config.properties

Donde:

  • Dockerfile: imagen de Rundeck extendida

  • .env: archivos con variables para pasar a docker-compose

  • data/realm.properties: archivo de configuración para agregar usuarios/grupos

  • carpeta lib: genera self-certificate para iniciar Rundeck con ssl

  • carpeta plugins: sirve para cargar plugins externos

  • carpeta remco: para extender archivos de configuración

Dockerfile:


ARG IMAGE
FROM ${IMAGE}

USER root

# install python
RUN apt-get -y update && \
   apt-get -y install python-pip && \
   pip install --upgrade pip

# install docker on container
RUN apt-get -y install docker.io

USER rundeck

ADD --chown=rundeck:root https://github.com/rundeck-plugins/docker/releases/download/1.4.1/docker-container-1.4.1.zip libext/

COPY --chown=rundeck:root remco /etc/remco

COPY --chown=rundeck:root plugins/* ./libext/

COPY --chown=rundeck:root lib docker-lib
RUN chmod +x docker-lib/generate-ssl.sh
RUN ./docker-lib/generate-ssl.sh

docker-compose.yaml


version: '3'
services:
 rundeck:
   build:
     context: .
     args:
       IMAGE: '${RUNDECK_IMAGE:-rundeck/rundeck:SNAPSHOT}'
   container_name: rundeck-demo
   command: "-Dserver.https.port=4443 -Drundeck.ssl.config=/home/rundeck/server/config/ssl.properties"
   ports:
     - 4447:4443
   environment:
     RUNDECK_GRAILS_URL: 'https://localhost:4447'
     #DATABASE CONNECTIO
     RUNDECK_DATABASE_DRIVER: com.mysql.jdbc.Driver
     RUNDECK_DATABASE_USERNAME: rundeck
     RUNDECK_DATABASE_PASSWORD: '${DB_PASSWORD}'
     RUNDECK_DATABASE_URL: 'jdbc:mysql://mysql/rundeck?autoReconnect=true&useSSL=false'
 #LOG STORAGE
     RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_NAME: org.rundeck.amazon-s3
     RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_ENDPOINT: http://minio:9000/
     RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_BUCKET: rundeck
     RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_REGION: us-east-2
     RUNDECK_PLUGIN_EXECUTIONFILESTORAGE_S3_PATHSTYLE: "true"
     AWS_ACCESS_KEY_ID: ${STORAGE_ACCESS_KEY_ID}
     AWS_SECRET_KEY: ${STORAGE_SECRET_KEY}
   volumes:
     - ./data/realm.properties:/home/rundeck/server/config/realm.properties
 mysql:
   image: mysql:5.7
   container_name: rundeck-mysql
   ports:
     - 33060:3306
   environment:
     - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
     - MYSQL_DATABASE=rundeck
     - MYSQL_USER=rundeck
     - MYSQL_PASSWORD=${DB_PASSWORD}
   volumes:
     - ./data/database:/var/lib/mysql
 minio:
   image: minio/minio:latest
   container_name: rundeck-minio
   ports:
     - "9000:9000"
   entrypoint: sh
   command: -c 'mkdir -p /export/rundeck && mkdir -p /export/plugins && /usr/bin/minio server /export --compat'
   environment:
     MINIO_ACCESS_KEY: ${STORAGE_ACCESS_KEY_ID}
     MINIO_SECRET_KEY: ${STORAGE_SECRET_KEY}
   volumes:
     - ./data/storage:/export

.env

RUNDECK_IMAGE=rundeck/rudeck:SNAPSHOT
DB_PASSWORD=admin.



Ver ejemplo completo en https://github.com/variacode/rundeck-docker-examples



1,067 views0 comments

Recent Posts

See All
bottom of page