Gestión de infraestructuras virtuales

Objetivos de la asignatura

  • Diseñar, construir y analizar las prestaciones de un centro de proceso de datos virtual.

  • Documentar y mantener una plataforma virtual.

  • Realizar tareas de administración en infraestructura virtual.

Objetivos específicos

  1. Aprender lenguajes de configuración usados en infraestructuras virtuales.
  2. Saber cómo aplicarlos en un caso determinado.
  3. Conocer los sistemas de gestión de la configuración, provisionamiento y monitorización más usados hoy en día.

Introducción

Los gestores de configuraciones trabajan sobre máquinas virtuales ya creadas y en funcionamiento, describiendo la configuración que necesitan para ejecutar una aplicación determinada. Estas aplicaciones se ejecutan directamente si ya tenemos tal máquina provisionada, pero es más eficiente e independiente de la configuración específica trabajar con ellos desde programas de orquestación de máquinas virtuales como Vagrant

Hay muchos gestores: Chef, Salt y Puppet, por ejemplo. Todos son libres, pero tienen características específicas que hay que tener en cuenta a la hora de elegir uno u otro. En el caso específico de sistemas operativos, que es del que vamos a hablar aquí, se trata de gestionar automáticamente todas las tareas de configuración de un sistema, automatizando la edición de ficheros de configuración, instalación de software y configuración del mismo, creación de usuarios y autenticación, de forma que se pueda hacer de forma automática y masiva.

Para poder configurar máquinas virtuales específicas primero hay que instanciarlas. Dejaremos para más adelante cómo hacerlo de forma independiente del proveedor de tales servicios y veremos a continuación cómo preparar una máquina virtual para ser provisionada.

Configurando una instancia

Se puede crear una máquina virtual de muchas formas, usando el interfaz web o el de línea de órdenes del proveedor de servicios correspondiente. Consulta el manual de la misma sobre cómo hacerlo. Sin embargo, si quieres hacer el provisionamiento desde fuera, no puedes usar una imagen cualquiera. Esta imagen tendrá que tener:

Cada imagen suele tener un usuario con privilegios de administrador configurado. Consultar en cada lugar cuál es, pero una vez hecho eso, el siguiente paso en el provisionamiento es crear un par de clave pública/privada y copiar la pública al objetivo. A partir de ahí ya se puede provisionar, empezando por Chef.

Usando Chef para provisionamiento

Chef es una herramienta que, en general, se usa en un servidor que se encarga no sólo de gestionar la configuración, sino también las versiones. Empezar a usarlo es complicado. Sin embargo, como introducción a la gestión de configuraciones se puede usar chef-solo, una versión aislada que permite trabajar en una máquina desde la misma y que, por tanto, se puede usar como introducción y para probar configuraciones.

Hay varios tutoriales que te permiten, con relativa rapidez, comenzar a trabajar con Chef-solo en un servidor; este te proporciona una serie de ficheros que puedes usar y este otro es más directo, dando una serie de órdenes. En todo caso, se trata básicamente tener acceso a un servidor o máquina virtual, instalar una serie de aplicaciones en él y ejecutarlas sobre un fichero de configuración

En una máquina tipo ubuntu, hay que comenzar instalando Ruby y Ruby Gems, el gestor de librerías

sudo apt-get install ruby1.9.1 ruby1.9.1-dev rubygems

chef se distribuye como una gema, por lo que se puede instalar siempre como

sudo gem install ohai chef

ohai acompaña a chef y es usado desde el mismo para comprobar características del nodo antes de ejecutar cualquier receta.

Una forma más rápida de instalar Chef es descargarlo directamente desde la página web:

curl -L https://www.opscode.com/chef/install.sh | bash

La última tendrá que ser sudo bash en caso de que se quiera instalar como administrador (que será lo normal).

Instalar chef-solo en la máquina virtual que vayamos a usar

Una receta de Chef consiste en crear una serie de ficheros: una lista de ejecución que especifica qué es lo que se va a configurar; esta lista se incluye en un fichero node.json, o recetario (cookbook) que incluye una serie de recetas que configuran, efectivamente, los recursos y, finalmente, un fichero de configuración que dice dónde están los dos ficheros anteriores y cualquier otro recursos que haga falta. Estos últimos dos ficheros están escritos en Ruby.

