Entorno Linux en Máquina Virtual

Virtualización pensando en la computación en la nube.
© 2020 by César Arcila

Las máquinas virtuales reservan recursos de un equipo de computo o un servidor para correr un entorno independiente con características disponibles como si fuera otra máquina. De ahí que se use el término máquina virtual, considerando que dentro de nuestra máquina se pueden ejecutar otras máquinas de modo virtual siempre y cuando se cumpla con unos requisitos, es decir, un computador con especificaciones intermedias o superiores que hace posible multiplicarse como varias máquinas. Por ejemplo, que tenga varios procesadores, buena memoria RAM (4GB en adelante), espacio de disco necesario, que la tarjeta principal lo permita y hasta el sistema operativo de la máquina física debe posibilitarlo (ej. 64bits).

Este concepto lo usa la plataforma de programación Java desde sus orígenes (hace 3 décadas) pero lo hace de un modo ligero y transparente para el usuario. Una década posterior, es decir, avanzando el nuevo siglo, se dió inicio a la acogida de las máquinas virtuales hasta ser popular en infraestructuras de computo y sistemas de ingeniería, incluso como un servicio a través de internet denominado Virtual Private Server (VPS) o servidores virtuales, que dan un salto o mayor enfoque respecto al servicio de alojamiento web convencional. Comprender los fundamentos de la virtualización es conveniente para introducirse también en la computación en la nube.

Una mirada a Windows Subsystem Linux 2 (WSL 2)

Usar el subsistema Linux para Windows es una opción conveniente para comenzar y tener una buena integración en entornos personales bajo sistemas Windows, por ejemplo, para tener la alternativa de una versión de Linux incorporada dentro de Windows. WSL 2 está disponible en Windows 10 pro actualizado a versión 2004+ (compilación 19041 o superior), por lo que debes verificar estos requisitos.

Para instalarlo, abres una terminal con PowerShell como Administrador y ejecutas el siguiente comando:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

Debes reiniciar la máquina para que asuma los cambios y al tenerla disponible nuevamente abres PowerShell como Administrador y ejecutas el siguiente comando:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

De nuevo reinicias y al volver abres PowerShell como Administrador y ejecutas:

wsl --set-default-version 2

Si crees que seguiste los pasos correctamente y se presenta un error, es posible que se requiera descargar del sitio oficial el archivo wsl_update_x64.msi (actualización de kernel de Linux) y luego de lanzar esta actualización vuelves a ejecutar este último comando.

