Contactar →
← Todas las entradas
Servicios2026.05.06

Añadir un nuevo servicio

Levantar un container son cinco minutos de trabajo. Todo lo que hace que un servicio realmente pertenezca a la plataforma en lugar de simplemente estar al lado de ella —accesible de la forma correcta, vigilado de la forma correcta, sin convertirse en una mina para quien esté de guardia cuando algo se rompa, que en una plataforma personal es siempre la misma persona— es una lista de decisiones que docker compose up no toma por ti. Me he pillado saltándome casi todos los puntos de esta lista al menos una vez cada uno, normalmente en algo que me decía a mí mismo que era “solo una cosita rápida”, y cada vez el atajo acabó apareciendo más tarde como un problema peor que los cinco minutos que habría costado pensarlo de antemano.

Ninguna de estas decisiones es exótica. Son las mismas cinco categorías cada vez, y dejarlas escritas como una lista fija es sobre todo una defensa contra la versión de mí mismo que está emocionada con el servicio nuevo y quiere saltar directamente a usarlo.

Dónde vive en la red

No todos los servicios necesitan la misma exposición, y lo predeterminado debería ser la mínima exposición que aún permita al servicio hacer su trabajo. Un servicio que solo se va a usar desde dentro de la red no necesita ningún camino hacia el exterior en absoluto: la decisión de colocarlo en un segmento accesible desde internet, aunque sea detrás de autenticación, debería tomarse deliberadamente, no heredarse por defecto solo porque ahí es donde fueron los últimos tres servicios.

Esto tampoco es una decisión de una sola vez que desaparece una vez tomada. Un servicio colocado hoy en un segmento solo interno porque “de momento nadie externo lo necesita” es un servicio que alguien acabará queriendo alcanzar desde fuera, y la versión honesta de este punto de la lista es decidir ahora si esa ubicación está pensada para cambiar más adelante, o si es un límite permanente frente al que una futura petición de relajarlo debería rechazarse de verdad. Lo que está en juego con esta decisión sube considerablemente en cuanto el servicio en cuestión pertenece por completo a otra persona en lugar de a mí; consulta Niveles de aislamiento de clientes para ver qué cambia cuando un workload pasa a ser propiedad externa en lugar de interno por defecto.

Cuál es su vía de ingress

Suponiendo que el servicio necesite que algo lo alcance, ¿cómo llega realmente el tráfico hasta él: una entrada en un reverse proxy, una exposición directa de puerto, un endpoint de túnel? Es una decisión más pequeña que la ubicación en la red pero más concreta, porque es lo que hay que deshacer con cuidado si el servicio llega a retirarse alguna vez: una ruta de reverse proxy olvidada o un puerto abierto para un servicio que ya no está en marcha es exactamente el tipo de entrada obsoleta que meses después se convierte en un “por qué puede alcanzar esto alguien” sin explicación.

La decisión de ingress y la decisión de ubicación en la red no son la misma pregunta formulada dos veces. Un servicio puede estar correctamente colocado en un segmento restringido y aun así tener una vía de ingress mal elegida: terminación TLS ocurriendo donde no debería, una regla de proxy más amplia que el único hostname al que necesita responder. Ambas hay que decidirlas, y ninguna sustituye a la otra.

Cómo se cablea en observability

Un servicio que existe pero no produce ninguna señal es un servicio que falla en silencio, y “ya añadiré monitorización más adelante” es el punto de la lista con más probabilidades de no llegar a suceder nunca, una vez que el servicio ya funciona y la atención se ha desplazado a otra cosa. Esto implica decidir, en el momento de la puesta en marcha, cómo informa este servicio concreto de su propia salud: si expone métricas que un scraper pueda recoger, si registra logs de una forma que resulte realmente útil una vez que aterrizan en el sistema de agregación de logs que use la plataforma, si necesita su propia entrada en el sistema externo de comprobación de uptime que exista.

Ese último punto importa especialmente porque es fácil asumir que un servicio con métricas y logs ya está “monitorizado” y saltarse la comprobación de fuera hacia dentro; pero las métricas internas no pueden ver una regla de firewall o un registro DNS que hace que el servicio sea inalcanzable desde donde realmente necesita ser alcanzado. Cablear un nuevo servicio en observability significa decidir las tres cosas, no solo la que resulta más fácil de añadir después.

Dónde viven sus secretos

Todo servicio que no sea una herramienta completamente estática y sin autenticación tiene al menos una credencial —un token de API, una contraseña de base de datos, una clave de firma— y “dónde vive” es una decisión que hay que tomar antes de que el servicio arranque, no descubrir más tarde cuando alguien pregunte “espera, ¿esa clave está ahí sin más en el archivo de compose?”. La respuesta a nivel de plataforma para esto ya debería existir (un almacén de secretos, una convención de archivos de entorno, lo que la plataforma tenga estandarizado), y el punto de la lista no es inventar una respuesta nueva para cada servicio: es asegurarse de que los secretos de este servicio concreto pasan de verdad por la respuesta ya existente, en vez de tomar el camino de menor resistencia que resulta ser el más rápido de poner en marcha hoy.

Este es también el punto con más probabilidades de acumular deuda silenciosa: un secreto codificado de forma temporal “solo para que funcione” que sigue codificado tres meses después porque el servicio ha estado funcionando bien y nadie ha tenido motivo para tocar ese archivo desde entonces.

