the ugly org - como gestionar dependencias operacionales

desu

the ugly org

Hello, hoy es voy a contar un poco como gestionamos las dependencias operacionales del equipo en la ugly organization.

Voy a empezar con las conclusiones.

Conclusion final

Si solo aplicas estas metodología a tu equipo, tu empresa ademas valora la seguridad y te ofrece un Vault, vas a tener una experiencia de desarrollo que no has tenido en la vida.

Y no, no la has tenido en la vida porque NIXOS no es tu Anaconda o tu entorno virtual de python, tu docker de MIERDA.

  • La diferencia entre usar esta metodología y no usarla es como usar SVC o no usarlo. Sabéis que hay gente que no sabe lo que es git? Que aun sube ficheros mediante FTP a mano a prod? Si te crees que ya estas bien eres como un tío que nombra a sus ficheros "version_final.java"y las manda por correo.

  • La diferencia entre mi metodología y no tenerla, es tener tests y no tenerlos. Sabéis que hay gente que no testea integracion porque dicen que es mala practica?

  • La diferencia es como tener logs/metricas o no...

  • La diferencia es como usar IaC y herramientas de migración a tener 10 tíos metiendo en la DB a hacer queries a mano!

Y no pasa nada, porque no llegas tarde, de hecho la ola aun no ha llegado ni a la costa. Así que súbete que estas a tiempo. Tu en que nivel de ingeniero estas? Eres fpero raso? O estas en la cima top 0,00001%?

Principios

  • Declarative: independiente de las dependecias a usar, arquitectura x86-64 o arch64. AMD vs Intel. Cualquier programador puede traer su maquina y garantizamos que funciona TODO al 100% automaticamente.
  • Reproducible: no hay dependencias ni configuraciones no declaradas, por lo que si algo funciona en una máquina, también funcionará en otra. Y si algo funciona en local, tambien lo hara en dev-pre-pro. Obviamente, podemos tener 4 entornos de CI. Tu cuantos tienes?
  • Reliable: Nada se va a romper, los cambios se pueden revertir.

Todo esto sin esfuerzo. Cada equipo de producto se encarga del ciclo de vida de su software. No hay devops ni personas externas involucradas.

Objetivos

  • development dependencies
    • compilers: java, go, rust, python
    • compile dependencies: libtorch, CUDA
  • operational dependencies
    • VPN
    • aws, azure, gcp clis
    • logs and metrics utilites
    • general scripts for toil operations, troubleshooting, debugging, etc.
  • operational configurations
    • shared secrets
    • access configuration: VPN, Okta (groups, tokens), SSH, SSM
    • artifact configuration for pulling and pushing: jfrog, artifactory, github
    • git

Development vs operational

Ayuda, soy fpero y no he trabajado en la vida, que diferencias hay?

  • Development: Picar código. CI/CD del código.
  • Operational: Tareas adicionales como solución de problemas, análisis de logs, conexiones a máquinas de AWS, tareas manuales en la base de datos, on-boarding y off-boarding, migraciones.

Todo proceso operacional manual puede llegar a ser un script si cumple con los tres principios: reproducible, declarativo y reliable. Si tu script genera efectos secundarios, no es funcional ni reproducible.

La linea entre development y operacional es muy fina no? No, seguramente eres un fpero. No has trabajado bien tu vida. Porque en tu empresa Paco para hacer un despliegue que pasa por QA y mil fases tienes que hacer piruetas no significa que este bien. Esta mal.

Por que las development dependencies entran?

Porque es un problema operacional.

  • Porque es un problema operacional: on-board de nuevo miembro.
  • Porque es un problema operacional: cambiar de lenguaje de programacion un proyecto.
  • Porque es un problema operacional: hacer un upgrade de una libreria que esta petando todo el codigo y requiere cambiar las dependencias dinamicas de desarrollo.

Si resuelves el problema operacional, tener un entorno funcional: declarative, reproducible and reliable. Nunca vas a tener los problemas que menciono porque no seran posibles.

Si tu haces un MVP de un proyecto no hace falta que compartas tus dependencias, en el momento en que quieres compartir ese proyecto con otros si.

Stack

Vamos a necesitar flox, un wrapper de nixos, un control de versiones como git aunque nos vale cualquiera, repositorios para codigo y secretos y por ultimo entornos y runners de CI/CD.

