El desarrollo de software se parece a esos trabajos grupales de colegio, en que cada compañero hace su parte en su casa y luego lo juntan en la escuela, pero al juntarlo no queda tan bien, queda una cosa rara. En el mundo de la programación es similar porque cada programador hace su parte “en su casa”. Es decir, en su propia computadora, pero luego tiene que “salir de su casa” y juntarse con el trabajo de otros programadores. Algunas cosas pueden no funcionar, algunas cosas pueden romperse, aunque en tu máquina funcionaba y eso es una frase común de programadores.
¿Y por qué en tu máquina funciona y en otro lado no? Básicamente, porque cada computadora no es igual. Hay diferentes dependencias, diferentes librerías instaladas y diferentes configuraciones. Entonces, necesitaríamos que todas las computadoras por las que vaya pasando el software en su ciclo de vida, tengan exactamente las mismas configuraciones y las mismas dependencias instaladas, pero eso es imposible. Entonces, ¿cómo solucionamos este problema para que el software pueda seguir avanzando sin que se rompa en ningún lugar? En este blog lo vas a aprender.
Si estás leyendo este blog, es porque te interesa todo el mundo del desarrollo del software. Tal vez ya eres un programador, que quiere reforzar algunos conocimientos, o quizás eres una persona que quiere convertirse en programador. Para ayudarte con eso, está EDteam. Tenemos cientos de cursos que te ayudarán a dominar las tecnologías más demandadas del mercado. Entra en ed.team/cursos y comienza cualquiera de nuestros cursos, completamente gratis. Porque en español, #NadieExplicaMejor que EDteam.
Ciclo de vida del software
El ciclo de vida del software pasa por varias etapas. Tenemos la etapa de desarrollo, que es la etapa local, en que cada desarrollador programa en su computadora. Luego viene la etapa de integración, donde hay que juntar el trabajo de varios programadores, sigue la etapa de test y la etapa de producción. Dependiendo de la compañía, pueden añadir más capas y más entornos en el medio de este proceso.
Entonces, el software se está moviendo y no está en un solo entorno. ¿Cómo garantizamos que el software pueda funcionar en diferentes entornos? La solución ideal sería que todos estos entornos sean espejo. Es decir, que sean absolutamente idénticos, pero eso es prácticamente imposible, porque un programador puede estar trabajando en más de un proyecto y no necesariamente va a tener las mismas cosas instaladas que el otro programador, o que el servidor de pruebas. Le tocaría tener una computadora diferente por cada proyecto y aun así, es bastante complicado porque habría que restringirle que actualice dependencias o que actualice librerías. Es un dolor de cabeza.
Esto lo podríamos resolver con las famosas máquinas virtuales, que si no sabes que son, básicamente es un entorno en el que se virtualiza un sistema operativo y un hardware. Del hardware físico de la computadora, se extrae: un pedazo del procesador, de memoria RAM, de disco duro, y se instala un sistema operativo. Al sistema operativo le hacemos creer que está en un hardware real, pero en realidad está virtualizado. Esa es la base de la nube. Todo el Cloud Computing funciona sobre máquinas virtuales y eso está perfecto.
Sin embargo, a nivel de desarrollo, de los programadores echando código, las máquinas virtuales son bastante pesadas porque consumen bastantes recursos. Tú no necesitas todo el sistema operativo: todo un Linux, todo un Windows, todo un macOS para una simple aplicación. Lo que necesitas es algo llamado contenedores.
¿Qué son las máquinas virtuales?
Los contenedores, como su nombre lo dice, contienen todo lo que necesita una aplicación para funcionar y nada más que eso. Pero profundicemos un poco más. Los contenedores son un entorno de ejecución para un software que contiene todas las dependencias que necesita este software, pero lo interesante, es que es un paquete aislado del sistema. Es decir, en un contenedor podrías tener una versión de Python, y en otro contenedor, otra versión de Python; en un contenedor, una versión de MySQL, y en otro contenedor, otra versión de MySQL, y lo más espectacular: no tienen conflictos entre ellos.
No tienes que estar cambiando de versión, sino que los contenedores pueden convivir en el mismo sistema operativo sin hacer conflictos porque todo lo que está dentro, está completamente aislado. Por eso se le llama contenedores, porque es una metáfora de los contenedores en los que se transportan mercaderías en los barcos, donde hay una enorme caja de metal y todo lo que está dentro, se encuentra completamente aislado. Entonces, los contenedores son así: todo está aislado y pueden convivir varios en el mismo sistema operativo. Con lo cual, se resuelve el problema de “en mi máquina sí funciona”, porque ese contenedor, es el que se replica en los diferentes entornos. Entonces, el programador A, tiene una réplica de ese contenedor, el programador B tiene otra réplica de ese contenedor, el programador C otra réplica, en el servidor de integración hay una réplica, en el servidor de pruebas también.
Entonces, la diferencia principal frente a una máquina virtual, es que la máquina virtual carga todo el sistema operativo, mientras que un contenedor solamente necesita el Kernel del sistema operativo. Es decir, el núcleo, no necesita ningún otro componente, así que es muy liviano, consume pocos recursos y es rápido de trabajar.
Los contenedores comenzaron en Linux a partir de un concepto llamado name spaces (o espacios de nombre), lo que hacen, es que un conjunto de aplicaciones tenga acceso a un conjunto específico de recursos del sistema. De tal manera, que cada conjunto de procesos no interfiera con los recursos que está usando otro proceso. Luego de los name spaces, se crea otro concepto llamado C groups (o grupos de control), que lo que hacen es permitirte administrar el uso de recursos de determinados procesos y también el acceso (o los permisos) a ellos.
Utilizando estos conceptos, de name spaces y C groups, que lo que hacen es aislar procesos del sistema operativo, en el año 2008 se crea LXC, que es el motor de contenedores de Linux. Es decir, ya estamos en el concepto de contenedores, ya no de procesos del sistema operativo para su propio funcionamiento, sino de un entorno para desarrollar. Es decir, para crear nuevas aplicaciones, pero utilizando estas ventajas del aislamiento.
¿Qué es Docker?
Docker es un gestor de contenedores, es el más utilizado en el mundo, y empezó en el año 2013 utilizando este motor del que te acabo de hablar LXC, de Linux. Sin embargo, en el año 2014, ellos crean su propio motor de contenedores, llamado Libcontainer, y que está escrito en Go. Por cierto, recuerda que puedes Linux y Go en EDteam.
Entonces, lo que hace Docker, es simplificar la gestión de los contenedores porque el concepto de contenedores, ya existía mucho antes de Docker. Sin embargo, con Docker, todo se simplifica, porque todo comienza a partir de un Docker file. De hecho, el trabajo con Docker tiene tres etapas:
- Docker file.
- Docker image.
- Docker container.
El docker file es un documento de texto que contiene todos los comandos e instrucciones para instalar todas las dependencias de una aplicación. Es como un manual. Con ese Docker file, con ese manual, se crea una imagen de Docker, que básicamente es un ejecutable que ya contiene todas esas dependencias y el software que vamos a correr. A partir de esa imagen de Docker, es que se pueden crear los contenedores. Si entiendes el concepto de programación orientada a objetos, podemos decir que la imagen es la clase y los contenedores, son los objetos. Es decir, la instanciación de esta imagen. Y si todavía no comprendes este concepto, tenemos la mejor explicación de la programación orientada a objetos en español, en nuestro canal de Youtube.
Y como te decía, a partir de la imagen de Docker, es que se crean los contenedores. Digamos que el contenedor es la imagen ya funcionando, es decir, que ya puedes programar directamente en ese contenedor. Y puesto que las imágenes se crean a partir de un Docker file, que es un documento de texto, podemos llevar el registro de versiones utilizando Git. De hecho, esto se llama registro de Docker. Con eso, garantizamos que estamos en la versión correcta y que todos nuestros programadores tienen la versión correcta del contenedor en sus entornos. Ya sean entornos de pruebas, entornos de integración, entorno de producción, entre otros. De esta forma, ya nunca estarás con el dilema “en mi máquina funciona, ¿por qué en la tuya no?”.
Además, existe un sitio llamado Docker hub, que como su nombre, lo dice es un hub. Es decir, es un concentrador mundial de trabajos, donde existen muchísimas imágenes de Docker que puedes utilizar en tus proyectos. Y, por supuesto, puedes aprender Docker en EDteam.
¿Qué son los Microservicios?
Y, si has escuchado hablar de Docker, seguramente también oíste hablar de Kubernetes, porque estos conceptos van muy de la mano. Sin embargo, antes de explicarte este concepto, hablaremos de microservicios. Y, no te olvides que también puedes comenzar a aprender de microservicios en EDteam.
Para no ponernos muy técnicos, las aplicaciones pueden crearse de dos maneras: de forma monolítica, que significa que todas las funciones de la aplicación están en un solo paquete, o con la arquitectura de microservicios, en la cual, cada microservicios es como una mini aplicación con una función específica. Por ejemplo, en EDteam, un microservicio para los cursos, un microservicio para la facturación, un microservicio para premium, un microservicio para la gestión de usuarios, etc.
Entonces, la partimos en varios pedacitos, que luego se conectan entre ellos, se comunican, para crear toda la aplicación. Obviamente, crear una aplicación con arquitectura microservicios es más complejo que de forma monolítica, por lo que no se recomienda utilizar microservicios para aplicaciones pequeñas, pero para aplicaciones grandes (y que van a crecer más aún) es la mejor forma de trabajar. Esto de debe a que, al tener cada componente aislado en un microservicio, puedes darle mantenimiento a cada uno, sin comprometer a la aplicación completa. ¿Y qué tiene que ver eso con Docker? Es que cada microservicio es una mini aplicación, por lo tanto, cada microservicio tiene su contenedor. Entonces, se acumulan varios contenedores de Docker que tienen que empezar a comunicarse y compartir información entre ellos, así como gestionarse. Mientras más microservicios haya, más contenedores de Docker habrá y más compleja se vuelve la gestión.
Y allí es donde entra Kubernetes.
¿Qué es Kubernetes?
Es un orquestador de contenedores. La palabra orquestador ya nos dice mucho, porque se encarga de organizar y de gestionar a esos contenedores. Lo que hace Kubernetes, es ayudarnos a automatizar los procesos con los contenedores, la asignación de recursos y el despliegue. Todo esto lo hace de forma declarativa. Es decir, casi como lo que hace Docker con Docker file: simplemente un conjunto de instrucciones. Pero en el caso de Kubernetes, se llama plano de control. Es donde están todas las instrucciones que debe tener una implementación de Kubernetes. Cada implementación de Kubernetes, se llama clúster.
Kubernetes fue creado por Google a partir de un proyecto interno llamado Borg, en el año 2014. Lo que buscaba Google era optimizar el uso de los recursos de hardware porque la empresa estaba creciendo muchísimo y el uso de recursos, y el valor de estos recursos, estaba desbordando. Es por eso que se crea Kubernetes. Pero, al año siguiente, Google lo libera y se lo dona a la fundación Linux, que se encarga de su mantenimiento. También están empresas como Google o Red Hat, que son quienes más aportan a este proyecto, que actualmente es open source.
Por eso, Kubernetes está en todas las plataformas de nube, como: Azure, Google Cloud y AWS. Así que tú puedes implementar una arquitectura de Kubernetes en cualquiera de las nubes y también puedes aprender Kubernetes en EDteam.
Un detalle interesante de Kubernetes, es que viene del griego, por eso no se pronuncia Kiuvernate (o sea, agringando la palabra), sino tal cual como suena: Kubernetes. Por eso también se le dice K8, porque es más fácil de pronunciar para los que hablan inglés. Además, el nombre Kubernetes, que viene del griego, hace referencia un timón. Por eso, el timón es el logo de Kubernetes.
¿Cómo se implementa Kubernetes?
Aquí la cosa se pone más complicada, porque cada implementación, como te decía, se llama clúster, y cada clúster, tiene una arquitectura dentro. Pero permíteme que te muestre con una infografía:
En primer lugar, los clúster funcionan a través de dos tipos de nodos:
- Los nodos maestros o master node.
- Los nodos trabajadores o worker node.
Los nodos trabajadores son donde se encuentra la aplicación en realidad, y el master node, es el que se encarga de la comunicación, de la automatización, de gestionar todos los procesos y de estar siempre en funcionamiento.
Entonces, en el master node, tenemos algunos servicios. Por ejemplo*, kube-scheduler*, que es el que ejecuta tareas programadas cada cierto tiempo. kube-apiserver, que es el que se encarga de comunicar a los nodos entre ellos. El kube-control-manager, que es el que se encarga de ejecutar el clúster y también tenemos la conexión a la base de datos. Todo eso sucede en el master node.
Ahora en los worker node es donde realmente están las aplicaciones dentro de Kubernetes, y cada uno de ellos tiene un servicio llamado kubelet, que es el que se comunica con el apiserver del master node y así es que ellos se conectan. Además, en cada worker node, hay un POD. Este POD es la aplicación y dentro de ese POD, están los contenedores de Docker, que son las dependencias a esta aplicación. Así que tenemos dependencias de la aplicación, la aplicación en sí misma (que es el POD), el kubelet (que es el servicio de comunicación) y luego todos los worker node se conectan con el master node.
Ahora, esto nos permite escalar las aplicaciones de manera vertical o de manera horizontal. De manera horizontal significaría añadir más PODS según la demanda, y de manera vertical significaría añadir más clústers. Lo importante es que ya tenemos una administración mucho más ordenada de nuestros microservicios. Pero cómo ves, esto ya es tema bastante avanzado de arquitectura del software, así que si quieres dominarlo más a fondo, te invito a nuestro curso de Kubernetes en EDteam.
Y si no lo sabías, #LoAprendisteEnEDteam.