Hace pocos días han lanzado el último curso que he impartido en OpenWebinars: Curso de OpenShift. Os dejo aquí dos vídeos que se han publicado en YouTube para promocionar el curso:
Curso de OpenShift en OpenWebinars
Curso de introducción a la programación con python3
Curso de introducción a la programación con python3
En este curso aprenderás los fundamentos del lenguaje de programación Python 3 desde cero, pensado para no programadores que se quieran iniciar en este mundo.
El lenguaje de programación Python es uno de los más valorados por la comunidad de programadores, además de uno de los que más crecen en los últimos años. Este curso de Python está basado en la versión 3 del mismo, para que conozcas todas sus novedades y aprendas a utilizarlas en tus futuros desarrollos.
Los siguientes contenidos forman parte de un curso que he impartido para OpenWebinars en febrero de 2019.
Puedes obtener todo el contenido del curso en el repositorio GitLab. Todas las observaciones, mejoras y sugerencias son bienvenidas.
Unidades
Introducción a la programación
- Análisis de problemas y diseño de algoritmos
- Introducción a los lenguajes de programación
- Introducción a python3
**Introducción a python3**
- Instalación de python3
- Escribir y ejecutar programas python
Tipos de datos básicos
- Datos y tipos de datos
- Tipos de datos numéricos
- Tipo de datos booleano
- Trabajando con variables
- Entrada y salida estándar
- Introducción a las cadenas de caracteres
- Pasando de pseudocódigo a python3
Ejercicios estructura secuencial
Estructuras de control
- Estructura de control: Alternativas
- Ejercicios estructura alternativas
- Estructuras de control repetitivas: while
- Estructuras de control repetitivas: for
- Uso específico de variables: contadores, acumuladores e indicadores
Ejercicios estructuras repetitivas
Tipos de datos secuencias
- Tipo de datos cadenas de caracteres
- Las cadenas de caracteres son inmutables
- Métodos principales de cadenas
- Ejercicios cadena de caracteres
- Tipo de datos secuencia: Listas
- Las listas son mutables
- Métodos principales de listas
- Tipo de datos secuencia: Tuplas
Tipos de datos mapas
- Tipo de datos mapa: diccionario
- Métodos principales de diccionarios
Excepciones
Introducción a los módulos
Programación estructurada
- Introducción a las funciones
- Funciones recursivas
- Ejercicios con funciones
Programación orientada a objetos
- Introducción a la programación orientada a objetos
- Encapsulamiento en la programación orientada a objetos
- Herencia y delegación
- Ejercicios de programación orientada a objetos
rclone: Gestionando nuestros servicios de almacenamiento en la nube
rclone es una herramienta que nos permite trabajar con los ficheros que tenemos almacenados en distintos servicios de almacenamiento en la nube (dropbox, google drive, mega, box, … y muchos más que puedes ver en su página principal). Por lo tanto con rclone
podemos gestionar y sincronizar los ficheros de nuestros servicios preferidos desde la línea de comandos.
La versión que obtenemos de los repositorios de Debian Buster es la 1.45-3, pero si queremos muchos más proveedores cloud para configurar es recomendable bajarse la última versión (en el momento de escribir este artículo, la versión 1.49.5) que encontraremos en la página de descarga. Nos descargamos el fichero deb
y los instalamos en nuestro servidor:
$ wget https://downloads.rclone.org/v1.49.5/rclone-v1.49.5-linux-amd64.deb
$ dpkg -i rclone-v1.49.5-linux-amd64.deb
$ rclone version
rclone v1.49.5
- os/arch: linux/amd64
- go version: go1.12.10
Configuración de los proveedores cloud
A continuación vamos a configurar distintos proveedores cloud, para ello se utilizan distintas formas según la API del proveedor: usuario y contraseña del servicio, autentifcación oauth y autorización por parte del servicio, …
Configuración de mega
Para configurar un nuevo proveedor ejecutamos:
$ rclone config
Y elegimos la opción:
n) New remote
Los datos que tenemos que indicar son los siguientes:
- Un nombre con el que vamos a identificar este proveedor.
- De las lista de proveedores elegimos el que nos interesa indicando el número, en el caso de mega es el 18.
- El nombre de usuario y la contraseña de la cuenta.
- Para nuestro ejemplo no vamos a introducir la configuración avanzada.
Por lo tanto los pasos serían:
# rclone config
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n
name> mega1
Type of storage to configure.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
...
18 / Mega
\ "mega"
...
Storage> 18
** See help for mega backend at: https://rclone.org/mega/ **
User name
Enter a string value. Press Enter for the default ("").
user> tucorreo@correo.com
Password.
y) Yes type in my own password
g) Generate random password
y/g> y
Enter the password:
password:*********
Confirm the password:
password:*********
Edit advanced config? (y/n)
y) Yes
n) No
y/n> n
Vamos a verlo en un vídeo:
Configurando dropbox
Cuando hemos configurado una cuenta con mega hemos usado como método de autentificación el nombre de usuario y la contraseña. La mayoría de proveedores van a usar oAuth2 como método de autentificación, es el caso , por ejemplo de dropbox. En este caso tenemos dos formas de autentificarnos:
- dando de alta una nueva aplicación en el servicio deseado, y obtener las credenciales (identificador de usuario, token de autentificación,…)
- Desde un navegador web autentificarnos en el servicio y da permiso a la aplicación
rclone
para que gestione nuestros ficheros.
Nosotros vamos a optar por esta segunda opción, sin embargo si estamos instalando rclone en un sistema operativo sin entorno gráfico debemos autorizar la aplicación desde un ordenador con entorno gráfico donde podamos acceder a un navegador, lo veremos a continuación (más opciones de configuración la puedes encontrar en la documentación: Configuring rclone on a remote / headless machine.
Para configurar un proveedor de dropbox:
$ rclone config
Y elegimos la opción:
n) New remote
...
name> dropbox
...
Choose a number from below, or type in your own value
...
8 / Dropbox
\ "dropbox"
...
Storage> 8
...
Use auto config?
* Say Y if not sure
* Say N if you are working on a remote or headless machine
y) Yes
n) No
y/n> n
For this to work, you will need rclone available on a machine that has a web browser available.
Execute the following on your machine (same rclone version recommended) :
rclone authorize "dropbox"
Then paste the result below:
result>
Como estamos configurando rclone
en una máquina sin entorno gráfico, ahora es el momento en el que tenemos que ejecutar el comando rclone authorize "dropbox"
en una máquina con entorno gráfico, acceder al navegador, autentificarse y configurar los permisos de la aplicación:
$ rclone authorize "dropbox"
If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth?state=212ac74326029a80a8d4aa0a707838ed
Log in and authorize rclone for access
Waiting for code...
Accdemos al navegador:
Y damos permisos a la aplciación:
Obtenemos una página que nos informa que todo ha ido bien (“Success!”) y volvemos al terminal:
Got code
Paste the following into your remote machine --->
{"access_token":"xxxxxxxxxxxxAAAAAAY2nfpKZKmI4tIDiy_ya37Tf1MT3no2rGW5PcV3znHJq0i","token_type":"bearer","expiry":"0001-01-01T00:00:00Z"}
<---End paste
Y como se nos indica tenemos que copia y pegar la línea obtenida en nuestro servidor remoto donde estamos trabajando con rclone
:
result> {"access_token":"xxxxxxxxxxxxAAAAAAY2nfpKZKmI4tIDiy_ya37Tf1MT3no2rGW5PcV3znHJq0i","token_type":"bearer","expiry":"0001-01-01T00:00:00Z"}
...
y) Yes this is OK
...
y/e/d> y
Para finalizar podemos ver los proveedores que hemos configurado:
$ rclone config
Current remotes:
Name Type
==== ====
dropbox dropbox
mega1 mega
...
Toda la información de estos servidores remotos los va almacenando en el fichero ~/.config/rclone/rclone.conf
.
Lo vemos en un vídeo:
Gestionando nuestros ficheros con rclone
Una vez que tenemos configurado el proveedor podríamos empezar a gestionalos ejecutando distintos subcomandos, por ejemplo usando nuestra cuenta de dropbox:
Podemos listar todos los ficheros del servicio:
rclone ls dropbox:
Podemos listar los directorios que tenemos:
rclone lsd dropbox:
Podemos crear un directorio:
rclone mkdir dropbox:/prueba
Y copiar un fichero desde nuestro ordenador a la carpeta que hemos creado:
rclone copy info.txt dropbox:/prueba rclone ls dropbox:/prueba 2072006 info.txt
También se pueden hacer operaciones entre varios servicios, por ejemplo copiar el fichero
info.txt
que acabamos de subir a dropbox, a un directorio de mega:rclone mkdir mega1:/prueba rclone copy dropbox:/prueba/info.txt mega1:/prueba rclone ls mega1:/prueba 2072006 info.txt
Puedes ver todas las operaciones que puedes hacer con tus servicios de almacenmaineto en la nube en la documentación de rclone.
Podemos ver estas operaciones en un vídeo:
Como hemos visto rclone
es una herramienta muy interesante para gestionar nuestros servicios de almacenamiento en la nube. En la próxima entrada veremos como podemos usarlo junto a Nextcloud para gestionar todo nuestro almacenamiento de forma centralizada.
Gestionando nuestro almacenamiento en la nube con nextcloud y rclone
En este artículo os cuento mis entretenimientos en las últimas semanas, jugando con nextcloud y ampliando su espacio de almacenamiento usando la aplicación rclone
. Con estas herramientas podemos automatizar fácilmente nuestras copias de seguridad en la nube. Veamos cada una de estas aplicaciones:
Nextcloud
Nextcloud es una aplicación web escrita en PHP cuyo objetivo es crear un servidor de alojamiento de archivos en cualquier servidor personal. Tiene la misma funcionalidad de otros servicios de almacenamiento en la nube, como Dropbox, pero la gran diferencia es que Nextcloud es de código abierto, por lo que podemos instalarlo y adaptarlos a nuestras necesidades.
Para poder instalar la aplicación Nextcloud necesitamos instalar un servidor LAMP, que podemos hacer de forma sencilla en Debian Buster de la siguiente forma:
Instalamos Apache2 como servidor web:
apt install apache2
Instalamos el servidor de base de datos:
apt install mariadb-server
A continuación accedemos al servidor y creamos la base de datos y el usuario con el que nos vamos a conectar a la base de datos:
$ mysql -u root -p > CREATE DATABASE nextcloud; > CREATE USER 'usernextcloud'@'localhost' IDENTIFIED BY 'passnextcloud'; > GRANT ALL PRIVILEGES ON nextcloud.* to 'usernextcloud'@'localhost'; > FLUSH PRIVILEGES; > quit
Instalamos la versión de php, así como la libería para que php pueda conectarse a la base de datos (por dependencia se instala el módulos de apache2
libapache2-mod-php7.3
que permite que el servidor web ejecute código php):apt install php7.3 php7.3-mysql
A continuación nos bajamos la aplicación Nextcloud de la página oficial de descargas (en el momento de escribir este manual hemos descargado la versión 17.0.1), lo descomprimimos y copiamos todos los ficheros y directorios en el
DocumentRoot
, en nuestro caso como vamos a usar el virtualhostdefault
será el directorio/var/www/html/
.# cd /tmp /tmp# wget https://download.nextcloud.com/server/releases/nextcloud-17.0.1.zip /tmp# unzip nextcloud-17.0.1.zip /tmp# cd nextcloud /tmp/nextcloud# cp -r * /var/www/html /tmp/nextcloud# cd /var/www/html /var/www/html# chown -R www-data: .
Accedemos a nuestro servidor desde un cliente, para ello en cliente vamos a configurar la resolución estática, en el fichero
/etc/hosts
añadimos la siguiente línea (la ip de nuestro servidor es 192.168.100.36):192.168.100.36 www.example.org
y comenzamos con la configuración de la aplicación:
Siguiendo la documentación necesitamos instalar algunas librerías más de php:
apt install php-zip php-xml php-gd php-curl php-mbstring
Ya tenemos instalada nuestra aplicación Nextcloud:
Almacenamiento externo
La aplicación “Almacenamiento externo” en nextcloud nos permite añadir a nuestro almacenamiento un directorio donde el contenido está en otro servicio. Para poder usar esta opción tenemos que activarlo en la configuración de aplicaciones, para ello elegimos las opciones Aplicaciones y activamos External storage support:
A continuación podemos configurar el “almacenamiento externo” accediendo a Configuración y eligiendo Almacenamiento Externo:
Vemos que podemos añadir almacenamiento de diferentes fuentes:
A continuación añadiremos directorios locales a nuestro almacenamiento, pero antes de ello veamos el siguiente punto.
Montar directorios locales con rclone
En el artículo anterior habíamos visto la herramientarclone
, que nos permitía gestionar el almacenamiento de distintos servicios de almacenamiento en la nube. rclone
lo tenemos configurado en la misma máquina donde hemos instalado nextcloud y recordamos que habíamos configurado dos servicios de almacenamiento y con el usuario sin privilegios (suponemos que el usuario se llama vagrant
) podemos ver los servicios que tenemos configurados:
$ rclone listremotes
dropbox:
mega1:
Una de las posibilidades que nos ofrece rclone
es poder montar en un directorio de la máquina cualquier servicio que tengamos configurado, para ello vamos a usar fuse
que nos permite montar un sistema de fichero con un usuario sin privilegios, por lo que lo primero es instalarlo como superusuario:
# apt install fuse
Además tenemos que cambiar una configuración para que puedan acceder al directorio montado otros usuarios (en nuestro caso es necesario porque posteriormente accederá el usuario www-data
de apache2), para ello descomentamos en el fichero /etc/fuse.conf
la siguiente línea:
user_allow_other
A continuación el usuario sin privilegios ya puede montar en un directorio sus ficheros de dropbox:
$ mkdir ficheros_dropbox
$ rclone mount -v dropbox:/ ficheros_dropbox --daemon --allow-other
$ ls ficheros_dropbox/
Comenzar.pdf Photos prueba Public
La opción --daemon
permite crear un proceso demonio responsable de mantener el directorio montado, y la opción --allow-other
permite que otros usuarios accedan al directorio. Tenemos muchas más opciones de configuración que podemos ver en la documentación de rclone mount.
Si necesitaremos desmontar el directorio:
$ fusermount -u /home/vagrant/ficheros_dropbox
Integración de nextrcloud con rclone
Ahora que ya tenemos montado los ficheros de nuestro dropbox en un directorio es hora de configura el Almacenamiento externo de nextcloud para montarlo en nuestro servidor, para ello configuramos un nuevo almacenamiento externo:
Y efectivamente comprobamos que tenemos acceso a los ficheros de dropbox desde nuestro nextcloud:
Conclusiones
Con las utilidades que hemos estudiados podemos de una forma fácil centralizar todos nuestros servicios de almacenamiento en nuestro servidor nextcloud, de esta menera por ejemplo sería muy sencillo hacer un backup de nuestros datos en distintos servicios además de hacer crecer el almacenamiento disponible de nuestra “nube” personal.
Implementación de un cortafuegos personal con nftables
El objetivo de esta entrada es hacer una introducción a nftables para empezar a implementar un cortafuego personal para nuestro ordenador.
Lo primero: ¿qué es nftables?. nftables es el nuevo framework que podemos usar para analizar y clasificar los paquetes de red y nos permite la implementación de cortafuegos. Es una aplicación desarrollada dentro del proyecto netfilter. Sustituye a la familia de aplicaciones {ip,ip6,arp,eb}tables. Es recomendable el uso de nftables ya que tiene una serie de ventajas respecto a su antecesor iptables. Esta entrada del blog introduce los principales conceptos de nftables, para profundizar en el tema es recomendable estudiar su documentación.
Configuración inicial de nuestro cortafuegos personal
Una de las diferencias de usar nftables es que las tablas y cadenas son totalmente configurables. En nftables lo primero que tenemos que hacer es crear las tablas (son las zonas en las que crearemos las distintas reglas del cortafuegos clasificadas en cadenas). A continuación crearemos las distintas cadenas en las tablas (que nos permite clasificar las reglas).
Creación de la tabla filter
Vamos a crear una tabla para filtrar los paquetes que llamaremos filter:
# nft add table inet filter
Tenemos varias familias para crear las tablas, en nuestro caso hemos escogido inet
que nos permite trabajar con ipv4 y ipv6.
Para ver la tabla que hemos creado:
# nft list tables
table inet filter
Puedes leer sobre más operaciones sobre las tablas.
Creación de las cadenas
A continuación vamos a crear las cadenas de la tabla filter. Para crear una cadena debemos indicar varios parámetros:
type
: Es la clase de cadena que vamos a crear, por ejemplofilter
(para filtrar) onat
(para hacer NAT).hook
: Determina el tipo de paquete que se va a analizar. Por ejemplo:input
: Paquetes que tienen como destino la misma máquina.output
: Paquetes que tienen origen la propia máquina.forward
: Paquetes que pasan por la máquina.prerounting
: Paquetes que entran en la máquina antes de enrutarlos. Nos permiten hacer DNAT.postrouting
: Paquetes que están a punto de salir de la máquina. Nos permite hacer SNAT.
priority
: Nos permite ordenar las cadenas dentro de una misma tabla. Las cadenas más prioritarias son las que tienen un número más pequeño.policy
: Se indica la política por defecto. Si el conjunto de reglas evaluadas no se ajusta al paquete se ejecuta la política por defecto. Por defecto la política esaccept
por lo que se aceptan todos los paquetes que no se ajusten al conjunto de reglas. Cuando desarrollamos un cortafuegos la política suele serdrop
no aceptando los paquetes que no se ajustan a ninguna regla.
En la tabla filter
que hemos creado anteriormente vamos a crear dos cadenas para nuestro cortafuego personal:
# nft add chain inet filter input { type filter hook input priority 0 \; counter \; policy accept \; }
# nft add chain inet filter output { type filter hook output priority 0 \; counter \; policy accept \; }
Por ejemplo para cambiar la política por defecto a drop
de las cadenas creadas:
# nft chain inet filter input { policy drop \; }
# nft chain inet filter output { policy drop \; }
Puedes leer la wiki para ver más operaciones sobre cadenas.
Finalmente ya hemos configurado nuestra tabla para filtrar paquetes y las cadenas que vamos a utilizar:
# nft list chains
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy drop;
}
}
Creación de reglas
Una vez que tenemos configurado la tabla y las cadenas de nuestro cortafuegos, podemos empezar a configurar reglas para configurar nuestro cortafuegos personal, que va filtrar la comunicación a nuestra propía máquina.
Al tener como política por defecto drop
, necesitaremos configurar reglas en la cadena input
y output
para gestionar los paquetes que salen de la máquina y los que entran.
Para leer sobre la gestión básica de reglas puedes leer la siguiente entrada de la wiki.
Vamos a poner algunos ejemplos de reglas para nuestro cortafuegos:
Permitimos tráfico para la interfaz loopback
Vamos a permitir todo el tráfico a la interfaz lo
:
# nft add rule inet filter input iifname "lo" counter accept
# nft add rule inet filter output oifname "lo" counter accept
Veamos cómo hemos definido la regla:
iifname "lo"
: Indicamos los paquetes que entren (cadenainput
) por la interfaz de entradalo
.oifname "lo"
: Indicamos los paquetes que salgan (cadenaoutput
) por la interfaz de salidalo
.
Como acciones que vamos a ejecutar cuando el paquete cumpla estas reglas serán:
counter
: Para que cuente los paquetes que cumplen la regla.accept
: Los paquetes se aceptan.
Podemos ver las reglas que hemos creado:
# nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iifname "lo" counter packets 0 bytes 0 accept
}
chain output {
type filter hook output priority 0; policy drop;
oifname "lo" counter packets 0 bytes 0 accept
}
}
Permitir peticiones y respuestas protocolo ICMP
En concreto vamos a permitir la posibilidad que puedan hacer ping a nuestra máquina:
# nft add rule inet filter output oifname "eth0" icmp type echo-reply counter accept
# nft add rule inet filter input iifname "eth0" icmp type echo-request counter accept
Veamos las nuevas expresiones que hemos usado para estas reglas:
icmp type echo-reply
: Se permiten las peticiones de ping (protocolo icmp) que se hagan poreth0
.icmp type echo-request
: se permiten las respuestas a las peticiones ping que entren poreth0
.
Permitir el acceso por ssh a nuestra máquina
Vamos a permitir la conexión ssh desde la red 172.22.0.0/16:
# nft add rule inet filter input ip saddr 172.22.0.0/16 tcp dport 22 ct state new,established counter accept
# nft add rule inet filter output ip daddr 172.22.0.0/16 tcp sport 22 ct state established counter accept
En este caso estamos usando las siguientes expresiones para crear estas reglas:
En la regla que hemos definido en la cadena input
permitimos los paquetes que provienen de una determinada red, que tienen como puerto de destino el 22 y que son nuevas conexiones o conexiones establecidas anteriormente:
ip saddr 172.22.0.0/16
: Se indica la dirección de red de origen.tcp dport 22
: se indica que el puerto de destino será el 22 (ssh).ct state new,established
: Controlamos el estado de la conexión, indicando que la conexión sea nueva o este establecida con anterioridad.
En la regla que hemos definido en la cadena output
permitimos los paquetes que se dirigen a la misma red, con puerto de origen 22 y que son conexiones establecidas.
ip daddr 172.22.0.0/16
: Se indica la dirección de red de destino.tcp sport 22
: se indica que el puerto de origen será el 22 (ssh).ct state established
: Controlamos el estado de la conexión, indicando que la conexión ya está establecida.
Permitir consultas DNS
# nft add rule inet filter output oifname "eth0" udp dport 53 ct state new,established counter accept
# nft add rule inet filter input iifname "eth0" udp sport 53 ct state established counter accept
En este caso para permitir las consultas DNS tenemos que controlar el protocolo UDP:
udp dport 53
: Indicamos que el puerto de destino es el 53(DNS) del protocolo UDP.udp dport 53
: Indicamos que el puerto de origen es el 53(DNS) del protocolo UDP.
Permitir tráfico HTTP/HTTPS
# nft add rule inet filter output oifname "eth0" ip protocol tcp tcp dport { 80,443 } ct state new,established counter accept
# nft add rule inet filter input iifname "eth0" ip protocol tcp tcp sport { 80,443 } ct state established counter accept
Las expresiones que hemos usado en este caso serían:
ip protocol tcp
: Indicando el protocolo TCP.tcp dport { 80,443 }
: Indicamos los puertos de destino: 80 (HTTP) y 443 (HTTPS).tcp sport { 80,443 }
: Indicamos los puertos de origen: 80 (HTTP) y 443 (HTTPS).
Permitir acceso a nuestro servidor Web
Si suponemos que en nuestra máquina tenemos un servidor web atendiendo peticiones en el puerto 80:
# nft add rule inet filter output oifname "eth0" tcp sport 80 ct state established counter accept
# nft add rule inet filter input iifname "eth0" tcp dport 80 ct state new,established counter accept
Finalmente podemos ver todas las reglas que hemos creado:
# nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iifname "lo" counter packets 0 bytes 0 accept
iifname "eth0" icmp type echo-request counter packets 2 bytes 168 accept
ip saddr 172.22.0.0/16 tcp dport ssh ct state established,new counter packets 569 bytes 38264 accept
iifname "eth0" udp sport domain ct state established counter packets 0 bytes 0 accept
iifname "eth0" ip protocol tcp tcp sport { http, https } ct state established counter packets 0 bytes 0 accept
iifname "eth0" tcp dport http ct state established,new counter packets 0 bytes 0 accept
}
chain output {
type filter hook output priority 0; policy drop;
oifname "lo" counter packets 0 bytes 0 accept
oifname "eth0" icmp type echo-reply counter packets 2 bytes 168 accept
ip daddr 172.22.0.0/16 tcp sport ssh ct state established counter packets 460 bytes 54392 accept
oifname "eth0" udp dport domain ct state established,new counter packets 0 bytes 0 accept
oifname "eth0" ip protocol tcp tcp dport { http, https } ct state established,new counter packets 0 bytes 0 accept
oifname "eth0" tcp sport http ct state established counter packets 0 bytes 0 accept
}
}
Borrado de reglas
Una posibilidad para poder borrar una determinada regla es mostrar las reglas con su handle
(identificador de la regla):
# nft list ruleset -a
table inet filter { # handle 1
chain input { # handle 1
type filter hook input priority 0; policy drop;
...
iifname "eth0" icmp type echo-request counter packets 2 bytes 168 accept # handle 9
...
Por ejemplo para borrar la regla que hemos mostrado en el ejemplo anterior:
# nft delete rule inet filter input handle 9
Traducción de reglas de iptables a nftables
Si todavía no estamos acostumbrados a la sintáxis de nftables pero dominamos iptables, tenemos a nuestra disposición la utilidad iptables-translate
que nos posibilita la traducción. Por ejemplo si tenemos la siguiente regla iptables:
# iptables -A INTPUT -i eth0 -p udp --sport 53 -m state --state ESTABLISHED -j ACCEPT
Podemos traducirla de la siguiente manera:
# iptables-translate -A INTPUT -i eth0 -p udp --sport 53 -m state --state ESTABLISHED -j ACCEPT
nft add rule ip filter INTPUT iifname "eth0" udp sport 53 ct state established counter accept
Hay que tener en cuenta dos detalles:
- La regla que que hemos generado es para un tabla de la familia
ip
, nostros estamos usando la familiainet
. - El nombre de las cadenas se devuelven en mayúsculas, nosotros hemos creado las cadenas en minúsculas.
Por la tento la regla traducida quedaría de la siguiente manera:
# nft add rule inet filter input iifname "eth0" udp sport 53 ct state established counter accept
Copia de seguridad de nuestro cortafuegos
Cuando reiniciamos nuestra máquina el cortafuego no mantiene el conjunto de reglas, por lo que tenemos que guardar las reglas para posteriormente recuperlas. Siguiendo el enlace de la wiki podemos hacer una copia de seguridad del cortafuegos de la siguiente manera:
# echo "nft flush ruleset"> backup.nft
# nft list ruleset >> backup.nft
Posteriormente podemos ejecutar el siguiente comando para recuperar las reglas del cortafuego:
# nft -f backup.nft
Conclusiones
En este artículo se ha hecho una breve introducción a nftables, una aplicación que nos posibilita la implementación de cortafuegos. En nuestro caso hemos introducido un ejemplo para desarrollar un cortafuegos personal que controle el tráfico de una sóla máquina. En la siguiente entrada del blog haremos una introducción de como desarrollar un cortafuegos perimetral con nftables que nos controle el tráfico a un conjunto de máquinas.
Reglas de NAT con nftables
En la entrada anterior hicimos una introducción a la implementación de un cortafuegos personal con nftables, en este artículo vamos a comenzar a implementar un cortafuegos perimetral.
Configuración inicial de nuestro cortafuegos perimetral
Un cortafuego personal nos controla las comunicaciones que entran y salen de un ordenador (usamos las cadenas input
y output
de la tabla filter
). En un cortafuegos perimetral estamos gestionando las conexiones que entran y salen de una o varias redes de ordenadores, o visto de otra manera, las conexiones que atraviesan el router que da acceso a estas redes, por lo tanto, lo más usual, es que el cortafuegos se implemente en el router. Para controlar los paquetes que atraviesan el router utilizaremos la cadena forward
de la tabla filter
.
El cortafuegos perimetral que nosotros vamos a configurar sería el más simple, y es el que controla el tráfico para una red local:
Sin embargo el cortafuegos perimetral puede controlar el tráfico de varias redes loscales, por ejemplo cuando tenemos en una red los equipos de nuestra red local y en otra red los servidores que exponen servicios al exterior (por ejemplo el servidor web). A esta última red se le suele llamar zona desmilitarizada (DMZ) y es este caso tendríamos un escenario como este:
Además de la función de filtrado, con nftables podemos hacer NAT, por ejemplo para permitir que los equipos de la red local puedan comunicarse con otra red (SNAT, source NAT) o para que un equipo externo acceda a una máquina de la red local (DNAT, destination NAT). Para ello utilizaremos la tabla nat
.
Configuración de NAT con nftables
NAT son las siglas del inglés network address translation o traducción de direcciones de red y es un mecanismo que se usa ampliamente hoy en día. Existen diferentes tipos:
- Source NAT: Se cambia la dirección IP de origen, es la situación más utilizada cuando estamos utilizando una dirección IP privada en una red local y establecemos una conexión con un equipo de Internet. Un equipo de la red (normalmente la puerta de enlace) se encarga de cambiar la dirección IP privada origen por la dirección IP pública, para que el equipo de Internet pueda contestar. También es conocido como IP masquerading, pero podemos distinguir dos casos:
- SNAT estático: Cuando la dirección IP pública que sustituye a la IP origen es estática (SNAT también significa Static NAT).
- SNAT dinámico o MASQUERADE: Cuando la dirección IP pública que sustituye a la IP origen es dinámica, caso bastante habitual en conexiones a Internet domésticas.
- Destination NAT o port forwarding: En este caso se utiliza cuando tenemos algún servidor en una máquina detrás del dispositivo de NAT. En este caso será un equipo externo el que inicie la conexión, ya que solicitará un determinado servicio y el dispositivo de NAT debe modificar la dirección IP destino.
- PAT (Port Address translation): Modifica específicamente el puerto (origen o destino) en lugar de la dirección IP. Por ejemplo si queremos reenviar todas las peticiones web que lleguen al puerto 80/tcp al mismo equipo pero al puerto 8080/tcp.
Creación de la tabla nat
Vamos a crear una tabla para crear las reglas de NAT que llamaremos nat (suponemos que nuestro cortafuegos ya tiene creada una tabla filter):
# nft add table nat
Para ver las tablas que tenemos:
# nft list tables
table inet filter
table ip nat
Como vemos hemos creado la tabla nat de la familia ip ya que vamos a trabajar con direccionamiento ipv4.
Creación de las cadenas
A continuación vamos a crear las cadenas de la tabla nat:
# nft add chain nat prerouting { type nat hook prerouting priority 0 \; }
# nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
Como podemos observar hemos indicado más prioridad en la cadena postrouting para que las reglas se ejecuten después de las reglas de prerouting.
Finalmente ya hemos configurado nuestra tabla nat:
# nft list chains
...
table ip nat {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
}
...
Configuración del enrutamiento
El equipo donde estamos construyendo nuestro cortafuegos también hace de router por lo tanto para que los paquetes que vienen o van a los ordenadores de la red local se puedan enrutar, necesitamos activar el bit de forwarding:
echo 1 > /proc/sys/net/ipv4/ip_forward
Esta activación se borra cuando se apaga el equipo, ya que el directorio /proc
está en memoria. Para que dicha activación permanezca lo habitual es definirla en el fichero /etc/sysctl.conf
, asegurándonos de que exista una línea como:
net.ipv4.ip_forward=1
POSTROUTING
Para que nuestro equipos de la red local tengan salida al exterior (por ejemplo a internet) tenemos que configurar el SNAT en nuestro cortafuegos. Tendríamos dos casos:
SNAT estático, por ejemplo la ip pública del router es una IP fija (por ejemplo la
80.58.1.14
):nft add rule ip nat postrouting oifname "eth0" ip saddr 192.168.100.0/24 counter snat to 80.58.1.14
SNAT dinámico o enmascaramiento, es el caso que tenemos en nuestra infraestructura, la ip del router es dinámica:
nft add rule ip nat postrouting oifname "eth0" ip saddr 192.168.100.0/24 counter masquerade
Veamos cómo hemos definido la regla:
add rule ip nat postrouting
: El cambio de la dirección de origen hay que hacerlo antes de enrutar el paquete a internet, por lo tanto usamos la cadenapostrouting
.oifname "eth0"
: Esta regla se aplica a los paquetes que salen poreth0
.ip saddr 192.168.100.0/24
: Esta regla se aplica a paquetes que provienen de la red192.168.100.0/24
.
Como acciones que vamos a ejecutar cuando el paquete cumpla estas reglas serán:
counter
: Para que cuente los paquetes que cumplen la regla.masquerade
: Estamos realizando enmascaramiento ya que la ip pública del router es dinámica.
Al introducir esta última regla ya tendríamos conexión a internet desde un equipo de la LAN:
debian@lan:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=5 ttl=54 time=41.5 ms
...
PREROUTING
El único equipo de la red local que es accesible desde Internet es el dispositivo de NAT (como hemos indicado suele ser el router) a través de su dirección IP pública (por ejemplo la 80.56.1.14
). Utilizando NAT, en concreto DNAT, podemos hacer que la conexión a la IP pública desde el exterior a un determinado puerto se redirija a un servidor en la red local que realmente este ofreciendo el servicio.
Supongamos que instalamos un servidor web en un equipo de la red local con dirección IP 192.168.100.10
y queremos que sea accesible desde Internet, tendremos que modificar las peticiones que lleguen al puerto 80/tcp des equipo que tiene la dirección IP pública y que cambie la dirección IP destino 80.56.1.14
por 192.168.100.10
, esto se hace con la siguiente regla:
nft add rule ip nat prerouting iifname "eth0" tcp dport 80 counter dnat to 192.168.100.10
Explicación de los parámetros::
add rule ip nat prerouting
: Se añade la regla a la cadenaprerouting
, donde las reglas se aplican antes de tomar la decisión de enrutamiento, así se tomará la decisión de encaminamiento con la nueva dirección IP destino.tcp dport 80
: Esta regla se ejecutará sobre paquetes que llegan al puerto 80/tcp.iifname "eth0"
:… y entran por la interfazeth0
.: Como acciones que vamos a ejecutar cuando el paquete cumpla estas reglas serán:counter
: Para que cuente los paquetes que cumplen la regla.dnat to 192.168.100.10
: Cambia la dirección IP destino (inicialmente 80.56.1.14) a 192.168.100.10
Si desde intenet accedemos con un navegador web a la URL http://80.56.1.14/
estaríamos accediendo al servidor web instalado en la máuina con IP 192.168.100.1
.
Hay algunos servicios que permiten utilizar puertos diferentes a los estándar, como por ejemplo ssh, ya que podemos acceder a un servidor por ssh utilizando un puerto distinto al 22/tcp. Como nftables nos permite no sólo modificar la dirección IP destino sino también el puerto destino, podríamos tener esta regla:
nft add rule ip nat prerouting iifname "eth0" tcp dport 2222 counter dnat to 1:2.168.100.10:22
En este caso si accedemos por ssh a nuestro router (a su IP pública) al puerto 2222 estaríamos accediendo al servidor ssh (puerto 22/tcp) de la máquina 192.168.100.10
:
ssh -p2222 debian@80.56.1.14
...
debian@lan:~$
Listados de reglas NAT
Para terminar veamos un resumen de las reglas que hemos creado:
nft list ruleset
table inet filter {
}
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname "eth0" ip saddr 192.168.100.0/24 counter packets 39 bytes 2648 masquerade
}
chain prerouting {
type nat hook prerouting priority 0; policy accept;
iifname "eth0" tcp dport http counter packets 4 bytes 240 dnat to 192.168.100.10
iifname "eth0" tcp dport 2222 counter packets 1 bytes 60 dnat to 192.168.100.10:ssh
}
}
Conclusiones
En este artículo hemos introducido la configuración de NAT con nftables. Hay que tener en cuenta que en un entorno en producción, además de la reglas NAT que necesitemos, tendremos que controlar los paquetes que llegan o salen de la máquina cortafuegos y de las máquinas de la red local. Ese tema es el que abordaremos en la siguiente entrada del blog.
Implementación de un cortafuegos perimetral con nftables
En la entrada anterior introducimos el concepto de cortafuegos perimetral e hicimos una introducción a la implementación de reglas NAT con nftables, en este artículo vamos a concluir la implementación del cortafuego añadiendo a las reglas NAT, las reglas de filtrado necesarias para aumentar la seguridad de nuestra infraestructura.
Nuestro escenario
El cortafuegos perimetral que nosotros vamos a configurar sería el más simple, y es el que controla el tráfico para una red local:
Tendremos dos clases de conexiones que tenemos que controlar:
- Las que entran y salen del propio cortafuegos, en este caso utilizaremos las cadenas
input
youtput
de la tablafilter
, de forma similar a como trabajamos en el artículo: Implementación de un cortafuegos personal con nftables. - Las que entran o salen de los ordenadores de nuestra red local, es decir, las que atraviesan el cortafuegos. Em este caso las reglas de filtrado se crearán en la cadena
forward
de la tablafilter
.
Creación de las cadenas
Suponemos que ya tenemos definida una tabla filter
de la familia inet
, por lo tanto tendremos que crear nuestras tres cadenas:
# nft add chain inet filter input { type filter hook input priority 0 \; counter \; policy drop \; }
# nft add chain inet filter output { type filter hook output priority 0 \; counter \; policy drop \; }
# nft add chain inet filter forward { type filter hook forward priority 0 \; counter \; policy drop \; }
Podemos observar que hemos usado la política drop
, por lo que por defecto todo el tráfico está denegado. Vemos las cadenas creadas:
# nft list chains
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy drop;
}
chain forward {
type filter hook forward priority 0; policy drop;
}
}
Filtrado de conexiones al cortafuegos
Como se ha indicado para permitir las conexiones que entran o salen al cortafuegos, utilizaremos reglas en las cadenas input
y output
de la tabla filter
. Veamos algunos ejemplos, aunque puedes ver más en el artículo citado anteriormente.
Permitimos tráfico para la interfaz loopback
Vamos a permitir todo el tráfico a la interfaz lo
:
# nft add rule inet filter input iifname "lo" counter accept
# nft add rule inet filter output oifname "lo" counter accept
Permitir peticiones y respuestas protocolo ICMP
En concreto vamos a permitir la posibilidad que puedan hacer ping a nuestra máquina:
# nft add rule inet filter output oifname "eth0" icmp type echo-reply counter accept
# nft add rule inet filter input iifname "eth0" icmp type echo-request counter accept
Permitir el acceso por ssh a nuestra máquina
Vamos a permitir la conexión ssh desde la red 172.22.0.0/16:
# nft add rule inet filter input ip saddr 172.22.0.0/16 tcp dport 22 ct state new,established counter accept
# nft add rule inet filter output ip daddr 172.22.0.0/16 tcp sport 22 ct state established counter accept
Permitir consultas DNS
# nft add rule inet filter output oifname "eth0" udp dport 53 ct state new,established counter accept
# nft add rule inet filter input iifname "eth0" udp sport 53 ct state established counter accept
Permitir tráfico HTTP/HTTPS
# nft add rule inet filter output oifname "eth0" ip protocol tcp tcp dport { 80,443 } ct state new,established counter accept
# nft add rule inet filter input iifname "eth0" ip protocol tcp tcp sport { 80,443 } ct state established counter accept
Filtrado de conexiones a los equipos de la red local
Aunque ya hemos configurado SNAT (en este artículo), como hemos puesto la política por defecto forward
a drop
, los equipos de la LAN están incomunicados, ya que no permitimos que ningún paquete pase por el cortafuego. Por lo tanto ahora tenemos que ir configurando los pares de reglas (forward en ambas direcciones) para ir permitiendo distintos protocolos, puerto… a la LAN.
En este caso vamos a permitir las conexiones que pueden establecer de o hacía los ordenadores de la red local, en este caso vamos a crear reglas en la cadena forward
de la tabla filter
.
Vamos a ir estudiando distintos ejemplos:
Permitir hacer ping desde la LAN
Para que la LAN haga ping al exterior los paquetes ICMP tiene que estar permitidos que pasen por el cortafuego:
# nft add rule inet filter forward iifname "eth1" oifname "eth0" ip saddr 192.168.100.0/24 icmp type echo-request counter accept
# nft add rule inet filter forward iifname "eth0" oifname "eth1" ip daddr 192.168.100.0/24 icmp type echo-reply counter accept
Consultas y respuestas DNS desde la LAN
# nft add rule inet filter forward iifname "eth1" oifname "eth0" ip saddr 192.168.100.0/24 udp dport 53 ct state new,established counter accept
# nft add rule inet filter forward iifname "eth0" oifname "eth1" ip daddr 192.168.100.0/24 udp sport 53 ct state established counter accept
Permitimos la navegación web desde la LAN
# nft add rule inet filter forward iifname "eth1" oifname "eth0" ip protocol tcp ip saddr 192.168.100.0/24 tcp dport { 80,443} ct state new,established counter accept
# nft add rule inet filter forward iifname "eth0" oifname "eth1" ip protocol tcp ip daddr 192.168.100.0/24 tcp sport { 80,443} ct state established counter accept
Permitimos el acceso a nuestro servidor web de la LAN desde el exterior
Como veíamos el artículo teníamos configurado DNAT para acceder al servidor web de la máquina de la LAN 192.168.100.10
. Pero al tener política por defecto drop
en la cadena forward
tendremos que permitir dicho tráfico:
# nft add rule inet filter forward iifname "eth0" oifname "eth1" ip daddr 192.168.100.0/24 tcp dport 80 ct state new,established counter accept
# nft add rule inet filter forward iifname "eth1" oifname "eth0" ip saddr 192.168.100.0/24 tcp sport 80 ct state established counter accept
Listado de reglas
Para finalizar podemos ver la configuración completa (NAT y filtrado) de nuestro cortafuegos perimetral:
# nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ip saddr 172.23.0.0/16 tcp dport ssh ct state established,new counter packets 2615 bytes 208304 accept
iifname "lo" counter packets 0 bytes 0 accept
iifname "eth0" icmp type echo-request counter packets 0 bytes 0 accept
ip saddr 172.22.0.0/16 tcp dport ssh ct state established,new counter packets 0 bytes 0 accept
iifname "eth0" udp sport domain ct state established counter packets 0 bytes 0 accept
iifname "eth0" ip protocol tcp tcp sport { http, https } ct state established counter packets 0 bytes 0 accept
}
chain output {
type filter hook output priority 0; policy drop;
ip daddr 172.23.0.0/16 tcp sport ssh ct state established counter packets 1522 bytes 203036 accept
oifname "lo" counter packets 0 bytes 0 accept
oifname "eth0" icmp type echo-reply counter packets 0 bytes 0 accept
ip daddr 172.22.0.0/16 tcp sport ssh ct state established counter packets 0 bytes 0 accept
oifname "eth0" udp dport domain ct state established,new counter packets 0 bytes 0 accept
oifname "eth0" ip protocol tcp tcp dport { http, https } ct state established,new counter packets 0 bytes 0 accept
}
chain forward {
type filter hook forward priority 0; policy drop;
iifname "eth1" oifname "eth0" ip saddr 192.168.100.0/24 icmp type echo-request counter packets 0 bytes 0 accept
iifname "eth0" oifname "eth1" ip daddr 192.168.100.0/24 icmp type echo-reply counter packets 0 bytes 0 accept
iifname "eth1" oifname "eth0" ip saddr 192.168.100.0/24 udp dport domain ct state established,new counter packets 0 bytes 0 accept
iifname "eth0" oifname "eth1" ip daddr 192.168.100.0/24 udp sport domain ct state established counter packets 0 bytes 0 accept
iifname "eth1" oifname "eth0" ip protocol tcp ip saddr 192.168.100.0/24 tcp dport { http, https } ct state established,new counter packets 0 bytes 0 accept
iifname "eth0" oifname "eth1" ip protocol tcp ip daddr 192.168.100.0/24 tcp sport { http, https } ct state established counter packets 0 bytes 0 accept
iifname "eth0" oifname "eth1" ip daddr 192.168.100.0/24 tcp dport http ct state established,new counter packets 7 bytes 798 accept
iifname "eth1" oifname "eth0" ip saddr 192.168.100.0/24 tcp sport http ct state established counter packets 6 bytes 3702 accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname "eth0" ip saddr 192.168.100.0/24 counter packets 91 bytes 6600 masquerade
}
chain prerouting {
type nat hook prerouting priority 0; policy accept;
iifname "eth0" tcp dport http counter packets 17 bytes 1020 dnat to 192.168.100.10
iifname "eth0" tcp dport 2222 counter packets 2 bytes 120 dnat to 192.168.100.10:ssh
}
}
Conclusiones
En estos últimos artículos hemos hecho una introducción a la implementación de cortafuegos de nftables
. Es muy conveniente que si quieres seguir profundizando en el tema te estudies la documentación de nftable.
Introducción a las redes en docker. Enlazando contenedores docker
Hace unos año escribí una entrada en este blog titulada: Enlazando contenedores docker donde hacía una primera aproximación al mecanismo que nos ofrece docker de que varios contenedores sean accesibles entre ellos por medio de su nombre (resolución de nombres). Este mecanismo funciona de manera distinta según la red docker donde estén conectados los contenedores. En este artículo vamos a introducir los distintos tipos de redes que nos ofrece docker y los distintos métodos de asociación o enlazado entre contenedores que tenemos a nuestra disposición.
Introducción a las redes en docker
Cuando instalamos docker tenemos las siguientes redes predefinidas:
# docker network ls
NETWORK ID NAME DRIVER SCOPE
ec77cfd20583 bridge bridge local
69bb21378df5 host host local
089cc966eaeb none null local
- Por defecto los contenedores que creamos se conectan a la red de tipo bridge llamada
bridge
(por defecto el direccionamiento de esta red es172.17.0.0/16
). Los contenedores conectados a esta red que quieren exponer algún puerto al exterior tienen que usar la opción-p
para mapear puertos. Si conecto un contenedor a la red host, el contenedor estaría en la misma red que el host (por lo tanto toma direccionamiento del servidor DHCP de nuestra red). Además los puerto son accesibles directamente desde el host. Por ejemplo:
# docker run -d --name mi_servidor --network host josedom24/aplicacionweb:v1 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 135c742af1ff josedom24/aplicacionweb:v1 "/usr/sbin/apache2ct…" 3 seconds ago Up 2 seconds mi_servidor
Podemos acceder directamente al puerto 80 del servidor para ver la página web.
- La red
none
no configurará ninguna IP para el contenedor y no tiene acceso a la red externa ni a otros contenedores. Tiene la dirección loopback y se puede usar para ejecutar trabajos por lotes.
Nosotros podemos crear nuevas redes (redes definidas por el usuario), por ejemplo para crear una red de tipo bridge:
# docker network create mired
Y para ver las características de esta nueva red, podemos ejecutar:
# docker network inspect mired
Para crear un contenedor en esta red, ejecutamos:
# docker run -d --name mi_servidor --network mired -p 80:80 josedom24/aplicacionweb:v1
Dependiendo de la red que estemos usando (la red puente por defecto o una red definida por el usuario) el mecanismo de enlace entre contenedores será distinto.
Enlazando contenedores conectados a la red bridge por defecto
Esta manera en enlazar contenedores no está recomendada y esta obsoleta. Además el uso de contenedores conectados a la red por defecto no está recomendado en entornos de producción. Para realizar este tipo de enlace vamos a usar el flag --link
:
Veamos un ejemplo, primero creamos un contenedor de mariadb:
# docker run -d --name servidor_mysql -e MYSQL_DATABASE=bd_wp -e MYSQL_USER=user_wp -e MYSQL_PASSWORD=asdasd -e MYSQL_ROOT_PASSWORD=asdasd mariadb
A continuación vamos a crear un nuevo contenedor, enlazado con el contenedor anterior:
# docker run -d --name servidor --link servidor_mysql:mariadb josedom24/aplicacionweb:v1
Para realizar la asociación entre contenedores hemos utilizado el parámetro --link
, donde se indica el nombre del contenedor enlazado y un alias por el que nos podemos referir a él.
En este tipo de enlace tenemos dos características:
Se comparten las variables de entorno
Las variables de entorno del primer contenedor son accesibles desde el segundo contenedor. Por cada asociación de contenedores, docker crea una serie de variables de entorno, en este caso, en el contenedor
servidor
, se crearán las siguientes variables, donde se utiliza el nombre del alias indicada en el parámetro--link
:# docker exec servidor env ... MARIADB_PORT=tcp://172.17.0.2:3306 MARIADB_PORT_3306_TCP=tcp://172.17.0.2:3306 MARIADB_PORT_3306_TCP_ADDR=172.17.0.2 MARIADB_PORT_3306_TCP_PORT=3306 MARIADB_PORT_3306_TCP_PROTO=tcp MARIADB_NAME=/servidor/mariadb MARIADB_ENV_MYSQL_USER=user_wp MARIADB_ENV_MYSQL_PASSWORD=asdasd MARIADB_ENV_MYSQL_ROOT_PASSWORD=asdasd MARIADB_ENV_MYSQL_DATABASE=bd_wp MARIADB_ENV_GOSU_VERSION=1.10 MARIADB_ENV_GPG_KEYS=177F4010FE56CA3336300305F1656F24C74CD1D8 MARIADB_ENV_MARIADB_MAJOR=10.4 MARIADB_ENV_MARIADB_VERSION=1:10.4.11+maria~bionic ...
Los contenedores son conocido por resolución estática
Otro mecanismo que se realiza para permitir la comunicación entre contenedores asociados es modificar el fichero
/etc/hosts
para que tengamos resolución estática entre ellos. Podemos comprobarlo:# docker exec servidor cat /etc/hosts ... 172.17.0.2 mariadb c76089892798 servidor_mysql
Enlazando contenedores conectados a una red definida por el usuario
En este caso vamos a definir una red de tipo bridge:
# docker network create mired
Y creamos los contenedores conectados a dicha red:
# docker run -d --name servidor_mysql --network mired -e MYSQL_DATABASE=bd_wp -e MYSQL_USER=user_wp -e MYSQL_PASSWORD=asdasd -e MYSQL_ROOT_PASSWORD=asdasd mariadb
# docker run -d --name servidor --network mired josedom24/aplicacionweb:v1
En este caso no se comparten las variables de entorno, y la resolución de nombres de los contenedores se hace mediante un servidor dns que se ha creado en el gateway de la red que hemos creado:
# docker exec -it servidor bash
root@a86f6d758eba:/# apt update && apt install dnsutils -y
...
root@a86f6d758eba:/# dig servidor_mysql
...
; ANSWER SECTION:
servidor_mysql. 600 IN A 172.20.0.2
...
;; SERVER: 127.0.0.11#53(127.0.0.11)
root@a86f6d758eba:/# dig servidor_mysql.mired
...
; ANSWER SECTION:
servidor_mysql.mired. 600 IN A 172.20.0.2
root@a86f6d758eba:/# dig servidor
...
; ANSWER SECTION:
servidor. 600 IN A 172.20.0.3
Como vemos desde un contenedor se pueden resolver tanto los nombres de los servidores, como el FHQN formado por el nombre del contenedor y como nombre de dominio el nombre de la red a la que están conectados.
Instalación de wordpress en docker
Veamos un ejemplo, vamos a instalar wordpress usando dos contenedores enlazados: uno con la base de datos mariadb y otro con la aplicación wordpress.
Creamos una red de tipo bridge:
# docker network create red_wp
Creamos un contenedor desde la imagen mariadb con el nombre servidor_mysql
, conectada a la red creada:
docker run -d --name servidor_mysql --network red_wp -e MYSQL_DATABASE=bd_wp -e MYSQL_USER=user_wp -e MYSQL_PASSWORD=asdasd -e MYSQL_ROOT_PASSWORD=asdasd mariadb
A continuación vamos a crear un nuevo contenedor, con el nombre servidor_wp
, con el servidor web a partir de la imagen wordpress, conectada a la misma red y con las variables de entorno necesarias:
docker run -d --name servidor_wp --network red_wp -e WORDPRESS_DB_HOST=servidor_mysql -e WORDPRESS_DB_USER=user_wp -e WORDPRESS_DB_PASSWORD=asdasd -e WORDPRESS_DB_NAME=bd_wp -p 80:80 wordpress
La variable de entorno del contenedor wordpress WORDPRESS_DB_HOST
la hemos inicializado con el nombre del contenedor de la base de datos, ya que como hemos explicado anteriormente, al estar conectado a la misma red los dos contenedores, este nombre se podrá resolver. Podemos acceder a la ip del servidor docker y comprobar la instalación de wordpress.
Enlazando contenedores con docker-compose
Cuando trabajamos con escenarios donde necesitamos correr varios contenedores podemos utilizar docker-compose para gestionarlos. En el fichero docker-compose.yml
vamos a definir el escenario. El programa docker-compose
se debe ejecutar en el directorio donde este ese fichero. Por ejemplo para la ejecución de wordpress persistente podríamos tener un fichero con el siguiente contenido:
version: '3.1'
services:
wordpress:
container_name: servidor_wp
image: wordpress
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: user_wp
WORDPRESS_DB_PASSWORD: asdasd
WORDPRESS_DB_NAME: bd_wp
ports:
- 80:80
volumes:
- /opt/wordpress:/var/www/html/wp-content
db:
container_name: servidor_mysql
image: mariadb
restart: always
environment:
MYSQL_DATABASE: bd_wp
MYSQL_USER: user_wp
MYSQL_PASSWORD: asdasd
MYSQL_ROOT_PASSWORD: asdasd
volumes:
- /opt/mysql_wp:/var/lib/mysql
Cuando creamos un escenario con docker-compose
se crea una nueva red definida por el usuario docker donde se conectan los contenedores, por lo tanto están enlazados, pero no comparten las variables de entorno (por esta razón hemos creado las variables de entorno al definir el contenedor de wordpress). Además tenemos resolución por dns que resuelve tanto el nombre del contendor (por ejemplo, servidor_mysql
) como el alias (por ejemplo, db
).
Para crear el escenario:
# docker-compose up -d
Creating network "dc_default" with the default driver
Creating servidor_wp ... done
Creating servidor_mysql ... done
La primera imagen de este artículo está tomada de la siguiente página web: https://www.nuagenetworks.net/blog/docker-networking-overview/
Curso de introducción al uso de la plataforma moodle
El 16 de marzo de 2020 se suspendieron las actividades docentes presenciales en el Sistema Educativo, debido a la declaración del estado de alarma a causa de la crisis causada por el COVID-19.
Los docentes hemos tenido que adaptarnos de forma muy rápida a esta situación y al uso de herramientas informáticas para llevar a cabo nuestra labor docente.
Este curso surge como una necesidad formativa expresada por algunos profesores de mi instituto (IES Gonzalo Nazareno). Junto a mi compañero Alberto Molina hemos preparado este minicurso sobre el uso de la plataforma educativa Moodle. El objetivo de este curso es introducir los recursos y funcionalidades más básicas de moodle de una manera sencilla y fácil. Además aunque vamos a tratar sólo algunas funcionalidades de la plataforma, creemos que son suficientes para empezar a usar dicha herramienta para organizar los contenidos y asegurar los recursos de comunicación con nuestros alumnos.
Curso de OpenShift
En este curso aprenderás a desplegar servicios con OpenShift desde cero y ampliar tus conocimientos sobre Cloud Computing y la capa de Plataforma como Servicio PaaS.
Los siguientes contenidos forman parte de un curso que he impartido para OpenWebinars en mayo de 2019.
Puedes obtener todo el contenido del curso en el repositorio GitHub. Todas las observaciones, mejoras y sugerencias son bienvenidas.
Nota: Cuando se impartió el curso la versión de openShift que usamos fue la 3, la interfaz en las últimas versiones de OpenShift ha cambiado pero los conceptos que se tratan en el curso son totalmente válidos.
Vídeos del módulo Lenguaje de Marcas
Durante esta tercera evaluación, en la que se ha suspendido las actividades docentes presenciales en el Sistema Educativo, los docentes nos hemos tenido que adaptar para ofrecer a nuestros alumnos los materiales necesarios y los medios para que pudieran seguir avanzando en el curso.
En mi caso, me decidí por ir grabando las distintas clases, y hacer vídeos cortos sobre los distintos conceptos y prácticas de los distintos módulos.
En esta entrada os dejo los vídeos que he grabado para el módulo de Lenguajes de Marcas de 1º ASIR (Administración de Sistemas Informáticos en Red). Corresponden a las últimas dos unidades didácticas:
Flask: (Miniframework python para desarrollar páginas web)
Puedes encontrar los materiales en está página web y un repositorio donde encontrarás los ejercicios que se realizan en los vídeos.
Los vídeos que he realizado son los siguientes:
- Introducción a HTTP (GET,POST)
- Instalación de python flask
- ¿Por qué usamos entornos virtuales?
- Cómo trabajamos con flask
- Mi primer programa en flask (ejemplo1)
- Servidor web y depuración de las aplicaciones flask (ejemplo1) (2ª parte)
- Empezamos a trabajar con plantillas flask (ejemplo2)
- Rutas dinámicas en flask (ejemplo3)
- Otro ejemplo con rutas dinámicas (ejemplo4)
- Bucles en las plantillas (ejemplo5)
- Otro ejemplo con bucles en plantillas (ejemplo6)
- Instrucciones alternativas en las plantillas (ejemplo7)
- Ejemplo completo con if y for en las plantillas (ejemplo8)
- Patrón diseño: Lista - Detalle (ejemplo9)
- Despliegue de aplicación Flask en Heroku (1ª Parte)
- Despliegue de aplicación Flask en Heroku (2ª Parte)
- Servir contenido estático en Flask (ejemplo10)
- Herencias plantillas (flask) (ejemplo11)
- Formularios en Flask I (ejemplo12)
- Formularios en Flask II (ejemplo13)
- Formularios en Flask III (ejemplo14)
- Creación de plantillas base (base.html)
- Ejemplo completo flask (1ª parte)
- Ejemplo completo flask (2ª parte)
Servicios Web. API Resful
Los materiales lo puedes encontrar en esta página y los vídeos que he realizado son:
- Introducción a los servicios web Restful
- Aplicaciones web us Servicios web Restful
- Peticiones a API restful con curl - swapi
- Peticiones a API restful con curl - redmine
- Peticiones a API restful con curl - openwheather
- Introducción a la librería python requests
- Librería requests. Ejemplo de petición sin autentificación y xml
- Librería requests. Ejemplo de petición con autentificación y xml
- Librería requests. Otro ejemplo de petición con autentificación y xml
- Librería requests. Modificación de los recursos de una API restful utilizando peticiones POST
- Desarrollo de aplicaciones flask con requests
- Despliegue de aplicaciones flask con requests en Heroku
Hacer streaming de vídeo usando software libre
En este artículo voy a documentar mi experiencia montando un sistema para poder realizar un streaming de vídeo usando software libre. En mi instituto hemos usado en estos meses jitsi para realizar videoconferencias entre los profesores y para impartir las clases a los alumnos. Al final de curso teníamos que celebrar el claustro final y montamos un sistema de streaming para emitir la videconferencia jitsi donde se encontraban los compañeros que iban a intervenir. Evidentemente con los medios que tenemos no era posible tener una videoconferencia para unas 60 personas, pero queríamos que todos los profesores pudieran seguir el claustro en directo. Por lo que días antes nos pusimos a estudiar alternativas (por supuesto, usando software libre) y os cuento los pasos que fuimos dando:
El protocolo RTMP
El primer artículo que encontramos fue: Create your own video streaming server with Linux y nos encontramos la definición del protocolo que íbamos a usar para realizar el streaming: el protocolo RTMP.
El protocolo RTMP (Real-Time Messaging Protocol) se usa para los servicios streaming, trabaja sobre TCP (Transmission Control Protocol) y usa por defecto el puerto 1935. Permite al cliente controlar la calidad de distribución de la transmisión y seguridad.
Para más información sobre este protocolo puedes leer el siguiente documento.
Además aprendimos que podíamos implementarlo usando un módulo del servidor web nginx.
Configurando un servidor RTMP con nginx
Vamos a explicar los pasos para configurar nginx para que funcione como un servidor RTMP. Para ello vamos a usar el sistema operativo Debian Buster donde tenemos instalado un servidor nginx. Al ordenador en el que tenemos el servidor instalado vamos a acceder con el nombre video.josedomingo.org
.
Lo primero que vamos a hacer es instalar el módulo rtmp
de nginx:
apt install libnginx-mod-rtmp
A continuación vamos a hacer una configuración mínima del servidor rtmp, para ello en el fichero /etc/nginx/nginx.conf
añadimos lo siguiente:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}
Reiniciamos el servidor:
systemctl restart nginx
Y ya podemos probarlo.
Transmitiendo vídeo con OBS
OBS, Open Broadcast Software es una aplicación libre y de código abierto para la grabación y transmisión de vídeo por internet (streaming), mantenida por OBS Project.
Para configurar OBS para transmitir vídeo a nuestro servidor rtmp, vamos a la opción Configuración -> Emisión, en Tipo de Emisión elegimos la opción Personalizar el servicio de retransmisión e indicamos los siguientes datos:
- URL: La URL de nuestro servidor rtmp, en nuestro caso sería
rtmp://video.josedomingo.org/live
- Clave de retransmisión: Es una cadena de caracteres qe identifica la retransmisión y que posteriormente usaremos para ver el streaming, en nuestro caso vamos a poner
test
.
Después de que configuremos el vídeo que queremos transmitir, ya podemos elegir la opción Iniciar Transmisión en la pantalla principal.
Para comprobar que la transmisión se está haciendo de manera adecuada nos debe aparecer una barra de estado, con un cuadro verde (recuerda: verde bueno, rojo malo):
Usando VLC para ver el streaming
VLC es un reproductor multimedia libre y de código abierto multiplataforma y un “framework” que reproduce la mayoría de archivos multimedia, muchos medios de almacenamiento y diversos protocolos de transmisión.
Podemos configurar VLC para visualizar el streaming que estamos haciendo, para ello nos vamos a la opción Medio -> Abrir ubicación de red… e indicamos la URL de la retransmisión que estaría formada por la URL de nuestro servidor rtmp más la clave de retransmisión que indicamos en OBS: rtmp://video.josedomingo.org/live/test
:
Y en pocos segundos estaríamos viendo la retransmisión en directo:
Añadiendo más funcionalidad a nuestro servidor de streaming
Parece que nuestro servidor está funcionando de manera adecuada, pero nos encontramos dos limitaciones:
Hemos hecho una configuración muy simple. Te puedo asegurar que podemos tener muchas más funcionalidades en nuestro servidor rtmp. Efectivamente buscando por internet llegué a la documentación oficial del módulo rtmp de nginx y te aseguro que hay que echarle un buen rato. Nos vamos a quedar (nos hará falta posteriormente) con que este módulo nos ofrece tres formatos para acceder al streaming: Stream Real-Time Messaging Protocol (RTMP), Apple HTTP Live Streaming (HLS), y Dynamic Adaptive Streaming over HTTP (DASH).
Hemos visualizado el streaming con VLC pero, ¿puedo tener un reproductor de vídeo en una página web que me permita verlo?. He encontrado muchas librerías javascript (luego hablaremos de ellas) que me permiten tener en mi página web un reproductor de vídeo, pero los reproductores que eran capaz de ver vídeos desde rtmp (como hemos hecho con VLC) necesitaban tener instalado en el navegador el plugin flash, no funcionaban con HTML5.
Llegados a este punto y para solucionar estas dos limitaciones (tampoco he tenido mucho tiempo para profundizar en la documentación de rtmp en nginx), me hice la siguiente pregunta: ¿Existirá alguna imagen en docker hub que me ofrezca un servidor rtmp configurado de forma adecuada?
Evidentemente la respuesta es que existen varios, finalmente elegí la imagen alqutami/rtmp-hls
(imagen en docker hub) que además de ofrecer un servidor completamente configurado, nos ofrece un conjunto de páginas web con distintos reproductores de vídeo que utilizan diferentes tecnologías para funcionar. Lo veremos en el siguiente apartado:
Instalación de un servidor rtmp usando docker
En nuestro servidor hemos desinstalado el servidor nginx, hemos instalado docker y creamos un contenedor como nos indica la documentación de la imagen:
docker run -d -p 1935:1935 -p 8080:8080 --name rtmp alqutami/rtmp-hls
Como vemos el puerto 1935 para acceder al servidor rtmp y el puerto 8080 para acceder a las páginas web que nos ofrece el servidor.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
112f5df28a19 alqutami/rtmp-hls "nginx -g 'daemon of…" 5 seconds ago Up 4 seconds 0.0.0.0:1935->1935/tcp, 0.0.0.0:8080->8080/tcp rtmp
Si queremos profundizar en los parámetros de configuración podemos ejecutar el siguiente comando para visualizar el fichero de configuración:
docker exec rtmp cat /etc/nginx/nginx.conf
Para emitir con OBS y visualizar con VLC lo haríamos exactamente como lo hemos estudiado anteriormente. Veamos lo nuevo que nos ofrece esta imagen:
Nuevos protocolos de streaming
Para solucionar la segunda limitación que indicamos anteriormente, este servidor esta configurado para acceder al streaming usando dos nuevos protocolos:
Estos protocolos de streaming están basados en HTTP y nos van a permitir tener reproductores de vídeos basados en HTML5.
- Para acceder al streaming usando HLS tendríamos que acceder a la siguiente URL:
http://<server ip>:8080/hls/<stream-key>.m3u8
, donde indicaremos la ip o el nombre del servidor y la clave de retransmisión. - Para acceder al streaming usando DASH tendríamos que acceder a la siguiente URL:
http://<server ip>:8080/dash/<stream-key>_src.mpd
, donde, de la misma forma, indicaremos la ip o el nombre del servidor y la clave de retransmisión.
Puedes probar desde VLC a reproducir desde una ubicación de red indicando estas URLs:
http://video.josedomingo.org:8080/hls/test.m3u8
http://video.josedomingo.org:8080/dash/test_src.mpd
Reproductores de vídeos disponibles
La imagen docker que estamos usando nos ofrece varias páginas web de demostración con distintos reproductores de vídeo que funcionan con los distintos protocolos. Estás páginas de demostración están configuradas para reproducir vídeos desde localhost
y usando la clave de reproducción test
. Por lo tanto lo que vamos a hacer es copiarnos los ficheros html a nuestro ordenador, modificar las páginas html a nuestra conveniencia (usando nuestra URL y nuestra clave de reproducción) y volver a crear el contenedor con un volumen para que tenga nuestras versiones de estos ficheros. Vamos a ello:
Lo primero que vamos a hacer es copiarnos en una carpeta que vamos a llamar players
los ficheros html a nuestro ordenador:
# docker cp rtmp:/usr/local/nginx/html/players players
# ls players
dash.html hls_hlsjs.html hls.html rtmp_hls.html rtmp.html
Tenemos 5 páginas de ejemplo, por lo tanto:
- Si queremos ver contenido RTMP (requiere flash) accederemos a
http://video.josedomingo.org:8080/players/rtmp.html
- Si queremos ver contenido HLS accederemos a
http://video.josedomingo.org:8080/players/hls.html
- Si queremos ver contenido HLS usando la librería hls.js accederemos a
http://video.josedomingo.org:8080/players/hls_hlsjs.html
- Si queremos ver contenido DASH accederemos a
http://video.josedomingo.org:8080/players/dash.html
- Si queremos ver contenido rtmp y HLS en la misma página accederemos a
http://video.josedomingo.org:8080/players/rtmp_hls.html
Para que estas páginas funcionen de manera adecuada debemos modificarlas para indicar nuestra URL y nuestra clave de retransmisión.
A continuación borramos el contenedor y lo volvemos a crear con un volumen para que tenga nuestras versiones de estos ficheros:
# docker rm -f rtmp
# docker run -d -p 1935:1935 -p 8080:8080 -v /root/players:/usr/local/nginx/html/players --name rtmp alqutami/rtmp-hls
Y podemos probar por ejemplo con la retransmisión hls:
Para terminar algunas indicaciones:
- Evidentemente las páginas webs proporcionadas son de demostración y nos pueden servir de guías para añadir a nuestras páginas web los reproductores de vídeo de nuestras retransmisiones.
- Sería muy recomendable la configuración de un proxy inverso para no utilizar el puerto 8080 y configurar el acceso HTTPS.
Conclusiones
Sin haber profundizando mucho en el tema, la utilización de esta imagen docker nos proporcionó la infraestructura necesaria para retransmitir el claustro final de mi instituto.
Para el próximo curso y basándonos en esta experiencia, queremos desarrollar un sistema que permita de forma automática retransmitir las videoconferencias en jitsi de los profesores para que los alumnos puedan acceder de forma más cómoda a las clases.
Ya os contaré la experiencia!!!
Jugando con la API de OVH
OVH es un proveedor de alojamiento web, computación en la nube y telecomunicaciones francés. Ofrece distintos servicios: VPS, dominios, Cloud Computing,… En este artículo voy a hacer una introducción al uso de la API pública de OVH para gestionar los recursos que tengamos contratados en la empresa.
Configuración de nuestro entorno de desarrollo
Vamos a utilizar el lenguaje Python para hacer programas que nos permitan interactuar con el servicio OVH para gestionar los recursos que tenemos contratados.
Vamos a usar una librería python que es un wrapper que nos facilita las llamadas a la API, para ello vamos a crear un entorno virtual:
$ python3 -m venv ovh
$ source ovh/bin/activate
(ovh)# pip install ovh
Creación de una aplicación para el uso de la API
El siguiente paso es crear una aplicación para el uso de la API que nos proporcionará las credenciales necesarias para el acceso a los recursos de la API, para ello accedemos a la página web de la API de OVH en Europa: https://eu.api.ovh.com/createApp/.
En esta página nos logueamos con nuestro usuario de OVH, e indicamos un nombre y una descripción de nuestra aplicación. Una vez creada la aplicación nos devolverán las credenciales: la Application Key y la Application Secret que identifican nuestra aplicación y nuestro usuario.
Configurando el acceso
La manera más fácil de configurar el acceso a la API es creando un fichero que llamamos ovh.conf
en el mismo directorio donde vamos a ejecutar nuestro programa. Este fichero tendrá el siguiente contenido:
[default]
; general configuration: default endpoint
endpoint=ovh-eu
[ovh-eu]
; configuration specific to 'ovh-eu' endpoint
application_key=xxxxxxxxxxxxxxxx
application_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
; uncomment following line when writing a script application
; with a single consumer key.
;consumer_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Como podemos comprobar indicamos el endpoint
, en este caso al usar OVh europe será ovh-eu
y indicamos nuestras credenciales: application_key
y application_secret
.
Nos faltaría la consumer_key
para poder utilizar la API. En la siguiente sección vamos a realizar un script que nos devuelve dicho valor, y que posteriormente colocaremos en este fichero y descomentaremos la última línea.
Solicitando la consumer_key
Para solicitar la clave de usuario consumer_key
tenemos que autentificarnos como usuario de OVH en una página que nos devolverá el valor de esta clave. El programa solicitar_consumer_key.py
es el responsable de generar la URL de está página y mostrarnos el valor de la clave:
import ovh
# create a client using configuration
client = ovh.Client()
# Request RO, /me API access
ck = client.new_consumer_key_request()
# Allow all GET, POST, PUT, DELETE on /* (full API)
ck.add_recursive_rules(ovh.API_READ_WRITE, '/')
# Request token
validation = ck.request()
print("Please visit %s to authenticate" % validation['validationUrl'])
input("and press Enter to continue...")
# Print nice welcome message
print("Welcome", client.get('/me')['firstname'])
print("Btw, your 'consumerKey' is '%s'" % validation['consumerKey'])
Veamos que hace cada instrucción:
client = ovh.Client()
: Crea el cliente que vamos a usar para hacer llamadas a la API. esta instrucción buscará nuestras credenciales en el ficheroovh.conf
.ck = client.new_consumer_key_request()
: Solicitamos laconsumer_key
.ck.add_recursive_rules(ovh.API_READ_WRITE, '/')
: Indicamos la autorización que vamos a tener para usar los recursos de la API. En este caso vamos a generar unconsumer_key
que será válido para hacer cualquier tipo de llamada HTTP (GET; POST, PUT, DELETE) (indicado conovh.API_READ_WRITE
) a todos los recursos de la API (indicado con/
).- Si indicamos, por ejemplo:
ck.add_rules(ovh.API_READ_ONLY, "/me")
pues autorizaríamos sólo peticiones GET a la ruta de la API/me
.
- Si indicamos, por ejemplo:
validation = ck.request()
: Solicitamos información sobre la solicitud de clave. En concreto envalidation['validationUrl']
tendremos el token que va a formar parte de la URL a la que tenemos que acceder para generar la clave..
Al ejecutar el programa, se nos indicará la URL a la que tenemos que acceder. En esa página nos tendremos que loguear e indicar la duración de validez del consumer_key
. Volvemos a la consola pulsamos Enter
y nos mostrará nuestro nombre (client.get('/me')['firstname']
) y el valor que estamos buscando (validation['consumerKey']
). El proceso sería el siguiente:
$ python3 solicitar_consumer_key.py
Please visit https://eu.api.ovh.com/auth/?credentialToken=xxxxxxxxxxxxxxxxxxxxxxxxxxxx to authenticate
and press Enter to continue...
En este momento accedemos a la URL, nos logueamos e indicamos el tiempo de validez de la clave:
Vovlemos al terminar, pulsamos Enter
y terminará el programa:
Welcome José Domingo
Btw, your 'consumerKey' is 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
Una vez que tenemos el valor de la consumer_key
lo indicamos en el fichero ovh.conf
, descomentando la última línea e indicando el valor:
consumer_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Ya estamos en disposición de estudiar las distintos objetos que nos ofrece la API de OVH, para crear programas que me permitan gestionar los recursos contratados. Veamos algunos ejemplos:
Mostrar los servicios que tienes contratado en ovh
import ovh
import json
client = ovh.Client()
result = client.get('/services',
#orderBy='', # Order services by services.expanded.Service properties (type: string)
#routes='', # Filter services by API route path (comma separated) (type: string)
#sort='',# Sort results generated by 'orderBy' (type: string)
)
for prod in result:
result2 = client.get('/services/%i'%prod)
print (json.dumps(result2, indent=4))
Obtener información de los VPS contratados
import ovh
import json
client = ovh.Client()
result = client.get('/vps')
for vps in result:
print(vps)
result2 = client.get('/vps/%s/serviceInfos'%vps)
print (json.dumps(result2, indent=4))
Modificar el contacto técnico de un VPS
import ovh
import json
client = ovh.Client()
vps=input("Indica el nombre de un vps:")
id=input("Indica el código del contacto técnico:")
try:
result2 = client.post('/vps/%s/changeContact'%vps,
contactAdmin=None, # The contact to set as admin contact (type: string)
contactBilling=None, # The contact to set as billing contact (type: string)
contactTech=id, # The contact to set as tech contact (type: string)
)
except:
print("Error. Nombre o usuario incorrecto.")
Conclusiones
Espero que este artículo pueda servir a aquellas personas que se quieren iniciar en el uso de la API pública de OVH utilizando python. Si quieres más información accede a estas páginas:
Introducción a LXD
LXD, Linux Container Daemon, es una herramienta de gestión de los contenedores y máquinas virtuales del sistema operativo Linux, desarrollada por Canonical.
Internamente usa LXC para la gestión de contenedores, pero facilita el uso de los contenedores añadiendo nuevas funcionalidades.
- LXD no trabaja con plantillas, trabaja con imágenes de sistemas operativos para crear los contenedores. Lista de imágenes.
- No ofrece soporte para diferentes backends de almacenamiento y tipos de red. Facilitando la gestión de red y almacenamiento.
- LXD ofrece una REST API que podemos usar con una simple herramienta de línea de comandos o con herramientas de terceros.
- LXD gestiona instancias, que pueden ser de tipos: contenedores, usando LXC internamente, y máquinas virtuales usando QEMU internamente.
Instalación de LXD
Vamos a usar el gestor de paquetes snap (si estás trabajando con la distribución Debian debes instalar el paquete sanpd
).
sudo snap install lxd
Antes de ejecutar una instancia (contenedor o máquina virtual) tenemos que hacer una configuración inicial de LXD, para ello ejecutamos como root:
lxd init
Interactivamente nos va preguntando distintos parámetros que nos permitirán realizar la configuración inicial:
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (cephobject, dir, lvm, btrfs, ceph) [default=btrfs]: dir
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Would you like the LXD server to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]:
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
Hemos dejado todos los valores por defecto, a excepción del tipo de pool de almacenamiento que he indicado que sea un directorio (dir). También ha creado una red puente para conectar los contenedores.
Creación de un contenedor
Para crear un contenedor, ejecutamos:
lxc launch <image_server>:<image_name> <instance_name>
Por ejemplo:
lxc launch images:ubuntu/20.04 ubuntu-container
Creación de máquinas virtuales
Para crear una máquina virtual, ejecutamos:
lxc launch <image_server>:<image_name> <instance_name> --vm
Por ejemplo:
lxc launch images:ubuntu/20.04 ubuntu-vm --vm
Y comprobamos que hemos creado un contenedor y una máquina virtual:
lxc list
+------------------+---------+-------------------------+-------------------------------------------------+-----------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------------------+---------+-------------------------+-------------------------------------------------+-----------------+-----------+
| ubuntu-container | RUNNING | 10.242.154.69 (eth0) | fd42:40c4:7788:440e:216:3eff:fe61:66b0 (eth0) | CONTAINER | 0 |
+------------------+---------+-------------------------+-------------------------------------------------+-----------------+-----------+
| ubuntu-vm | RUNNING | 10.242.154.119 (enp5s0) | fd42:40c4:7788:440e:216:3eff:fea3:8748 (enp5s0) | VIRTUAL-MACHINE | 0 |
+------------------+---------+-------------------------+-------------------------------------------------+-----------------+-----------+
Redes en LXD
Por defecto se ha creado un red de tipo bridge, que ha creado un Linux Bridge llamado lxdbr0
.
lxc network list
+-----------------+----------+---------+----------------+---------------------------+-------------+---------+---------+
| NAME | TYPE | MANAGED | IPV4 | IPV6 | DESCRIPTION | USED BY | STATE |
+-----------------+----------+---------+----------------+---------------------------+-------------+---------+---------+
+-----------------+----------+---------+----------------+---------------------------+-------------+---------+---------+
| ens3 | physical | NO | | | | 0 | |
+-----------------+----------+---------+----------------+---------------------------+-------------+---------+---------+
| lxdbr0 | bridge | YES | 10.93.154.1/24 | fd42:1b3c:2651:4df1::1/64 | | 3 | CREATED |
+-----------------+----------+---------+----------------+---------------------------+-------------+---------+---------+
Esta red es de tipo NAT con DHCP, es decir, posibilita que las instancias tengas conexión a internet y tiene configurado un servidor DHCP responsable de asignar el direccionamiento a las instancias. En este ejemplo la dirección 10.93.154.1
es la IP del host en esta red y sería la puerta de enlace de las instancias.
Podemos crear nuevas redes y modificar las existentes pero lo estudiaremos en otro post del blog.
Gestión de imágenes
En la creación de las dos instancias hemos descargado dos imágenes que podemos gestionar con el subcomando lxc image
, por ejemplo para ver las imágenes que hemos descargado:
lxc image list
+-------+--------------+--------+-------------------------------------+--------------+-----------------+----------+------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+-------+--------------+--------+-------------------------------------+--------------+-----------------+----------+------------------------------+
| | 3aa3fa64e5d0 | no | Ubuntu focal amd64 (20220911_07:42) | x86_64 | VIRTUAL-MACHINE | 230.98MB | Sep 12, 2022 at 7:28am (UTC) |
+-------+--------------+--------+-------------------------------------+--------------+-----------------+----------+------------------------------+
| | 7628425e768e | no | Ubuntu focal amd64 (20220911_07:42) | x86_64 | CONTAINER | 110.65MB | Sep 12, 2022 at 7:22am (UTC) |
+-------+--------------+--------+-------------------------------------+--------------+-----------------+----------+------------------------------+
Para más información ejecuta lxc image --help
.
Gestión de instancia
Vamos a usar la utilidad de línea de comandos lxc
, para ver todas las funcionalidades puedes ejecutar lxc --help
. Veamos algunas de ella:
lxc list
: Listar instancias. Podemos filtrar la lista, por ejemplolxc list type=container
olxc list ubuntu.*
.lxc info
: Nos da información de una instancia. Con la opción--show-log
nos muestra los logs de la instancia.lxc start
: Inicia una instancia.lxc stop
: Detiene una instancia.lxc delete
: Borra una instancia.
Si queremos ejecutar un comando en una instancia, ejecutamos:
lxc exec <instance_name> -- <command>
Por ejemplo:
lxc exec ubuntu-container -- apt update
Si queremos acceder a una shell de la instancia:
lxc exec ubuntu-container -- /bin/bash
Si queremos conectarnos a una instancia por una consola, ejecutamos:
lxc console <instance_name>
Nota: Deberíamos configurar una contraseña para un usuario anteriormente accediendo al bash de la instancia.
Configuración de las instancias
Tenemos muchos parámetros de configuración de las instancias, que podemos devivir en tres bloques: propiedades de las instancias, openciones de las instancias y dispositivos de las instancias.
Al crear una instancia podemos indicar los parámetros de configuración deseados, por ejemplo, si queremos limitar el número de CPU y la memoria de un contenedor, podemos ejecutar:
lxc launch images:ubuntu/20.04 ubuntu-limited -c limits.cpu=1 -c limits.memory=192MiB
Con el subcomando lxc config
podemos gestionar la configuración de las instancias, por ejemplo para mostrar la configuración de una instancia, ejecutamos:
lxc config show ubuntu-container
Por ejemplo, para cambiar un parámetro:
lxc config set ubuntu-container limits.memory=128MiB
Para seguir profundizando
- Más información sobre la configuración de instancias.
- Más información sobre la gestión de imágenes.
- Con el subcomando
lxc network
gestionamos las redes. Más información. - Con el subcomando
lxc storage
gestionamos los pools de almacenamiento. Más información.
Contenedores en instancias de OpenStack
Una de las características de trabajar con infraestructura en la nube como OpenStack es la posibilidad de virtualizar la red. Para ello OpenStack puede utilizar varios mecanismos, pero en instalaciones estándar de OpenStack se suele usar la redes XVLAN, que es un protocolo donde se encapsula tráfico de la capa de enlace sobre la capa de red, en concreto el tráfico Ethernet sobre una red IP.
Por otro lado vamos a recordar que la MTU (Unidad máxima de transferencia) expresa el tamaño en bytes que puede tener la unidad de datos de un protocolo de red. En concreto para Ethernet es, por defecto, 1500 bytes.
Cuando usamos redes XVLAN, estamos definiendo interfaces de red virtuales sobre interfaces físicas, y para que esto funcione necesitamos añadir información a las tramas que estamos encapsulando, normalmente necesitamos unos 50 bytes de información extra. Al crecer el tamaño de la trama, tendríamos dos opciones:
- Modificar la MTU de los dispositivos físicos sobre lo que estamos montando nuestra infraestructura de OpenStack, por ejemplo a 1550 bytes, y configurar el componente de red de openstack neutron, para trabajar con redes virtuales de 1500 bytes.
- No realizar modificación sobre los dispositivos físicos de nuestra infraestructura, y configurar neutron para trabajar con una mtu de 1450 bytes. En este caso las instancias que se conecten a las redes virtuales se adaptarán a esta mtu y tomarán el valor de 1450 bytes.
La segunda opción es la que se realiza en una instalación de OpenStack estándar. Veamos estos datos:
$ openstack network create mi_red
+---------------------------+--------------------------------------+
| Field | Value |
+---------------------------+--------------------------------------+
...
| mtu | 1450 |
| name | mi_red |
...
Si tenemos una instancia conectada a esta red observamos que se ha configurado con este valor de mtu:
$ ip a
...
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP group default qlen 1000
...
Todo esto funciona muy bien y sin ningún problema. El problema lo encontramos cuando sobre una instancia de OpenStack instalamos algún software de virtualización de contenedores (Docker, LXC, LXD, …), en este caso los contenedores y los bridge virtuales que se crean para su interconexión se configuran con el valor estándar de mtu de 1500 bytes y nos encontramos con problemas de conectividades en el contenedor.
En este artículo vamos a repasar distintas soluciones a este problema para las distintas tecnologías de contenedores.
Configuración del mtu en contenedores Docker
Instalamos docker sobre una instancia en OpenStack y comprobamos que el bridge que se ha creado por defecto para conectar los contenedores se ha configurado con una mtu de 1500:
$ ip a
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
...
Si creamos un contenedor en esta red, podemos comprobar como, evidentemente, toma una mtu de 1500 bytes:
$ docker run -it --rm alpine ip a
...
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
Primera solución: Configuración del demonio docker
Para solucionar este problema debemos crear el fichero /etc/docker/daemon.json
con el siguiente contenido:
{
"mtu": 1450
}
Y reiniciamos el demonio de docker:
# systemctl restart docker
A partir de ahora los contenedores que creemos tomaran una mtu de 1450.
Segunda solución: Configuración de la mtu en la creación de redes docker
Otra alternativa sería a la hora de crear nuevas redes en docker configurar el valor adecuado de la mtu, para ello:
$ docker network create --opt com.docker.network.driver.mtu=1450 mi_red
Y ahora comprobamos la configuración del contenedor conectado a esta red:
$ docker run -it --rm --network mi_red alpine ip a
...
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue state UP
...
Si utilizamos docker-compose
para crear la red, tendríamos que configurar la mtu, de esta forma en el fichero docker-compose.yml
:
...
networks:
mi_red:
driver: bridge
driver_opts:
com.docker.network.driver.mtu: 1450
Configuración de la mtu en contenedores LXC
Al instalar LXC en una instancia de OpenStack, nos encontramos con el mismo problema: el bridge por defecto que se crea para conectar los contenedores LXC tiene una mtu de 1500:
$ ip a
...
2: lxcbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
...
De la misma manera comprobamos que el contenedor que hemos creado se ha configurado con esta mtu:
$ lxc-execute contenedor1 -- ip a
...
2: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
...
Primera solución: Cambiar la configuración del contenedor
Podemos configurar el contenedor para que tome el valor de la mtu que deseemos. Tenemos dos opciones:
Si queremos que todos los nuevos contenedores tengan un valor de mtu predeterminado, añadimos al fichero /etc/lxc/default.conf
la línea:
lxc.net.0.mtu = 1450
Ahora creamos un nuevo contenedor y vemos su configuración:
lxc-execute contenedor2 -- ip a
...
2: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
...
Si queremos cambiar la configuración de un contenedor que ya estaba creado tenemos que añadir la línea lxc.net.0.mtu = 1450
en su configuración, para el contedor1
sería en el fichero /var/lib/lxc/contenedor1/config
. después de reiniciar el contenedor, volvemos a probar:
lxc-execute contenedor1 -- ip a
...
2: eth0@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
...
Segunda solución: Cambiar la configuración del bridge
En esta solución no hemos cambiado la configuración de los contenedores LXC como en la primera solución. Vamos a cambiar manualmente el valor de la mtu para el bridge por defecto lxcbr0
. Por supuesto, si vamos a crear nuevos bridge para trabajar con nuestros contenedores tendríamos que crearlos con el valor mtu adecuado.
Para cambiar la mtu del bridge lxcbr0
ejecutamos:
ip link set dev lxcbr0 mtu 1450
Ahora los contenedores que se conecten a este puente tomarán la misma mtu:
$ lxc-execute contenedor3 -- ip a
...
2: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
...
Configuración del mtu en contenedores LXD
Al instalar LXD en nuestra instancia se ha creado un bridge donde se van a conectar los contenedores, que tiene una configuración de mtu de 1500 bytes:
$ ip a
...
32: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
En este caso vamos a cambiar la configuración de la red para cambiar el valor de la mtu:
$ lxc network set lxdbr0 bridge.mtu=1450
Y podemos comprobar que los contenedores creados conectados a esta red han tomado el valor adecuado de mtu:
$ lxc exec contenedor4 -- ip a
...
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
Conclusiones
Si alguien le viene bien lo aquí expuesto, me alegro. Pero, como casi siempre esta entrada esta dedicada a mis alumnos de 2º de ASIR, que se estrujan la cabeza para que las prácticas les salgan lo mejor posible. Va por ellos.
Curso: Introducción a Proxmox VE
En estos últimos meses hemos desarrollado y tutorizado (junto a Manuel Domínguez (@Mafradoti) dos ediciones de un curso sobre Proxmox. El curso ha sido elaborado para el CEP de Castilleja de la Cuesta (Sevilla) y los destinatario han sido profesores de secundaria de la familia de informática de Andalucía.
Desde hace varios años se ha ido extendiendo el uso de la virtualización como técnica que nos permite aumentar el rendimiento de los equipos informáticos. De esta manera el trabajo con máquinas virtuales, y más recientemente el uso de contenedores, han facilitado la gestión de las aplicaciones y servicios ofrecidos por un equipo informático.
El concepto de virtualización hace referencia a una tecnología que permite la ejecución de varias máquinas virtuales sobre una máquina física con el objetivo de aprovechar al máximo los recursos de un sistema y que su rendimiento sea mayor. Esto nos ofrece la posibilidad de crear instancias con distintos sistemas operativos en un único servidor, utilizando así menos equipos para ejecutar una mayor cantidad de aplicaciones.
Desde el punto de vista educativo, el uso de la virtualización ha cambiado la forma de impartir los contenidos de los curriculum de los módulos de los ciclos formativos de la familia de informática. Podemos señalar varias ventajas que nos aporta su uso: los alumnos tienen una plataforma donde crear diferentes escenarios, obtener máquinas de una forma ágil, tener escenarios reproducibles, probar nuevos sistemas operativos, …
En este curso conoceremos las principales características de Proxmox VE. Esta aplicación nos proporciona la gestión de máquinas virtuales y contenedores de una forma sencilla y centralizada en un servidor o grupo de servidores. De esta manera, gestionamos recursos virtualizados en un servidor, con lo que obtenemos la independencia de usar los equipos de los alumnos y nos ofrece un servicio centralizado para la gestión de la virtualización. Los contenidos del curso han sido:
- Introducción a la virtualización con Proxmox VE
- Instalación de Proxmox VE
- Creación de máquinas virtuales
- Gestionando el almacenamiento
- Clonación, instantáneas y copias de seguridad
- Trabajando con Linux Containers
- Introducción a las redes en Proxmox
- Gestión de usuarios en Proxmox VE
Trabajando con claves ssh
En el trabajo cotidiano de los administradores de sistemas una de las tarea que se hace a menudo es la conexión remota a servidores usando el protocolo ssh. Además de la posibilidad de usar nombre de usuario y contraseña para autentificarnos en la máquina remota, en este post vamos a estudiar otra manera de autentificación que nos proporciona ssh: Autentificación usando claves ssh.
Como casi siempre, escribo este artículo para mis alumnos, en esta ocasión, para mis alumnos de 2º del ciclo de grado medio de Sistemas Microinformáticos y Redes. Vamos a ello:
Entorno de trabajo
Vamos a trabajar con dos máquinas donde hemos instalado el sistema operativo Debian 11:
- nodo1: Actuará de cliente, desde donde nos vamos a conectar. Tiene la dirección IP
10.0.0.10
y hemos creado un usuario que hemos llamado usuario1. - nodo2: Actuará como servidor ssh, es la máquina a la que nos vamos a conectar. Tiene la dirección IP
10.0.0.11
y hemos creado un usuario que hemos llamado usuario2.
Por lo tanto nos vamos a conectar desde la máquina nodo1
con el usuario usuario1
a la máquina nodo2
con el usuario2
.
Creación de las claves ssh en el cliente
En la máquina cliente nodo1
, el usuario1
va a crear sus claves ssh, en concreto, un par de claves pública/privada cifradas con el algoritmo RSA. Para generar las claves vamos a usar el comando ssh-keygen
y durante la generación se nos solicita alguna información:
- La ubicación y el nombre de las claves: En principio el directorio donde se guarda es
.ssh
en el home del usuario, y el nombre puede ser cualquiera, pero para empezar os sugiero que dejéis el que viene por defectoid_rsa
, de esta manera no habrá que indicar el nombre de la clave al realizar la conexión (se toma el nombreid_rsa
por defecto). Por lo tanto en la primera pregunta dejamos los valores por defecto. - Frase de paso (passphrase): Se nos pide a continuación una palabra de paso. Por seguridad, os sugiero que la pongáis porque será la contraseña de vuestra clave privada. Al utilizar la clave privada se os pedirá la frase de paso. Si vuestra clave privada cae en malas manos necesitarán esta frase para poder usarla.
usuario1@nodo1:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/usuario1/.ssh/id_rsa):
Created directory '/home/usuario1/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/usuario1/.ssh/id_rsa
Your public key has been saved in /home/usuario1/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:FfyzzFqODXZi+sFeLei+1ILURDTmzHwt8khSUvj+TjY usuario1@nodo1
The key's randomart image is:
+---[RSA 3072]----+
| .=O |
| .X.o . |
| ..X.o . |
| *.=o. |
| S.oo.o |
| . o*o*. |
| .+*@E . |
| .+o*+o |
| o*o. |
+----[SHA256]-----+
Si hacemos ahora un listado de los ficheros del directorio ~/.ssh
, aparecerán los ficheros:
usuario@cliente:~$ ls -l ~/.ssh/
usuario1@nodo1:~$ ls -al .ssh
total 16
drwx------ 2 usuario1 usuario1 4096 Jan 24 16:04 .
drwxr-xr-x 3 usuario1 usuario1 4096 Jan 24 16:02 ..
-rw------- 1 usuario1 usuario1 2655 Jan 24 16:04 id_rsa
-rw-r--r-- 1 usuario1 usuario1 568 Jan 24 16:04 id_rsa.pub
...
id_rsa
es la clave privada del usuario adecuadamente protegida (permisos 0600). No la pierdas, esta clave te identifica. ¡Guárdala bien!.id_rsa.pub
es la clave pública del usuario.
Configuración del servidor
Para que con nuestra clave privada podamos autentificarnos al conectarnos con ssh con el servidor, tenemos que copiar nuestra clave pública en el servidor. Copiaremos el contenido de la clave pública en el fichero ~/.ssh/authorized_keys
del usuario del servidor con el que vamos a realizar la conexión.
Para realizar esta copia vamos a usar la instrucción ssh-copy-id
desde el cliente, indicando la clave pública que vamos a copiar:
usuario1@nodo1:~$ ssh-copy-id -i .ssh/id_rsa.pub usuario2@10.0.0.11
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
usuario2@10.0.0.11's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'usuario2@10.0.0.11'"
and check to make sure that only the key(s) you wanted were added.
Ahora podemos comprobar en el servidor que en el home del usuario2
se ha creado un fichero .ssh/authorized_keys
con el contenido de la clave pública del usuario1
del cliente:
usuario2@nodo2:~$ ls -al .ssh
total 12
drwx------ 2 usuario2 usuario2 4096 Jan 24 16:26 .
drwxr-xr-x 3 usuario2 usuario2 4096 Jan 24 16:26 ..
-rw------- 1 usuario2 usuario2 568 Jan 24 16:26 authorized_keys
usuario2@nodo2:~$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC9WwLHgn7oJxGOyc7zCfEg+FFF/mL0pSkGsLHHb6wC+hvV4BDGBTfNrXEnDQvlLt+FmZ9Fv4fvFgfILbg2+ZEyMIuDDz1zcK8kJp5hcUQPksfAdVJGDLAdoj77qkKeb6uEZ6765aXYHh9sEY6A1hqsXitS9S007AvdYpZdd6Q4/5gwGNUlUw28fqDEoY1IjsC177yxvKXzgoL49Fl4ozf5bb6u9skugVpmzlfS3/ZRELtgCNgyxRnG3lP5Iu7NP8h9o58Eba/EHOtCUKV08UyfvDTFgPqoKiR0HntKAvqMTBsf/ZFbp99XSAkP+qli3KSBhQKIyMeqoha+n75NVY1/DTeW1uirfEVuUaQ/rBDBexib4kzj66c16AqqPIaFzV8z+UB5nZSA13I0XnkJkn/7pWcN9+4/gazH7kdGtqA0DSx7gOxw4ZrVMARK8i5QWKSeAJbfFdgHe4LEZiQ7KU/jYWltbXxNa+Xga5kpy1/UGlPvcE7k1KfGeqpqOvpju+0= usuario1@nodo1
Nota: Podríamos copiar el contenido de la clave pública del cliente al servidor de forma manual, sin utilizar el comando ssh-copy-id
. Simplemente tendríamos que copiar en el portapapeles el contenido del fichero id_rsa.pub
en el cliente y pegarlo en el fichero .ssh/authorized_keys
del servidor.
Accediendo por ssh sin contraseña
Ahora desde el cliente podremos acceder desde el usario1
(utilizando su clave privada) al usuario2
del servidor sin necesidad de introducir la contraseña de ese usuario, sin embargo como estamos usando la clave privada se nos pedirá la frase de paso:
usuario1@nodo1:~$ ssh usuario2@10.0.0.11
Enter passphrase for key '/home/usuario1/.ssh/id_rsa':
Linux nodo2 5.10.0-20-amd64 #1 SMP Debian 5.10.158-2 (2022-12-13) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Jan 24 16:26:04 2023 from 10.0.0.10
usuario2@nodo2:~$
Accediendo por ssh sin contraseña desde Gnome
Si la conexión la hacemos desde una terminal de Gnome, la primera vez aparecerá una ventana donde se nos pedirá la frase de paso, al introducirla se guardará en una aplicación llamada GNOME Keyring, que es un almacén de claves y en las próximas conexiones que hagamos en la sesión que tenemos abierta no se nos volverá a pedir la frase de paso.
Accediendo por ssh sin contraseña desde Gnome y ssh-agent
Si la conexión la hacemos desde una máquina en la que no tenemos un entorno gráfico instalado, como vimos anteriormente, cada vez que hagamos una conexión (usemos nuestra clave privada) se nos pedirá la frase de paso.
ssh-agent en un programa que almacena las claves privadas y las utiliza en cada sesión ssh que establezcamos en la sesión actual, lo ejecutamos y añadimos nuestra clave privada:
suario1@nodo1:~$ ssh-agent /bin/bash
usuario1@nodo1:~$ ssh-add .ssh/id_rsa
Enter passphrase for .ssh/id_rsa:
Identity added: .ssh/id_rsa (usuario1@nodo1)
Una vez que hemos añadido nuestra clave privada, en las próximas conexiones dentro de esta sesión, no se nos volverá a pedir la frase de paso:
usuario1@nodo1:~$ ssh usuario2@10.0.0.11
Linux nodo2 5.10.0-20-amd64 #1 SMP Debian 5.10.158-2 (2022-12-13) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Jan 24 16:30:50 2023 from 10.0.0.10
usuario2@nodo2:~$
Conclusiones
Espero que con esta entrada haya quedado claro la configuración del servidor ssh para el acceso por ssh sin contraseña, usando claves criptográficas ssh. Si en nuestro trabajo tenemos que conectar de forma remota con servidores de forma continuada, es la forma más sencilla de realizarlo. Además, aunque la autentificación con contraseña es sencilla y segura, no es válida para procesos no interactivos o para usuarios sin contraseña, es decir, siempre es necesario que haya una persona esperando la solicitud de la contraseña para escribirla y es imprescindible que el usuario del equipo remoto tenga definida una contraseña, cosa que no ocurre siempre sobre todo con usuarios vinculados a servicios o similares.
Instalación de instancias OpenStack desde imágenes ISO
De forma general cuando usamos un software que proporciona infraestructura en la nube (IaaS) como puede ser OpenStack, creamos las instancias a partir de imágenes de sistemas operativo preconfigurados. La propia filosofía de Cloud Computing, la posibilidad de obtener infraestructura bajo demanda y de una manera ágil, nos lleva a esta manera de trabajar en estos sistemas.
Sin embargo, en determinadas ocasiones, por ejemplo desde el punto de vista educativo, puede ser interesante realizar una instalación manual de una instancia a partir de una imagen ISO. En este artículo vamos a ver los pasos que tendríamos que dar en OpenStack para realizar una instalación de este tipo.
Pasos iniciales
Vamos a realizar este ejemplo utilizando el cliente de línea de comandos de Openstack (OSC), sin embargo, si estás familiarizado con el dashboard de OpenStack, los pasos también se pueden realizar desde Horizon.
En primer lugar, tenemos que tener un fichero de imagen ISO en nuestro catálogo de imágenes:
$ openstack image show "Debian 11 ISO"
...
| disk_format | iso
...
Creación de la instancia de instalación
Para realizar la instalación desde la imagen ISO vamos a realizar los siguientes pasos:
-
Creación de la instancia de instalación. OpenStack soporta el arranque de instancias utilizando imágenes ISO, por lo tanto, vamos a crear una instancia a partir de la imagen ISO:
$ openstack server create --image "Debian 11 ISO" --network "red de josedom" --flavor m1.normal instancia_instalador
La imagen
Debian 11 ISO
es la imagen ISO, además hemos indicado la red a la que se conecta y el sabor de la instancia. -
Vamos a crear un volumen que conectaremos posteriormente a la instancia como disco principal, donde se realizará la instalación del sistema operativo:
$ openstack volume create --size 5 --bootable disco_debian $ openstack server add volume instancia_instalador disco_debian --device /dev/vda
-
A continuación accedemos a una Consola de la instancia y procedemos a la instalación manual del sistema.
Hacer funcionales la instancia instalada desde la imagen ISO
Una vez terminada la instalación, la instancia que hemos creado no nos sirve para nada. Al reiniciar la instancia volverá a iniciar el instalador de Debian. Lo que realmente nos interesa es el volumen donde hemos realizado la instalación. Por lo tanto podemos borrar la instancia sin problemas:
$ openstack server delete instancia_instalador
A continuación tendremos el volumen con el sistema operativo desasociado:
$ openstack volume list
...
| 2c788674-ed40-450f-a8b2-a7659a5cfba4 | disco_debian | available | 5 | ...
Y tenemos varios opciones para trabajar con él:
-
Crear una instancia a partir de este volumen. Tendríamos una instancia con el sistema operativo que acabamos de instalar, para ello:
openstack server create --flavor vol.normal \ --volume disco_debian \ --security-group default \ --network "red de josedom" \ instancia_prueba
-
Convertir el volumen en una imagen, para poder crear instancias a partir de ella. Podríamos crear distintas instancias con el sistema operativo que hemos instalado. Para ello:
openstack image create --volume disco_debian nueva_imagen_debian_11
Y podemos comprobar que hemos creado una nueva imagen desde la que podemos crear nuevas instancias:
$ openstack images list ... | 447968c9-c2d6-4ad7-8526-d3fc4be26325 | nueva_imagen_debian_11 | active | ...
Conclusiones
En determinados escenarios, por ejemplo si tenemos algún sistema operativo que no tengamos una imagen preconfigurada para OpenStack, o en entornos educativos, como indicábamos anteriormente, la posibilidad de arrancar una instancia en OpenStack a partir de una imagen ISO nos brinda la posibilidad de realizar una instalación personalizada de nuestros sistemas.
Como siempre para seguir profundizando podemos estudiar la documentación oficial de OpenStack: Launch an instance using ISO image.
Hello Minikube
Hello Minikube es un tutorial de iniciación sobre el uso básico de Kubernetes. ¿Por qué escribo un artículo en Pledin sobre este tutorial? Porque desde la página del tutorial podemos ejecutar un clúster de minikube en una máquina remota y podemos gestionarlo desde un terminal desde la propia página web.
minikube es un software que crea un clúster de Kubernetes en una máquina virtual o en un contenedor Docker con un propósito educativo y permitirnos hacer pruebas del orquestador de contenedores Kuberentes.
Katacoda es una plataforma perteneciente a O’Reilly y que proporciona entornos operativos de diferentes tecnologías con un propósito formativo y que nos ofrece en el tutorial Hello Minikube la posibilidad de ejecutar en una máquina remota un clúster de Kubernetes usando minikube.
Para ello, tan sólo tenemos que pulsar sobre el botón Launch Terminal en la página de Hello Minikube:
Uso de minikube en “Hello Minikube”
Una vez hemos pulsado el el botón de creación del terminal, nos aparece una ventana en la parte inferior, donde vemos el proceso de la instalación de minikube:
Por ejemplo si queremos acceder al dashboard de Kubernetes, tenemos que ejecutar minikube dashboard
y acceder al puerto 30000
del host, para ello accedemos a la pestaña Preview Port 30000:
Y accedemos a la página web donde gestionamos Kubernetes desde su dashboard:
Tutorial “Hello Minikube”
Vamos a seguir los pasos del ejercicio que nos propone el tutorial Hello Minikube. Creamos un Deployment a partir de una imagen docker de ejemplo:
kubectl create deployment hello-node --image=registry.k8s.io/echoserver:1.4
A continuación, creamos un Service de tipo LoadBalancer:
kubectl expose deployment hello-node --type=LoadBalancer --port=8080
Para los proveedores Cloud que soportan balanceadores de carga, una dirección IP externa será provisionada para acceder al servicio, para el Minikube proporcionado por Katacoda que estamos usando nos interesa el puerto que ha asignado al Service y que hará la redirección al puerto 8080
donde está respondiendo la aplicación, en nuestro caso es el puerto 31251.
Ahora, hacemos clic sobre el símbolo +, y luego en Select port to view on Host 1, en la página que nos sale tenemos que poner el puerto que se ha asignado al servicio:
Y al pulsar sobre el botón Display Port se accederá a la aplicación:
Habilitar extensiones en Minikube
Podemos habilitar y deshabilitar las extensiones de minikube. Por ejemplo, para ver las extensiones, ejecutamos:
minikube addons list
Si queremos habilitar la extensión que nos aporta las métricas de recursos, podemos ejecutar:
minikube addons enable metrics-server
Y para ver los recursos que se han creado:
kubectl get pod,svc -n kube-system
Desplegando una aplicación guardada en un repositorio GitHub
En la máquina virtual que se crea, tenemos muchas herramientas instaladas, por ejemplo git
, esto nos ofrece la posibilidad de clonar cualquier repositorio que tengamos y poder trabajar con los manifiestos YAML de Kubernetes que nos permiten el despliegue de una aplicación.
Por ejemplo, voy a trabajar con el repositorio https://github.com/josedom24/example-hello-minikube
, donde tenemos un fichero YAML para crear un despliegue usando la imagen paulbouwer/hello-kubernetes:1
que crea una aplicación en node.js que muestra un mensaje Hello world! y alguna otra información. Para más información sobre esta imagen, puedes estudiar el repositorio de la aplicación y el repositorio en Docker Hub.
Vamos a clonar el repositorio y creamos los recursos a a partir de los ficheros YAML:
git clone https://github.com/josedom24/example-hello-minikube.git
cd example-hello-minikube/
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Podemos ver los recursos creados, ejecutando kubectl get all
:
Y para acceder, pulsamos sobre el símbolo +, y luego en Select port to view on Host 1, en la página que nos sale ponemos el puerto que han asignado al servicio, en este ejmplo el 30025 y pulsando sobre el botón Display Port, accedemos a la aplicación:
Conclusiones
Si tienes que hacer alguna prueba con Kubernetes y no tienes tu ordenador personal a mamo, puedes usar esta instalación de minikube totalmente operativa y online. Un saludo a todos.
Introducción a OpenShift v4
OpenShift v4 es una plataforma de contenedores desarrollada por RedHat y de código abierto basada en Kubernetes que proporciona una solución completa de orquestación de contenedores y servicios de aplicaciones para desarrolladores y equipos de operaciones.
Por lo tanto nos ofrece muchas de las ventajas de usar un orquestador de contenedores como Kubernetes:
- Desplegar aplicaciones de forma muy sencilla.
- Tolerancia a fallos.
- Escalalabilidad de las aplicaciones.
- Actualizaciones automáticas de las aplicaciones.
- Permite limitar los recursos a utilizar.
- Enrutamiento a nuestras aplicaciones.
- Uso de volúmenes para guardar la información.
- …
Pero lo más importante, es que podemos considerar OpenShift como una plataforma PaaS, que permite a los desarrolladores centrarse en el desarrollo del código, para que posteriormente de una manera muy sencilla y automática sean capaces de desplegar sus aplicaciones en contenedores y con las ventajas que obtenemos de tenerlos gestionados por Kubernetes.
¿Qué aspectos caracterizan a OpenShift para considerarlo una plataforma PaaS?
- No es necesario diseñar la definición YAML de los recursos de kubernetes que vamos a gestionar.
- Tenemos a nuestra disposición herramientas de despliegue de aplicaciones que crean y gestionan los recursos kubernetes por nosotros.
- Tiene procesos de construcción automática de imágenes de contenedores.
- Nos simplifica el ciclo de vida de implantación de nuestras aplicaciones.
- Es muy fácil de implementar un despliegue continúo que haga que una modificación del código conlleve, de forma automática, el despliegue de una nueva versión de la aplicación.
- Permite la integración con herramienta de IC/DC, que nos facilita la gestión del ciclo de vida de la aplicación.
- Nos permite de forma sencilla desplegar aplicaciones en distintos entornos: Desarrollo, Pruebas, Producción,…
- Tenemos a nuestra disposición distintas herramientas de métrica y monitorización.
- Despliegue sencillo de aplicación con el uso de Plantillas.
- Tenemos varios mecanismos para interactuar con OpenShift: entorno web, cliente de línea de comandos o uso de la API.
- Se integra con muchas herramientas de ecosistema de Kubernetes que nos ofrecen distintas funcionalidades: Tekton (integración y despliegue continuo), Knative (aplicaciones Serverless), Helm (despliegue y gestión del ciclo de vida de aplicaciones),…
Red Hat OpenShift Dedicated Developer Sandbox
La versión Developer Sandbox de OpenShift Dedicated nos permite probar OpenShift v4 en una plataforma con las siguientes características:
- Accedemos a un clúster de OpenShift administrado por Red Hat. Tenemos a nuestra disposición un proyecto para trabajar con un usuario sin privilegios.
- El uso de esta plataforma no tiene ningún coste (no hace falta introducir la tarjeta de crédito para darte de alta).
- Para acceder a la plataforma es necesario tener una cuenta en el portal de Red Hat y es necesario validar tu número de teléfono.
- El periodo de uso es de un mes. Una vez terminada la prueba se borrará el proyecto, pero siempre puedes volver a crear uno nuevo para tener otro mes de prueba.
- Nos ofrece la mayoría de las funcionalidades de OpenShift. Aunque como es administrada por Red Hat, si falta alguna funcionalidad no podemos instalarla.
- La cuota de recursos que podemos usar en nuestro proyecto es de 7 GB RAM, y 15 GB de almacenamiento.
- La idea es que no se utilice esta plataforma como entorno de producción, por lo que las aplicaciones se paran a las 12 horas de su creación. Aunque siempre podemos volver a activarlas.
- La plataforma está implementada sobre un clúster de instancias de AWS. En este caso, cuando trabajemos con el almacenamiento tendremos a nuestra disposición los medios de almacenamiento que ofrece el proveedor: AWS Elastic Block Store (EBS).
- Al usar un usuario sin privilegios, no tendremos acceso a algunos recursos: la gestión de proyectos, los nodos del clúster, los volúmenes de almacenamiento,…
Acceso a Red Hat OpenShift Dedicated Developer Sandbox
Visión general de la consola web
Podemos usar la consola web (aplicación web) para interactuar con el clúster de OpenShift y nos permite gestionar todos los recursos del clúster. La consola web, nos permite trabajar con ella usando dos vistas distintas: la de Administrador y la de Desarrollador.
Consola web: vista Developer
En la vista Developer, los usuarios tienen acceso a herramientas para desarrollar, implementar y supervisar aplicaciones en el clúster de OpenShift.
Algunas de las opciones que tenemos disponibles en esta vista son:
- +Add: Tenemos a nuestra disposición una página donde podemos escoger entre los distintos mecanismos que nos ofrece OpenShift para crear aplicaciones en el clúster: desde un repositorio Git, desde el catálogo de aplicaciones, desde imágenes de contenedores, desde ficheros YAML,…
- Topology: En este apartado vemos gráficamente los recursos que tenemos creados en el clúster y de una manera sencilla podemos acceder a ellos para su gestión.
- Observe: En este apartado tenemos las herramientas de monitorización y supervisión. Podemos ver paneles gráficos con el consumo de recursos (CPU, memoria, uso de la red,…), elegir distintas métricas, las alertas que hemos definido o los eventos que han ocurrido en el clúster.
- Search: Nos permite, de una manera sencilla, buscar los recursos que hemos creado en el clúster, pudiendo filtrar por las etiquetas.
- Build: En esta opción accedemos a los recursos Builds que hemos creado y que nos permiten la construcción automática de imágenes.
- Pipelines: Nos permite gestionar los flujos de IC/DC que hemos definido.
- Helm: Nos permite la configuración de la herramienta Helm, que nos proporciona una manera rápida y sencilla de realizar instalaciones en nuestro clúster.
- Project: Nos permite gestionar los proyectos a los que tenemos acceso.
- Desde la opción Search, podemos escoger un recurso de la API y “engancharlo” en el menú de navegación de la vista Developer, por defecto nos encontramos los recursos ConfigMaps y Secrets.
Consola web: vista Administrator
En la vista Administrator, los usuarios tienen acceso a herramientas para administrar el clúster de OpenShift y las aplicaciones que se ejecutan en él.
Al estar usando un usuario sin privilegios en Red Hat OpenShift Dedicated Developer Sandbox, algunas de las opciones no nos dan todas las funcionalidades de administración.
Algunas de las opciones que tenemos disponibles en esta vista son:
- Home: Nos da acceso a los proyectos definidos en el clúster, a la opción de búsqueda de recursos, a un explorador de los recursos de la API y a los eventos que han ocurrido en el clúster.
- Operators: Los operadores nos permiten añadir funcionalidades a nuestro clúster. En el caso del uso de Red Hat OpenShift Dedicated Developer Sandbox, al ser un clúster administrado por Red Hat, no tenemos permisos para añadir nuevos operadores.
- Workloads: Nos permite la gestión de los recursos de la API relacionados con el despliegue de aplicaciones: Deployment, ReplicaSet, Pod, …
- Serverless: Nos proporciona la posibilidad de gestionar las aplicaciones que hemos desplegado como Serverless, que nos permite desplegar aplicaciones sin tener que preocuparse por el número de réplicas en ejecución. En lugar de utilizar réplicas, la aplicación se ejecuta en un pod autoscaling que se adapta automáticamente según la demanda.
- Networking: Nos permite la gestión de todos los recursos de la API que nos permiten el acceso a las aplicaciones: Service, Routes,…
- Storage: Nos da acceso a la gestión de los recursos relacionados con el almacenamiento: PersistentVolumeClaim, PersitentVolume,…
- Build: En esta opción accedemos a los recursos Builds que hemos creado y que nos permiten la construcción automática de imágenes. Nos ofrece más opciones que en la vista Developer.
- Pipelines: Nos permite acceder a los flujos de IC/DC que hemos definido. Nos ofrece más opciones que en la vista Developer.
- User Management: Gestión de los usuarios del clúster.
- Administration: Configuración general del clúster.
Instalación del CLI de OpenShift: oc
La herramienta oc
nos permite gestionar los recursos de nuestro clúster de OpenShift desde la línea de comandos.
Para más información de esta herramienta puedes acceder a la documentación oficial.
Tenemos varios métodos de instalación de esta herramienta, nosotros vamos a hacerlo desde la consola web de OpenShift.
Instalación de oc desde la consola web
Accedemos a la consola web y escogemos el icono de ayuda en la parte superior derecha, y posteriormente elegimos la opción Command Line Tools:
Nos aparecerá una página donde podremos descargarnos las distintas versiones de la herramienta, en mi caso he escogido la versión Linux x86_64.
Nos descargamos un fichero comprimido oc.tar
, lo descomprimimos y lo copiamos con permisos de ejecución en un directorio del PATH:
tar xvf oc.tar
sudo install oc /usr/local/bin
Y comprobamos la versión que hemos instalado:
oc version
Client Version: 4.12.0-202303081116.p0.g846602e.assembly.stream-846602e
Kustomize Version: v4.5.7
Si ejecutamos cualquier comando con la herramienta oc
nos recuerda que nos tenemos que loguear:
oc get deploy
error: You must be logged in to the server (Unauthorized)
Configuración de oc para el Developer Sandbox
Una vez que tenemos instalado la herramienta oc
, el siguiente paso el realizar el login en nuestro clúster. En el caso de Red Hat OpenShift Dedicated Developer Sandbox, la autentificación se hace por medio de un token.
Para obtener este token accedemos al menú que aparece al pulsar sobre nuestro nombre de usuario (parte superior derecha), eligiendo la opción Copy login command:
Copiamos la instrucción de login:
Y la ejecutamos:
oc login --token=sha256~xxxxxxxxxxxxx... --server=https://api.sandbox-m3.1530.p1.openshiftapps.com:6443
Logged into "https://api.sandbox-m3.1530.p1.openshiftapps.com:6443" as "josedom24" using the token provided.
You have one project on this server: "josedom24-dev"
Using project "josedom24-dev".
Como vemos, hemos accedido con el usuario y estamos usando un proyecto, que en mi caso se llama josedom24-dev
.
Al igual que en kubernetes, la configuración de acceso se guarda en el fichero ~/.kube/config
:
apiVersion: v1
clusters:
- cluster:
server: https://api.sandbox-m3.1530.p1.openshiftapps.com:6443
name: api-sandbox-m3-1530-p1-openshiftapps-com:6443
contexts:
- context:
cluster: api-sandbox-m3-1530-p1-openshiftapps-com:6443
namespace: josedom24-dev
user: josedom24/api-sandbox-m3-1530-p1-openshiftapps-com:6443
name: josedom24-dev/api-sandbox-m3-1530-p1-openshiftapps-com:6443/josedom24
current-context: josedom24-dev/api-sandbox-m3-1530-p1-openshiftapps-com:6443/josedom24
kind: Config
preferences: {}
users:
- name: josedom24/api-sandbox-m3-1530-p1-openshiftapps-com:6443
user:
token: sha256~UDgHaWXrosaNOAJEFxjhqZMPgH8ksbREvd8LZ_7mFYw
Donde vemos que se ha creado un contexto, donde se guarda el servidor al que nos conectamos (cluster
), el namespace o proyecto que estamos usando (namespace
) y el usuario (user
). Como hemos indicado el usuario utiliza el token para autentificarse sobre el clúster.
Esta operación habrá que repetirla cada vez que el token se caduque.
Como hemos indicado anteriormente el proyecto que estamos usando se corresponde con un recurso namespace
que nos permite agrupar todos nuestros recursos. Con el usuario que usamos tenemos acceso a nuestro proyecto, pero no podemos acceder a los recurso namespaces
que están definidos en el clúster:
oc get project
NAME DISPLAY NAME STATUS
josedom24-dev josedom24-dev Active
oc get namespace
Error from server (Forbidden): namespaces is forbidden: User "josedom24" cannot list resource "namespaces" in API group "" at the cluster scope
Terminal desde la consola web
Si pulsamos sobre el siguiente icono en la parte superior derecha de la consola web:
Nos permitirá abrir eun terminal en la consola web:
Debemos indicar el proyecto donde se creará un recurso DevWorkspace donde se creará un Deployment que creará un Pod donde se ejecutará el terminal que estamos usando:
Visión general del proyecto de trabajo
Un proyecto permite a OpenShift agrupar distintos recursos. Es similar al recurso namespace de Kubernetes, pero guarda información adicional.
De hecho, cada vez que se crea un nuevo proyecto, se crea un recursos namespace con el mismo nombre.
En Red Hat OpenShift Dedicated Developer Sandbox, no podemos crear nuevos proyectos y se nos asigna de forma automática un proyecto con el mismo nombre que el de nuestro usuario.
Para acceder a la información de nuestro proyecto, en la Vista Administrator, escogemos la opción Home -> Projects:
Si pulsamos sobre el nombre del proyecto, obtendremos los detalles del mismo: definición, inventario, uso de recursos, métricas, cuotas, eventos,…
Tenemos varias opciones:
- Details: Detalles de la definición del proyecto.
- YAML: Definición YAML del recurso proyecto.
- Workloads: Acceso a todos los recursos definidos en este proyecto.
- RoleBindings: Permisos definidos para este proyecto.
Conclusiones
En esta entrada hemos estudiado las características fundamentales de la plataforma OpenShift v4. Hemos visto los dos métodos fundamentales de interactuar con ella: la consola web y la herramienta de línea de comandos oc. En el próximo articulo veremos algunos ejemplos ppara enseñar como desplegar aplicaciones en contenedores usando OpenShift v4.