Lo que viene siendo el tipico Github/Gitlab pero anadiendo flox.

Lo que flox nos va aportar es, al mix habitual para tener CI/CD sobre repositorios (development) otro mix para nuestros entrnos operacionales (operational).

Y aqui, para tener el pack completo necesitaríamos un Vualt de secretos! Este no forma parte de las responsabilidades del equipo, voy a obviarlo de momento.

IaC vs flox

Ayuda, soy fpero y no entiendo que diferencia hay con usar terraform con scripts para esto.

Terraform e infraestructura entra dentro de development no operacional. Tener tests de integracion, acceptance, multiples entornos, CD, todo esto es development.

Que todos los miembros de tu equipo al entrar a AWS puedan acceder a los entornos de desarrollo, a la VPN, al correo corporativo. Es operacional. Un equipo central seguramente administra estas cosas, y tu, das de alta y gestionas (OPERATIONAL).

Yo soy streamer en Twitch y tengo un canal de Youtube con el que estafo a chavales de 15 y creo que Terraform me vale. Usa Terraform.

Ejemplo

Enhorabuena fpero! No requiere mucho esfuerzo entender lo que vamos a hacer. Se han hecho miles de experimentos en los últimos 50 años de industria. Seguro que habras probado muchos! La diferencia es que ahora tenemos un stack que por fin va a resolver el problema de manera SIMPLE y FACIL.

Utilizar NIXOS es COMPLEJO y DIFICIL. Flox es un wrapper para que sea MUY SIMPLE y MUY FACIL.

Vamos al lio. Paso 1? Paso 1 on-boarding claro.

Paso 1 - instalar dependencias development

Facil. Inicializar en tu home un entorno. En el arranque de tu shell cargar el entorno.

Ahora instalas las dependencias de lenguajes. Que sera instalar el compilador-interprete para tu lenguaje Python, Javacript, Java, PHP, Go, Rust.

Cualquier cosa que tuvieses GLOBAL en tu maquina para todos los proyectos, ahora es una dependencia compartida en tu equipo.

Si usas Go o Rust, esto sera 1 instalación. Pero si usas python, javascript necesitaras tener mil movidas como NPM, Yarn, Poetry porque estos lenguajes y ecosistemas son una porqueria.

Paso 2 - instalar dependencias operational

Buscar paquetes operacionales e instalarlos.

  • Ejemplos de dependencias típicas: curl, wget, fd, sd, fzf.
  • Ejemplos mas concretos serian: aws o azure, y todas las cli, k9s, docker, docker-compose si no lo tienes en development lo puedes poner aquí.

Estas haciendo pair programming con un compañero y no tiene una puta utility que tu usas? Mira son 5MiB de dependencia. Compártela con tu equipo y déjate de bobadas. Y lo mismo con la configuración de esta dependencia! Siguiente paso.

Si tu equipo necesita una VPN para entrar a paginas internas de la empresa, pero no necesitas la VPN para desarrollo. La pondrías aquí. Instala la VPN que todo tu equipo, toda tu puta empresa usa, y la configuramos a continuación.

Paso 3 - configurar dependencias development

Os voy a dar otro ejemplo para Java y Gradle. Tengo un compañero que el muy hijo de puta, cuando peta un proyecto de Java con Gradle en los tests porque se supera la memoria que le das a la VM, se lo modifica en su local... En lugar de tocar los parámetros de gradle en el proyecto. Mira, una manera de lidiar de una vez por todas con todos estos problemas, es tener una config de Gradle compartida para TODOS los programadores y TODOS los proyectos.

Ahora imaginate que estas trabajando en el proyecto X y te falla el Gradle. Que vas a hacer? Tienes una obligación y dos opciones.

  • La primera obligación es decirle a tu puto equipo lo que ha pasado.
  • La segunda es elegir si cambiar la configuración en el Gradle de TODO el equipo o solo el Gradle en el repo del proyecto X. Que es igualmente una opción valida.

Optaría por cambiar el Gradle del proyecto X.

Si mas proyectos petan, cambiar la configuración de todo el mundo.

Paso 4 - configurar dependencias operational

