24,99 €
En un mundo donde la velocidad y la calidad del software son esenciales, la implementación de Integración Continua (CI) y Despliegue Continuo (CD) se ha convertido en un estándar imprescindible. Este libro ofrece una guía completa para arquitectos, desarrolladores y equipos técnicos que buscan optimizar sus procesos de desarrollo y despliegue, con un enfoque práctico en tecnologías .NET y Azure. A lo largo de sus capítulos, se exploran desde los conceptos fundamentales de CI/CD hasta la implementación avanzada de arquitecturas modernas. Aprenderás a utilizar herramientas clave como Docker y Kubernetes, diseñar arquitecturas basadas en microservicios, gestionar despliegues en la nube con Azure Kubernetes Service (AKS) y automatizar procesos con GitHub Actions y Azure DevOps. Con ejemplos prácticos, estrategias arquitectónicas y mejores prácticas, este libro es el recurso ideal tanto para quienes buscan modernizar aplicaciones monolíticas como para aquellos que desean implementar soluciones escalables desde cero. Si quieres transformar la forma en que desarrollas y despliegas software, esta obra te proporcionará el conocimiento y las herramientas necesarias para lograrlo con éxito.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 333
Veröffentlichungsjahr: 2025
CI/CD de Arquitecturas .NET, despliegue en Azure
© 2025 Ramón Serrano Valero y Miguel Ángel Núñez Sabín
Primera edición, 2025
© 2025 MARCOMBO, S. L. www.marcombo.com
Gran Via de les Corts Catalanes 594, 08007 Barcelona
Contacto: [email protected]
Ilustración de cubierta: Jotaká
Maquetación: Reverté, S.L.
Corrección: Nuria Barroso
Directora de producción: M.a Rosa Castillo
Cualquier forma de reproducción, distribución, comunicación pública o transformación de esta obra solo puede ser realizada con la autorización de sus titulares, salvo excepción prevista por la ley. Diríjase a CEDRO (Centro Español de Derechos Reprográficos, www.cedro.org) si necesita fotocopiar o escanear algún fragmento de esta obra
ISBN del libro en papel: 978-84-267-4015-1
ISBN del libro electrónico: 978-84-267-4042-7
Producción del ePub: booqlab
Miguel Ángel
A mis padres y hermanos, por su cariño incondicional y por ser las raíces firmes que sustentan mis convicciones y valores.
A mi mujer, Tina, por tu paciencia infinita, por estar siempre a mi lado, en lo bueno y en lo malo, y por todo lo que compartimos, mi refugio.
Y, por supuesto, a mis pekes, Iker y Hugo, la razón de mi existencia, mi mayor motivación y el secreto de mi felicidad. Todo lo que hago lo hago pensando en vosotros.
Ramón
A mi madre Carmen; aunque los recuerdos se difuminen, lo bien que lo hiciste como madre permanecerá intacto, con cada enseñanza, en lo que somos gracias a ti.
A mi mujer Sara, por estar siempre ahí, por demostrarme que los sueños son más fáciles de alcanzar cuando caminas con la persona adecuada; gracias por ser tan increíble.
A mi hija Emma. Tienes una luz única. Nunca dejes que nada ni nadie apague esa chispa. Siempre contarás con tu madre y conmigo para apoyarte en cada sueño que persigas.
En este libro se utiliza la tipografía Courier en los casos en los que se hace referencia a código o acciones por realizar en el ordenador, ya sea en un ejemplo o cuando se refiere a alguna función mencionada en el texto. También se usa para indicar menús de programas, teclas, URL, grupos de noticias o direcciones de correos electrónicos.
Los términos y definiciones que se utilizan mayormente en lengua inglesa se mantienen en este libro en dicho idioma, y en cursiva.
El código fuente de los ejemplos, así como todos los recursos didácticos y de programación que se utilizan en este libro podrán descargarse a medida que se avanza en la lectura.
Estos recursos están disponibles en www.marcombo.info con el código NET25.
Cubierta
Título
Créditos
Contenido
1 Introducción
1.1 Acerca del libro
1.2 Acerca de los autores
1.3 Motivación
1.4 Arquitectura IT
1.4.1 Roles de arquitectos IT
1.5 Proyecto de arquitectura
1.5.1 Cómo comienza un proyecto
1.5.2 El rol del arquitecto de soluciones
1.5.3 El rol del arquitecto software
1.5.4 El rol de DevOps
1.5.5 Implementación de arquitecturas limpias
1.6 Arquitectura en CI/CD
1.6.1 Origen de CI/CD y la transición desde monolitos hacia microservicios
1.6.2 Patrones de diseño en arquitectura para CI/CD
1.6.3 Proyectos ’tipo’ con colaboración de arquitectura en CI/CD
1.7 Resumen del capítulo
2 CI/CD
2.1 Introducción CI/CD
2.2 Principios fundamentales de CI/CD
2.3 Ciclo completo DevOps y CI/CD
2.4 Integración continua (CI)
2.4.1 Ventajas de la integración continua
2.4.2 Ejemplo flujo de integración continua
2.4.3 Herramientas para CI
2.5 Despliegue continuo (CD)
2.5.1 Ventajas del despliegue continuo (CD)
2.5.2 Ejemplo flujo de despliegue continuo
2.5.3 Herramientas para CD
2.5.4 Estrategias de despliegue
2.6 Contenedor e imagen
2.7 Docker
2.7.1 El uso de Docker en CI/CD sobre Azure
2.7.2 Arquitectura de Docker
2.7.3 Imagen en Docker y cómo se construye
2.7.4 Proceso subida imagen al registro
2.7.5 Docker Desktop
2.7.6 Comandos esenciales con Docker
2.7.7 Docker Compose: Orquestación local
2.7.8 Otros comandos de Docker
2.7.9 Bonus: Casos de uso relevantes en Azure
2.8 Container Registry
2.8.1 Funciones del Container Registry
2.8.2 El papel de los Container Registries en CI/CD
2.8.3 Alternativas de Container Registries
2.9 Kubernetes
2.9.1 Conceptos básicos
2.9.2 Arquitectura de Kubernetes
2.9.3 Instalación de Kubernetes
2.9.4 Primeros pasos con Kubernetes
2.9.5 Declarativa vs. imperativa
2.9.6 Comandos esenciales con Kubernetes
2.9.7 Configuración y despliegue con YAML en Kubernetes
2.9.8 Tipo de servicios en Kubernetes
2.9.9 Dashboard de Kubernetes
2.9.10 Bonus: Instalación en Azure Kubernetes Service (AKS)
2.10 Bonus: Herramientas y tecnologías en Azure DevOps
2.11 Resumen del capítulo
3 Implementación de la arquitectura
3.1 Crear solución de la arquitectura
3.2 Crear proyecto front-end
3.2.1 Prerrequisitos de herramientas
3.2.2 Personalizando proyecto front-end
3.2.3 Gestión de estados en componentes – Pinia
3.2.4 Módulo de registro de actividad. WorkRegistration
3.2.5 Módulo de histórico de actividad. WorkRegistrationTable
3.2.6 Router
3.2.7 Variables de entorno
3.3 Crear solución backend
3.3.1 Prerrequisitos de herramientas
3.3.2 Librería – Minimal API
3.4 Arquitectura transversal – comunicación
3.5 Arquitectura vertical – microservicio Registry
3.5.1 Configuración perfil ejecución
3.5.2 Configuración Minimal API
3.5.3 Configurar microservicio para usar Docker Compose
3.5.4 Configurar contenedor PostgreSQL
3.5.5 Configurar contenedor RabbitMQ
3.5.6 Implementación dominio
3.5.7 Implementación acceso a datos
3.5.8 Implementación Features
3.5.8.1 Feature CreateUserWorkTimeRecord
3.5.8.2 Feature GetUserWorkTimeRecord
3.5.9 Verificar microservicio
3.6 Arquitectura vertical – microservicio auditoría
3.6.1 Configuración perfil ejecución
3.6.2 Configuración Minimal API
3.6.3 Configurar microservicio para usar Docker Compose
3.6.4 Configurar contenedor MongoDB
3.6.5 Implementación dominio
3.6.6 Implementación acceso a datos
3.6.7. Implementación Features
3.6.7.1 Feature CreateUserRecordHistory
3.6.7.2 Feature GetUserRecordsHistory
3.6.8 Verificar microservicio
3.7 Adaptar proyecto front-end
3.8 Resumen del capítulo
4 Despliegue CI/CD Docker Hub – Azure Container Apps
4.1 Configuración monorepo GitHub
4.2 Creación cuenta de Azure y consideraciones
4.3 Configuración Docker Hub
4.4 Despliegue manual a Azure Container Apps
4.4.1 Despliegue PostgreSQL
4.4.2 Despliegue MongoDB
4.4.3 Despliegue RabbitMQ
4.4.4 Despliegue Registry API
4.4.5 Despliegue Auditory API
4.4.6 Despliegue interfaz usuario worktime-app
4.5 Despliegue automático CI/CD a Azure Container Apps
4.6 Resumen del capítulo
5 Despliegue sobre Kubernetes local
5.1 Configurar Kubernetes local en Docker Hub
5.2 Crear namespace
5.3 Despliegue PostgreSQL a Kubernetes local
5.4 Despliegue MongoDB a Kubernetes local
5.5 Despliegue RabbitMQ a Kubernetes local
5.6 Despliegue Registry API a Kubernetes local
5.7 Despliegue Auditory API a Kubernetes local
5.8 Despliegue UI Vue a Kubernetes local
5.9 Resumen del capítulo
6 Despliegue CI/CD AKS con Azure Container Registry
6.1 Instalación CLI de Azure
6.2 Creación grupo recursos
6.3 Creación ACR
6.4 Preparación de imágenes y publicación en ACR
6.5 Crear clúster AKS
6.6 Crear recursos en el clúster AKS
6.7 Verificar Pods
6.8 Resumen del capítulo
7 Azure DevOps
7.1 Qué es Azure DevOps
7.2 Azure Pipelines
7.3 Creación del repositorio en GitHub
7.4 Registrar AzureDevops
7.5 Configurar conexión de servicios
7.6 Crear agente de ejecución pipeline
7.7 Creación de los recursos ACR, AKS e IP
7.8 Crear pipeline
7.9 Verificar despliegue
7.9.1 Bonus extra: Troubleshooting en CI/CD
7.10 Resumen del capítulo
8 Reflexiones finales
Cover
Contenido
Start
En la última década, la forma en que las organizaciones desarrollan, implementa y gestionan el software ha cambiado radicalmente. El ritmo acelerado de la innovación tecnológica y las crecientes expectativas de los usuarios han obligado a las empresas a transformar sus procesos de desarrollo, adoptando prácticas modernas como integración continua (CI) y despliegue continuo (CD).
Este libro está diseñado para servir como una guía exhaustiva para arquitectos, desarrolladores y equipos técnicos que buscan optimizar sus procesos de desarrollo y despliegue, especialmente en arquitecturas basadas en tecnologías .NET y Azure. A través de una estructura progresiva, se exploran los fundamentos, herramientas, arquitecturas y casos prácticos que permitirán a los lectores transformar sus proyectos en soluciones ágiles, escalables y confiables.
• Fundamentos de CI/CD: En el capítulo inicial, se detallan los conceptos fundamentales de CI/CD, explicando su origen, beneficios y los principios clave que impulsan estas prácticas. También se abordan las herramientas y metodologías esenciales para su implementación.
• Exploración de Docker y Kubernetes: Los capítulos intermedios se centran en herramientas como Docker y Kubernetes, que han revolucionado la forma en que se gestionan aplicaciones modernas. Se incluye una guía práctica sobre cómo construir y gestionar contenedores, además de desplegarlos en entornos como Azure Kubernetes Service (AKS).
• Implementación de la arquitectura: Uno de los pilares del libro es el diseño e implementación de arquitecturas modernas. Desde la creación de soluciones basadas en microservicios hasta la integración de herramientas como RabbitMQ y bases de datos como PostgreSQL y MongoDB. También se explora cómo combinar estas tecnologías con patrones de diseño y principios como arquitecturas limpias y verticales.
• Despliegues en Azure: Se realiza el despliegue de la arquitectura anterior sobre la nube de Azure, abarcando estrategias como el uso de Docker Hub para el almacenamiento de los repositorios de las imágenes, desplegando manual y automáticamente sobre Azure Container Apps. El despliegue automático se realiza haciendo uso de las GitHub Actions, que definen un flujo de trabajo (workflow), que automatiza la compilación del código, ejecución de pruebas y finalmente realice el despliegue.
• Despliegue sobre Kubernetes local: Preparamos la arquitectura anterior, para ser desplegada sobre un orquestador de contenedores como Kubernetes.
• Despliegue en AKS: En capítulos avanzados, se guía al lector en la configuración de clústeres en AKS, el uso de Azure Container Registry (ACR) para gestionar imágenes y el despliegue manual sobre AKS.
• Automatización de despliegue usando Azure DevOps: Una sección completa está dedicada a Azure DevOps, explorando la creación de pipelines, integración con repositorios como GitHub, que nos permitan desplegar nuestra arquitectura basada en contenedores, sobre AKS de forma automática, tras ejecutarse una pipeline que reacciona a un cambio producido en el código.
• Casos prácticos y mejores prácticas: Finalmente, el libro presenta casos reales y consejos prácticos para superar desafíos comunes, optimizar pipelines y garantizar la seguridad en los despliegues.
En un mundo donde el tiempo de entrega y la calidad del software son críticos, CI/CD se ha convertido en un estándar indispensable. Este libro no solo le proporciona el conocimiento técnico necesario, sino también las estrategias arquitectónicas y metodológicas para implementar estas prácticas de manera efectiva.
Ya sea que esté modernizando aplicaciones monolíticas, diseñando microservicios desde cero o implementando soluciones en Azure, este libro le guiará a través de cada paso del proceso, asegurando que sus sistemas sean más ágiles, seguros y escalables.
Acompáñenos en este recorrido para descubrir cómo CI/CD y las herramientas de Azure pueden transformar su forma de trabajar, brindándole una ventaja competitiva en el desarrollo de software moderno.
Ambos formamos parte del departamento de arquitectura de Sopra Steria, siendo Miguel Ángel la persona que lidera el departamento de arquitectura de Levante.
Miguel Ángel tiene más de 25 años de experiencia en el mundo de la consultoría especializado en arquitectura de soluciones, mientras que Ramón posee más de 15 años de experiencia en el desarrollo de arquitecturas basadas en .NET y actualmente como arquitecto de soluciones como Miguel Ángel.
Ambos trabajamos juntos en múltiples proyectos y sabemos trabajar en equipo, ya que nos entendemos a la perfección, de modo que cuando Ramón le contó que anteriormente había realizado un libro sobre diseño de arquitecturas .NET orientadas a microservicios y tenía ganas de continuar el libro dando un paso más, ya no hablando tanto sobre desarrollo de microservicios, sino enfocado al despliegue continuo sobre Azure, a Miguel Ángel le encantó la idea. Siempre había querido plasmar sus conocimientos en un libro y que mejor forma de iniciarse en el mundo de la escritura que escribiendo con un amigo.
En ese momento, nos pusimos a realizar el hilo conductor de todo el libro como alguien que no hubiera realizado nunca un despliegue continuo y pudiera aprender conocimientos básicos sobre contenedores, orquestadores y los servicios proporcionados por Azure, de tal forma que fuera adquiriendo poco a poco las habilidades precisas primero en entornos locales, luego preparar el entorno a Kubernetes y finalmente desplegar sobre Azure AKS mediante pipelines.
Tras esto nos pusimos manos a la obra. Pensamos en qué más podría aportar valor al lector, de modo que surgió la idea de crear pequeños consejos le que ayudasen en su orientación como arquitecto.
Tras muchas madrugadas trabajando en el libro, finalmente nos sentimos orgullosos de haber aportado nuestro granito de arena a esta comunidad.
Por lo que, si le ha gustado el libro o simplemente quiere colaborar con nosotros, ampliemos nuestra red:
• Ramón Serrano Valero: https://www.linkedin.com/in/ramon-serrano-valero-2154113b
• Miguel Ángel Nuñez Sabín: https://www.linkedin.com/in/miguel-angel-nu%C3%B1ez-sabin-6028b693
Estaremos encantados de compartir impresiones sobre el libro y otros temas de arquitectura.
En la actualidad, el desarrollo de software enfrenta una presión constante para entregar nuevas funcionalidades a un ritmo más rápido y con mayor calidad. La transformación digital ha llevado a las organizaciones a adoptar prácticas modernas como DevOps y CI/CD (integración y despliegue continuos) para mantenerse competitivas en un mercado que exige agilidad y precisión.
Los enfoques tradicionales, caracterizados por ciclos de desarrollo largos y procesos manuales de despliegue, han demostrado ser insuficientes frente a las demandas modernas. Estas metodologías no solo retrasan la entrega de valor al cliente, sino que también incrementan los riesgos de errores en producción.
Adoptar CI/CD no es solo una tendencia tecnológica, sino una necesidad estratégica. Según un estudio reciente de DORA (DevOps Research and Assessment), las organizaciones que implementan prácticas avanzadas de CI/CD realizan despliegues 46 veces más frecuentes, reduciendo un 96% el tiempo medio de recuperación ante fallos.
Además, la implementación de arquitecturas modernas, como microservicios, ha revolucionado la forma en que se diseñan y operan las aplicaciones. Estas arquitecturas complementan perfectamente las prácticas de CI/CD al permitir que los equipos trabajen de manera autónoma y desplieguen componentes de forma independiente, maximizando la escalabilidad y reduciendo la complejidad.
Este libro tiene como objetivo proporcionar a arquitectos y desarrolladores una guía clara para implementar CI/CD en arquitecturas modernas sobre Azure. A través de casos prácticos, herramientas y principios fundamentales, los lectores podrán transformar sus procesos de desarrollo y despliegue para alcanzar niveles de productividad y calidad nunca vistos.
La arquitectura define los cimientos sobre los cuales se construyen las aplicaciones modernas. En el contexto de CI/CD, la arquitectura juega un papel crucial para garantizar que los sistemas sean escalables, modulares y fáciles de desplegar. Las arquitecturas modernas, como microservicios, han transformado la forma en que los equipos desarrollan, prueban y despliegan aplicaciones.
El éxito de la implementación de CI/CD depende en gran medida de la colaboración entre diferentes roles de arquitectos dentro de un equipo, roles que se describen en el siguiente punto.
En el mundo IT (tecnologías de la información), generalmente profesionales con el perfil de ingenieros en Informática, tras alcanzar un alto grado de experiencia en el campo de las tecnologías de la información, suelen poseer muy buen conocimiento técnico y de negocio, que acostumbra a ir ligado a la participación en multitud de proyectos, de diverso tamaño y complejidad.
Estos profesionales poseen la capacidad de realizar diseños y planificación de sistemas complejos, asegurando la interoperabilidad de los diferentes componentes dentro del sistema, estos profesionales son arquitectos IT.
Dependiendo de la responsabilidad de estos arquitectos IT, existen diversos tipos de arquitectos [Ilustración 1]:
Ilustración 1. Roles.
• Arquitecto empresarial:
∘ Dentro del campo de tecnologías de información, el arquitecto empresarial tiene un rol estratégico dentro de la organización. Actúa como un intermediario entre la visión empresarial y las capacidades tecnológicas de la misma, estableciendo estándares que aseguren soluciones escalables y actualizables.
∘ Responsabilidad en CI/CD: Asegurar que las prácticas de integración y despliegue se alineen con la estrategia tecnológica global y sean sostenibles a largo plazo.
• Arquitecto de negocio:
∘ Tiene como foco principal comprender las necesidades organizativas y traducirlas en requerimientos funcionales. Este rol requiere un conocimiento profundo de los procesos empresariales y su interacción con la tecnología.
∘ Responsabilidad en CI/CD: Garantizar que los sistemas desarrollados resuelvan problemas reales del negocio y que las soluciones técnicas estén alineadas con los objetivos organizativos.
• Arquitecto de soluciones:
∘ A menudo considerado el diseñador del sistema, transforma los requerimientos funcionales en soluciones técnicas integradas.
∘ Responsabilidad en CI/CD: Diseñar pipelines y soluciones técnicas que cumplan con los lineamientos definidos por los arquitectos empresarial y de negocio.
• Arquitecto de software:
∘ Centrado en el diseño detallado y la implementación técnica de los componentes del sistema. Trabaja directamente con los equipos de desarrollo para asegurar modularidad y mantenibilidad.
∘ Responsabilidad en CI/CD: Diseñar componentes compatibles con pipelines de CI/CD.
∘ Arquitecto de datos:
∘ Diseña y gestiona la estructura de datos de la organización, desde modelos conceptuales hasta estrategias de calidad de datos.
∘ Responsabilidad en CI/CD: Garantizar que los datos fluyan eficientemente entre sistemas y que estén disponibles de forma segura para los usuarios finales.
∘ Arquitecto de infraestructura:
∘ Responsable de diseñar y mantener la infraestructura tecnológica necesaria para soportar las aplicaciones.
∘ Responsabilidad en CI/CD: Asegurar que la infraestructura soporte las necesidades de despliegue continuo y sea escalable y resiliente.
∘ Arquitecto de seguridad:
∘ Define y supervisa estrategias de protección de la información y los sistemas tecnológicos.
∘ Responsabilidad en CI/CD: Integrar la seguridad en cada etapa del proceso, desde el desarrollo hasta el despliegue.
Todo empieza cuando nos plantean un problema que debemos resolver, es en ese momento en que el departamento de arquitectura se pone a trabajar. Entre las tareas a las que este equipo puede enfrentarse se encuentran, entre otras:
• Retro-arquitectura: El cliente posee una arquitectura actual y no se ha documentado; el equipo de arquitectura analizará y documentará dicha arquitectura.
• Arquitectura de reemplazo: El cliente posee una arquitectura y esté o no documentada, el equipo de arquitectura analizará el sistema y cómo se comporta y hará hincapié en el componente a reemplazar. Una vez tenga el conocimiento de que datos de entrada y salida poseen el componente a reemplazar y de su interacción con otros sistemas, extrayendo las funcionalidades y capacidades que posee, debemos hacer un análisis de componentes que pueden servirnos en el mercado para reemplazarlo y que no tenga pérdida de funcionalidades existentes. De esta forma, analizamos una lista de posibles alternativas y, en caso de que alguna funcionalidad no la podamos cubrir, proporcionar el diseño de la implementación de un componente que cubra la funcionalidad necesaria, de tal forma que la interoperabilidad del sistema reemplazado no se vea afectado.
• Nueva arquitectura: El cliente no posee una arquitectura o la posee y la quiere modernizar o cambiar de tecnología por completo, por obsolescencia tecnológica o por otros motivos. En este caso, el equipo de arquitectura analizará las nuevas especificaciones y propondrá una o varias alternativas de arquitectura para que el cliente tome la decisión oportuna.
• Resolución de problemas de arquitectura: El cliente posee una arquitectura existente y quiere modificarla con el mínimo impacto y coste, pero sabe que es necesario adaptarla, de tal forma que se resuelvan posibles problemas de rendimiento, problemas de comunicación, escasa escalabilidad, entre otros. En este caso, se debe analizar primero los problemas que están encontrando en la arquitectura actual y proponer varias soluciones que puedan solventar dichos problemas a corto, medio y largo plazo, incluyendo el esfuerzo estimado y el impacto, para que el cliente pueda tomar una decisión sobre si abordar o no el problema.
Según las diferentes tareas especificadas anteriormente, se prepara un documento de arquitectura con las siguientes secciones:
• Arquitectura de negocio: Incluyendo el alcance del documento y objetivo del sistema a analizar, los diferentes actores que participan en el negocio, las funcionalidades y los casos de uso.
• Arquitectura de datos: Incluyendo las entidades que utiliza el sistema, la gobernanza de datos y quienes son los responsables, toda entrada y salida de datos de cada uno de los sistemas que intervengan en la arquitectura y si añadimos un diagrama de flujo de datos, sería genial.
• Arquitectura de aplicación: En esta sección se definen cada uno de los sistemas que intervienen en la arquitectura, se relaciona cada sistema con una capacidad de negocio, así como las capacidades técnicas del sistema y sus funcionalidades. Por último, se especifica si se han tomado en consideración alguna decisión de arquitectura en base a algún criterio de negocio o técnico y se prepara el diagrama de aplicaciones.
• Arquitectura de infraestructura o tecnología: En este caso, se preparan las consideraciones que se han llevado a cabo en la selección de una u otra infraestructura para alojar los diferentes sistemas, si se ha preparado el sistema para ser escalable y accesible la mayor parte del tiempo, así como también un diagrama de infraestructura, relacionando componentes de infraestructura como servidores y su sistema operativo, con componentes de red y cómo se relacionan con el diagrama de aplicaciones, es decir, que el componente de infraestructura aloja un componente de aplicación, por ejemplo una API.
Por último, cada uno de estos diagramas de negocio, aplicación e infraestructura se presentarán en un único diagrama para ver cómo está todo relacionado.
De este modo, representemos mediante un lenguaje de modelado llamado ArchiMate, utilizado por arquitectos empresariales, para analizar y visualizar relaciones entre distintos dominios arquitectónicos, un diagrama con la arquitectura que se implementará en próximos capítulos [Ilustración 2]. Las tres capas representadas son:
• Capa de negocio: Es la business layer; será aquí donde identifiquemos los roles y actores, las funciones y/o procesos que el negocio debe realizar.
• Capa de aplicación: Es la application layer; se definen las aplicaciones que soportan la capa de negocio, por ejemplo, componentes software como frontales o API o sistemas ERP, son ejemplos de estos componentes, así como servicios que las aplicaciones proporcionan a otros componentes.
• Capa de tecnología: Es la technology layer; se describe la infraestructura tecnológica que soporta la capa de las aplicaciones. Aquí se incluyen sistemas operativos, máquinas virtuales, balanceadores, recursos de red, bases de datos y cómo soportan a las aplicaciones.
Ilustración 2. Modelado de arquitectura con Archimate.
La estructura puede cambiar, pero, por lo general, todo documento de arquitectura debería poseer estas secciones. Por ejemplo, en el caso de evaluar un componente de reemplazo, además incorporará una sección con la evaluación de alternativas y cobertura de las funcionalidades o en el caso de la mejora de problemas de arquitectura, incluirá una sección con listado de problemas que enfrenta la arquitectura actual y cada posible acción que se puede realizar para tratar de solventar el problema.
Empezando por el diseño de alto nivel de la solución, que incluye diagramas en las tres capas, visto anteriormente con la herramienta ArchiMate, o con otros tipos de diagramas para representar los componentes del sistema o mediante el modelo C4.
Aunque no es el objeto de este libro detallar estos modelos, el modelo C4, es interesante utilizarlos cuando queremos representar diferentes niveles de detalle de una arquitectura desde los sistemas hasta las clases que los implementan. Se divide en 4 niveles:
• C1: Alto nivel de interacción de todos los sistemas de la arquitectura.
• C2: Se hace zoom a uno de estos sistemas y se detalla cada uno de los contenedores que componen dicho sistema, por ejemplo, un contenedor puede ser un front-end o una API.
• C3: Se hace zoom en uno de estos contenedores y se puede ver los componentes que contienen el contenedor a analizar y la interacción con el resto de los contenedores. Un ejemplo de componente es un controlador de una API.
• C4: Se hace zoom en uno de estos componentes y podemos detallar a nivel de clases e interfaces, tipo UML para ver cómo se debe implementar el componente. Aunque bajar hasta este nivel no suele ser lo habitual.
El arquitecto de soluciones trabaja junto al arquitecto de negocio, ya que conoce aquellas funcionalidades que a nivel de negocio el sistema cubre o debería cubrir, relacionando estas necesidades con los diferentes sistemas, su tecnología, la infraestructura y cómo todo el sistema se comunica entre sí.
El arquitecto de soluciones también deberá definir las estrategias de integración y despliegue continuo, dado que cada componente, se implemente con la tecnología que se implemente, deberá de desplegarse automáticamente por diferentes entornos, desde desarrollo, pasando por preproducción, hasta llegar a entornos productivos. Este documento de despliegue será utilizado, por un lado, por el equipo de desarrollo para preparar los repositorios de código fuente y por parte del equipo de DevOps, para crear las pipelines y que todo se despliega como se espera.
El arquitecto software es el profesional encargado de transformar los objetivos funcionales y técnicos en un diseño concreto que guíe el desarrollo del sistema. Este rol se centra en la definición y estructuración de los componentes que forman parte de la solución tecnológica, garantizando que se adhieran a principios de diseño como modularidad, cohesión y desacoplamiento. Su responsabilidad va más allá de escribir código; establece los fundamentos que aseguran la mantenibilidad, escalabilidad y extensibilidad del sistema.
En el contexto de CI/CD sobre Azure, el arquitecto software juega un papel esencial al diseñar sistemas que se integren sin fricciones con las herramientas y servicios de la nube. Por ejemplo, al implementar una arquitectura basada en microservicios, debe diseñar API bien definidas y asegurar que los servicios puedan desplegarse de manera independiente utilizando pipelines automatizados en Azure DevOps. Además, selecciona los frameworks más adecuados, como ASP.NET Core para backends o Blazor para front-ends, optimizando cada decisión tecnológica según las capacidades del equipo y las necesidades del proyecto.
Otro aspecto clave del rol es la definición de patrones y normas que guiarán al equipo de desarrollo. Esto incluye la elección de patrones de diseño como CQRS para segmentar comandos y consultas, o Mediator para gestionar flujos de trabajo complejos. También establece directrices para la gestión de dependencias entre capas, favoreciendo la implementación de principios SOLID y el uso de interfaces para fomentar la flexibilidad.
El arquitecto software trabaja en estrecha colaboración con el equipo de DevOps para definir y optimizar los pipelines de CI/CD. Esto implica integrar pruebas automatizadas, desde pruebas unitarias hasta pruebas de integración y performance, asegurando que los despliegues sean consistentes y libres de errores. Además, supervisa la creación de entornos replicables en Azure, como entornos staging en App Services o clústeres AKS dedicados para pruebas.
Durante el ciclo de vida del proyecto, el arquitecto software desempeña un rol activo, revisando la calidad del código y asegurándose de que las decisiones técnicas iniciales continúen alineadas con los objetivos del negocio y la arquitectura. Su visión estratégica y técnica garantiza que el sistema no solo cumpla con los requisitos actuales, sino que esté preparado para evolucionar frente a nuevas necesidades.
El rol de DevOps es fundamental en la implementación y operación de soluciones CI/CD sobre Azure. DevOps no solo conecta los equipos de desarrollo y operaciones, sino que también impulsa una cultura de colaboración y automatización que acelera los ciclos de entrega y mejora la calidad del software. En este contexto, DevOps actúa como un facilitador clave para implementar prácticas de integración y despliegue continuos en entornos dinámicos.
Uno de los principales objetivos de DevOps es diseñar pipelines de CI/CD que automaticen cada etapa del desarrollo, desde la integración del código hasta su despliegue en producción. Utilizando herramientas como Azure DevOps o GitHub Actions, los equipos pueden construir, probar y desplegar aplicaciones de manera eficiente. Por ejemplo, un pipeline típico incluiría tareas como la ejecución de pruebas unitarias con xUnit, la construcción de contenedores Docker y su despliegue en AKS.
DevOps también se encarga de configurar y gestionar la infraestructura como código (IaC), permitiendo que los entornos en Azure sean creados y replicados de forma automática. Esto incluye el uso de herramientas como Terraform o ARM Templates para definir recursos como App Services, bases de datos o redes virtuales. Al adoptar IaC, DevOps garantiza consistencia en todos los entornos, desde desarrollo hasta producción.
Otro aspecto crítico es la monitorización continua del sistema. Utilizando herramientas como Azure Monitor y Application Insights, el equipo de DevOps recopila métricas y logs para identificar y resolver problemas antes de que impacten al usuario final. También configura alertas automáticas para notificar eventos críticos, como caídas de rendimiento o errores en los despliegues.
La seguridad es una prioridad en el trabajo de DevOps. Integrar DevSecOps en los pipelines asegura que cada etapa incluya validaciones de seguridad, como análisis de vulnerabilidades en contenedores y escaneos de código estático. Además, herramientas como Azure Security Center permiten a DevOps identificar configuraciones inseguras y aplicar correcciones proactivas.
El rol de DevOps no se limita a implementar tecnología; también fomenta una cultura de mejora continua, eliminando silos entre equipos y acelerando la entrega de valor al negocio. En un entorno como Azure, donde los servicios se adaptan dinámicamente a las necesidades del proyecto, DevOps es el pilar que asegura que la tecnología y las operaciones trabajen en perfecta armonía.
Una vez el arquitecto de soluciones ha definido la interoperabilidad del sistema, los componentes del sistema y la infraestructura a utilizar, es el momento en que el arquitecto software plantea el diseño y la implementación de los diferentes componentes.
Tomando de la mano estas premisas, comienza el proceso de diseño estructural del sistema que queremos implementar, siempre pensando en que, posiblemente, nuestro sistema puede evolucionar el día de mañana y debería ser abierto a extensión y lo más escalable posible.
Una parte importante de la arquitectura es el momento en que definimos en nuestro equipo la forma en que debemos implementar cada módulo, la elección del framework empleado para la persistencia de datos, la comunicación entre capas, la nomenclatura a seguir, el uso unificado de patrones en el sistema, en definitiva, la serie de normas que establecemos y que todo el equipo debe seguir.
De hecho, si cada desarrollador empleara sus propias maneras de definir las clases, de intercomunicar entre capas o utilizase múltiples patrones para resolver cada caso de uso, sería un caos para el core del equipo. Está claro que cada persona tiene su forma de desarrollar, sobre todo porque nunca todos los componentes del equipo tienen la misma experiencia, o han trabajado en equipos distintos y no conocen los mismos patrones de diseño o arquitecturas similares.
No existe una misma arquitectura que solucione todo, incluso dependiendo del nivel de experiencia del equipo es posible que haya que replantearse la manera de diseñar el software que queremos o incluso una vez implementada, realizar algunos ajustes. La arquitectura suele estar viva en el tiempo de desarrollo de la solución.
Y es que hacer que nuestra arquitectura sea flexible a cambios y no dependiente entre capas o incluso entre concreciones, puede permitirnos trabajar de manera desacoplada y desarrollarla en un entorno tolerante a modificaciones. No deberíamos depender en nuestra arquitectura de implementaciones concretas, sino de abstracciones, que nos permitan utilizar la inyección de dependencias para servirse de la concreción pertinente en el momento que lo requiera.
Hay que huir en la medida de lo posible de que como está de moda realizar todo el software orientado a microservicios, siempre, enfocarlo en cada aplicación hacia este mismo punto.
Si piensa que su aplicación de 5 años ha quedado obsoleta y es inmantenible, pero desea migrarla a microservicios... Cuidado... Si la aplicación ya es inmantenible en una arquitectura monolítica, es muy probable que también lo sea en microservicios, dado que la orientación a los microservicios implica una complejidad adicional al sistema, sobre todo en cuanto a la intercomunicación entre estos.
Volviendo al tema de las arquitecturas, hay una norma básica que debemos cumplir en el diseño de arquitecturas, necesitamos que nuestro software deje de estar acoplado u orientado a un framework y que nuestras capas no dependan ni conozcan el framework utilizado; esto nos permitiría que, si un día cambiamos el framework o simplemente la versión de este, no se vean afectadas cada una de las capas superiores.
Un ejemplo de este uso tan acoplado al framework es la arquitectura por capas [Ilustración 3], donde en el núcleo de la aplicación se encuentra el dominio donde se encapsula además el framework de acceso a datos y tiene una dependencia de la capa de acceso a datos; el resto de las capas conocen las entidades de este framework, el tipo de base de datos empleada y su implementación, de modo que cualquier cambio en el framework afectaría de forma considerable al resto de capas. En definitiva, el núcleo de la aplicación no debería conocer el framework empleado, ya que puede cambiar con el tiempo.
Ilustración 3. Arquitectura por capas.
Claro está que puede ser resuelta esta dependencia en el modelo por capas tradicional, simplemente haciendo uso de interfaces declaradas en la capa de dominio y del principio SOLID de inversión de control.
Para ayudar con la problemática mencionada, Uncle Bob propuso un esquema a seguir para cambiar la dependencia de estas capas; él lo define como arquitecturas limpias o clean architectures.
La denominación de arquitectura limpia tiene como origen un artículo escrito por Robert C. Martin, también conocido como Uncle Bob. Este ingeniero de software americano es autor de otro libro que lleva por título Clean Code y en el que se reflexiona acerca de buenas prácticas y estudio de patrones a la hora de escribir software.
Entendamos por arquitectura limpia aquella que pretende conseguir estructuras modulares bien separadas, de fácil lectura, con código limpio y que puedan realizarse test con facilidad.
Ilustración 4. Clean architecture.
Si observamos la figura [Ilustración 4], nuestro modelo o lógica de negocio está en el interior, en el corazón del diagrama y por encima de esta capa tenemos la capa de casos de uso, la de lógica de negocio de la aplicación, la de controlador y, finalmente, la capa correspondiente a la vista, base de datos, interfaces externas; en definitiva, librerías que no pertenezcan al sistema y acceso externo.
Además de las diferentes capas, quedémonos con la flecha que vemos atravesar cada capa; se denomina regla de dependencia y nos la propone Uncle Bob. Nos indica que existe un único sentido para atravesarlas, deben apuntar desde el extremo de la figura hacia su núcleo y no a la inversa. Con esta separación, si comparamos dos capas, la capa interior no debe conocer nada de las capas exteriores a ella.
De esta forma conseguimos que nuestra lógica de negocio o casos de uso sean independientes y no empleen ningún elemento de cualquier otra capa externa.
Los diferentes elementos que vemos en la figura [Ilustración 4] serían:
• Entidades: Objetos de negocio de nuestra aplicación, que poseen propiedades y métodos, deben ser reutilizables y con una estructura que varíe escasamente.
• Casos de uso: Son acciones que implementan las reglas de negocio de la aplicación, orquestando el flujo de datos desde y hacia las entidades.
• Adaptadores de interfaz: Transforman los datos desde el formato más conveniente para los casos de uso y entidades, hasta transformarlos en el formato que mejor convenga a “Base de datos” o “Interfaz de usuario”. Los objetos transferidos son objetos DTO (data transfer objects), son simples, sin lógica de negocio, de tal forma que su formato pueda ser transformado por los adaptadores de interfaz al formato que más convenga al resto de capas.
• Frameworksydrivers: Es la capa más externa que debe comunicarse
hacia las capas interiores y hacia el exterior del sistema, aquí encontramos el acceso a datos o la publicación de eventos.
Lo que propone es realmente interesante. Se basa en la dirección de la dependencia entre capas, las capas de nivel superior dependen de las capas de nivel inferior, pero no a la inversa. Ello implica un cambio brutal a lo que habíamos aplicado hasta el momento, ahora podíamos cambiar cualquier capa superior, sin que las internas se vieran afectadas por el cambio realizado.
Ahora bien, dentro de las arquitecturas limpias, está la arquitectura hexagonal [Ilustración 5], también conocida como puertos y adaptadores, que ayuda a los desarrolladores a orientar el software hacia el dominio de la aplicación, la organización de código y desacoplamiento entre capas.
Esta arquitectura resuelve el problema de acoplamiento entre proyectos de N-capas y pone en el núcleo del sistema toda la lógica del dominio, definiendo puertos primarios para interacción desde el exterior como son las interfaces de usuario, puertos secundarios de acceso a base de datos o de comunicación con sistemas o servicios externos, haciendo uso de unos adaptadores especializados en implementar dicha funcionalidad, bien sean controladores, acceso a base de datos o envío de emails, etc.
Ilustración 5. Arquitectura hexagonal.
En la figura [Ilustración 5] podemos observar cada una de las capas:
• Dominio: Capa más interna del sistema; no debe depender de ninguna otra capa. Podemos encontrar las entidades, interfaces, usadas en inversión de dependencias, que implementa la capa de infraestructura y la lógica de negocio que nosotros mismos consideremos el core de nuestra aplicación.
Otro de los recursos a tener en cuenta en esta capa podría ser el de objetos de valor o value objects, clases sencillas, que representan un valor y que pueden contener su propia lógica de negocio, como propia validación. En el momento que hacemos uso de estos recursos, estamos reemplazando, por ejemplo, en lugar de trabajar con un parámetro string como un identificador de usuario, trabajar con un UserId que representa internamente un código hash que lleva implícito que no pueda ser nulo, además de otras posibles validaciones como longitud fija del código, etc. Además, nos aporta legibilidad al código, ya que no es lo mismo indicar string UserId que UserId UserId o en caso de ser un string que sería algo más genérico, y por tanto podría enviarse cualquier cosa, sin embargo, al ver que es de tipo de dominio personalizado UserId, vemos que dicho string tendrá unas características específicas.
Cabe destacar que podemos definir validaciones a nivel de dominio, como hemos visto con los value objects, sobre tipos de objetos, longitud de atributos, validación de lógica de negocio, etc.
Otro de los elementos que encontraremos en esta capa será el registro de eventos de dominio, a través de los métodos de los modelos de dominio.
En definitiva, los servicios que contienen la implementación de la lógica de negocio definida por nosotros se definirán en esta capa, aunque únicamente debemos definir la lógica en estos servicios si se va a reutilizar por otros servicios de aplicación o casos de uso.
• Aplicación: Capa que depende de la capa de dominio de la aplicación, y por tanto puede hacer uso de las entidades definidas en la capa de dominio, así como los contratos o interfaces definidas en dicha capa. Aquí se originan todas las entradas a nuestro sistema; podemos encontrar, además, los casos de uso, es decir, acciones que nuestro sistema realiza; el conjunto de estas acciones compone el funcional de la aplicación.
Incluimos en esta capa los servicios de aplicación, responsables de invocar otros servicios de la capa de dominio, reutilizables por la capa de aplicación, además de gestionar las transacciones o publicar eventos de dominio.
Debemos, además, considerar que un servicio de aplicación deberá hacer uso de las interfaces definidas en la capa de dominio, para poder invocar a la implementación de repositorios que se encuentran en la capa de infraestructura, haciendo uso de la inversión de control (principio SOLID).
• infraestructura: Esta capa depende de la capa de dominio, es aquí donde incluiremos todo aquello que ejecute cambios hacia el exterior del sistema. Como, por ejemplo, la implementación de acceso a datos, el envío de eventos hacia otros sistemas, o el uso de paquetes externos a nuestro sistema que implementamos fuera del dominio de la aplicación; de esta forma, no intoxicaremos nuestro dominio y nos desacoplamos de esta capa.
Por este motivo, aquí encontraremos la implementación de los repositorios, que serán accesibles por otras capas, haciendo uso de interfaces definidas en la capa de dominio, para que, en caso de que un día modifiquemos dicha implementación, el resto de las capas no se vean afectadas por dicho cambio, como versiones de bases de datos o incluso cambio de persistencia de base de datos.
Observemos, pues, que la regla de la dependencia sigue activa al tratar como arquitectura limpia; la dependencia sería desde la capa más externa, infraestructura, pasando por la de aplicación y acabando en el dominio del sistema. O, lo que es lo mismo, la regla de fuera hacia dentro.
Esto implica que no deberíamos encontrar en la capa dominio ninguna referencia que no sea a sí misma, ni la capa de aplicación debería tener referencias distintas de la capa de dominio.
Y ¿de qué forma el dominio o lógica de negocio puede conocer la capa externa de infraestructura? Realmente no la conoce; simplemente, al tener definida la interfaz que implementa la infraestructura, la capa de aplicación o las reglas de negocio del dominio pueden llegar a invocar a los repositorios de acceso a datos y, por tanto, ejecutar su implementación. Para ello hace uso de la inyección de dependencias, para resolver la interfaz por una implementación concreta, y de la inversión de dependencias de los principios SOLID.
De hecho, si no definiéramos esta interfaz en el dominio, cada capa debería invocar a la concreción, creando dependencias entre capas, y, por tanto, no solo rompería la regla de dependencia, sino que cualquier cambio en la implementación afectaría al resto de capas.
