2015

Artículos y columnas publicados en 2015

Los detalles de implementación en la era de las abstracciones

Title Los detalles de implementación en la era de las abstracciones
Publication TypeMagazine Article
Year of Publication2015
AuthorsWolf G
Refereed DesignationNon-Refereed
MagazineSoftware Gurú
Issue Number47
Pagination48-49
Date Published07/2015
Type of Articlecolumn
ISSN1870-0888
Full Text

– Me llamo Gunnar, y soy programador.
– ¡Hola, Gunnar!
– Tengo que contarles hoy respecto a mi abuso de las abstracciones y de la automatización. Por aprovechar lasfacilidades de un /framework/ completo y poderoso, me he ido olvidando de las interacciones reales. Me engolosiné con un ORM que me presenta los datos como objetos, y me olvido de la realidad de su representación entidad-referencial. Mis métodos son todos cortitos y asumo que el ciclo de atención a solicitudes es corto, olvidando que dejo referencias en memoria. Hago llamadas a procedimientos remotos en proveedores SaaS y no considero que pueden fallar.
– Pero ahora estas consciente de ello. ¡Has dado el Primer Paso! ¡Ese es el camino para ser un Programador, para ser!
– Sí, pero… ¿Por dónde comienzo? Hay tantas abstracciones, tanto por reaprender. A todos lados a donde volteo a buscar, me encuentro con más abstracciones. ¡Me siento perdido! ¿Dónde quedó la simple realidad del cómputo que teníamos antes?
Sí, no hay ni cómo esconderlo: Tiene ya varias décadas que me apasionó comprender lo que pasa dentro de una computadora, cómo opera su aparente magia. Y cuando aprendí, cuando muchos de nosotros aprendimos, incluso un niño de diez años podía comprender cómo operaban ciertos procesos, si bien tal vez no a nivel electrónico, sí a partir de una visión muy cercana. Piensen, por ejemplo, en qué tan a profundidad podía un niño de los 1980s conocer a una magnífica /Commodore 64/, e incluso cuánto puede haber aprendido con una PC. Recuerdo largas horas de leer documentación, modificar binarios a mano con un editor hexadecimal para cambiar las cadenas que presentaban al usuario, buscando comprender todo lo que veía — Simplemente, porque era posible hacerlo.
Como nota al calce: Si alguno de ustedes se siente identificado con este disfrute histórico, no puedo dejar de invitarlos a una de las lecturas que más he disfrutado en los últimos meses: Un libro titulado sencillamente /«10 PRINT CHR$(205.5+RND(1)); : GOTO 10»/, y que pueden descargar gratuitamente de [http://10print.org/]. Este libro aborda muy distintos aspectos que se desprenden de la línea de BASIC que lleva por título; un análisis técnico, social, cultural, incluso artístico de esa era que a tantos nos atrapó convirtió en lo que hoy somos.
Como segunda nota al calce y recomendación literaria: El libro /«Lauren Ipsum: A story about computer science and other improbable things»/, de Carlos Bueno ([http://laurenipsum.org/]). Aprender los fundamentos del cómputo siendo aún niño definió mi vida. Este libro presenta, a través de un cuento inspirado en /Alicia en el país de las maravillas/, conceptos fundamentales de la ciencia de la computación: Problemas clásicos, estructuras de datos, conceptos fundamentales, presentados con el cuento de una niña perdida en el bosque de los árboles rojo-negros, buscando volver a casa.
Pero volviendo a nuestro tema: con el tiempo, el mundo ha ido cambiando. Y yo también. Al volverme un miembro útil a la sociedad, como les habrá pasado a ustedes también, fui eligiendo mi /nicho ecológico/: Desarrollo de aplicaciones Web y administración de sistemas. Primero, exprimiendo los detallitos que me ofrecía cada pedacito del protocolo… Aunque recuerdo muy bien una discusión con un colega: Yo era bastante reacio a emplear /frameworks/ de desarrollo precisamente porque, al automatizar las tareas repetitivas, esconden del programador su funcionamiento real, y dificultan tener verdadero control de lo que hacen, pero él me mostró las ventajas que conllevaban.
Pero bueno, acortando la historia: De desarrollar mis aplicaciones completas con el lenguaje Perl, cabalgando /a pelo/ sobre el API de Apache, me /subí al tren/ de Ruby on Rails. Y disfruté muchísimo de la libertad que me brindó esta experiencia: Una programación más limpia, orientada a objetos. Configuración por convención. Muchas muy buenas prácticas de desarrollo, y un marco de desarrollo con opiniones propias que me marcó cómo estructurar mi desarrollo. Y sí, las aplicaciones resultantes eran comprensiblemente más rápidas de desarrollar, y al tener el comportamiento base resuelto, me topé con muchos menos errores lógicos en las capas más bajas.
Pero la vida sobre un /framework/ también trae sus desencantos. En mi caso, me topé con los primeros al encontrar la cantidad de código que había que reescribir cuando Rails pasó de su versión 1 a 2, de 2 a 3… Como es de esperarse, los cambios que introducen las versiones mayores no son /compatibles hacia atrás/, y buena parte de mi código histórico iba emitiendo advertencias por usos desaconsejados — O rompiéndose por completo. Y entre más sistemas desarrollaba, menos tiempo tenía para mantenerlos a todos al día.
La respuesta de la comunidad Rails a mis cuitas es relativamente simple: Un sistema que ya está en producción no requiere ser actualizado. El programador puede /congelar/ el sistema base y las /gemas/ (bibliotecas) que emplea, y convivir fácilmente en el mismo sistema con otras aplicaciones Rails — Incluso si estas usan otras versiones de prácticamente todo en el sistema.
En ese momento, comenzó una lucha interior, entre mi Dr. Jekyll, un administrador de sistemas que prepara las cosas y, con la cabeza fría, mantiene una visión consistente y coherente del conjunto, y mi Mr. Hyde, un programador que quiere vivir al límite probando las últimas versiones del último grito de la moda, cambiando de arquitectura subyacente, abandonando a /FCGI/ por /Mongrel/, a /Mongrel/ por /Thin/, a /Thin/ por /Passenger/, incorporando a /Rack/… Y claro, encarnando a esa aberración de la que hablaremos en otra ocasión que hoy deambula libremente: el temido /DevOp/, criatura que encarna lo más obscuro tanto de desarrolladores como de administradores.
Y ojo, me centro en este aspecto porque mi Dr. Jekyll es administrador de sistemas. Pueden imaginar lo que diría uno con formación de DBA al ver el caos resultante del ORM: ¿Cómo se grea mi esquema de datos? ¿Dónde están las verificaciones de integridad? ¿Cómo se generan las consultas para cada una de las operaciones que el buen ActiveRecord realiza?
En fin, podemos recordar esa máxima de la ciencia de la computación, que he visto atribuída tanto a David Wheeler como a Butler Lampson: /Todos los problemas en la ciencia de la computación pueden resolverse/ /con un nivel adicional de indirección — A excepción del de tener/ /demasiados niveles de indirección./
Mientras esa pelea ocurría en mi /yo desarrollador/, muchos otros importantes cambios se presentaron en mi vida. Uno de ellos, me convertí en profesor en la Facultad de Ingeniería de la UNAM. Imparto una materia que siempre me emocionó: Sistemas Operativos. He disfrutado muchísimo con la preparación del material y con el dictado de las clases. En esta materia estudiamos las funciones básicas de todo sistema operativo — Comunicación entre procesos, multiplexión de recursos, organización de sistemas de archivos, gestión de memoria, etc.
Conforme estudio y repito mi material, y conforme comento al respecto con mis colegas, vuelvo a uno de los planteamientos de origen que siempre hago a mis alumnos: No espero que de mi clase salgan autores de sistemas operativos; sería un gran orgullo que así fuera, pero no es lo que la materia persigue. Una de las principales razones para estudiar esta materia es que, si no se comprenden los fundamentos de lo que estamos haciendo, nuestros programas van a resultar de muy baja calidad.
Si nos olvidamos que a fin de cuentas todo nuestro código se traduce a instrucciones de muy bajo nivel, si nos olvidamos de cuidar la eficiencia de los /cachés/ y de reducir accesos a disco, si no tenemos en cuenta el costo de cada llamada al sistema, si no consideramos la necesaria sincronización en problemas que enfrentan concurrencia… Vamos a terminar creando código lento y frágil. Vamos a terminar siendo malos desarrolladores.
Entonces bien… El motivo de esta columna no es llamar a que abandonemos las herramientas que facilitan nuestra tarea. Los /frameworks/ no únicamente son cómodos, sino que son necesarios para la realidad del desarrollo de software hoy en día. Pero debemos mantener en mente, siempre, la importancia de /comprender qué pasa/. Si hay un comportamiento dado que parece mágico, ese es el punto donde debemos revisar el código fuente del /framework/ y averiguar cómo está haciéndolo. Porque sólo de esa forma podremos sacar el provecho correcto del sistema — y escribir mejor código, que a fin de cuentas, por eso nos hacemos llamar /profesionales/.
Entonces, vestidos de investigadores privados y lupa en mano, ¡vamos a investigar implementaciones! ¡Disfruten el viaje!

AttachmentSize
gw_SG_47.pdf3.25 MB

Drupal in Debian: System Integration for Drupal

TitleDrupal in Debian: System Integration for Drupal
Publication TypeMagazine Article
Year of Publication2015
AuthorsWolf G
Refereed DesignationNon-Refereed
MagazineDrupal Watchdog
Volume5
Issue Number1
Pagination42-43
Date Published06/2015
ISSN2372-241X
KeywordsDebian, drupal, integration
URLhttps://drupalwatchdog.com/volume-5/issue-1/drupal-debian
Full Text

As far as how to install and maintain Drupal, it would seem there is no need to dig any further. Installing Drupal in any hosting provider is just a matter of decompressing a tarball, and Drush large-scale automation gives the seasoned sysadmin a wealth of administrative aides. However, when considering integration with the system as a whole, there is ample room for improvement.
Drupal cannot exist outside of a given environment. Say, the PHP version used, the way it is integrated into its host operating system, the modules for connecting to the database — And the database engine itself. Ideally, they will all make up a coherent entity, with a single, unified administrative logic. Looking at each component individually would quickly lead to madness, specially for the sysadmin, who has to keep the whole stack secure and updated.
Debian
Debian is one of the earliest Free Software distributions built around Linux1. By the time this article is printed, Debian 8 (codenamed Jessie) should have been released, with over 35,000 binary packages (that is, independent programs), and lives according to the distribution's motto, the universal operating system: It runs from the smallest embedded devices to the largest workstations, across many different hardware architectures.
System-wide integration
One of Debian's strongest merits that has made it not only exist but be a lively, energetic community with a sound technological platform and projection into the future is its policy: Despite the amount of available packages, they are all standardized: They are all configured in the same location, follow the same layout logic, and are guaranteed not to clash with one another.
But where this policy shines most is when it is applied to keeping things optimally administered: Debian provides
not just easing the installation of the system, but security support throughout the stable release cycle. As it was already stated, our Drupal installs involve quite a bit beyond just Drupal itself. So, on a just-installed system, it's just a matter of stating:
# apt-get install drupal7
And all of the necessary software (that is, an HTTP server, the PHP programming language and execution environment, a relational database engine, and the needed glue between them) will be installed. And, in order to apply all of the pending security and reliability fixes all across the system:
# apt-get update && apt-get upgrade
is all that's needed to get every component in the system up to date.
The Drupal installation is multisite-aware. This means that all of the sites Drupal will respond to are to be configured from the same location: If your host will serve both example.com and anotherexample.org, you only need to create both the /etc/drupal/7/sites/example.com and /etc/drupal/7/sites/anotherexample.org directories and put there the configuration files. All of the codebase will be shared, installed only once in the /usr/share/drupal7/ directory.
This has an interesting advantage security-wise when compared with what I have seen at most shared hosting providers: As the Drupal code belongs all to root, any attacker that manages to subvert Drupal's (or any of the installed modules') security, they will not have enough privileges to modify your site's code and will thus have a harder time leaving a backdoor or modifying your site's behavior for their interests. And even if they got a local privilege escalation exploit, finding their misdeed will be easier as Debian ships cryptographic signatures for all of its files — By simply running:
$ debsums drupal7
any file that was modified will be reported.
Handling
modules
The Drupal ecosystem is very rich on third-party code: Almost 30,000 modules and over 2,000 themes. Packaging them all for Debian is plainly unfeasible — But we have a tool, dh-make-drupal, that takes care not only to package modules and themes pointed to it, but to process dependency handling as well. This way, even having a complex, multi-site and multi-server deployment, it's easy to deliver code with all of the characteristics mentioned in the previous section.
Version stability
Just as, within Drupal, all of the related PHP and Javascript libraries are frozen prior to a release and not changed since that point to avoid breaking internal stability throughout the life cycle of a stable release, packages in Debian are frozen and do not get updated when new versions come out — But in order to keep security tracking to the level required by our users, all important fixes get backportedto the corresponding release.
As an example, Debian 7 (frozen gradually since June 2012 until its release in May 2013) shipped with Drupal 7.14. But that does not mean that it went on for its three years of life unpatched: While feature releases were not incorporated, as you can see in our public Git repository,2 all bugfix releases were.
What about Drupal 8?
Now... With all the hype set in the future, it might seem striking that throughout this article I only talked about Drupal 7. This is because Debian seeks to ship only
production-ready software — And by the time this article is being written, Drupal 8 is still in Beta. Not too long ago, we saw still internal reorganizations of its directory structure.
Once Drupal 8 is released, of course, we will take care to package it. And although Drupal 8 will not be a part of Debian 8, it will be offered through the Backports archive, following all of Debian's security and stability requirements.
Wrapping
up
Of course, I understand the workflow and tools mentioned here are not for every person and situation. Drupal developing is clearly served better by the “traditional” way of installing Drupal. However, for administering a large-scale Drupal installation, operating-system integration through Debian might be just what you need!

AttachmentSize
GW_Drupal_Watchdog.pdf635.72 KB

Los contenedores: Aislamiento, sí, pero... ¿distribución?

TitleLos contenedores: Aislamiento, sí, pero... ¿distribución?
Publication TypeMagazine Article
Year of Publication2015
AuthorsWolf G
Refereed DesignationNon-Refereed
MagazineSoftware Gurú
Issue Number48
Date Published09/2015
Type of Articlecolumn
ISSN1870-0888
Keywordscontainers, devops, virtualization
URLhttp://sg.com.mx/revista/48/los-contenedores
Full Text

Discutir acerca de mecanismos de virtualización implica cubrir una gran cantidad de tecnologías distintas. Y no me refiero con esto a diferentes proveedores que ofrecen productos con funcionalidad similar, sino que a herramientas de muy distinta naturaleza, que a veces incluso no parecen tener nada que ver entre sí.
La primera acepción que vendrá a la mente de muchos, es la virtualización asistida por hardware, donde una computadora con ciertas capacidades de hardware (disponibles en la arquitectura x86 desde hace ya diez años, y hoy presentes incluso en los CPUs de más baja gama) ejecuta un hipervisor, software específico que se ubica por debajo del sistema operativo y permite que la computadora sea compartida entre distintos sistemas operativos (o distintas instancias del mismo), aparentando ante cada uno de ellos ser una computadora independiente. Como apéndice de esta categoría entrarían los paravirtualizadores, que corren versiones de dichos sistemas operativos que saben que se ejecutarán dentro de una máquina virtual, con lo cual delegan algunos procesos al sistema anfitrión, muchas veces aumentando la estabilidad o reduciendo la penalización de velocidad.
Por otro lado, la emulación de hardware completamente distinto del sistema primario puede también considerarse virtualización. Podemos encontrarla como parte de los kits de desarrollo para dispositivos móviles, en que el código generado se compila para procesadores típicamente de arquitectura ARM, mientras que el desarrollo se efectúa sobre computadoras x86. La emulación incluso cubre a las máquinas virtuales empleadas nativamente, como la JVM (Java) o CIL (.NET): El bytecode compilado para estas arquitecturas no corre nativamente en ningún procesador, son arquitecturas diseñadas para ser siempre emuladas
Una modalidad más de virtualización es el uso de contenedores. Esta modalidad puede comprenderse mejor si se contrasta con las anteriores dónde está el engaño — O (más bonito) dónde está la magia. En vez de proveer una computadora virtual a los sistemas operativos huéspedes, los contenedores buscan proveer un sistema operativo virtual a conjuntos de programas.
¿Qué significa esto? Que a cambio de reducir la flexibilidad, esta modalidad de virtualización provee un mucho mejor rendimiento (las aplicaciones virtualizadas tienen exactamente la misma velocidad que en el hardware nativo) y menor impacto en el resto del sistema (cuando los procesos que forman parte del contenedor no tienen trabajo por realizar, su consumo de recursos es verdaderamente cero, a diferencia de un sistema virtualizado, que debe seguir pendiente a posibles eventos).
La reducción de flexibilidad referida consiste en que, dado que el núcleo del sistema operativo en ejecución es uno solo, todos los procesos que sean ejecutados empleando esta técnica deben estar compilados para la misma arquitectura y sistema operativo —esto significa que por ejemplo, en un sistema anfitrión x86 con Linux, todos los contenedores deberán ser también x86 con Linux. Esta tecnología hereda directamente de la llamada al sistema chroot(), en 1982. Claro está, a esta simple llamada se tuvieron que agregar numerosas funciones implementando una separación más limpia y completa entre los distintos espacios de nombres. Poco a poco se desarrollaron mecanismos para limitar el uso total de memoria o de CPU de cada contenedor, y aislar la vista de la red que cada uno de ellos puede tener. El primer sistema en implementar lo que hoy conocemos con contenedores fue FreeBSD, en el año 2000; dado que están construidos alrededor de la llamada chroot(), resulta natural que casi todos los sistemas operativos en implementar contenedores sean tipo Unix; en el mundo Windows, hoy en día se tiene la promesa de que la versión 10 incluirá esta característica.
En Linux hay distintas implementaciones disponibles, y que han logrado madurar cada cual a su ritmo. Durante muchos años, la más fuerte fue VServer, pero requería de cambios demasiado invasivos, que nunca fueron aceptados por Linus Torvalds para la rama principal del kernel. Posteriormente se popularizó OpenVZ, la versión libre de Virtuozzo, pero sufrió del mismo problema. Sin embargo, a partir de la incorporación de los grupos de contexto (cgroups) al kernel de Linux 2007, el proyecto Linux Containers (lxc) logró una implementación suficientemente eficaz y sencilla, y es hoy en día la más popular y consolidada.
Distribución basada en contenedores
A principios de 2013, se anunció la liberación de un innovador programa que ha cambiado en gran medida las reglas del juego para el despliegue de aplicaciones: Docker. Su principal contribución es que cambia el enfoque: presenta a cada contenedor ya no como una máquina virtual, como una instalación completa de una computadora, sino que como el entorno completo de ejecución de una aplicación. Esto tiene aspectos muy positivos, pero también tiene otros francamente dignos de cuidado. Pero antes de abordarlos, permítanme explicar un poco.
Originalmente, instalar o aprovisionar un contenedor implicaba como paso necesario la instalación del software de sistema tal como si se tratara de una computadora real. La delgada capa de virtualización de los contenedores permitían tomar a un conjunto de máquinas virtuales como si fuera una granja de servidores — Y el trabajo del administrador de sistemas es, a fin de cuentas, gestionar a cada una de las máquinas virtuales cual si fuera un servidor completo — Que si bien es mucho menos complejo que si se tratara de una sola instalación con todo el software bajo el mismo espacio, implica una innegable complejidad. El principal cambio que introduce Docker es que permite generar un contenedor por aplicación, y gestionarlo directamente como si fuera una unidad — ya no una colección de paquetes relacionados.
Bibliotecas, versiones, infiernos y apps
Demos un brinco conceptual a un tema, aparentemente, sin relación. Prometo pronto explicar a qué viene esto.
El desarrollo de los sistemas operativos que empleamos hoy en día cruzó hace unos treinta años por un punto crucial en lo concerniente a su flexibilidad: La introducción de formatos estándar de bibliotecas compartidas, que pueden ser utilizadas entre diversas aplicaciones. Gracias a ellas, el tamaño de cada uno de los programas se redujo fuertemente (puesto que éstos no tenían que incluir expresamente todas las definiciones que emplean), se estandarizaron interfaces (puesto que diversos programas aprovecharían las mismas bibliotecas ampliamente conocidas), y –muy importante– dado que redujo fuertemente la duplicación de código, mejoró significativamente la seguridad de los sistemas operativos: Ante un error o vulnerabilidad, basta con actualizar una copia del código vulnerable para que todos los programas afectados reciban la corrección.
Claro, surge complejidad del manejo de los cientos de bibliotecas compartidas que se instalan en un sistema típico, de la cual se deriva la expresión “DLL hell” (el infierno de los DLLs). Sin embargo, este es un problema en el que se ha invertido una gran cantidad de trabajo, y la situación hoy en día es radicalmente diferente a la de hace veinte años, cuando se acuñó dicho término.
Ahora bien, ante la popularización de las apps en dispositivos móviles y el abaratamiento del almacenamiento, se impuso el concepto inverso: El empaquetamiento de todas las dependencias dentro de un mismo binario. Para evitar que el usuario final tenga que descargar todas las dependencias que empleó cada desarrollador, y asegurar que cada paquete funcionará independientemente de los demás que tenga instalado el sistema, se ha optado por –de facto– reconvertir las bibliotecas dinámicas en objetos ligados estáticamente. Claro, esto obliga a que ante la actualización de una biblioteca compartida, cada una de las aplicaciones que la usa sea actualizada también — Pero en una era de conexión permanente a Internet, esta idea ha resultado del favor del mercado.
Distribución y servidores virtuales
Uniendo, pues, los dos temas expuestos: La principal contribución de Docker es que convierte el engorroso despliegue de servidores virtuales en un sencillo despliegue de aplicaciones — Y, claro está, de aplicaciones empaquetadas a la moda, con el mínimo de dependencias.
Desde una perspectiva meramente de DevOps, esto suena muy bien. Sin embargo, también involucra grandes riesgos, como lo ilustran entre otros muchos los textos que han escrito al respecto dos de los desarrolladores de Debian GNU/Linux: Joey Hess [1] y Erich Schubert [2].
En primer lugar, un uso irresponsable de Docker (aunque sea el recomendado por sus desarrolladores) nos puede llevar a confiar en software cuyo origen no necesariamente es el que esperamos, sin saber en qué consisten los cambios y cómo éstos nos afectarán. Los paquetes que dicen ser oficiales de determinadas distribuciones han demostrado haber sido alterados, lo cual debe poner a pensar mal a cualquier administrador de sistemas.
En segundo lugar, y esto me parece más complicado y peligroso aún, el modelo que impulsa Docker nos invita a olvidarnos de la seguridad que debe mantenerse como parte de la gestión de cada sistema instalado. Un contenedor no puede ser creado una única vez y visto, a partir de ese momento, como una app, como un objeto estático e independiente. Y no, cada sistema debe integrar las correcciones a las vulnerabilidades (o simples bugs) que constantemente van apareciendo y siendo corregidas, y un administrador de sistemas siempre debe estar familiarizado con la tecnología que tiene instalada. Resulta inexcusable poner al mismo nivel a un sistema operativo completo y a aplicaciones como Wordpress, pero eso es precisamente lo que ocurre [3].
Obviamente, la tecnología no es mala, y la adopción que ha tenido habla de sus virtudes técnicas. Sin embargo, el uso y crecimiento que ha tenido dejando de lado las buenas prácticas de administración de sistemas, y el impacto que esto puede tener en nuestro campo, merecen ser consideradas
Referencias
[1] “What does docker.io run -it debian sh run?”, https://joeyh.name/blog/entry/docker_run_debian/
[2] “The sad state of sysadmin in the age of containers”, http://www.vitavonni.de/blog/201503/2015031201-the-sad-state-of-sysadmin...
[3] Repositorios oficiales de Docker: https://registry.hub.docker.com/search?q=library&f=official

AttachmentSize
SG48_gwolf.pdf68.87 KB