/

Montar Gitlab Self Hosted Con Linux Containers Lxc

Created 2020-02-15 Modifyed 2020-02-15
1632 Words

¿Qué es lxc?

La Wikipedia nos da la siguiente información:

LXC (Linux Containers) es una tecnología de virtualización en el nivel de sistema operativo (SO) para Linux. LXC permite que un servidor físico ejecute múltiples instancias de sistemas operativos aislados, conocidos como Servidores Privados Virtuales (SPV o VPS en inglés) o Entornos Virtuales (EV). LXC no provee de una máquina virtual, más bien provee un entorno virtual que tiene su propio espacio de procesos y redes.

¿Por qué querríamos usar lxc?

Lxc nos provee de un entorno virtual en el que podremos arrancar diferentes sistemas operativos, además, podremos hacer copias de estos sitemas, pasarlos de una máquina física a otra, hacer snapshots, y muchas cosas más.

Para demostrarlo, vamos a realizar nuestra prueba de concepto instalando un gitlab en uno de estos entornos.

Caso práctico

Lo primero que tenemos que hacer, es comprobar si tenemos instalado lxc, para ello vamos a ejecutar el siguiente comando:

lxc --version
3.0.3

En caso de que no lo tuviesemos instalados podemos instalarlo con nuestro gestor de paquetes, en mi caso apt

apt install lxc

Los comandos básicos de los que disponemos podemos verlos con:

lxc --help
Description:
  Command line client for LXD

  All of LXD's features can be driven through the various commands below.
  For help with any of those, simply call them with --help.

Usage:
  lxc [command]

Available Commands:
  alias       Manage command aliases
  cluster     Manage cluster members
  config      Manage container and server configuration options
  console     Attach to container consoles
  copy        Copy containers within or in between LXD instances
  delete      Delete containers and snapshots
  exec        Execute commands in containers
  file        Manage files in containers
  help        Help about any command
  image       Manage images
  info        Show container or server information
  launch      Create and start containers from images
  list        List containers
  move        Move containers within or in between LXD instances
  network     Manage and attach containers to networks
  operation   List, show and delete background operations
  profile     Manage profiles
  publish     Publish containers as images
  remote      Manage the list of remote servers
  rename      Rename containers and snapshots
  restart     Restart containers
  restore     Restore containers from snapshots
  snapshot    Create container snapshots
  start       Start containers
  stop        Stop containers
  storage     Manage storage pools and volumes
  version     Show local and remote versions

Flags:
      --all           Show less common commands
      --debug         Show all debug messages
      --force-local   Force using the local unix socket
  -h, --help          Print help
  -v, --verbose       Show all information messages
      --version       Print version number

Use "lxc [command] --help" for more information about a command.

Vamos a ver que contenedores tenemos funcionando:

lxc list
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

Como podemos comprobar, no tenemos ningún contenedor, vamos a listar las imágenes que tenemos disponibles con el siguiente comando:

lxc image list images:

Vamos a utilizar la imagen ubuntu:16.04, así que lanzaremos…

lxc launch ubuntu:16.04

En el comando anterior, podemos indicar después del nombre de la imagen (ubuntu:16.04) un nombre identificativo para el contenedor.

También podemos indicar el flag -c security.nesting=true, que necesitaremos para hacer funcionar docker dentro del contenedor lxc

En este caso no hemos puesto el flag, para poder ver el error que nos da docker si no lo ponemos y como solucionarlo

Una vez que termine el comando, podremos ver el contenedor con lxc list

lxc list
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
|    NAME     |  STATE  |        IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
| skilled-bat | RUNNING | 10.61.111.23 (eth0) | fd42:1f1a:7d4f:4c55:216:3eff:fe59:fde4 (eth0) | PERSISTENT | 0         |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+

Podremos iniciar el contenedor con lxc start nombreDelContenedor, pararlos con lxc stop nombreDelContenedor, crear un snapshot con lxc snapshot nombreDelContenedor o levantar un segundo contenedor con otra instancia del mismo, u otro sitema operativo.

+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
|    NAME     |  STATE  |        IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
| topical-koi | RUNNING | 10.61.111.52 (eth0) | fd42:1f1a:7d4f:4c55:216:3eff:fe46:7a85 (eth0) | PERSISTENT | 1         |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+
| ubuntu1804  | STOPPED |                     |                                               | PERSISTENT | 0         |
+-------------+---------+---------------------+-----------------------------------------------+------------+-----------+

Una vez tenemos nuestro contenedor lxc funcionando, nos vamos a conectar a el y vamos instalar docker.io y docker-compose, esto lo vamos a hacer en el contenedor topical-koi, asi que nos conectaremos a el con lxc exec topical-koi bash

Ahora que estamos dentro, vamos a realizar diferentes tareas. Actualizaremos apt, instalaremos docker.io, docker-compose y openssh-server. Además, meteremos nuestra llave publica a authorized_keys para poder conectarnos por ssh

apt update && apt install -y docker.io docker-compose openssh-server

Esta parte es opcional, pero es útil si queremos conectarnos desde otra máquina

root@topical-koi:~# echo "ssh-rsa tuclavesshpublica athos@athos-Z97P-D3" >> /home/ubuntu/.ssh/authorized_keys 
root@topical-koi:~# echo "ssh-rsa tuclavesshpublica athos@athos-Z97P-D3" >> /root/.ssh/authorized_keys 

Después de haber instalado docker, al hacer un lxc list veremos que nos ha creado una interface de red nueva.