Vamos a empezar a escribir una recetilla del Chef. Generalmente, escribir una receta es algo más complicado, pero comenzaremos por una receta muy simple que instale el imprescindible emacs y le asigne un nombre al nodo. Creamos el directorio chef en algún sitio conveniente y dentro de ese directorio irán diferentes ficheros.

El fichero que contendrá efectivamente la receta se llamará default.rb

package 'emacs'
directory '/home/jmerelo/Documentos'
file "/home/jmerelo/Documentos/LEEME" do
	owner "jmerelo"
	group "jmerelo"
	mode 00544
	action :create
	content "Directorio para documentos diversos"
end

El nombre del fichero indica que se trata de la receta por omisión, pero el nombre de la receta viene determinado por el directorio en el que se meta, que podemos crear de un tirón con

mkdir -p chef/cookbooks/emacs/recipes

Este fichero tiene tres partes: instala el paquete emacs, crea un directorio para documentos y dentro de él un fichero que explica, por si hubiera duda, de qué se trata. Evidentemente, tanto caminos como nombres de usuario se deben cambiar a los correspondientes en la máquina virtual que estemos configurando.

El siguiente fichero, node.json, incluirá una referencia a esta receta

{
	"run_list": [ "recipe[emacs]" ]
}

Este fichero hace referencia a un recetario, emacs y dado que no se especifica nada más se ejecutará la receta por defecto.

Finalmente, el fichero de configuración solo.rb incluirá referencias a ambos.

file_cache_path "/home/jmerelo/chef"
cookbook_path "/home/jmerelo/chef/cookbooks"
json_attribs "/home/jmerelo/chef/node.json"

Una vez más, cambiando los caminos por los que correspondan. Para ejecutarlo,

sudo chef-solo -c chef/solo.rb

(si se ejecuta desde el directorio raíz). Esta orden producirá una serie de mensajes para cada una de las órdenes y, si todo va bien, tendremos este útil editor instalado.

Crear una receta para instalar nginx, tu editor favorito y algún directorio y fichero que uses de forma habitual.

Para usar chef-solo hay simplemente que instalar unos cuantos programas, pero en gran parte ya está automatizado: aquí explica como usarlo en Ubuntu, por ejemplo basándose en este Gist (programas cortos en GitHub) que instala todas las herramientas necesarias para comenzar a ejecutar chef.

Este curso en vídeo te enseña también a trabajar con Chef

De ninguna manera JSON es un lenguaje universal para gestión de configuraciones. Prácticamente todo el resto de los sistemas de configuración usan YAML (yet another markup language). Recientemente se ha publicado una introducción al tema que será suficiente para el uso que le vamos a dar más adelante

Escribir en YAML la siguiente estructura de datos en JSON

{ uno: "dos",
  tres: [ 4, 5, "Seis", { siete: 8, nueve: [ 10, 11 ] } ] }

Normalmente estas recetas van a estar bajo control de un sistema de gestión de fuentes; de esta forma se pueden probar diferentes configuraciones, crear nuevas versiones de la misma pero, sobre todo, tener claro en cada momento qué configuración es la que se está ejecutando en producción, que será habitualmente la que esté en una rama designada de la misma.

Gestionando configuraciones con Salt

Salt es otra herramienta de configuración que se ha hecho popular en los últimos años. Aunque algo más complicada de configurar que Ansible, tiene como ventaja que permite modularizar la configuración para poder adaptarla a sistemas de la forma más conveniente. salt-ssh está basado en Python y sólo requiere, en principio, que este lenguaje esté instalado en el sistema que se va a provisionar.

La mejor forma de empezar es instalarlo desde Github aunque nosotros vamos a trabajar con salt-ssh, un sistema que no requiere ningún tipo de instalación en el ordenador objetivo y que se puede usar, hasta cierto punto, como Ansible. Vamos a usarlo para instalar los servicios necesarios para el bot de Telegram en Scala que hemos visto en alguna otra ocasión.

