Configurar SnipeIT como deployment en Kubernetes sobre Google Cloud Platform
La nota mental de hoy va sobre una herramienta OpenSource para la gestión de inventario que estamos probando en la oficina: SnipeIT. La manera de documentar como realizar una instalación, ya fuera sobre VM o sobre docker me pareció realmente confusa.
Invertí bastantes horas en entender los ficheros de configuración. Cosas tan sencillas como especificar que el docker-compose up debía ir con el atributo -d, para poder seguir utilizando la consola, no estaban especificadas. Al igual que el orden para realizar los pasos.
A continuación, os detallo los pasos que seguí para poder llevar a cabo el despligue como deployment en el entorno de Kubernetes de GCP.
Introducción
Snipe-IT permite una gestión fácil para 4 tipos principales de activos:
- Equipos/Terminales
- Licencias
- Accesorios
- Consumibles
Permite tener una traza de quién tiene qué portátil/pc, cuándo se ha comprado, dónde, qué licencias de software y accesorios están disponibles, etc.
Es un software con solamente interfaz web, y alguna de las cosas que más me han gustado es la capacidad de vincular los usuarios con un LDAP o AD. Está basado en el framework Laravel, y el fichero de configuración es el estándar del mismo.
Snipe-IT requiere de una conexión a base de datos para almacenar el contenido. Es compatible con varios tipos diferentes de bases de datos, pero en esta nota mental, trabajaremos con MySQL 5.6
Ojo: Para poder lanzar correctamente la aplicación en Kubernetes es necesario generar una key.
Instalación en local
En la documentación de SnipeIT no hay un apartado para Kubernetes, así que lo que tuve que hacer es adaptar los archivos que ellos facilitaban.
Estos son los archivos para poder lanzar snipe-it como contenedor local.
docker-compose.yml
version: '3'
services:
snipe-mysql:
container_name: snipe-mysql
image: mysql:5.6
env_file:
- ./.env
volumes:
- snipesql-vol:/var/lib/mysql
command: --default-authentication-plugin=mysql_native_password
expose:
- "3306"
snipe-it:
image: snipe/snipe-it
env_file:
- ./.env
ports:
- "80:80"
depends_on:
- snipe-mysql
volumes:
snipesql-vol:
SnipeIT corre un Apache de manera interna. En este caso he mapeado el 80 de la aplicación al 80 de mi máquina, para simplificarlo todo.
Por otra parte, este es el fichero de variables de entorno oficial:
.env
# Mysql Parameters
MYSQL_PORT_3306_TCP_ADDR=snipe-mysql
MYSQL_ROOT_PASSWORD=YOUR_SUPER_SECRET_PASSWORD
MYSQL_DATABASE=snipeit
MYSQL_USER=snipeit
MYSQL_PASSWORD=YOUR_snipeit_USER_PASSWORD
# Email Parameters
# - the hostname/IP address of your mailserver
MAIL_PORT_587_TCP_ADDR=smtp.whatever.com
#the port for the mailserver (probably 587, could be another)
MAIL_PORT_587_TCP_PORT=587
# the default from address, and from name for emails
[email protected]
MAIL_ENV_FROM_NAME=Your Full Email Name
# - pick 'tls' for SMTP-over-SSL, 'tcp' for unencrypted
MAIL_ENV_ENCRYPTION=tcp
# SMTP username and password
MAIL_ENV_USERNAME=your_email_username
MAIL_ENV_PASSWORD=your_email_password
# Snipe-IT Settings
APP_ENV=production
APP_DEBUG=false
APP_KEY=<<Fill in Later!>>
APP_URL=http://127.0.0.1:80
APP_TIMEZONE=US/Pacific
APP_LOCALE=en
Para lanzarlo en local, situaremos nuestra consola en la carpeta donde hayamos generado estos dos archivos anteriores. A continuación, ejecutaremos el siguiente comando:
docker-compose up -d
El -d lo hará correr en segundo plano y podremos seguir trabajando con el mismo terminal
Generar la APP_KEY
Tenemos que acceder al bash del contenedor de snipe-it, para ello:
docker exec -it nombre-del-contenedor-snipe-it sh
Y ejecutamos el siguiente comando:
php artisan key:generate
Nos debería devolver un texto tal que:
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
Escribimos yes y pulsamos Enter. Debería devolver algo similar a:
Application key [base64:mW05bo4UXv6D/t3ldTzjUvIbUkwyKdrPSVlr/mrE3Ac=] set successfully.
La key en este caso sería:
base64:mW05bo4UXv6D/t3ldTzjUvIbUkwyKdrPSVlr/mrE3Ac=
Es importante no olvidar el base64, puesto que sino, la aplicación no funcionará correctamente.
Archivos de configuración en Kubernetes
Necesitamos:
- Disco de almacenamiento persistente (PVC)
- Configmap para guardar las variables de sistema
- Secrets para guardar las variables sensibles y contraseñas
- Servicios, uno para mysql y otro para snipe-it.
- Deployment
01-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: snipeit-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
02-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: snipe-it-config
data:
# Mysql Parameters
MYSQL_PORT_3306_TCP_ADDR: "mysql-service"
MYSQL_PORT_3306_TCP_PORT: "3306"
MYSQL_DATABASE: "snipeit"
MYSQL_USER: "snipeit"
# Email Parameters
# - the hostname/IP address of your mailserver
MAIL_PORT_587_TCP_ADDR: smtp.whatever.com
#the port for the mailserver (probably 587, could be another)
MAIL_PORT_587_TCP_PORT: 587
# the default from address, and from name for emails
MAIL_ENV_FROM_ADDR: [email protected]
MAIL_ENV_FROM_NAME: Your Full Email Name
# - pick 'tls' for SMTP-over-SSL, 'tcp' for unencrypted
MAIL_ENV_ENCRYPTION: tcp
# SMTP username and password
MAIL_ENV_USERNAME: your_email_username
MAIL_ENV_PASSWORD: your_email_password
# Snipe-IT Settings
APP_ENV: "production"
APP_DEBUG: "false"
APP_KEY: "base64:mW05bo4UXv6D/t3ldTzjUvIbUkwyKdrPSVlr/mrE3Ac="
APP_URL: "http://0.0.0.0:80"
APP_TIMEZONE: "Europe/Madrid"
APP_LOCALE: "es-ES"
Dónde:
- MYSQL_PORT_3306_TCP_ADDR: «mysql-service» corresponde al servicio de de MySQL que crearemos en archivos posteriores.
- MYSQL_PORT_3306_TCP_PORT: «3306» es el valor por defecto del puerto de MySQL
- MYSQL_DATABASE: «snipeit» es el nombre por defecto de la base de datos
- MYSQL_USER: «snipeit» es el usuario por defecto de la base de datos.
- APP_KEY: Es la clave que hemos generado previamente en local.
03-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: snipe-it-secret
type: Opaque
data:
MYSQL_ROOT_PASSWORD: "tu-contraseña-root-mysql-en-base-64"
MYSQL_PASSWORD: "tu-contraseña-root-mysql-en-base-64"
04-mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-service
labels:
app: snipeit
spec:
ports:
- port: 3306
protocol: TCP
targetPort: 3306
selector:
app: snipeit
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer: {}
En cuanto hablamos de servicios, no hay que perder de vista las etiquetas. Son las que nos permitirán asociar pods y deployments a servicios. En mi caso utilizo la etiqueta «app» para realizar posteriormente la concordancia en el deployment.
En mi caso he elegido desplegar tanto el servicio de MySQL como el de Snipe-IT como balanceador de carga, lo cual me generará una IP pública accesible. Podría hacerse también usando IP de Clúster y un Ingress, entre otras opciones.
05-snipeit-service
apiVersion: v1
kind: Service
metadata:
name: snipeit-service
labels:
app: snipeit
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: snipeit
sessionAffinity: None
type: LoadBalancer
status:
loadBalancer: {}
06-deployment.yaml
apiVersion: "apps/v1"
kind: "Deployment"
metadata:
name: "snipeit-deployment"
labels:
app: "snipeit"
spec:
replicas: 1
selector:
matchLabels:
app: snipeit
template:
metadata:
labels:
app: snipeit
spec:
containers:
### mysql image ###
- name: snipe-mysql
image: mysql:5.6
ports:
- containerPort: 3306
envFrom:
- configMapRef:
name: snipe-it-config
- secretRef:
name: snipe-it-secret
volumeMounts:
- name: snipeit-vol
mountPath: /var/lib/mysql
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "sleep 60"]
### snipe it image ###
- name: snipeit
image: snipe/snipe-it
envFrom:
- configMapRef:
name: snipe-it-config
- secretRef:
name: snipe-it-secret
ports:
- containerPort: 80
volumeMounts:
- name: snipeit-vol
mountPath: /var/lib/snipeit
#volumes of the pod
volumes:
- name: snipeit-vol
persistentVolumeClaim:
claimName: snipeit-pvc
Dónde:
- snipe-it-config: Es el nombre asignado al fichero de ConfigMap
- snipe-it-secret: Es el nombre asignado al fichero de Secrets.
- snipeit-pvc: Es el nombre asignado al disco persistente creado.
- snipeit-vol: Es el nombre asignado al volumen para utilizar el pvc dentro de la plantilla del depliegue.
Recuerda: Has de tener previamente instalada la herramienta Google SDK y el plugin kubectl.
Para finalizar, desde la consola de SDK, nos situamos en la carpeta donde hayamos generado los ficheros de configuración y lanzamos.
kubectl create -f . --save-config
No te olvides de probar que todo funciona como se espera. En este caso, bastaría con poner en un navegador la IP pública que haya asignado Google para el balanceador de carga.
Os dejo la documentación oficial en la que me he basado, por si os es de utilidad.
Problema resuelto!
Synology C2 y sus diferentes opciones de backup
No se trata de una nota mental patrocinada (¡ojala!). Va destinada a todos aquellos que por suerte o por desgracia cuentan con una NAS Synology en su infraestructura.
El objetivo es desglosar los principales problemas que te puedes encontrar cuando usas este tipo de producto, ventajas y desventajas que ofrece la solución C2 frente a estos errores, los requerimientos para poder empezar, y por último, las opciones de la copia y sus diferencias.
Introducción
Synology se ha sabido adaptar bien al mercado, y ofrece bastantes opciones para hacer la copia en cloud: Azure, Google Drive, AWS… Esto está muy bien porque si ya trabajas con alguno de estos proveedores de nube, en pocos pasos, es bastante sencillo integrarlo.
Ahora bien, no nos engañemos. Lo que esperas de una copia de seguridad de una NAS es no tener que revisar que funcione, que la copia sea íntegra, fácil de restaurar, que puedas tener varios puntos de recuperación, y ya puestos a hacer la carta a los reyes magos, que en caso de necesitarlo tengas un soporte que te pueda echar un cable en el momento lo necesites.
Synology C2 es una solución cloud nativa diseñada para integrarse con las NAS de la misma marca.
Problemas habituales
- El tamaño de la NAS crece y crece, y te quedas sin espacio de almacenamiento en el Cloud.
- Falta de discriminación. Las copias a soluciones cloud suelen volcar el contenido sin filtrar si los archivos o carpetas han cambiado de nombre, lo que duplica contenido.
- Puntos de recuperación. Las copias a servicios cloud suelen carecer de esta funcionalidad, y es muy útil. Todos nos hemos tropezado con usuarios que querían la versión de hace una semana.
- Errores al restaurar. Podría ser el título de una película de terror. Tienes tu copia, y cuando vas a restaurar ¡Boom! Error desconocido.
Ventajas de Synology C2
- Herramienta nativa. Va a tener una integración mayor que el resto de las soluciones. Suele facilitar el soporte, al ser ambos Synology.
- Diferentes políticas de retención, personalizables.
- Múltiples puntos de restauración, en función de la política.
- Opción más económica, si lo comparamos con plataformas como GCP o Azure.
Desventajas
- La primera copia suele tardar varios días en hacerse. Recomiendo siempre previsión, antelación y planificación antes de hacer esta primera copia.
Rotación de copia
Es posible configurar C2 para que realice una rotación de las copias. Se trata de copias tipo GFS, lo que las convierte en una opción muy interesante. Este tipo de sistema no es nuevo, sin ir muy lejos, lo lleva usando Veeam Backup hace años. Es muy potente y nos ayuda a retener muchos datos al mismo tiempo nos da un alto nivel de compresión.
¡Ojo! Activar la rotación de copia hará que las copias de seguridad se eliminen automáticamente según la configuración de rotación.
Pero seamos realistas: Nadie va a querer restaurar un archivo eliminado de hace más de x meses. Esto nos ayudará con el problema archivos obsoletos nos consuman espacio de la copia. Además, que es posible evitar este comportamiento si se bloquean versiones desde el explorador de Información.
Requerimientos
- Synology NAS.
- DSM 6.0 o una versión posterior.
- Hyper Backup 2.1.2 o superior. Va a ser la herramienta con la que vas a gestionar la creación y la restauración de las copias.
- Cuenta de Synology.
Opciones de rotación de copia
A partir de versiones anteriores
Creará los puntos de restauración que le indiques en el apartado «Número máximo de versiones». Por defecto, te pondrá el valor 256 que equivale a 9 meses.
Synology te ofrece dos maneras de crear los puntos de restauración:
La opción «M» creará un punto diario con una sola versión por punto.
La opción «Y» creará un punto semanal, con 7 versiones en cada punto.
El resultado es el mismo, tienes una copia diaria de tus datos, así que la opción que elijas tiene que ser en función de tus necesidades.
Smart Recycle
Para mi, sin duda, la opción más cómoda. La política de retención es:
- Versiones cada hora desde las últimas 24h
- Versiones diarias desde hace 1 día hasta hace 1 mes.
- Versiones semanales con más de 1 mes.
Es cómodo, funcional y suele adecuarse a casi cualquier tipo de retención que necesite un contenido almacenado en NAS.
Retención personalizada
Si las opciones por defecto no se ajustan, puedes crear una retención personalizada.
Instalar Spark 2.3.2 + Scala 2.11 sobre Debian 10
En la nota mental de hoy voy a indicar cómo desplegar dos aplicaciones, las cuales nos van a facilitar mucho trabajar con BigData y lago de datos como Hadoop, con versiones en desuso (deprecated) pero que funcionan con JDK8.
Para está instalación nos hace falta tener instalado previamente JDK8. Puedes consultar como hacerlo para Debian 10 aquí.
Introducción
¿Qué es Spark?
Apache Spark es un framework de programación para procesamiento de datos distribuidos diseñado para ser rápido y de propósito general. Cuenta con flexibilidad e interconexión con otros módulos de Apache como Hadoop, Hive o Kafka.
En nuestro caso, lo vamos a utilizar para poder hacer uso de Scala.
¿Qué es Scala?
Es un lenguaje de programación orientado a objetos, bastante popular e integrable con herramientas como IntelliJ, Eclipse, . Una de sus mayores ventajas es la escalabilidad. Comúnmente, se dice que scala suple las carencias de Java, con lo que su uso y adopción está en auge.
El objetivo de esta nota mental no es entrar en detalle de scala, así que si tenéis curiosidad, os dejo un par de entradas interesantes:
Despliegue
Aunque se trata de una versión obsoleta, me parece interesante exponer el proceso que he seguido y me ha funcionado. Y es que a la hora de la verdad, cuando te tropiezas con el mundo real y las infraestructuras de muchas empresas «normales», prima la economía de la empresa. El resultado es que muchos de los sistemas no soportan últimas versiones.
Previo a todo esto, buenas prácticas, update y upgrade:
sudo apt-get update
sudo apt-get upgrade
Este es el repositorio del cual voy a obtener los datos para la instalación:
https://github.com/apache/spark/archive/v2.3.2.zip
Lo primero es descargar spark, descomprimirlo y eliminar los ficheros descargados, dentro de la máquina donde vayamos a realizar la instalación.
sudo wget https://github.com/apache/spark/archive/v2.3.2.zip
sudo unzip v2.3.2.zip
sudo rm -rf v2.3.2.zip
En mi caso, voy a crearle una carpeta específica para la instalación, y voy a mover los archivos descomprimidos dentro de ella.
sudo mkdir /opt/spark
sudo mv spark-2.3.2/* /opt/spark
Entramos en la carpeta que acabamos de crear y lanzamos los comandos de configuración para instalar scala. Para ello utilizaremos Maven (mvn) y Hadoop.
cd /opt/spark/
sudo ./dev/change-scala-version.sh 2.11
sudo ./build/mvn -Pyarn -Phadoop-2.6 -Dscala-2.11 -DskipTests clean package
Para verificar la instalación, podemos lanzar:
./bin/run-example SparkPi 10
El siguiente paso quitar la extensión .template
del script de configuración.
sudo mv conf/spark-env.sh.template conf/spar-env.sh
sudo nano conf/spark-env.sh
Tenemos que buscar una linea similar a SPARK_LOCAL_IP
, que suele ir comentada con #. Le asignaremos el siguiente valor:
SPARK_LOCAL_IP=127.0.0.1
Por último, para utilizar scala, lanzaremos el siguiente comando:
./bin/spark-shell — master local[2]
Problema resuelto!