Cómo se le hace backup, o se decide explícitamente que no

La última decisión es la más fácil de saltarse porque saltársela no produce ningún síntoma visible… hasta el día en que lo produce. Todo servicio nuevo o bien contiene un estado que merece la pena poder recuperar (una base de datos, archivos subidos, una configuración que costó tiempo real construir) o bien genuinamente no lo contiene (un proxy sin estado, una caché que se reconstruye sola, una herramienta trivialmente reinstalable a partir de su propio config-as-code). El punto de la lista no es “haz backup de todo”: es tomar esa decisión explícitamente, en un sentido u otro, en el momento de la puesta en marcha, para que “esto no tiene backup” quede como una decisión registrada y no como una brecha que nadie notó hasta que los datos del servicio desaparecieron.

Un servicio con estado que nunca recibe una decisión explícita sobre backup acaba por defecto, por omisión, en “sin backup”, y el modo de fallo ahí no es sutil: es aquel en el que la conversación de recuperación empieza con “espera, ¿alguien llegó a configurar backups para esto?”.

También ayuda separar “tiene backup” de “es restaurable”, porque no son la misma afirmación. Un trabajo de backup que lleva meses ejecutándose silenciosamente pero que nunca se ha probado restaurando realmente desde él es una creencia, no una garantía; y en una plataforma personal, donde el propio trabajo de backup es una pieza más de infraestructura sin monitorizar a menos que se cablee en la misma decisión de observability de arriba, es perfectamente posible que ese trabajo lleve un tiempo fallando en silencio antes de que nadie necesitara lo que se suponía que protegía. El punto de la lista no se completa con “existe un trabajo de backup para esto”: se completa con “existe un trabajo de backup, y sé que produce realmente algo restaurable”, que es un listón considerablemente más alto y el que de verdad importa el día en que hace falta.

El orden importa más que la lista

Tener las cinco categorías por escrito no evita por sí solo el modo de fallo más habitual, que es hacerlas en el orden equivocado: en concreto, arrancar primero el container y tratar el resto como limpieza posterior. En cuanto un servicio está en marcha y es accesible, la presión por volver de verdad y terminar el cableado de observability, o mover la credencial codificada al flujo real de secretos, cae en picado, porque el servicio ya parece terminado. Responde a las peticiones. Hace aquello para lo que se añadió. La brecha entre “parece terminado” y “está terminado de verdad” es invisible desde fuera, que es exactamente por qué tiende a quedarse abierta.

El orden más fiable, en mi experiencia, es tratar la ubicación en la red y la gestión de secretos como decisiones que bloquean por completo el arranque del container; no porque sean técnicamente difíciles de aplicar a posteriori, sino porque aplicarlas después exige volver y tocar algo que ya está en marcha, lo cual es una fricción que de forma fiable nunca se acaba pagando más tarde. El cableado de ingress y de observability puede razonablemente ocurrir en la misma sesión que poner en marcha el servicio, justo después, antes de pasar a aquello para lo que realmente se necesitaba el servicio. La política de backup es el único punto que puede legítimamente esperar un poco más sin daño, siempre que “esperar” signifique “aplazado explícitamente con un motivo”, no “olvidado”: un servicio sin estado realmente puede tener su decisión de backup correctamente resuelta como “no hace falta”, y ese es un buen sitio donde quedarse, siempre que se haya decidido de verdad y no se haya llegado ahí por defecto.

El patrón detrás de todo esto es que una lista solo cumple su función si se consulta antes de que la parte satisfactoria (el servicio funciona, hace lo suyo) quite la motivación para consultarla. Una lista que solo vive en la cabeza de alguien, para aplicarse “cuando me acuerde”, se acaba saltando de forma fiable justo cuando más falta hace: en el servicio añadido al final de un día largo, en el que se añade porque otra cosa está rota ahora mismo y necesita un sustituto rápido, en el que parece demasiado pequeño como para merecer los cinco puntos completos. Esos son los servicios con más probabilidades de seguir sin cableado de observability y sin una historia real de secretos un año después, no porque nadie decidiera saltarse la lista, sino porque nadie la consultó en primer lugar.

El verdadero sentido de la lista

Ninguna de estas cinco categorías es difícil por separado. La ubicación en la red es una conversación contigo mismo sobre exposición. El ingress es elegir la entrada de proxy correcta. El cableado de observability son tres pequeños añadidos, no uno grande. Los secretos ya tienen una respuesta a nivel de plataforma; usarla es toda la tarea. El backup es una decisión de sí o no con un motivo adjunto.

El valor de mantenerlas como una lista fija en lugar de confiar en la memoria está precisamente en que “simplemente arranca el container” se siente completo por sí solo —el servicio funciona, responde, parece terminado— mientras en realidad se están saltando las cinco. Una plataforma personal no tiene una segunda persona que atrape la brecha en una revisión de código, ni tiene un proceso de onboarding que te obligue a pasar por la lista la primera vez. La lista es el sustituto de ambas cosas: no una barrera burocrática, solo una lista fija de las categorías de decisión que “arranca el container” aplaza en silencio, aplicada de la misma forma cada vez que un nuevo servicio se une a la plataforma.

← Todas las entradas