Una vez instalado salt-ssh, una de los principales problemas es que requiere una cierta cantidad de configuración global. Generalmente vamos a usar un directorio tal como ~/lib/salt/ como directorio de trabajo y configuración; y este directorio va a estar fuera del repositorio y en un directorio de superusuario por omisión. Se puede usar el directorio local, pero en ese caso habrá que decir específicamente donde se encuentra cada tipo de fichero. En el README.md del bot vienen las instrucciones necesarias para crear ese fichero de provisionamiento y la configuración global.

Pero para configurar nuestro propio sistema, uno de los más importantes es el fichero roster:

app: 
  host: 104.196.9.185
  user: one_user
sudo: True

Aquí no sólo se declara la dirección a la que vamos a conectar, sino también si hace falta ser sudo o no. Con esto podemos ejecutar ya parte de la configuración que vamos a ejecutar más adelante:

salt-ssh '*' --roster-file=./roster -r "sudo apt-get install python-apt" -c ~/lib/salt --force-color

En este caso, se trata de ejecutar una orden para poder instalar python-apt, un módulo para poder ejecutar órdenes de instalación de paquetes directamente desde Python.

Pero para efectivamente provisionar se usan ficheros salt-stack. Por ejemplo, estos ficheros instalan Java en la versión necesaria para poder instalar más adelante Scala. Y Scala lo instalamos en este fichero

include:
  - javasetup

scala:
pkg.installed

Este fichero se ejecutaría con

salt-ssh app state.apply scala --roster-file=./roster -c ~/lib/salt --force-color

Este programa, como Ansible, actúa de manera descriptiva. Indica que el paquete scala tiene que estar instalado, pero para ello tiene que cumplir una serie de prerrequisitos incluidos en el fichero javasetup.sls; el nombre de estado se tiene que corresponder con el nombre del fichero en sí. Este a su vez requiere la instalación de otra serie de paquetes, e incluye otro fichero. Lo bueno es que esos dos ficheros, javasetup y java, se pueden usar para todos los paquetes que usen esa máquina virtual; para instalar Scala sólo hay que crear este último fichero.

Todos estos, por cierto, tienen que ejecutarse desde directorios específicos, al menos la forma más simple de hacerlo es copiar todos los ficheros .sls a ~/lib/salt/states y hacerlo desde ahí.

En general, y por la forma que tiene un poco rígida de hacer las cosas, resulta algo más complicado usarlo que Ansible o incluso Chef. Sin embargo y limitado a salt-ssh, una vez que la configuración está completa y si se tienen configuraciones base, construir a partir de ellas es relativamente sencillo.

Provisionar una máquina virtual en algún entorno con los que trabajemos habitualmente usando Salt.

Otros sistemas de gestión de configuración

Las principales alternativas a Chef son Ansible, Salt y Puppet. Todos ellos se comparan en este artículo, aunque los principales contendientes son Puppet y Chef, sin que ninguno de los dos sea perfecto.

De todas ellas, vamos a ver Ansible que parece ser uno de los que se está desarrollando con más intensidad últimamente. Ansible es sistema de gestión remota de configuración que permite gestionar simultáneamente miles de sistemas diferentes. Está basado en YAML para la descripción de los sistemas y escrito en Python.

Se instala como un módulo de Python, usando por ejemplo la utilidad de instalación de módulos pip (que habrá que instalar si no se tiene)

sudo pip install paramiko PyYAML jinja2 httplib2 ansible

El resto de las utilidades son también necesarias y en realidad se instalan automáticamente al instalar ansible. Estas utilidades se tienen que instalar en el anfitrión, no hace falta instalarlas en el invitado, que lo único que necesitará, en principio, es tener activada la conexión por ssh y tener una cuenta válida y forma válida de acceder a ella.

Cada máquina que se añada al control de Ansible se tiene que añadir a un fichero, llamado inventario, que contiene las diferentes máquinas controladas por el mismo. Por ejemplo

 $ echo "ansible-iv.cloudapp.net" > ~/ansible_hosts