athos@athos-Z97P-D3:~/Documents/athosnetwork.es/front$ lxc list
+-------------+---------+----------------------+-----------------------------------------------+------------+-----------+
|    NAME     |  STATE  |         IPV4         |                     IPV6                      |    TYPE    | SNAPSHOTS |
+-------------+---------+----------------------+-----------------------------------------------+------------+-----------+
| topical-koi | RUNNING | 172.17.0.1 (docker0) | fd42:1f1a:7d4f:4c55:216:3eff:fe46:7a85 (eth0) | PERSISTENT | 1         |
|             |         | 10.61.111.52 (eth0)  |                                               |            |           |
+-------------+---------+----------------------+-----------------------------------------------+------------+-----------+
| ubuntu1804  | STOPPED |                      |                                               | PERSISTENT | 0         |
+-------------+---------+----------------------+-----------------------------------------------+------------+-----------+

Además, vemos que nos podemos conectar desde fuera del contenedor con ssh

athos@athos-Z97P-D3:~/$ ssh ubuntu@10.61.111.52

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

ubuntu@topical-koi:~$ 

Vamos a probar docker, para ello ejecutaremos:

ubuntu@topical-koi:~$ docker run hello-world
docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "process_linux.go:449: container init caused \"rootfs_linux.go:58: mounting \\\"proc\\\" to rootfs \\\"/var/lib/docker/overlay2/d7f6e572823333a168cda30337b4acfb578ed9d2e5e058a77da05f87f7962e3d/merged\\\" at \\\"/proc\\\" caused \\\"permission denied\\\"\"": unknown.
ERRO[0000] error waiting for container: context canceled 

Es posible que en vez de este error, nos de un error de permisos, que solucionaremos añadiendo a nuestro usuario al grupo docker

sudo usermod -aG docker $USER más información aquí

Volviendo al error que nos ha dado, lo solucionaremos haciendo lo siguiente:

Primero pararemos nuestro contenedor lxc stop topical-koi

Despues pondremos security.nesting a true lxc config set topical-koi security.nesting true

Y pondremos security.nesting a true lxc config set topical-koi security.privileged true

Volvemos a iniciar el contenedor lxc start topical-koi

Nos conectamos por ssh al contenedor ssh ubuntu@10.61.111.52

Y probamos si esta vez docker funciona

ubuntu@topical-koi:~$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Bien!! ya estamos preparados para lanzar un contenedor docker con gitlab-ce

Podemos mirar la documentación de gitlab aquí

Vamos a probar a ejecutar la imagen según nos dicen en la página de la documentación:

sudo docker run --detach \
  --hostname gitlab.example.com \
  --publish 443:443 --publish 80:80 --publish 22:22 \
  --name gitlab \
  --restart always \
  --volume /srv/gitlab/config:/etc/gitlab \
  --volume /srv/gitlab/logs:/var/log/gitlab \
  --volume /srv/gitlab/data:/var/opt/gitlab \
  gitlab/gitlab-ce:latest

Al ejecutarlo, vemos que nos da un error, diciendo que el puerto 22 está en uso, así que moficiamos un poco el comando docker y hacemos que el mapeo del puerto que dirige al 22 del contenedor sea otro, para que no haya conflicto con el ssh del contenedor (lxc)

Previamente limpiamos con docker system prune -a --volumes

sudo docker run --detach \
  --hostname gitlab.example.com \
  --publish 443:443 --publish 80:80 --publish 222:22 \
  --name gitlab \
  --restart always \
  --volume /srv/gitlab/config:/etc/gitlab \
  --volume /srv/gitlab/logs:/var/log/gitlab \
  --volume /srv/gitlab/data:/var/opt/gitlab \
  gitlab/gitlab-ce:latest

Como podemos ver, esta vez el contenedor se ha levantado

ubuntu@topical-koi:~$ docker ps
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                             PORTS                                                           NAMES
aeeac3ecb436        gitlab/gitlab-ce:latest   "/assets/wrapper"   21 seconds ago      Up 19 seconds (health: starting)   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:222->22/tcp   gitlab

Ahora, si accedemos a la ip del contenedor lxc (10.61.111.52) podremos ver el gitlab. El proceso de instalación, tarda un par de minutos, así que se paciente

montar-gitlab-self-hosted-con-linux-containers-lxc

Después de introducir la contraseña, podremos loguear como usuario root

montar-gitlab-self-hosted-con-linux-containers-lxc-2

Vamos a hacer la prueba de fuego, que es crear un repo, y hacer un push a el. Para esto, primero vamos a introducir nuestra clave ssh. Esto lo haremos en settings -> ssh keys

Una vez hecho esto y creado el repo en nuestro gitlab, nos lo vamos a clonar. Hay que mencionar, que como hemos cambiado el puerto ssh del contenedor de gitlab, el comando varía un poco con respecto al que nos da gitlab al crear el repo.

Gitlab nos da el siguiente comando:

git clone git@10.61.111.23:root/prueba.git

Esto funcionaría si no hubiesemos cambiado el puerto, al haberlo hecho, tendremos que ejecutar este otro comando:

git clone ssh://git@10.61.111.23:222/root/prueba.git

git clone ssh://git@10.61.111.23:222/root/prueba.git
Cloning into 'prueba'...
warning: You appear to have cloned an empty repository.

Ahora creamos un archivo y lo pusheamos

echo "## Esto funciona" > readme.md
git add .
git commit -m "Primer commit"
[master 8c61654] Primer commit
 1 file changed, 1 insertion(+)
 create mode 100644 readme.md
git push origin master
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 464 bytes | 464.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To ssh://10.61.111.23:222/root/prueba.git
 * [new branch]      master -> master

Y como podemos ver en nuestro gitlab, tenemos nuestro commit

montar-gitlab-self-hosted-con-linux-containers-lxc-3

Y con esto tenemos nuestro servidor gitlab montado.