Este blog es el segundo de una serie de blogs que cubren diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS :
En un blog anterior , proporcionamos algunos antecedentes sobre nuestras necesidades que nos llevaron a construir una nueva plataforma. Al utilizar esta plataforma, permitimos a nuestros clientes crear un conjunto complejo y diverso de aplicações , como fabricación inteligente, análisis forense de video para seguridad pública, comercio algorítmico y redes de telecomunicaciones 5G.
El primer blog de esta serie cubrió un plano de control distribuido para entregar múltiples clústeres de aplicação basados en Kubernetes de múltiples inquilinos en la nube pública, nuestros PoP de red privada y sitios de borde.
Este blog específico abordará los desafíos de conectar y proteger estos clústeres de aplicação distribuidas desde tres puntos de vista: de aplicação a aplicação, de usuario/máquina a aplicação y de aplicação a Internet público. Presentaremos una ruta de datos L3-L7+ completamente nueva y totalmente integrada, un plano de control distribuido globalmente y nuestra red global de alto rendimiento. Estas tres cosas se combinan para brindar un conjunto integral de servicios de red y seguridad en el borde, dentro de cualquier VPC en la nube o en nuestros PoP de red global . Después de funcionar en producción con más de 35 clientes durante más de un año, comenzamos a escalar la implementación y sentimos que ahora es un buen momento para compartir nuestra experiencia.
A medida que nuestros clientes crean aplicações bastante complejas y de misión crítica (como fabricación inteligente, análisis forense de video para seguridad pública, comercio algorítmico y transición a 5G de las telecomunicaciones), necesitamos brindar una experiencia siempre activa, conectada y confiable para las aplicações y los usuarios finales de estas aplicações. Algunas de estas aplicações ejecutan canales de datos a través de clústeres dentro de una nube, o necesitan realizar copias de seguridad de datos entre proveedores de la nube, o necesitan una entrega confiable de solicitudes desde una base de usuarios global a los backends de las aplicaciones, o necesitan una conectividad de alto rendimiento desde sus máquinas a los backends que se ejecutan en nubes centralizadas.
Para satisfacer estas necesidades, había dos requisitos de la red física:
R1 — Nube a nube : alto rendimiento y conectividad a pedido de aplicações en ubicaciones de nube pública o privada en todo el mundo
R2 — Internet a la nube — Para que los dispositivos y las máquinas en ubicaciones periféricas se conectaran de manera confiable al backend de la aplicação , necesitábamos proporcionar múltiples rutas redundantes, así como finalizar las conexiones lo más cerca posible de estos usuarios, en lugar de retransmitir el tráfico hasta los backends usando Internet.
Podríamos haber resuelto el requisito R1 y R2 yendo a un proveedor de servicios de red como AT&T, pero no podrían habernos brindado una experiencia de red perfecta ni una integración con nuestros servicios de aplicação (configuración basada en API, telemetría de transmisión, capacidad de agregar fácilmente nuestros propios prefijos de IP o los de nuestros clientes, servicios de red basados en API, etc.). Además, obtener cobertura global por parte de los proveedores de servicios es muy difícil o prohibitivamente caro. Podríamos haber recurrido a dos o tres proveedores de servicios diferentes para resolver todos estos problemas, pero habríamos terminado con un caos de sistemas diferentes que se comportan de manera diferente, tienen diferentes modos de fallo, diferentes SLA, sistemas de soporte y tienen diferentes (o ninguna) API.
Así que terminamos necesitando construir nuestra propia red y esto significaba que la red necesitaba tener tres propiedades:
Para cumplir con estas tres propiedades, necesitábamos hacer muchas cosas. Sin embargo, destacaremos cinco grandes elementos:
Nos dimos cuenta muy pronto en nuestro desarrollo de que construir y operar una red global requiere tiempo y habilidades, y necesitábamos aportar esta experiencia. Después de meses de discusiones con los fundadores de Acorus Networks (proveedor de seguridad con sede en París, Francia), terminamos fusionando Acorus con Volterra. Esto nos ayudó a resolver el problema de nuestra infraestructura global y el despliegue de la red. Acorus había puesto en marcha una gran red y un equipo de operaciones que había automatizado completamente la configuración de la red física utilizando Ansible y había creado API externas para telemetría y configuración que nuestro equipo de software podía usar.
Ahora que teníamos un equipo enfocado en construir una red privada global con alta confiabilidad y rendimiento, podíamos resolver fácilmente los problemas de tráfico tanto de aplicação a aplicação como de usuario/máquina a aplicação a través de ubicaciones de borde o de nube como se muestra en la Figura 1. Además, la infraestructura de cómputo y almacenamiento en nuestros PoP de red también nos permitió agregar terminación de API, seguridad de aplicaciones y descarga de carga de trabajo (desde el borde o la nube) a nuestra red. Esto nos permitirá seguir desarrollando nuestras capacidades durante mucho tiempo y ampliar fácilmente nuestra red y nuestro catálogo de servicios en función de la demanda.
Una vez que tuvimos una red global en funcionamiento, necesitábamos comenzar a agregar clústeres de aplicação y nuestras cargas de trabajo. Estas cargas de trabajo necesitan su propio conjunto de servicios de seguridad y conectividad a nivel de aplicación.
Como explicamos en nuestro blog anterior , nuestro objetivo con la plataforma era mejorar la productividad y reducir la complejidad de nuestros equipos que administran cargas de trabajo que se ejecutan en múltiples entornos (nube, borde y nuestros PoP de red).
Cada proveedor de nube requiere configurar, administrar y monitorear muchos recursos de nube diferentes para lograr una conectividad segura con los clústeres de aplicação . Por ejemplo, en Google Cloud, para configurar un servicio de red de extremo a extremo para un clúster de aplicação , será necesario que administremos muchos conjuntos diferentes de servicios:
Genial, aunque sería un gran desafío, podríamos haber decidido abordarlo construyendo una capa de configuración y operaciones para armonizar entre todos los proveedor de nube. Sin embargo, sabíamos que no habría resuelto nuestros problemas ya que los servicios de los proveedores de la nube no satisfacían todas nuestras necesidades (por ejemplo, los CSP no tienen la capacidad de realizar seguridad de aplicação y API), no son los mejores del tipo y están cambiando continuamente.
Además, ¿qué pasa con nuestros PoP de red y sitios de borde? Tendríamos que obtener capacidades similares de proveedores de hardware o software e integrarlas todas; por ejemplo, Cisco/Juniper para enrutamiento, NAT y VPN, F5 para equilibrio de carga y firewall, etc. En los puntos periféricos, el problema se agrava porque ni los proveedores de la nube ni los grandes proveedores de redes pudieron resolver los problemas de servicios de red para un entorno con recursos limitados. Otra opción potencial para el borde podría haber sido mover toda la conectividad de las aplicação , la seguridad y los servicios de red a nuestra red global , pero estaba claro que eso no funcionaría ya que el tráfico de aplicación a aplicación dentro del mismo sitio del borde también necesitaba algunos de estos servicios.
Después de realizar muchas discusiones y examinar el panorama, nos dimos cuenta de que realizar la integración entre muchos proveedores de servicios y vendedores (configuración, telemetría, monitoreo, alertas) y mantenerse al día con sus cambios en las hojas de ruta y API iba en contra de nuestro objetivo de simplicidad y velocidad.
Otro problema que necesitábamos resolver en toda la plataforma era la multitenencia: esto era más fácil de hacer para los servicios WAN y el enrutamiento de red, pero un desafío para los servicios de redes de aplicação , dado que la mayoría de los balanceadores de carga en el mercado no tienen soporte para multitenencia o este es muy limitado.
Como resultado, decidimos asumir este desafío y construir una ruta de datos de red de alto rendimiento que no solo brinde servicios de enrutamiento de red, sino también aplicação, seguridad y servicios de área amplia. Esto nos permitiría unificar la cartera de servicios en nuestro entorno de nube híbrida y distribuida y nos obligaría a depender de un conjunto mínimo de servicios nativos en nubes públicas.
Dado que el equipo tenía una buena experiencia en redes y que habíamos lidiado con problemas similares en nuestras vidas anteriores con Contrail/Juniper, pensamos que la mejor ruta para resolver este problema sería comenzar con una pizarra limpia y construir una nueva solución de red que integre servicios L3 a L7+ en una única ruta de datos que pueda ejecutarse en cualquier nube o borde mientras es administrada de manera centralizada por nuestra plataforma.
Elegimos los mejores proyectos para comenzar el diseño de esta nueva ruta de datos: OpenContrail vRouter (para L3-L4) en el que ya habíamos pasado 6 años desarrollando y Envoy para L7, ya que cuenta con un gran respaldo de la comunidad. Dicho esto, tuvimos que hacer varios cambios y adiciones para construir una nueva ruta de datos L3-L7+ unificada: multitenencia para Envoy, dpdk para Envoy, pila TCP dpdk de espacio de usuario, política de red, VPN SSL/IPSec, conexión http, proxy inverso dinámico, proxy directo transparente, puerta de enlace API, política de aplicação programable, ACL rápidas para protección DDoS, integración de identidad PKI, motor Chrome v8, seguridad de aplicação y redes, etc.
Esta ruta de datos (como se muestra en la Figura 2 ) se implementa como puerta de enlace de entrada/egreso para nuestros clústeres de aplicação , puerta de enlace de software en el borde, para brindar capacidad de malla de servicios dentro de un clúster o entre múltiples clústeres, o para brindar servicios de red desde nuestros PoP globales.
Para alinearnos con nuestra necesidad de tenencia múltiple para la plataforma (cubierta en el blog anterior), también necesitábamos brindar tenencia múltiple completa para esta ruta de datos de red. Esto fue relativamente sencillo para la capa de enrutamiento ya que vRouter ya soportaba VRF ; sin embargo, tuvimos que hacer cambios en Envoy para que fuera multiinquilino. Como no estábamos usando la pila TCP del kernel, cambiamos la interfaz del socket TCP de Envoy y agregamos reconocimiento de VRF.
Esta ruta de datos también necesitaba realizar seguridad de API, firewalls de aplicação y seguridad de red: utilizamos una combinación de técnicas algorítmicas e inferencia de máquina para esto y cubriremos este tema en una próxima publicación del blog.
Obtuvimos muchas ventajas al construir esta ruta de datos de red:
Capacidades completas L3-L7+ con configuración, control y observabilidad uniformes
El soporte para escalamiento horizontal dentro de un solo clúster nos permite admitir una variedad de dispositivos de borde, desde uno de tamaño muy reducido y de menor rendimiento, hasta una capacidad de 100 Gbps o más en nuestra red o ubicaciones de nube pública.
Agregue rápidamente nuevas capacidades a la ruta de datos de la red sin depender de ningún proveedor de red y/o proveedor de nube
Solución común con características de falla y rendimiento similares en cualquier entorno: muy importante para nuestros equipos de operaciones.
Ahora que podíamos implementar múltiples clústeres de aplicaciones con esta nueva ruta de datos de red, era fundamental construir un plano de control distribuido globalmente para configurarlos, controlarlos y monitorearlos.
Nuestro equipo de plataforma tuvo que abordar varios problemas como parte de la construcción de un plano de control distribuido para administrar una gran cantidad de nodos de procesamiento de rutas de datos distribuidas. Dado que construimos una nueva ruta de datos, no había un plano de control listo para usar que pudiéramos aprovechar y tuvimos que escribir el nuestro: Plano de control local para administrar múltiples rutas de datos que se ejecutan dentro de un solo clúster (nube, borde o PoP de red). Estos nodos de ruta de datos necesitaban un plano de control local para administrar cambios de configuración, actualizaciones de ruta, realizar controles de estado, realizar descubrimientos de servicios, conectarse con otros dispositivos de red mediante un protocolo como BGP, agregar métricas y registros de acceso, etc. Plano de control distribuido para administrar múltiples planos de control locales: hay un plano de control distribuido que se ejecuta en nuestros PoP de red global ( Figura 3 ) y este plano de control es responsable de la administración de la configuración de los planos de control locales, la distribución del estado operativo en cada uno de los planos de control locales y la recopilación de datos de cada uno de los nodos. Para distribuir el estado operativo, decidimos utilizar BGP porque es consistente y robusto. Dado que habíamos creado una implementación de BGP a gran escala y de múltiples subprocesos como parte de OpenContrail, la aprovechamos y agregamos extensiones para equilibrar la carga (distribución de comprobaciones de estado, puntos finales http/api, propagación de políticas, etc.).
Además, hay un plano de administración centralizado que se ejecuta en dos regiones de nube (AWS y Azure) que se utiliza junto con el plano de control distribuido para brindar multitenencia, como se muestra en la Figura 4 . Nuestro equipo de SRE puede crear múltiples inquilinos y cada inquilino está completamente aislado de otro inquilino en nuestra red global. Sólo pueden enrutarse entre sí mediante una “red pública”. Dentro de un inquilino, los servicios a través de espacios de nombres pueden comunicarse entre sí según reglas de seguridad y enrutamiento http/api/network.
Los planos de control se ejecutan como cargas de trabajo de Kubernetes en un inquilino separado y un espacio de nombres aislado que está bajo el control únicamente de nuestros equipos de SRE. Como resultado, ningún desarrollador y/o cliente puede interrumpir este servicio. Además, dado que el plano de control está distribuido, una interrupción de un plano de control en una ubicación no afecta el servicio general.
Una vez que determinamos las necesidades de nuestra red global y definimos los requisitos para los servicios de red L3-L7+ para clústeres de aplicaciones (una nueva ruta de datos y un plano de control distribuido), nuestro equipo de producto ideó más requisitos que hicieron nuestra vida aún más emocionante. Básicamente, querían que entregáramos una malla de servicios global entre clústeres con las siguientes características:
Con los requisitos n.° 2 y n.° 3, el objetivo era mejorar el tiempo de respuesta y el rendimiento de la conectividad de cliente a servidor y esto es realmente crítico en la comunicación de aplicação a aplicação o para aplicações SaaS a gran escala. Para cumplir con los requisitos n.° 2 y n.° 3, quedó claro que el mejor enfoque era construir un proxy distribuido (Figura 5): un proxy de ingreso y un proxy de egreso y una ruta basada en el direccionamiento de la aplicação y no en el direccionamiento de la red. Además, decidimos distribuir la salud de los puntos finales de servicio (o servidores) aprovechando el plano de control distribuido y las extensiones BGP (como se describió anteriormente). Esta implementación del proxy distribuido se muestra en el diagrama a continuación.
Dado que se convirtió en un proxy distribuido con una pila de red L3-L7+ completa, lo llamamos puerta de enlace de aplicação distribuida globalmente. Toda la funcionalidad que está disponible en nuestra ruta de datos de red ahora está disponible en nuestra red global ; por ejemplo, equilibrio de carga y enrutamiento basado en HTTP o API, aplicación de políticas en el borde, transformación de API, terminación TLS más cerca del usuario, etc.
El equipo logró obtener múltiples beneficios con la implementación de un portal de aplicação distribuido globalmente. Estas ganancias se dieron en las áreas de mejoras operativas, seguridad, rendimiento y TCO:
Esta serie de blogs cubrirá diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS distribuido globalmente con muchos clústeres de aplicação en la nube pública, nuestros PoP de red privada y sitios de borde. A continuación tenemos la Plataforma y seguridad de datos …