Instalación poco común de Debian y redimensión de volúmenes lógicos.

Después de instalar Debian Stretch de nuevo en mi ordenador, lo hice de una manera que nunca lo había realizado, en volúmenes lógicos y con un sistema de ficheros xfs.

Anuncios

Después de instalar Debian Stretch de nuevo en mi ordenador, lo hice de una manera que nunca lo había realizado, en volúmenes lógicos y con un sistema de ficheros xfs.

Me podrían llamar raro, y no les culpo, pero todo esto tiene una explicación. Mi esquema es el siguiente:

  • Tengo un volumen físico que ocupa todo el disco.
  • Un grupo de volúmenes igual.
  • Un volumen lógico de 30GiB donde tengo el sistema
  • Tres volúmenes en los que están por separado /var, /home y la swap.

Con esto solamente tendré unos 50GiB a lo sumo de utilización del disco y lo demás sin utilizar.

Pero, lo bueno no viene aquí, sino que si se da el caso que me quede sin hueco, simplemente con crear un nuevo volumen y extender el volumen y el sistema de ficheros volveré a tener espacio, esto tanto para este disco como si quiero añadir otro diferente. Y aquí es donde interviene el sistema de ficheros xfs.

Al contrario que ext4, este sistema de ficheros no permite volver a dimensionar en caliente sin tener que reiniciar el sistema, en el caso de servidores (para lo que está pensado este caso), significa no tener que dejar de dar servicio.

Todos estos volúmenes se crean durante la instalación de Debian con su gestor de volúmenes lógicos. A continuación vamos a ver lo necesario para expandir un volumen que se nos haya quedado corto.

Redimensión de volúmenes lógicos:

Si nos ponemos en el caso que nos quedamos con una bonita pantalla negra porque la partición /var se nos ha quedado pequeña deberemos crear otro volumen lógico y anexarlo al existente y así conseguiremos volver a arrancar el entorno gráfico.

Para extenderlo sobre el proṕio disco que estamos utilizando:

root@Leon:~# lvextend -L +10G /dev/sistema/var

Le indicaremos que queremos extender un volumen lógico diez GiB y este volumen es el que se encuentra en /dev/sistema y se llama var.

Aquí, no hemos acabado todavía, pues tendremos que redimensionar nuestro sistema de ficheros para que ocupe el nuevo espacio que le hemos asignado:

root@Leon:~# xfs_growfs /dev/sistema/var

Podemos comprobar que el tamaño de nuestro volumen ha aumentado, esto, podemos verlo con df -h.

Y bien, si incluimos un disco duro nuevo que no se encuentra en el volumen físico que se ha creado en la instalación:

  1. Creamos el volumen físico
  2. Lo añadimos al grupo de volúmenes
  3. Pasos anteriores de extender y redimensionar.

Creación del volumen físico en un disco nuevo:

root@Leon:~# pvcreate /dev/hdc1

Y extendemos el grupo de volúmenes:

root@Leon:~# vgextend sistema /dev/hdc1

Y listo ya tendríamos listo el volumen nuevo y totalmente operativo nuestro sistema.

Ante cualquier duda podéis preguntar en los comentarios y responderé encantado.

MongoDB: Expresiones regulares

Antes de comenzar la explicación sobre como utilizar expresiones regulares en MongoDB, vamos a introducir los registros que nos van a hacer falta:

db.test.insert(“correo” : “correo1_1@gmail.com”)

db.test.insert(“correo” : “correo2_2@gmail.com”)

db.test.insert(“correo” : “correo3_3@gmail.es”)

Podemos realizar búsquedas por patrones, para ello aquí también tenemos un equivalente a like:

db.test.find( { correo : /@/ } )

O también podemos olvidarnos de los backslash y utilizar regex que bajo mi opinión deja más claro que estamos utilizando expresiones regulares.

db.test.find( { correo : { $regex : “@” } } )

Con esto vamos a buscar todos los correos que contengan una arroba entre caracteres.

db.test.find( {correo : { $regex : “.com$” } } )

Nos enseñará todos los correos que acaben en el patrón puesto anteriormente. Hay que tener en cuenta que el símbolo $ se utiliza como delimitador, es decir dirá si atrás puede haber más caracteres o no.

db.test.find( { correo : {$regex : “^c” } } )

Al contrario, el acento circunflejo (^), hará que nos filtre las cadenas que empiecen por el carácter puesto a continuación.

En el siguiente post hablaremos de los documentos embebidos. Si ha quedado alguna duda o no funcionase algo, dejad un comentario y os lo resolveré sin problemas. Un saludo.

LXC: Primeros pasos