Esta es la parte dificil. De momento solo has instalado, ahora toca configurar alguna cosa. Voy a poner un par de ejemplos.

Imagina que tienes un Github interno, no usas GitHub.com, o tienes un Jfrog. De nuevo github.acme.com y jfrog.acme.com.

Cuando vayas a trabajar, pull, push, necesitaras apuntar a estos y configurar las SSH y tokens necesarios.

Por ejemplo en git, podríamos instalar una herramienta para tener git diffs de mayor calidad, y crear un .gitconfig compartido para todo el equipo que utilice este git por default.

Paso 5 - configurar secretos compartidos

Cada empresa gestiona los secretos compartidos de manera distinta. Algunos tienen un vault que se accede por API, otros una carpeta compartida con un fichero protegido.

La conclusion es que algunos de estos secretos son necesarios en nuestro entorno. Tenemos que cargarlos automáticamente, y ponerlos. Ojo, quizás esto NO ES POSIBLE. No pasa nada. No nos pongamos nerviosos porque al hacer on-boarding nos falta un paso y hay que hacerlo a mano.

Paso 6 - configurar secretos priviados

En el ejemplo de SSH por ejemplo. Cargamos nuestras SSH compartidas y después tenemos un fichero con nuestras SSH privadas. De esta manera cada persona solo necesita poner sus datos y todos funcionamos igual.

Cosas que he visto? El que solo 1 miembro del equipo tenga unas SSH o unos tokens que NADIE sabe como se han generado, ni de donde vienen, y cada vez que hay un on-board hay que pedirle a esa persona que te pase las cosas.

Cuando se va tardar en ir esa persona del equipo? O realizar una migración de proyectos? Y que se tengan que ROTAR TODAS LAS KEYS porque nadie puede configurar el proyecto?

Este seria un claro ejemplo, las key privadas son privadas, NUNCA afectan al onboard.

Paso Final - compartir en GitHub tu entorno

Una vez esta todo. Git push de tu carpeta .flox con todas las cosas compartidas.
Para usarlo pues git pull y rellenar los datos privados.

Problemas de esta metodologia

Solo he visto dos e imagino que mas gente lo habra visto. Pero es el tema de secretos. Necesitaríamos tener una VAULT por equipo que funcionase con API para poder automatizar todo. Así que no solo necesitamos Flox y Github, sino Flox, Github Y UN VAULT.

Gestionar el VAULT es lo mas difícil la verdad, y no lo he puesto porque el VAULT on lo debe gestionar un equipo de producto. Por eso he querido compartir este tutorial de como hacerlo todo de la manera mas simple, fácil y guarra posible para que veáis que la tecnología esta MUY preparada y resuelve el 99% de los problemas de la gente.

El segundo son las dependencias RARAS. Si tu proyecto usa una dependencia rara, pues la tendrás que añadir tu mismo a nixos-flox.

MV CHALLANGE

Voy a crear un repo con una configuración de dependencias, secretos etc. Que podáis ejecutar.

Estoy pensando en como montarlo todo en GitHub, y quizás tener como secretos privados llaves de ssh para el runner. Así si si el runner se ejecuta es que tu PC esta bien configurado.

Experiencia de usuario

Si tienes el PC hecho una mierda, usas shells raras como nushell, puedes tener problemas. Los mismos problemas que tendrás con cualquier gestor de paquetes. Si tienes 4 paths, 4 zshrc, cosas instaldas con brew o apt, cosas instaladas con cargo o a mano... Tienes un follon. Formatea y empieza con Flox.

Otra cosa es que si tienes un paquete interno que tienes que compartir no sera tan fácil como "flox install paquete", lo tendrás que poner a mano.

Si no tienes un Vault corporativo, no podrás tener entornos 100% automáticos y tus programadores necesitaran configurar un par de cosas a mano.

  • Flox + SVC + Vault = 9/10
  • Flox + SVC + Secretos a mano = 7.5/10
  • Flox + SVC + (Sin secretos, todo accesible) = 3/10
  • No usar flox, ni SVC y hacer esto a mano = fpero/10

El 9/10 se debe, a que si pretendes hacer esto en un entorno corporativo, Flox para TODA tu empresa, ya no sera simple y fácil. Sera complejo y algunos scripts pueden ser difíciles.

