¿Cómo lanzar un proceso en una máquina Digital Ocean creada al vuelo?

¿Quién no ha necesitado ejecutar un comando en un servidor en ciertos momentos sin necesitad de tenerlo levantado todo el día?

Me explico mejor. Imaginaros que tenemos una aplicación que hemos desarrollado y que debemos ejecutar desde un servidor en ciertos momentos, pero no queremos tener que pagar por todo el tiempo que está levantado el servidor sin usarse.

Para ello podemos crear un Shell Script que haga uso del API Digital Ocean para crear una máquina, ejecutar nuestra aplicación y terminar dicha máquina cuando haya terminado la ejecución.

Digital Ocean

Lo primero de todo es preparar nuestra aplicación

Lo primero que tendremos que hacer es preparar una máquina con todo lo necesario para poder ejecutar esa aplicación maravillosa que hemos creado.

No se nos debe olvidar marcar como autentificación el acceso por SSH keys.

Crear droplet

Creación de la imagen de nuestra máquina

Una vez creada la máquina, y una vez que hemos probado que nuestra aplicación funciona correctamente, procederemos a crear el snapshot de la máquina que será instanciado cada vez que necesitemos ejecutar la aplicación.

Para ello pararemos nuestra máquina y desde el menú Snapshots de nuestro Droptlet creado procederemos a hacer la imagen.

Crear droplet

Instalación de doctl

Digital Ocean tiene una aplicación de consola que nos permite acceder a su API llamada doctl. Gracias a esta aplicación podremos obtener la información necesaria para que nuestro script funcione y que podamos ejecutar la apliación al vuelo.

Las instrucciones actualizadas de instalación las podemos encontrar en la página de Digital Ocean.

Optención de la información necesaria para el Script

Vamos a necesitar dos valores para poder ejecutar la aplicación, el id del shapshot que hemos creado (desde ahora lo llamaremos droplet_image) y el id de la clave de ssh con la que vamos a crear la máquina (ssh_key_id).

Para ello ejecutaremos los siguientes comandos:

doctl compute image list
ID          Name                           Type        Distribution    Slug    Public    Min Disk
79242666    okiburi-host1-1639133427958    snapshot    Ubuntu                  false     25

y

doctl compute ssh-key list
ID          Name               FingerPrint
29396666    macbook_XXXXX    c1:f5:72:6a:4a:cc:10:71:4d:e2:b9:1e:2c:a3:46:49

Guardaremos dichos valores para ponerlos en el script.

Configuración del Script

Una vez que tenemos los valores, configuramos el siguiente script (disclaimer: este script lo encontré hace mucho tiempo en Internet pero no encuentro la fuente):

#!/bin/bash

##
# Variables
# Add the details of the Droplet that you would like to create
##

droplet_name='test-droplet' #new droplet name
droplet_size='s-1vcpu-1gb' #name of cpu size
droplet_image='79242666' #doctl compute image list
droplet_region='nyc3' #new droplet region
ssh_key_id='29396666' #doctl compute ssh-key list

##
# Droplet info session file
##
temp_droplet=$(mktemp /tmp/temp-droplet.XXXXXX)

##
# Create Droplet
##
function new_droplet() {
    echo "Creating Droplet with the following details:"
    echo "Droplet name: ${droplet_name}"
    echo "Droplet size: ${droplet_size}"
    echo "Droplet image: ${droplet_image}"
    echo "Droplet regon: ${droplet_region}"

    doctl compute droplet create ${droplet_name} --size ${droplet_size} --image ${droplet_image} --region ${droplet_region} --ssh-keys ${ssh_key_id} > ${temp_droplet}
    echo "Waiting 60 seconds for Droplet to be created..."
    sleep 60

    new_droplet_id=$(cat ${temp_droplet} | tail -1 | awk '{ print $1 }')
    new_droplet_ip=$(doctl compute droplet get ${new_droplet_id} --template "")
    echo "Droplet IP: ${new_droplet_ip}"
}
new_droplet

##
# Check if Droplet is running
##

function ssh_key_scan() {
    while [ "$status" != "active" ] ; do
        echo "Waiting for status to become active.."
        sleep 5
        status=$(doctl compute droplet get ${new_droplet_id} --template "")
    done
    echo "Droplet status is: ${status}. Proceeding to SSH Key Scan"
    ssh-keyscan ${new_droplet_ip} >> ~/.ssh/known_hosts
}
ssh_key_scan

##
# Execute a command
##

function run_commands() {
    echo "Running commands.."
    ssh  -i ~/.ssh/digital_ocean_key root@${new_droplet_ip} 'cat /etc/os-release'
}
run_commands

##
# Delete Droplet and session file
##
function clean_up(){
    echo "Deleting Droplet and temp files.."
    doctl compute droplet delete -f ${new_droplet_id}
    rm ${temp_droplet}
}
clean_up

Ejecución

Sólo nos queda ejecutar nuestro script.

Primero creará la máquina desde la función new_droplet.

A través de la función ssh_key_scan esperará a que la máquina esté lista.

Una vez lista la máquina, usaremos la aplicación run_commands para ejecutar la aplicación desde una conexión SSH con la clave que hemos indicado.

Por último eliminará la máquina creada desde la función clean_up para que no nos sigan cobrando por el uso.

Conclusiones

Siempre es interesante el poder ejecutar una aplicación desde un servidor de Internet sin tener asumir el coste de tener una máquina siempre levantada. En mi caso uso una máquina de mínimo coste que ejecuta desde un CRON diferentes scripts que ejecutan a su vez aplicaciones que necesitan máquinas de mayor coste. Prueba a crear tu script y contáctame si tienes algún problema enviándome un email a lcbarco@gmail.com o a través de mi cuenta de Twitter https://twitter.com/lcbarco.

08/12/2021