Después de nuestra presentación sobre los contenedores Linux, vamos a ver como empezar a trabajar con ellos, este primero post va a ser muy ligero sobre como utilizarlos. Más adelante introduciré nuevas configuraciones.

Comenzaremos instalando los paquetes necesarios para su uso:

# apt install lxc bridge-utils libvirt-daemon-system libvirt-dev libvirt-clients debootstrap -y

Una vez tenemos los paquetes instalados, vamos a comprobar que todo está bien configurado:

# lxc-checkconfig

Si todo ha salido bien, deberemos de tener todo los apartados con un bonito color verde donde pondrá enabled.

Ahora vamos a crear nuestro primer contenedor, para ello teclearemos:

lxc-create -t download -n debian1

Con esto le decimos que nos cree un contenedor de nombre debian1 mediante descarga. El sistema operativo se lo pondremos a continuación:

root@Leon:/home/manu# lxc-create -t download -n debian1
Setting up the GPG keyring
Downloading the image index


DIST RELEASE ARCH VARIANT BUILD

alpine 3.3 amd64 default 20170915_17:50
alpine 3.3 armhf default 20170103_17:50
[…]

Distribution: debian
Release: stretch
Architecture: amd64

Using image from local cache
Unpacking the rootfs


You just created a Debian container (release=stretch, arch=amd64, variant=default)

To enable sshd, run: apt-get install openssh-server

For security reason, container images ship without user accounts
and without a root password.

Use lxc-attach or chroot directly into the rootfs to set a root password
or create user accounts.

Comprobamos que nuestro contenedor está creado con:

# lxc-ls -f

Si está creada la arrancamos:

# lxc-start -n debian1

Para recibir información sobre el contenedor:

# lxc-info -n debian1

Si queremos destruir nuestro contenedor:

# lxc-destroy -n debian1

Para pararlo:

# lxc-stop -n debian1

Y por último para entrar en nuestro contenedor:

# lxc-attach -n debian1

De momento como primera entrada sobre contenedores es suficiente, en las siguientes hablaremos sobre sus ficheros de configuración y conexiones a redes.

MongoDB: Group

Vamos a trabajar con documentos agrupados, al igual que en SQL tenemos group by, en MongoDB vamos a utilizar group.

Comenzamos con los siguientes documentos:

{ “_id” : ObjectId(“59ba683fb384e2e054652223”), “producto” : “caja”, “precio” : 20, “stock” : 2 }
{ “_id” : ObjectId(“59ba6853b384e2e054652224”), “producto” : “caja”, “precio” : 10, “stock” : 5 }
{ “_id” : ObjectId(“59ba6861b384e2e054652225”), “producto” : “vino”, “precio” : 50, “stock” : 10 }
{ “_id” : ObjectId(“59ba6877b384e2e054652226”), “producto” : “botella”, “precio” : 5, “stock” : 50 }

Ahora vamos a agrupar según que campos, este método se encuentra dentro de aggregate:

db.test.aggregate( [ {$group : {_id: “$producto” } } ] )

Con esto agruparemos por producto, y sabremos que productos tenemos en nuestra base de datos.

A partir de aquí podemos seguir avanzando:

db.test.aggregate( [ {$group : {_id: “$producto”, “cantidad”: {$sum: 1} } } ] )

Con esto podemos ver cuantos tipos de producto tenemos en nuestra BBDD, nos arrojará que tenemos dos tipos de cajas, una de vino y otra de botella.

db.test.aggregate( [ {$group : {_id: “$producto”, “cantidad”: {$sum: 1}, “total_stock”: {$sum: “$stock”} } } ] )

Aquí tenemos el total de tipos de productos que tenemos y el stock en conjunto de todos ellos.

Si quisiéramos saber el precio medio de todos los productos de nuestra BBDD tendríamos que recurrir $avg :

db.test.aggregate ( [ {$group : { _id: “$producto”, “promedio” : { $avg: “$precio” } } } ] )

Y hasta aquí los agrupamientos.

¿Qué son los contenedores? LinuX Containers o LXC

LXC, es la tecnología propia de linux con la cual, es capaz de generar contenedores. Un contenedor es una máquina linux totalmente funcional aislada del servidor principal pero compartiendo kernel.

LXC, es la tecnología propia de linux con la cual, es capaz de generar contenedores. Un contenedor es una máquina linux totalmente funcional aislada del servidor principal pero compartiendo kernel. Podríamos considerar que se trata de una virtualización tan ligera que no tiene un impacto significativo en el rendimiento del sistema.

LXC nos permite tener diferentes sistemas dentro de nuestro servidor principal siempre y cuando compartan la misma versión de kernel. Como decía antes son máquinas aisladas, esto conlleva que estas máquinas tienen su propio espacio de procesos y de red. Esto es posible gracias a que LXC utiliza Cgroups y Namespaces (espacios de nombres) para proporcionar el aislamiento requerido.