se puede ejecutar desde el shell para meter (echo) una cadena con una dirección (en este caso, una máquina virtual de Azure) en el fichero ansible_hosts situado en mi directorio raíz. El lugar de ese fichero es arbitrario, por lo que habrá que avisar a Ansible donde está usando una variable de entorno:

export ANSIBLE_HOSTS=~/ansible_hosts

Y, con un nodo, ya se puede comprobar si Ansible funciona con

$ ansible all -u jjmerelo -m ping

Esta orden hace un ping, es decir, simplemente comprueba si la máquina es accesible desde la máquina local. -u incluye el nombre del usuario (si es diferente del de la máquina local); habrá que añadir --ask-pass si no se ha configurado la máquina remota para poder acceder a ella sin clave.

De forma básica, lo que hace Ansible es simplemente ejecutar comandos de forma remota y simultáneamente. Para hacerlo, podemos usar el inventario para agrupar los servidores, por ejemplo

[azure]
iv-ansible.cloudapp.net

crearía un grupo azure (con un solo ordenador), en el cual podemos ejecutar comandos de forma remota

$ ansible azure -u jjmerelo -a df

nos mostraría en todas las maquinas de azure la organización del sistema de ficheros (que es lo que hace el comando df). Una vez más, -u es opcional.

Esta orden usa un módulo de ansible y se puede ejecutar también de esta forma:

$ ansible azure -m shell ls

haciendo uso del módulo shell. Hay muchos más módulos a los que se le pueden enviar comandos del tipo “variable = valor”. Por ejemplo, se puede trabajar con servidores web o copiar ficheros o incluso desplegar aplicaciones directamente usando el módulo git

Desplegar los fuentes de una aplicación cualquiera, propia o libre, que se encuentre en un servidor git público en la máquina virtual Azure (o una máquina virtual local) usando ansible.

Finalmente, el concepto similar a las recetas de Chef en Ansible son los playbooks, ficheros en YAML que le dicen a la máquina virtual qué es lo que hay que instalar en tareas, de la forma siguiente

---
- hosts: azure
  sudo: yes
  tasks:
	- name: Update emacs
	  apt: pkg=emacs state=present

Esto se guarda en un fichero y se le llama, por ejemplo, emacs.yml, y se ejecuta con

ansible-playbook ../../ejemplos/ansible/emacs.yml

(recordando siempre el temita del nombre de usuario), lo que dará, si todo ha ido bien, un resultado como el siguiente

Instalación de emacs usando ansible

En el fichero YAML lo que se está expresando es un array asociativo con las claves hosts, sudo y tasks. En el primero ponemos el bloque de servidores en el que vamos a actuar, en el segundo si hace falta hacer sudo o no y en el tercero las tareas que vamos a ejecutar, en este caso una sola. El apartado de tareas es un vector de hashes, cada uno de los cuales tiene en name el nombre de la tarea, a título informativo y en las otras claves lo que se va a hacer; apt indicará que hay que instalar un paquete (pkg) llamado emacs y que hay que comprobar si está presente o no (state). El que se trabaje con estados y no de forma imperativa hace que los playbooks sean idempotentes, es decir, si se ejecutan varias veces darán el mismo resultado que si se ejecutan una sola vez.

  1. Desplegar la aplicación que se haya usado anteriormente con todos los módulos necesarios usando un playbook de Ansible.

A donde ir desde aquí

El siguiente tema sería el de orquestación de máquinas virtuales, donde se aprenderá a trabajar con configuraciones más complejas que usen varias máquinas virtuales a la vez.

A partir de aquí se puede seguir aprendiendo sobre devops en el blog o en IBM. Libros como DevOps for Developers pueden ser también de ayuda. Esta comparativa de sistemas de configuración te permite ver todos los que hay, ver la última columna cuáles son los más recientemente actualizados y qué esperar de cada uno de ellos. También en este gist explica las diferencias entre herramientas en este área, incluyendo también Puppet e incluso Docker. En presentaciones como esta se habla de CAPS: Chef, Ansible, Puppet and Salt como una categoría en sí. En este artículo también los comparan y en este último llevan a cabo la configuración de un servidor simple usando los cuatro.