3
desu

Sigo con ejemplos concretos de Flox.

En nuestro $HOME inicializamos el main y lo ponemos en nuestra shell. En mi caso esto con un Macbook y uso zsh.

Abro una terminal flox init y listos.

Esto crea un directory .flox en nuestro $HOME, que ya podemos pasar a git con un git init. Aquí es importante añadir el .gitignore, pero eh, usamos flox, por que no ponemos un .gitignore global para todos nuestros sub entornos que compartan todos los programadores? Lo dejo de deberes.

Aqui tenéis un ejemplo: https://github.com/uglyorganization/flox/blob/main/env/manifest.toml
Fijaros en los paquetes, en la arquitectura, en los arranques de las shells. Todo muy simple y fácil de usar.

Para activar la shell tenemos el comando flox activate. Podemos correrlo a mano cuando lo necesitemos pero lo suyo, al igual que cualquier otro path o dependencia es que la shell lo haga por nosotros en arranque. En nuestra configuración de shell, por ejemplo .zshrc solo hay que realizar añadir nuestro nuevo entorno:

eval "$(flox activate --dir ~)"

Listos, vamos a crear un proyecto en python e instalar python y poetry.

  1. Hacemos un git init my-python && cd my-pthon.
  2. Inicializamos un flox por proyecto, flox init && flox install python311 poetry.
  3. Y automatizamos el poetry en nuestro arranque:
shell.hook = ''
  poetry init
  poetry add
  export PATH="$PWD/.venv/bin:$PATH"
'';

Y listos.

  • Entorno $HOME: Tenemos 1 flox compartido para todo el equipo para todos los proyectos
  • Entorno my-python: Tenemos 1 flox para un proyecto python, que a su vez me carga el poetry
  • Si creamos ahora el proyecto my-python-2 que también usa poetry, pues seria buena idea mover este poetry a nuestro $HOME no?

Cada vez que queramos instalar cualquier cosa, lo hacemos con poetry de manera normal y todo funciona.

Que usas tu VSCode, pycharm o similares? A ver fpero, estas herramientas usan tu shell, así que todo funcionara siempre.

De hecho Poetry y gestores de paquete son completamente INNECESARIOS y REDUNDANTES. Para que quieres gestor de paquetes y versiones, como un npm para javascript o poetry para python, si tienes entornos que siempre funcionan y nunca se rompen?

Ah, por cierto, si quieres un contenedor y tirar docker:

flox containerize -o - | docker load

Y listos.

Pero para que quieres un contenedor como docker, que no aporta una mierda de seguridad si ya tienes entornos modulares y funcionales que no se rompen? : - )

Con Flox dockers y docker-compose se van al guano para muchísimos casos de uso.

1
1 mes después
desu

Muy bueno, hoy he hecho un git clone y al lanzar el flox init automáticamente ha detectado que era un proyecto con package.json y me ha instalado todo en el environment : - )

flox [default] ➜  lifts git:(master) flox init
Flox detected a package.json

Flox can add the following to your environment:
* nodejs 20.12.2 with npm bundled
* An npm installation hook

Would you like Flox to apply this suggestion?
You can always change the environment's manifest with 'flox edit' Yes
✨ Created environment 'lifts' (aarch64-darwin)
✅ 'nodejs' installed to environment 'lifts'

Next:
  $ flox search <package>    <- Search for a package
  $ flox install <package>   <- Install a package into an environment
  $ flox activate            <- Enter the environment

No solo me ha inicializado el environment con las dependencias globales, cuando he activado el environment de Flox me ha instalado con un hook automáticamente todas las dependencias del repo o_O

git clone https://github.com/vrnvu/lifts
flox init
flox activate
npm run dev

Y todo esto se hace para tu arquitectura automáticamente, en mi caso ahora estoy con un MacBook M3, la ultima vez tenia un x86-64

1 mes después
Yekale7

Pues lo he probado con NodeJS, Python, Poetry y dentro de uno de los entornos con jupyter lab... Todo funcionando por lo que bastante top. Eso sí, aún no me he metido con el git que tiene el propio flox, ni sé si merece la pena.

Pena que a nivel de hardware las herramientas sean una mierda.

Usuarios habituales

  • Yekale7
  • desu