Vamos a hacer un alto en el camino para dar una breve explicación sobre que son cgroups y namespaces.

En primer lugar cgroups es una características del kernel que nos permite limitar los recursos del sistema, fue lanzado en el kernel 2.6.24 después de ser desarrollados por ingenieros de Google durante 2007. Más tarde se le añadieron funcionalidades como priorización dentro de los recursos o control de un grupo de procesos.

Y los namespaces es un espacio donde uno o mas identificadores de proceso pueden existir. Esto permite que tengamos varios PID’s juntos y separados de otros sin que puedan ver que recursos están utilizando cada uno de los espacios de nombres.

La combinación de estos dos, nos permite que nuestro contenedor tenga su propia visión del sistema operativo, de los procesos del mismo, de la estructura del sistema de ficheros y de las interfaces de red.

La funcionalidad de los contenedores es muy ágil, ya que como hemos dicho anteriormente no tenemos emulación de hardware, la carga que tenemos es mínima lo que provoca que el encendido, apagado o destrucción de un contenedor sea una operación realizada en cuestión de segundos.

Y además, no hay que perder de vista que un contenedor es una máquina linux completa, lo que nos garantiza tener logs, init, daemons, instaladores de paquetes…

Hay que dejar bien claro que LXC es diferentes de Docker y que no son opuestos, mientras que LXC hace un contenedor con un servidor completo, Docker es ideal para microservicios ya que solo genera el entorno justo para la aplicación.

Perdón, por esta parrafada pero ha sido una introducción a LXC, durante las siguientes entradas iremos iniciándonos en esta herramienta.

MongoDB: Arreglos o Listas

Veremos como modificar registros que ya están introducidos en la base de datos, añadiendo nuevos valores las listas que tenemos incluidas.

var arreglo = [1,2,3]

var usuario = { nombre: “prueba”, valores : arreglo}

db.test.insert( usuario )

Vamos a empezar con los arreglos más simples, a nuestro campo valores que tiene una lista con [1,2,3], añadiremos nuevos caracteres.

db.test.update( {}, {$addToSet: { valores : 4 } } )

El funcionamiento de $addToSet es simple, busca dentro del campo “valores” el número que le hemos introducido, si está no hace nada y si no se encuentra lo pone en la última posición.

db.test.update( {}, {$push : { valores : 4} })

Sin embargo, con la palabra reservada $push indistintamente, se añade el valor que le hemos puesto.

Y en el caso que queramos añadir más de un valor a nuestro arreglo tendremos que:

db.test.update ( {}, {$addToSet: { valores : {$each : [5,6]} } } )

Hasta ahora los elementos han sido siempre añadidos al final, vamos a hacerlo de manera que entren en otra posición, esto solo funciona con push:

db.test.update( {}, {$push: { valores: {$each : [100, 101], $position: 4 } } } )

Y cuando queramos ordenar nuestra secuencia en de valores utilizaremos sort y 1 o -1 para indicar si lo queremos ascendente o descendente.

db.test.update( {}, {$push : { valores: {$each : [95, 97], $sort:1 } } } )

Eliminar arreglos:

Partiendo del documento que hemos generado antes, vamos a eliminar algunos valores de nuestro arreglo.

Para esto utilizaremos la palabra reservada pull:

db.test.update( {}, {$pull : { valores : 100 }  } )

Esto podemos combinarlo con los intervalos vistos anteriormente como por ejemplo gte para que elimine todos los valores mayores a 50.

db.test.update( {}, {$pull : { valores : {$gte : 50} } } )

Con Pull solamente podemos eliminar un valor o especificarle que elimine solo uno, en cambio, si utilizamos PullAll podemos introducir una lista con los valores que queremos que elimine.

db.test.update( {}, {$pullAll : { valores : [4, 5] } } )

Select Arreglos:

Para esta parte vamos a introducir un nuevo documento de la siguiente manera:

var lista = [ “MongoDb”, “C#”, “SQL”, “PLSQL”, “Java”, “Python” ]

var usuario = {nombre: “Manu”, ejemplo:lista}

db.test.insert(usuario)

De esto solamente vamos a trabajar con la lista de ejemplo, entonces, para obtenerla sin nada alrededor haremos:

db.test.find( {}, { _id:false , ejemplo:true } )

Ahora vamos a ver slice se trata de un método que nos va a truncar las listas hasta el valor que le pongamos, por ejemplo:

db.test.find( {}, { _id:false, ejemplo : {$slice : 3} } )

La salida que nos dará esta línea será:

{ “nombre” : “Manu”, “ejemplo” : [ “MongoDb”, “C#”, “SQL” ] }

Si ponemos el valor en negativo, empezará a contar desde la parte final. O también podemos ponerle un intervalo y nos regresará los valores que se encuentren en esas posiciones:

db.test.find( {}, {_id: false, ejemplo: {$slice : [1, 3] } } )

Ahora vamos a ver como hacer comparaciones dentro del documento, vamos a realizar una sentencia donde nos busque todos los documentos donde en el elemento ejemplo tenga “MongoDb”.

db.test.find( { ejemplo : { $in : [ “MongoDb” ] } } )

Después de “MongoDb”, podemos añadirle otros elementos precedidos de comas, esto funcionará como un OR a la hora de buscar coincidencias.

Ahora si queremos negar el IN utilizaremos la palabra reservada NIN :

db.test.find( { ejemplo : { $nin : [ “MongoDb” ] } } )

 

MongoDB: Between y cursores

Partiendo de que tenemos una colección de documentos en nuestra base de datos, antes de ver between y cursores vamos ver como mostrar un campo específico de una búsqueda que realicemos:

db.usuarios.find ( {}, {nombre:1, _id:0} )

Con esto, hemos hecho una búsqueda donde nos aparecerá el nombre de todos los usuarios y el id permanecerá oculto, esto nos sirve para quitar información inútil de una consulta.

Between

Ahora, empezamos con between si queremos saber que registros están entre un valor y otro necesitamos los operadores que nos ofrece MongoDB estos  son:

  • $gt   > greater than
  • $gte >= greater than equals
  • $lt < less than
  • $lte <= less than equals

Vamos a ponerlo en práctica averiguando los usuarios que nacieron despues de 1999:

db.usuarios.find( { fecha_nac : {$gt: 1999} })

Con esto obtendríamos los resultados.

Por lo tanto, si queremos hacer un between deberemos de utilizar los operadores mayor y menor:

db.usuarios.find ( { fecha_nac : {$gte:1999, $lte: 2017 } }, {nombre: 1} )

Tenemos los nombre de todos los usuarios que hayan nacido entre 1999 y 2017. Y podríamos seguir añadiendo condicionales a nuestra sentencia para ir refinando nuestro resultado.

Cursores

Es la forma de la que podemos modificar o leer un documento, el método que hemos utilizado desde un principio, find, siempre nos ha devuelto un cursor. Pero al estar utilizando menos de 20 registros no hemos tenido problemas, así que al introducir 100 registros veremos que nos hará falta el uso de cursores.

Realizamos un bucle for para hacer 100 iteraciones en la base de datos con la inserción de 100 registros:

for(i = 0; i < 100 ; i++){db.test.insert({ valor:i }) }

Si queremos ver los registros que hemos insertado, solo nos permitirá ver los 20 primeros o intervalos de 20 registros introduciendo “it”. En este punto es donde empezamos a ver el papel que juega el cursor.

Para empezar a utilizar el cursor es muy fácil:

var cursor = db.test.find()

Hemos declarado una variable tipo cursor con toda la información que tenemos dentro de nuestra colección.

Ojo, si intentamos mostrar la variable, volveremos al principio teniendo solo los registros de 20 en 20 y además perdiendo el cursor, pues este  solo puede ser utilizado una vez.

El cursor, al ser un objeto, tiene métodos, así que vamos a trabajar con ellos a ver que nos ofrecen:

cursor.forEach( function(d){ print(d.valor) } )

Con esto nos sacará por pantalla todos los valores que tenemos en el cursor y podremos visualizarlos.

También podemos recorrerlos de la siguiente manera:

while ( cursor.hasNext() ) printjson( cursor.next() )

Mientras que el cursor tenga un documento, saca por pantalla el siguiente.

Métodos de cursor

Hemos visto como sacar por pantalla un cursor, ahora vamos a ver otros métodos.

db.test.find().count()

Estamos aplicando el método count() a find(), que aunque no este una variable llamada cursor, sigue siendo uno. Esto no permitirá contar el número de documentos que tenemos en la colección.

db.test.find().sort( {valor:1} )

Sort, recibe un parámetro que debe ser un campo del documento para que ordene por este, al ponerle el valor 1, lo hace ascendente y en caso de ponerle -1 lo hará de manera descendente.

db.test.find().sort( {valor:1} ).limit( 3 )

Con esto nos devolverá solo los tres primeros valores.

db.test.find().sort( {valor:1} ).skip( 1 ).limit( 1 )

Skip, nos permite saltarnos el numero de valores que pongamos como parámetro.

Esto sería un entrada introductoria a los cursores y métodos de MongoDB.

En caso de que tengáis cualquier duda comentad.