Para obtener las distribuciones dirígete a la tienda de Windows (https://aka.ms/wslstore), allí puedes elegir una como Ubuntu o Debian (este último es preferible para asemejarse a un entorno de producción)

Puedes consultar la lista de distribuiciones instaladas y acceder al subsistema Linux con los siguientes comandos respectivamente:

wsl -l -v
wsl -d Debian

En la última línea, Debian correspondería al nombre de una de las distribuciones instaladas. De hecho, se podría ejecutar en ese caso debian.exe. Adicionalemnte, odemos dejar el sistema por defecto ejeuctando: wsl -s Debian

Una vez instalada la distribución, la máquina inicia en modo texto (sin entorno gráfico). Para instalar un entorno de escritorio gráfico como xfce4 se podría ejecutar dentro de la máquina el comando sudo apt install xfce4 y una vez instalado se iniciaría con el comando startxfce4.

Debes tener presente que para la visualización como un escritorio remoto debes descargar un software como VcXSrv (lo encuentras en internet) y reportar la variable de salida de pantalla asignando la IP reservada en Windows para WSL, por ejemplo usando export DISPLAY=DISPLAY=172.21.240.1:0, o mejor aún export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0. Además, si llega a requerirse configurar el acceso al entorno gráfico X puedes editar el archivo /etc/X11/Xwrapper.config cambiando el privilegio de console por anybody, teniendo presente que puede significar un hueco de seguridad.

También podríamos darle a xfc4 un toque de mejora en su apariencia y agregarle un navegador instalando lo siguiente:

sudo apt install xfce4-goodies arc-theme numix-icon-theme-circle
sudo apt install chromium

La ventaja de WSL es que puedes integrar el uso de archivos del sistema windows, incluso ejecutando el comando explorer.exe . para ver archivos en el explorador, así como el comando code . para abrir el editor VSCode (siempre y cuando éste tenga instalado el complemento remoto para WSL), y si tienes un servidor web corriendo en el subsistema Linux puedes abrir tu navegador en Windows y acceder a la dirección localhost. Como la unidad de disco C es montada en la ruta /mnt/c podrías vincular tu carpeta de inicio con un enlace simbólico, por ejemplo:

ln -s /mnt/c/Users/user/ myhome

Debes identificar user como el nombre de usuario de tu equipo. Dado un entorno de desarrollo con la carpeta onmind y si tienes una carpeta onminder en C, puedes aplicar en su lugar las siguientes sentencias:

ln -s /mnt/c/Users/user/onmind/ onmind
sudo ln -s /mnt/c/onminder/ /opt/onminder

Virtualizando en tu máquina con VirtualBox

A continuación veremos un ejercicio usando Oracle VirtualBox que es una herramienta gratuita que permite virtualizar máquinas en nuestras estaciones de trabajo y viene con versión para Windows, macOS y para el escritorio de Linux (ej. Ubuntu). Cuando se cuenta con Windows 10 Pro y superiores, se podría usar Hyper-V siendo en muchos casos aconsejable pero supeditado a Windows. En este caso, al trabajar con VirtualBox se logra portabilidad entre sistemas, motivo por el cual se puede usar cuando se trata de algún entorno de desarrollo que opere tanto en Windows como en macOS. Existe tambíen una solución como VMWare Workstation pero no es gratuita.

Para máquinas de laboratorio con sistema distinto a Windows 10 Pro, en OnMind puede usarse VirtualBox en lugar de sus alternativas, aunque tiene mayor acogida trabajar con la tecnología de Docker (software usado frecuentemente para la computación en nube).
Referencia sobre Linux

Instalación de VirtualBox

Debes dirigirte al sitio oficial de VirtualBox y descargar el instalador respectivo (por ejemplo, para Windows a 64bits), luego lanzas el instalador y sigues los pasos. Es así de sencillo.

Nótese que se usa inicialmente el adaptador puente (en la configuración de red) para conectarse de modo natural a Internet (con DHCP por defecto).
Una vez instalado este software, el proceso de configuración de una máquina virtual, que se verá con un caso aplicado a continuación, consiste en establecer un nuevo conjunto de características tales como la memoria, el almacenamiento y la red, entre otras. Generalemente, se requiere contar con el medio virtual (.iso) del instalador del sistema operativo.

En Windows 10 Pro+ es conveniente habilitar características para máquinas virtuales. Esto se hace abriendo PowerShell como Administrador y ejecutando el siguiente comando:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

En este caso, debes reiniciar tu máquina para que se asuman los cambios.

Entorno con Linux Debian bajo VirtuaBox

Para Linux Ubuntu puedes remitirte al artículo Entorno de Desarrollo bajo Linux

La imagen ilustra la configuración de una máquina para el sistema Linux Debian. Todo comienza ingresando a la opción etiquetada como Nueva, e indicando en el paso a paso de VirtualBox las especificaciones respectivas, tan simple como: Nombre y Sistema Operativo, Tamaño de Memoria, Disco Duro, Red (Adaptador Puente).

La ventaja de usar una distribución Linux como Debian es que alcanza un nivel empresarial (aunque no lleve esa etiqueta) promoviendo un sistema seguro, viene con un buen número de paquetes disponibles que facilitan su instalación, y es gratuito. Además, la reconocida distribución para el escritorio Linux Ubuntu se basa en Debian, por lo que si has usado Ubuntu, puedes comprender fácilmente Debian. Y aunque compañías grandes tienden a dar acogida a distribuciones como Red-Hat o CentOS, quién comprenda que es más cuestión de políticas adoptadas, barreras comerciales y mentales, y del equipo de trabajo con el que se cuenta, entonces puede ser cuestión de gustos y contextos.

Generalemente, se requiere contar con el medio virtual (.iso) del instalador del sistema operativo. A diferencia de contar con un disco aprovisionado con el sistema base (como otro escenario que veremos posteriormente), estos instaladores requieren también un paso a paso en donde se define el usuario, el nombre de máquina y la distribución del sistema de archivos en el disco, incluso la red, hasta terminar con el sistema instalado en la máquina virtual.

Para referencia del instalador puedes consultar también el sitio sobre servidor Debian

Procedemos a actualizar paquetes y agregar algunos ejecutando comandos iniciales con privilegios de root:

su
apt update -y
apt install -y zip unzip
apt install -y p7zip-full
apt install -y git-core
apt install -y wget
apt install -y curl
apt install -y gcc g++ make
apt install -y python-pip
apt install -y neovim
apt install -y ssh
apt install -y sudo
gpasswd -a user sudo
exit

En la penúltima sentencia (gpasswd -a user sudo), user corresponde al usuario definido en la instalación. Como alternativa podría usarse también usermod -aG sudo user. Y para que tome ese cambio puede ser necesario volver a iniciar sesión con el usuario (doble exit).

Una vez terminada la instalación del sistema, se procede a continuación con la instalación de paquetes de software como Node.js, Java, Go, Rust, Ruby, MariaDB, NGinx y Docker. Comencemos con el entorno Node.js:

sudo apt install -y nodejs npm
sudo apt install -y build-essential
node -v
npm -v

Sin embargo, los repositorios pueden venir con la version 10. Para instalar la version 12, las lineas anteriores se reemplazaria por las siguientes:

curl -sL https://deb.nodesource.com/setup_12.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt install -y nodejs

Continuemos con la máquina virtual de Java (JVM) y su kit de desarollo (JDK):

sudo apt install -y default-jdk
javac -version
echo $JAVA_HOME

Para lenguaje Go sólo tienes que ejecutar la siguiente instrucción:

sudo apt install -y golang

Para lenguaje Rust ejecutas:

curl https://sh.rustup.rs -sSf | sh

Para lenguaje Ruby y Ruby On Rails ejecutas.

sudo apt install -y ruby-full
sudo gem install rails

Pasemos ahora al motor de base de datos MariaDB:

sudo apt install -y mariadb-server
sudo apt install -y mariadb-plugin-rocksdb
sudo systemctl enable mariadb
sudo mysql

Para acceder con el usuario root en Debian se usa sudo mysql en lugar de la forma estándar (mysql -u root -p), debido a que usa atenticación con unix_socket sin requerir contraseña (asumiendo la del usuario Linux). Por este mismo motivo evite usar el instalador de configuración segura. Si se presentan incovenientes con el socket es posible que el servicio no se haya iniciado, verificalo usando sudo service mysql status. Para iniciar el servicio podría ejecutarse sudo service mysql start, o si se usa systemctl el comando sería sudo systemctl start mariadb.

Veamos NGinx que nos servirá como proxy invertido (para traducir puertos de un modo natural y seguro en la aplicación):

sudo apt install -y nginx
sudo systemctl enable nginx

Puedes verificar el estado del servicio usando sudo service nginx status. Para iniciar el servicio podría ejecutarse sudo service nginx start, o si se usa systemctl el comando sería sudo systemctl start nginx.

Y si se piensa usar Docker se ejecuta lo siguiente:

sudo apt install -y apt-transport-https ca-certificates gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable"
sudo apt update
sudo apt install docker-ce
sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker user

En la última sentencia, user corresponde al usuario definido en la instalación.

Instancias de computo con Vultr & Linux Debian

Se puede decir que Vultr es un proveedor reconocido o popular que puede servir de ejemplo. En el mercado también encuentras otros proveedores semejantes y los pasos consisten básicamente en:

Después de seguir el video y/o crear la instancia puedes acceder con la consola respectiva para instalar Nginx (Servidor Web Lógico y Proxy reverso) bajo Debian (como vimos anteriormente).

sudo apt update && sudo apt install -y nginx
sudo systemctl enable nginx

Al consultar la dirección correspondiente del servidor desde un navegador web encuentras un mensaje de bienvenida.

Para comprender el concepto, simplemente la primera línea instala el servidor web (en este caso Nginx, pero podría ser Apache Web Server) y la segunda línea lo habilita para que inicie el servicio cada vez que se reinicia el sistema.

Podrías probar modificando en la ruta /var/www/html el bloque de body del archivo de ejemplo que encuentras en solitario y consultando nuevamente en un navegador con la dirección del servidor correspondiente. También podrías preparar tu propio html y reemplazar todo el contenido, es decir, el archivo que encuentras originalmente en /var/www/html debe conservar el mismo nombre para no alterar muchas cosas por lo pronto, salvo que conozcas sobre Nginx y establezcas tu configuración o sitio.

Agregando PHP 8

Suponiendo que deseas instalar también PHP puedes ejecutar lo siguiente:

sudo apt update
sudo apt install -y lsb-release apt-transport-https ca-certificates
sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list
sudo apt update
sudo apt install php8.0-fpm -y
sudo apt install php8.0-{mysql,curl,mbstring} -y

La última línea instala extensiones del lenguaje PHP (versión 8), por ejemplo, también podrías incorporar entre los corchetes {...,cli,common,snmp,ldap,zip}, o los que identifiques para tu aplicación.
En la penúltima línea se instala la versión compatible con nginx pero podría instalarse en su lugar PHP para apache2 usando simplemente: php8.0
Adicionalmente puedes verificar la version de PHP ejecutando: php -v

Para configurar PHP puedes editar el archivo de configuración /etc/php/8.0/fpm/pool.d/www.conf y establecer los parametros que se ajusten. Por ejemplo, verificamos que la propiedad listen sea igual a /run/php/php8.0-fpm.sock (según la instalación). Luego, para la configuración correspondiente a Nginx se edita el archivo /etc/nginx/sites-enabled/default y en el trozo o bloque que corresponde a PHP (el cual puede encontrarse en comentarios), se establece lo siguiente:

location ~ \.php$ {
        include fastcgi.conf;
        fastcgi_pass unix:/run/php/php8.0-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Una vez establecida la configuración reinicias los servicios así:

sudo nginx -t
sudo systemctl restart php8.0-fpm
sudo systemctl restart nginx

La sentencia sudo nginx -t valida que la sintaxis de Nginx sea correcta.
Si se trata de un entorno bajo Windows Subsystem for Linux, cambias el comando systemctl por service y la instrucción restart va al final de la línea (despúes del nombre del servicio).

Finalmente, puedes probar PHP creando un archivo, por ejemplo, /var/www/html/info.php con el siguiente código:

<?php
phpinfo();
?>

Consulta en un navegador la dirección de tu servidor y la ruta /info.php para ver el resultado.
Para instalar MySQL/MariaDB, entornos y lenguajes puedes remitirte a los comandos respectivos vistos anteriormente, ejemplo: sudo apt install -y mariadb-server

Entorno con Amazon Linux 2 (AL2/EC2)

EC2 significa Elastic Compute Cloud (Computación en la Nube Elástica) por ser de tamaño modificable

Para preparar nuestro entorno de desarrollo con Amazon Linux 2 (AL2), usado generalmente en instancias de computo EC2 de Amazon, tendríamos que descargarnos el archivo Seed.iso y la imágen para la máquina virtual que se encuentran en la documentación de Amazon, luego se siguen sus pasos. Suponiendo que vas directamente a la versión para VirtualBox avanzando 2020, puedes usar el enlace: https://cdn.amazonlinux.com/os-images/2.0.20200304.0/virtualbox/

Esta distribución de Linux (AL2) se ilustra con fines cercanos a los propósitos de OnMind, pero podría usarse otro tipo de Linux si se desea algo personalizado (Ej. CentOS, Debian) y no se necesitaría el archivo Seed.iso sino un .iso oficial del instalador.
Internamente, OnMind propone un archivo personalizado para el Seed.iso, pero esto no altera el concepto si el objetivo es comprender cómo se prepara un entorno de desarrollo con AL2.

Si se arma el archivo Seed.iso, el cual incluye meta-data (para la red) y user-data (para el usuario), podemos revisar la propuesta de OnMind.
Para meta-data se tendría el siguiente contenido:

local-hostname: onmindami

# eth0 is the default network interface enabled in the image. You can configure static network settings with an entry like the following.
network-interfaces: |
  auto eth0
  iface eth0 inet dhcp

Y para user-data un contenido semejante al siguiente (dónde las llaves deben sustituirse por alguna propia):

#cloud-config
#vim:syntax=yaml
users:
# A user by the name `ec2-user` is created in the image by default.
  - default
  - name: onminder
    ssh-authorized-keys:
            - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9wSe9a1wo/qISBga7yz4OAjzixy/dlKAcRSgJmytRts3CmxTtRAYk/3JYx0bAvnQRH85...
    lock_passwd: true

chpasswd:
  list: |
    ec2-user:ec2-user
# In the above line, do not add any spaces after 'ec2-user:'.

# NOTE: Cloud-init applies network settings on every boot by default. To retain network settings from first boot, add following ‘write_files’ section:
write_files:
  - path: /etc/cloud/cloud.cfg.d/80_disable_network_after_firstboot.cfg
    content: |
      # Disable network configuration after first boot
      network:
        config: disabled

timezone: America/Bogota

Los archivos .iso son el equivalente virtual a una imágen de CD/DVD y pueden reproducirse de modo semejante. Windows 10 permite modificar y grabar este tipo de archivos, en el caso de versiones anteriores puedes usar en su lugar una herramienta como PowerISO.

Una vez obtenida la imágen de disco para la máquina virtual (en formato VDI) y el archivo Seed.iso, podemos trasladarlos a la ubicación de máquinas de VirtualBox para tenerlos al alcance (luego quedarán en la subcarpeta creada mediante el proceso). Por ejemplo, en Windows sería C:\Users\user\VirtualBox VMs (dónde user corresponde al usuario que ha iniciado la sesión). Cuando se crea la nueva máquina virtual se establece la nueva subcarpeta. Por ejemplo, si nuestra máquina la nombramos OnMindAMI, los archivos quedarían en C:\Users\user\VirtualBox VMs\OnMindAMI.

Procedemos a abrir VirtualBox y seguir los pasos que se ilustran a continuación:

Normalmente, el proceso con otras distribuciones consiste en iniciar una .iso que instala el sistema sobre un disco creado (nuevo) y se sigue el instalador paso a paso de cada sistema, pero como se observa ya contamos con el disco y el sistema preparado (nuestro archivo .iso sólo aplica un ajuste para la red y el usuario).
Una vez que la máquina virtual haya arrancado y el servicio cloud-init se haya establecido y subido (mostrándose los mensajes en consola), se puede iniciar sesión con la cuenta de usuario respectiva (ej. ec2-user).

Es conveniente apagar la máquina para recordar desconectar el .iso (Seed.iso o similar) e iniciar de nuevo el servidor. La desconexión se hace en la opción de configuración.

Al iniciar sesión con el usuario ec2-user y la contraseña respectiva (ej. ec2-user) nos aparecerá el indicador de comandos.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user ~]$ _

EC2 significa Elastic Compute Cloud (Computación en la Nube Elástica) y AMI significa Amazon Machine Images (Imágenes de Máquina de Amazon).
En el próximo momento de apagado de la máquina virtual (posterior a la configuración incial) es preferible guardar el estado. Esto permitirá iniciar rápidamente sin necesidad de volver al arranque, ventaja del escenario virtual.

Procedemos a actualizar versión de paquetes ejecutando:

sudo yum update -y

Instalando y configurando software con AL2

Amazon Linux 2 (AL2) es una versión compatible con Red-Hat y CentOS, implementando sus mejoras para la computación en la nube con instancias de computo EC2 en AWS (Amazon Web Services). Esto sugiere que la instalación de software es semejante y varía principalmente por los repositorios de software que facilita Amazón para simplificar y soportar software frecuentemente usado. En cuanto a los comandos de Linux serían los mismos que Red-Hat o CentOS.

Veremos a continuación sentencias usadas para la instalación de paquetes de software como Node.js, Java, Go, Rust, MariaDB, NGinx y Docker. Comencemos con el entorno Node.js:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
. ~/.nvm/nvm.sh
nvm install lts/erbium
node -v
npm -v
sudo chown -R $(whoami) ~/.npm

Continuemos con la máquina virtual de Java (JVM) y su kit de desarollo (JDK):

sudo amazon-linux-extras enable corretto8
sudo yum install java-1.8.0-amazon-corretto-devel
java -version
echo $JAVA_HOME

Para lenguaje Go se debe ejecutar lo siguiente:

cd /usr/local/
sudo wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
sudo tar -xzf go1.13.4.linux-amd64.tar.gz
cd /etc/profile.d
sudo echo 'export PATH=$PATH:/usr/local/go/bin' > go.sh
sudo echo 'export GOPATH=$HOME/go' >> go.sh

Lo que se busca en las dos últimas líneas es agregar al archivo go.sh las líneas: export PATH=$PATH:/usr/local/go/bin y export GOPATH=$HOME/go

Para lenguaje Rust ejecutas:

curl https://sh.rustup.rs -sSf | sh

Pasemos ahora al motor de base de datos MariaDB:

sudo amazon-linux-extras install -y lamp-mariadb10.2-php7.2
sudo yum remove -y php*
sudo systemctl start mariadb
mysql -V
sudo mysql_secure_installation

Veamos NGinx que nos servirá como proxy invertido (para traducir puertos de un modo natural y seguro en la aplicación):

sudo amazon-linux-extras install -y nginx1.12
sudo systemctl start nginx

Y si se piensa usar Docker se ejecuta lo siguiente:

sudo amazon-linux-extras install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user

Los paquetes que facilita AL2 corresponden a comandos con amazon-linux-extras, como puede observarse en la mayoría de los casos.

Ajustes de Red para operar como “pro”

Si se desea un entorno semejante a producción (con dirección estática interna), en el que se conecta al servidor a través de ssh (habiendo aprovisionado la clave respectiva, por ejemplo con la imagen Seed.iso), se puede modificar la configuración de red en el administrador de máquinas virtuales (VirtualBox), estableciendo el adaptador de red como NAT de modo que se deben mapear los puertos de la máquina virtual con la máquina física, así podrá usarse el navegador para acceder naturalmente a la máquina virtual como si fuera la física (aunque internamente se podría perder conectividad a Internet, mas siendo un sistema local y aislado no se necesitaría salvo por actualizaciones de software).

En este escenario, los archivos se transmiten con el comando scp o sftp.

Esto también puede acondicionarse y aplicarse para el sistema Linux Debian.