Dev&Ops es el espacio donde hablamos de cultura tech, compartimos anécdotas reales y damos consejos prácticos para todo entusiasta del mundo del desarrollo y la tecnología. Acompáñanos a descubrir las últimas tendencias, aprender de nuestras experiencias y recibir tips que te ayudarán a destacar en este entorno digital en constante evolución.
Douglas (00:00)
los contenedores por sí solos no rompen producción. Es la mala operación de los contenedores los que terminan corriendo producción.
muchos van a decir obvio, un contenedor no se maneja solo, esto que está diciendo es muy obvio, no entiendo por qué te querés hacer el listo y lo mencionás, lo menciono porque los otros equipos, los project managers, los ejecutivos, los gerentes no entienden esto muchas veces. Los retos en los cuales yo me he enfrentado
y que he hablado con gerentes, con directores de departamentos, cuando se empieza a implementar Kubernetes, cuando se a implementar contenedores, yo escucho cosas como, estos problemas no los teníamos cuando corríamos en VMs, o esas dificultades no estaban antes cuando corríamos en VMs, porque llega a un punto de creer de que el problema es el contenedor y se combina con pensar que no tenemos la capacidad.
Hola a todos, bienvenidos a un episodio más de Dev & Ops, su podcast en español donde hablamos de desarrollo, tecnología, DevOps y lo que es su cultura en general. El día de hoy no me va a poder acompañar nuevamente mi buen amigo y co-host Juan Ramos. Digo nuevamente, aquellos que nos siguen se habrán dado cuenta que el episodio anterior también Juan no pudo estar aquí para acompañarme y para darnos su perspectiva.
a su punto de vista, el cual siempre nos aporta mucho valor y de hecho genera ese balance que tenemos aquí en Dev en OBS, él pone la parte de Dev y yo trato de aportar con la parte de OBS de operaciones y sistemas.
Y si alguien se está preguntando, el motivo por el cual Juan no puede estar hoy también es que él recientemente se convirtió en padre por segunda vez. Esta es una noticia que él hubiese preferido dar obviamente por su propia boca. Además, a él es quien le corresponde hacerlo, pero me dio la autorización para hacerles el comentario y que sepan que ese es el motivo por el cual no ha podido estar presente. Sin embargo, en medio de todo lo que
tiene que ver y todo lo que implica con convertirse en padre, aquellos que somos padres lo podemos entender perfectamente, en medio de lo que implica y las responsabilidades y el cuidado que él tiene, no está alejado de este podcast en general, siempre tenemos planificaciones, reuniones donde definimos y decidimos qué se va a hacer y qué temas se van a tratar, entonces felicitando públicamente a Juan, mi buen amigo, por convertirse en padre.
por segunda vez darle gracias a dios porque su esposa y el bebé están muy bien y con el permiso de ellos procedamos entonces a discutir el episodio de hoy y por discutir me refiero a que me escuchen hablar a mí al respecto con el tema que tenemos verdad sin la perspectiva de juan pero de nuevo vamos a intentar que esta charla tenga valor para ustedes
y es que he querido mantenerme un poco en lo que es el tema de contenedores, verdad, con...
Docker, desktop, que discutimos la semana anterior, esta semana mantenerme en el tema de contenedores, porque creo que es una área en la que yo puedo proveerles información basado en experiencia, basado en conocimiento, basado en errores que he cometido a lo largo de los años trabajando con esta tecnología. Yo que hoy quisiera mencionar algunos errores comunes usando Docker.
que normalmente rompen producción. Errores comunes, que normalmente cuando trabajamos en nuestro ambiente local no son un problema.
no generan ningún inconveniente, pero que una vez que vamos a producción vienen a hacer algo serio y terminan rompiendo producción. Y eso genera en nuestro alrededor, genera entre la nivel gerencial la mala idea de que Docker como tal no es una buena tecnología y que en lugar de solventar problemas y que aquellas cosas que dijimos y que advocamos de que los contenores iban a solventar,
en realidad lo que ha traído es más problemas y es que muchas veces cuando estamos en ese proceso de implementar contenedores por primera vez se cometen ciertos errores. Errores como cuales, la mayoría de las cosas que hacemos en nuestro ambiente local pueden ir...
Podemos tener cero cuidado por la seguridad, bueno, tal vez cero cuidado es una expresión muy fuerte, pero muy poco cuidado por la seguridad porque estoy en mi ambiente local y levanto la base de datos local y el usuario es usuario y el password es password y no hay ningún problema porque es una base de datos solo mía para desarrollo. Privilegios o el rendimiento de la aplicación en realidad no lo pruebo porque soy yo la única persona que se conecta y hace test y pruebas.
en ello, una vez que empiece a tener usuarios reales, que empieza a tener información sensitiva que es la que tenemos en producción muchas veces, es donde estos problemas vienen a surgir, vienen a reventar como normalmente lo decimos.
Cuando estamos implementando Docker por primera vez o contenedores por primera vez para ser más generalizados, suelen ocurrir estos problemas. A nivel personal, he trabajado ya en varias ocasiones en migrar aplicaciones y ambientes enteros de no solo de monolíticos, pero de VMs hacia contenedores. De hecho, con Juan, que es una lástima que no nos puede dar su perspectiva el día de hoy, pero con Juan,
he trabajado y en algunos episodios anteriores hemos mencionado un poquito al respecto, con Juan he trabajado el migrar aplicaciones y aparte implementación de microservicios en contenedores, entonces de por ahí vienen ciertas experiencias a ciertos, experiencias con otras personas, mal entendido de otras personas que a veces toca arreglar, alinear para que realmente en nuestros ambientes de producción veamos los beneficios que traen los
en lugar de que los retos, porque hay retos, cada implementación genera retos, pero queremos evitar que esos retos nos hundan y nos hagan volver a VMs, verdad, no queremos que los gerentes digan eso. Y aclarando que lo que voy a mencionar ahorita va a aplicar, no importa cómo o quieran correr contenedores en producción o que ya estén corriendo contenedores en producción.
Esto aplica si corren los contenedores o piensan correrlos en Kubernetes o si los corren o piensan correrlos en Docker Swarm. Funciona. Si lo quieren correr o lo están corriendo con Docker Compose o con Docker Run, el comando Docker Run, verdad, si lo quieren ejecutar de esa manera en producción, aplica aclarando, haciendo la aclaratoria, Y estoy obligado a hacer la aclaratoria. Docker Compose.
Y el comando Docker Run no están diseñados para producción. No deberían de utilizarse en producción. Sin embargo, voy a ser el primero que levanta la mano y admite su culpa. Yo tengo por ahí uno que otro servicio que el cual tengo corriendo en Docker Compose.
es un servidor aislado por aquí, otro servidor aislado por allá que tenga una herramienta y en lugar de instalar los paquetes locales bajo un contenedor de Docker y con Docker Compose levanto la base de datos y levanto el frontend y ya lo pongo a correr, yo soy el primero que tengo por ahí todavía dos que tres servidorcitos corriendo con Docker Compose, sin embargo no tengo ninguno con Docker Run, creo que hasta ahí no he llegado, pero aclaro
idealmente si vamos a correr en producción usemos o docker Kubernetes o docker Swarm pero si lo que usan en docker Compose o docker Run estos consejos que voy a dar el día de hoy van a aplicar. Vamos a comenzar con el primer consejo para que avancemos el primer consejo va a sonar un poquito
extraño, tal vez para muchos, pero en realidad es un reto bien grande y yo me enfrenté a este reto y es tratar los contenedores como VMs, tratar los contenedores como VMs. Les voy a contar una experiencia rapidito, he contado algo similar en el pasado, cuando estuve trabajando que fue el primer proyecto que trabajé con Juan en migrar aplicaciones de VMs a contenedores, una de las cosas que me
costó aclarar a varias personas, entre ellos gerentes de otras áreas que tienen que ver con desarrollo, era que los contenedores no son una VM. Yo recibía preguntas como, al momento de publicar, ¿cómo vamos a sacar el contenedor del clúster? Porque nosotros teníamos VMs que estaban detrás de un clúster y muchas veces al momento de publicar se sacaba la VM del clúster que no
era tráfico, se publicaba en ella y luego se metía la vm al cluster y se hacía lo mismo con las demás máquinas virtuales hasta que la publicación estaba completa. Es un proceso que los contenedores lo hacen por sí solo, van quitando uno por uno y van metiendo, pero los contenedores no son vms, verdad, o me decían si hay un error
¿Cómo voy a saber el hostname del contenedor que dio el error? ¿Cómo voy a saber cuál es el hostname? Porque, de nuevo, en nuestro monitoreo, en los logs, mirábamos el hostname de qué servidor estaba dando el error y podríamos luego conectarnos a esa VM, a ese servidor, y hacer el troubleshooting y tratar de identificar cuál es el problema. en lograr llevar a las personas a esa mentalidad,
fue retante para mi, fue retante, verdad, se logró, gracias a Dios se logró y es que aquí hay un concepto bien importante espero que la mayoría de ustedes ya lo hayan escuchado pero para aquellos que no lo hayan escuchado está el concepto de ganado versus mascota
y por qué esto es tan importante cuando se trabaja con contenedores o cuando se trabaja con administrar servidores en general, verdad? y es que es una mascota, el concepto de una mascota es algo que cuidamos personalmente, lo cuidamos de manera personal, le damos comidita de manera personal y lo acariciamos mientras le estamos dando nuestra mascota, la mascota que ustedes tengan, puede ser un perrito, puede ser un gatito.
puede ser una lagartija, un hamster, lo que ustedes decidan tener como mascota, lo cuidamos de manera personal, tiene un nombre.
le ponemos un nombre, iba a decir un nombre de ejemplo pero no quiero ofender a nadie, tal vez alguien que nos ve y nos escucha se llama de esa manera, pero llamamos a la mascota por un nombre y la tratamos con cariño y esas son características que normalmente tienen los servidores, a un servidor le asignamos una dirección IP o aunque el DHCP le asigne tiene un hostname, tiene un DNS record de manera cuidadosa, le instalamos paquetes
que usemos automatización, le instalamos paquetes y si hay un problema nos conectamos al servidor y hacemos trouble shooting y lo estamos cuidando y no queremos que se dañe, verdad, sobre todo si es el servidor la mascotita de producción menos queremos que se dañe, eso es el concepto de mascota en servidores. El concepto de ganado, el ganado son muchos, El ganado son digamos que sea un ganado vacuno, son vacas, son muchos
todos se parecen y todos tienen la misma función pero en realidad son muchos siempre se cuidan nadie está diciendo que no se cuidan sin embargo lo normal es que no tienen nombre no veo yo ahí a granjeros que tengan dos mil tres mil vaquitas
y le estén poniendo nombre a las 2.000, 3.000 vaquitas. No creo que alguien sepa el nombre de 2.000, 3.000 personas, mucho menos del ganado. Entonces tienen un cuidado, pero es general. Se pone la comida en un área para que todos lleguen a comer. Se vacunan y se cuidan de manera masiva a todos. Entonces, eso es un concepto que se aplica más a contenedores, porque en realidad un contenedor no nos preocupa.
que tenga que ser desechado, de hecho es lo esperado cuando se hace una nueva publicación el contenedor que ahorita está corriendo es desechado, es destruido por completo y uno nuevo con la misma configuración lo va a reemplazar, no me preocupa cuál es el hostname, no me preocupa que IP le asignó de manera interna, no tengo ese cuidado y realmente dejo de preocuparme por él y lo empiezo a ver como ganado que es algo que voy a estar guiando de forma masiva para que tenga
⁓ un orden, Y de hecho, yo quiero aclarar aquí que cuando, antes de que los contenedores llegaran a ser
El estándar de la industria todavía hay muchos servicios que corren en VMs. Si tenemos Redis, Cluster to Redis, pesados, Elasticsearch pesado, bases de datos, la industria normalmente sigue usando VMs para esas cosas. Pero lo que tiene que ver otro tipo de hosting, sobre todo hosting web, Application Server, Web Server, hoy en día definitivamente el estándar es más común verlo en contenedores.
pero antes de que eso, llegue a ser un estándar.
ya habían empresas grandes que trataban las VMs como ganado y no como mascota. Empresas, yo recuerdo muy bien, empresas como Walmart fueron precursores en su momento, ellos usaban POPPET, que era este Configuration Management que configuraba las VMs de forma masiva y ya ellos en sus pipelines para despliegue, realmente que un despliegue era una nueva máquina virtual y si una máquina virtual daba
errores esa máquina se sacaba del clúster de manera automática y se creaba una nueva en poco tiempo y era puesta en lugar de la anterior y la anterior o se descartaba o la usaban para troubleshooting como para evitar que eso se volviese a repetir, entonces
Estas empresas ya de hecho trataban las máquinas virtuales como de ganado y no como mascota. qué esto es importante y por qué lo menciono y por qué esto puede romper producción? Porque si queremos tratar los contenidores como VMs, lo que nos va traer son frustraciones grandes. Frustraciones grandes con el equipo, vamos a tener gerentes o ejecutivos que cuando hubo un error...
pidiendo, quiero que me den los logs del contenedor que falló o quiero que se conecten al contenedor que falló y me digan qué hay, pues ya ese contenedor ya está muerto, los logs y los configuraron, que hay que configurarlos, ahí están, pero conectarme a un contenedor que ya fue descartado, desechado, no se puede, entonces...
Si yo mismo, al momento de querer arquitectar la aplicación, la solución que estoy haciendo, quiero ver los contenedores como VMs, voy a generar arquitecturas, voy a generar soluciones que no van a dar el ancho porque los contenedores no son VMs, no son mascotas, los contenedores son ganados y deben verse como tal manera. Ahora.
Otro error común que miro al momento de implementar contenedores en producción y les recalco, les recuerdo, estos son errores a los cuales me enfrenté mayormente al inicio cuando estaba implementando contenedores por primera vez y me sigo enfrentando cuando estoy migrando clientes de máquinas virtuales a ambientes con contenedores y uno de ellos es no definir límites.
para los contenedores. es esto es bien importante y bien crítico porque normalmente en mi local no lo hago. En mi local no le pongo un límite a los contenedores que levanto para desarrollo o para pruebas porque solo yo me conecto a ellos porque solo yo hago pruebas, ¿verdad? Pero cuando estos contenedores van a producción y empiezan a tener tráfico real, empiezan a tener muchos llamados, empiezan a consumir mucha memoria,
el contenedor empieza a adquirir recursos, recursos, recursos, agarrar recursos, recursos y como no hubo un límite termina matando el nodo por out of memory, deja el nodo sin memoria y hace que el nodo que normalmente va a estar corriendo otros contenedores, el nodo crashea, se caiga no solo botando mi aplicación, pero botando la aplicación de otros que están corriendo en el mismo nodo, verdad.
Y esto, esto es algo que yo he visto mucho que genera en gerentes porque miren, ya hemos hablado, ya hemos discutido un poco antes, pero lo recuerdo aquí un poco, no todos los gerentes de departamentos dictales realmente son personas...
profundas en aspectos técnicos. Son personas que saben administrar los recursos, incluyendo el personal y presupuesto, entre otras cosas. Entonces, no siempre van a entender eso. Y si están viendo que constantemente, cuando antes una VM, si fallaba, solo afectaba a esa aplicación, a menos que sea una VM, un servicio crítico que muchas aplicaciones consumen, ¿no? Pero entonces ya era que porque falló esto, las demás empiezan a dar
error, pero solo esa VM fallaba, pero ahora si una VM falla, está corriendo muchos contenedores y ya no solo hace que otras aplicaciones den error, hacen que las otras aplicaciones también crasheen, porque el contenedor no tenía límites y empezó a crecer, a crecer, a crecer y utilizó todos los recursos siempre, siempre debemos de darle límites mínimos
cuando ya estamos en producción a nuestros contenedores, decirles vas a arrancar con mínimo tanto CPU, tanta memoria, esto va a ser acorde a la aplicación, no les puedo decir cuál es un valor exacto porque esto la aplicación que está corriendo en él lo va a definir, pero si le vamos a decir vas a arrancar
cuando nazca este contenedor van a ser con tan mínimo, tanta memoria, tanto CPU y vas a llegar a un máximo de tanta memoria y tanto CPU, verdad? y entonces si se descontrola un proceso interno dentro del contenedor va a llegar al límite que tiene y lo único que va a crashear es ese contenedor y no va a crashear
todo el nodo y los demás contenedores corriendo en el mismo nodo. Y otra razón por la cual esto es muy importante es que si definimos, tenemos que definir límites si queremos que el auto scaling de contenedores o de pods, si fuese Kubernetes, en realidad funcione para que agregue más réplicas. Le configuramos que un servicio queremos que tenga mínimo cuatro réplicas, digamos.
pero dependiendo del tráfico que pueda escalar hasta 20 réplicas pero para que escale a 20 réplicas dependiendo del tráfico
tenemos que ponerle parámetros tenemos que decirle cuando usé el 80 % del CPU por ejemplo del del del contenedor es crear una nueva o le podemos decir que scale en base al uso de memoria RAM del contenedor o pudiéramos decirle otro tipo de métricas hay otras maneras de hacerlo que si tenemos x cantidad de tráfico vas agregando más réplicas eso es una configuración bien avanzada pero al principio normalmente se configura el auto scaling mayor
en
CPU o en memoria pero
si el contenedor o el pod no tiene un límite, ¿cuántos 80 % de algo que no tiene límite? Si yo le digo, vas a agregar más instancias, cuando las que estén ahorita van a consumar 80 % del CPU, pero 80 % de cuánto si no hay un límite definido, el auto scaling no nos funciona y las mismas cuatro instancias que pusimos de entrada, matan el nodo porque esas cuatro instancias no ocupan escalar porque consumen la memoria o el CPU a su antojo.
como lo necesitan entonces es importante es clave
que en producción definamos límites de recursos a nuestros contenedores. De nuevo, ya sea que corramos en DockerSorm o que corramos en Kubernetes, que quieran correr en DockerRun, en DockerCompose, todas estas diferentes formas de correr contenedores permiten que definamos límites, recordando que DockerRun y DockerCompose idealmente no se debería de correr en producción. Ahora, un tercer consejo.
de cosas que normalmente hacemos cuando trabajamos con contenedores, con docker que en producción hacemos que todo explote y que nos crashe, verdad.
Y una de estos errores bien comunes que se daba al inicio, yo me declaro culpable de haber cometido este error al principio, es que nuestros servicios, nuestros contenedores, corrían con el tag de latest. Ya sabemos que al momento de correr un contenedor tenemos una imagen y tenemos la imagen de engine X, digamos, ¿no? Y luego va seguido de dos puntos y lo que vale esos dos puntos es un tag o es una versión, si lo queremos decir así, ¿no? Entonces...
Nginx 1.19, 1 punto lo que sea que tengamos en, como se llama definido, como está.
en particular y normalmente en contralos hay un tag que se llama latest que es cada nuevo build de esa imagen se le asigna el tag latest, sea la última versión que existe porque esto es un problema porque siempre nosotros queremos tener en producción
versiones específicas, ya sea de nuestra propia aplicación, la aplicación interna que maneja nuestro equipo de desarrollo, que va teniendo versionamiento interno o las herramientas que corramos fuera, esto puede ser herramientas como NGINX, como ya mencioné, Redis, Elasticsearch, cualquier herramienta que estemos corriendo que a veces se puede correr en contenedores como una manera donde no hay alto tráfico, es como nosotros
por ejemplo en field es como que corramos redis en Kubernetes, las distancias de redis que utiliza WordPress las corremos directamente en Kubernetes, son muy pocos escenarios o son clientes que necesitan caching demasiado grande donde se crean contenedores externos, perdón, clusters externos fuera de Kubernetes para redis, verdad, usando redis como ejemplo.
Ahí queremos tener la versión específica que queremos correr. ¿Qué ocurre? Estamos en producción, está el sistema en producción y de repente nos comienza a dar error y no sabemos por qué en la mañana estaba trabajando y hoy falló, ¿verdad? ¿Por qué hoy falló y en la mañana trabajaba bien? ¿O por qué luego de esta publicación falló si la publicación solo cambió un texto?
Pero por qué esta nueva publicación falló y es que tenemos el de latest y actualizó la versión de Nginx, actualizó la versión de Redis o actualizó la versión de la aplicación y no tenía que haberla actualizado porque tenía un feature que también no estaba listo para ser lanzado y eso comienza a generar errores en producción y de nuevo crea la impresión cuando estamos queriendo comenzar a implementar contenedores.
genera la sensación de las personas alrededor de los project managers, de los otros departamentos, de los gerentes, crean la impresión de que los contenedores...
crean más problemas de lo que en realidad están resolviendo. Recordemos siempre, siempre en producción queremos tener el control de la versión específica que queremos correr y antes de actualizar la versión se prueba. Cuando queremos actualizar la versión de nuestra aplicación, queremos actualizar la versión de Redis, de ElasticPress, de lo que queramos, se actualiza en ambiente local primero, controlando la versión, se prueba cuando hay errores, luego se actualiza en los
diferentes ambientes de pruebas de edging, preproducción, lo que sea que tengan y una vez que está listo se actualiza en producción. Tenemos que tener todas las imágenes en producción con un tag específico, con una versión específica y nunca correr con la versión latest. Esto ha generado muchos problemas, créanme se los digo y en un momento yo fui culpable de esto, esto me generó de muchos problemas y esto les va a quitar muchísimos dolores de cabeza.
su travesía implementando o migrando hacia contenedores. Ahora un cuarto consejo y este va a ser el último consejo en el que voy a profundizar en lo que tiene que ver con ejemplos y detalles, verdad? Este cuarto consejo es un error bien común utilizar imágenes gigantes, utilizar imágenes pesadas.
¿Por qué? Antes de contenedores estábamos acostumbrados a que como el servidor ya estaba ahí corriendo y tenemos el servidor de backend, digamos, ya está corriendo Node.js y tiene que los Node models y tiene un montón de dependencias instaladas porque a la hora de publicar pues yo genero un código y lo copio en el servidor.
Pero al momento de hacer todo eso con contenedores, comenzamos primero que si la imagen es gigante, el tiempo de construir esa imagen, de hacer el build, el Docker build, va a tardar bastante tiempo porque es una imagen gigante que que descargando, instalando node, instalando npm, que bajando la mitad del internet con el npm install y que estoy bajando otras dependencias e instalándolas y entonces tomo aquel montón de tiempo.
en hacer el build de la imagen y luego terminé con una imagen de 1.5 gigas, 1.2 gigas y esa imagen pesada, entonces ahora tengo que empujarla al hacer el push al Docker registry, puede ser el Docker Hub, puede ser el registry de GitHub, puede ser un registry perdón privado.
y estoy subiendo 1.2 gigas a ese registry de la imagen que acabo de generar y cuando termino de subirla ahora mando a mi servidor que estoy corriendo los contenedores con Kubernetes, con Dockerswap, con lo que sea a que haga un pull, que baje esa imagen del registry otra vez esa gran cantidad y solo ese proceso a veces yo he visto pipelines y esto es real, pipelines de aplicaciones relativamente sencillas
que tardan entre 30 y 40 minutos. Todo el proceso de build, push, luego pull y deploy. Y que generan imágenes y yo vi en algún momento me topé con una aplicación que usaba una de estas bases de datos de coordenadas, de geolocation.
y bajaban todas las bases de datos y las metían en el contenedor en sí porque les parecía que era más simple. Y pues más simple tal vez para el desarrollador hacer algo como eso, ¿no? Pero el mantenimiento de eso, lo que tardaba, hacer el copy de esa base de datos en cada build y el peso final con el que quedaba hasta que yo llegué a ese proyecto y dije, hey, eso no puede ser así, tenemos que cambiar esta estrategia, tenemos que ver cómo tenemos un servicio.
aparte con un API que llame a esta base de datos, no sé si pagamos un servicio externo, pero no lo podemos estar copiando en cada uno de los contenedores. Se comete ese error de ver o de creer de que el contenedor final para producción tiene que contener todas las dependencias para el build.
Todas las dependencias, si yo trabajo con PHP, ejemplo, y voy a generar WordPress, usamos WordPress, yo trabajo en mi día día bastante administrando instancias de WordPress que corren en Kubernetes. Y utilizamos Composer para manejar las dependencias de WordPress, plugins, paquetes de PHP, etcétera. Composer solo lo necesito cuando estoy haciendo en Build. El contener Composer.
en el contenedor final de producción no me genera ningún uso, más allá es una dependencia que me genera un riesgo. Entonces no tiene por qué estar en mi contenedor final que va a estar en producción. Igual.
En WordPress existen plugins que se usan de Query Monitor y otros plugins que me permiten en desarrollo ver qué query se llamaron, ver cuánto tarda una respuesta de un query, porque para desarrollo me sirven para poder ver dónde encuentro cuello de botella. Esos plugins no se encuentran en producción. Mi paquete final que va a producción no tiene por qué contener ese tipo de plugins, ¿verdad? Entonces...
se comete ese error.
nos crea pipelines que tardan mucho tiempo y de nuevo genera descontento en nuestro equipo, genera descontento en otros equipos o en la parte gerencial y un problema más que trae y que le va romper producción manejando imágenes tan pesadas es que luego de tres a cinco deployments diferentes personas de la aplicación el nodo simplemente crashea no sabemos por qué y es que
el
disco duro se llenó porque tenemos un nodo con 20 o 30 gigas y después de haber bajado las dependencias, más haber bajado 6, 7 diferentes versiones de mi aplicación cada una de 1.2 gigas se llenó, se llenó por completo, eso, eso nos quita espacio en disco y lo miro pasar seguido, miren esto al día de hoy cuando me toca hacer auditorías con diferentes empresas que tienen
problemas con sus flujos de trabajo, con sus workflows que tienen en contenedores, uno de los errores comunes que encuentro es que las imágenes son muy pesadas o algunas tienen el disco de los nodos muy pequeños, crean el nodo y lo agregan a otros sortes de Kubernetes con el disco por defecto de 8 gigas, 8 gigas aunque usemos imágenes pequeñas se va a llenar relativamente rápido, pero tener la imagen muy pesada es un problema serio y se resuelve
relativamente fácil verdad, no instalemos dependencias que se ocupan sólo durante el build, dejemos únicamente lo que se ocupa en producción en la imagen final y aprovechemos los multi stage builds, multi stage builds que son este donde tengo un stage donde están todas las dependencias que necesito para hacer el build
y tengo un stage mínimo, un stage final donde agarré mi aplicación ya buildeada, ya build completado y solo lo copio en una imagen final, solo con las dependencias necesarias para producción. Entonces, estos son los cuatro tips principales que les quería compartir. Estos son los más comunes.
con lo que me tope yo la primera vez, algunas de estas situaciones, yo mismo fui culpable y yo mismo fallé en ellas. En algunas de estas ocasiones el equipo de desarrollo falló en ellas, en otras eran los gerentes y me tocó tratar de explicar y me tocó invertirle tiempo en entrenar a la gente. Y hoy en día me toca más seguido lo que ustedes pueden imaginarse.
mover empresas algunas grandes, sus flujos de trabajo de bienes a contenedores y estos son los retos que me sigo topando. Quiero hacer una mención
de otros errores comunes, en esto solo voy a hacer mención, no voy a profundizar porque no es que estos sean menos importantes, de hecho son muy importantes, pero uno por cuestión de tiempo no podemos ahondar en todos los tips y segundo ocurren menos al principio, los que voy a mencionar ahorita, una vez que ya hemos definido esa base de un flujo de contenedores que ya fluye, aprovechándonos de la palabra flujo.
que ya está fluyendo, que ya está trabajando, es como para la fase 2 nos comenzamos a topar con estos retos, pero que lo sepan desde ahorita, los pueden ir de repente considerando para que en la fase 2 esto no sea un problema. Errores comunes, uno de ellos es ⁓ exponer el socket de Docker sin control en los contenedores. El Docker.socket muchas veces se monta en los contenedores porque ocupamos que un contenedor haga build de imágenes.
a
veces pasa para contenedores de CICD.
o tenemos un contenedor que corre comandos auxiliares y necesitamos que le montamos el socket de docker a él y entonces eso se puede volver un problema serio si no se controla de la mejor manera, esto no aplica en flujo de Kubernetes, Kubernetes ya no soporta docker de esa manera, pero en docker swarm o si usan docker compose sigue siendo una práctica común lamentablemente, voy a decirlo, y cuando se tiene que hacer algo como esto,
utiliza el Least Privileged, que vamos dando la menor cantidad de privilegios posibles y hacemos esto de montar el socket de docker en un contenedor única y exclusivamente si es necesario, pero hoy en día cada vez es menos necesario y hay otras alternativas. Yo los animo a que busquen esas otras alternativas.
Otro error común, de nuevo que voy a mencionar, es tener logs sin rotación, ¿verdad? La aplicación está configurada para guardar logs, a veces puede estar configurada para guardarlos de manera local o si no se configura bien el plugin de Docker, si usamos Docker, de cómo va a guardar esos logs, no nos damos cuenta de que el disco duro se está llenando rapidísimo y es porque no tenemos rotación configurada para los logs y por eso digo que estos son, se dicen que
que son problemas del día 2, día 2 después de la implementación, una manera de decir que es la fase 2, normalmente instalo, el flujo está funcionando bien y ya llevo dos meses que está trabajando bien y de repente el disco duro está lleno y qué pasó, los logs está completamente lleno, no se configuró rotación para ellos y ese descuido causó que se cayera toda producción por minutos o posiblemente por horas hasta que se corrija el problema, entonces
seamos intencionales con la estrategia de rotación del logs cuando trabajamos con contenedores. Otro error común, normalmente del día 2, es mal manejo de secretos.
ya sea secretos que se usan durante el build, porque se puede usar ARCs o variables durante el build, y a veces ocupamos, inyectar tokens durante el build para que baje dependencias, inyectar, ocupamos inyectar llaves de SSH, lo que sea que se necesite, o ya en runtime, cuando ya está corriendo, ocupamos pasarles secretos para que la aplicación corra, secretos mal manejados en producción, corre peligro de que expongamos información sensitiva,
de manera involuntaria, entonces secretos mal manejados, seamos intencionales en cómo se maneja secretos, si es Kubernetes, cuando creamos un secreto en Kubernetes, normalmente se codifica en Base64, recordemos por favor que el Base64 se puede decodificar, o sea yo codifico, no es encriptación, es codificación, yo codifico en Base64 y
lo puedo decodificar. Entonces no suban sus manifestos de secretos codificados en Base64 al repositorio porque no está encriptado, está codificado. Mal manejo de secretos en producción se convierte un problema serio en el camino.
Y un error común más que voy a mencionar sin ahondar en él es no implementar health checks. Este es grave y es sencillo de corregir, pero a la vez nos puede generar problemas que no nos demos cuenta, ¿verdad? Si no tenemos un health check, el contenedor nos va a decir que está en estado running.
que está running, pero eso no significa que está listo, que está en un estado ready. Los health checks son los que se encargan de ver que la aplicación realmente esté healthy, esté saludable para permitirle a ese contenedor que comience a recibir tráfico. No un health check puede ser un endpoint cualquiera que cuando la base de datos ya está lista y cuando tu aplicación ya se conecta a los servicios que tienen o los servicios que requiere ya están corriendo, ese endpoint va de vuelta
ver
un estado 200 y ese health check me permite que funciona entonces muchas veces no configurar health check de nuevo, muy seguido problema de día dos, día uno tengo corriendo todo está bien, al siguiente deployment veo que nunca arranca el siguiente deployment porque el contenedor nuevo nunca pasa a un estado healthy o el siguiente deployment es un problema porque dice que está running pero como no tiene health check empieza a recibir tráfico y en realidad no
listo para recibir tráfico y hay mucho error al momento de la publicación porque contenedores que no están listos han comenzado a recibir tráfico por no tener un health check configurado. Estos son otros errores que no quería dejarlos sin mencionar.
Sin embargo, nuevo, son errores del día 2. Ahora, para ir cerrando, y como quisiera cerrar estos consejos de esta charla del día de hoy, verdad, es que lo primero, los contenedores por sí solos no rompen producción. Es la mala operación de los contenedores los que terminan corriendo producción.
muchos van a decir obvio, contenedor solo, un contenedor no se maneja solo, esto que está diciendo es muy obvio, no entiendo por qué te querés hacer el listo y lo mencionás, lo menciono porque los otros equipos, los project managers, los ejecutivos, los gerentes no entienden esto muchas veces. Los retos en los cuales yo me he enfrentado
y que he hablado con gerentes, con directores de departamentos, cuando se empieza a implementar Kubernetes, cuando se a implementar contenedores, yo escucho cosas como, estos problemas no los teníamos cuando corríamos en VMs, o esas dificultades no estaban antes cuando corríamos en VMs, porque llega a un punto de creer de que el problema es el contenedor y se combina con pensar que no tenemos la capacidad.
Y bueno, a veces si estos problemas siguen siendo recurrentes puede ser que necesitemos dar un paso atrás, prepararnos mejor, planearlo mejor y luego volver a intentar la implementación. por eso lo menciono, los contenedores por sí solos no son los que rompen producción, no son el problema. Si estamos teniendo problemas con contenedores Docker Swarm, Kubernetes, Docker Compose, como sea, una mala operación lo que está.
creando este problema y si hacemos lo básico bien vamos a lograr escalar de forma confiable y segura. Si comenzamos con teniendo en consideración estos consejos arquitectando básicamente bien, perdón, lo básico en nuestras aplicaciones
vamos a poder implementarlos de forma segura, confiable y van a escalar mejor. Entonces eso lo que yo quería compartirles. Espero que lo hayan pues servido, les sea de valor estos consejos. Si tienen otros consejos que quieran mencionar, por favor dejen en los comentarios, compartan con personas que están tal vez queriendo implementar contenedores. Queremos que nuestra comunidad crezca, queremos que nos apoyemos.
a otros que aprendamos de experiencias, si están teniendo otros problemas, si están actualmente implementando contenedores y están teniendo otros problemas que no es ninguno de los que mencioné, déjenlo en los comentarios y vamos a hacerlos posibles por proveer guía alrededor de ellos. Gracias por su tiempo, gracias por haber llegado hasta acá, nos veremos en el próximo episodio, adiós.