BLOG

Plano de control para PaaS de Kubernetes distribuido

Miniatura de Ankur Singla
Ankur Singla
Publicado el 15 de noviembre de 2019

Este blog es el primero de una serie de blogs que cubren diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS :

  1. Plano de control para PaaS de Kubernetes distribuido
  2. Malla de servicios global para aplicações distribuidas
  3. Seguridad de la plataforma para infraestructura distribuida, aplicaciones y datos
  4. Seguridad de aplicação y redes de clústeres distribuidos
  5. Observabilidad en una plataforma distribuida globalmente
  6. Operaciones y SRE de una plataforma distribuida globalmente
  7. Marco de servicios Golang para microservicios distribuidos

Como describimos en nuestro blog anterior , nuestros clientes están construyendo conjuntos complejos y diversos de soluciones comerciales (como fabricación inteligente, análisis forense de video para seguridad pública, comercio algorítmico, redes de telecomunicaciones 5G) y, por lo tanto, necesitamos brindar una experiencia siempre activa, conectada y confiable para estas aplicações y sus usuarios finales.

Dado que estas aplicações podrían ejecutarse en múltiples clústeres entre proveedores de nube o ubicaciones periféricas de clientes, nuestro equipo de plataforma tuvo que construir un plano de control distribuido y un servicio PaaS para implementar, proteger y operar múltiples clústeres de Kubernetes de múltiples inquilinos. Este plano de control distribuido ha proporcionado muchos beneficios operativos, de escalamiento y de rendimiento que abordaremos en nuestra presentación ( enlace de video ), por ejemplo, cómo administrar miles de clústeres K8 de borde con GitOps, y también como una publicación de blog separada en las próximas semanas.

TL;DR (Resumen)

  • No pudimos encontrar una solución fácil de usar en el mercado que pudiera resolver el problema de implementar, proteger y operar múltiples clústeres de aplicação distribuidos entre proveedores de nube, nubes privadas o múltiples ubicaciones de borde.
     
  • No pudimos encontrar una distribución robusta de Kubernetes o PaaS (por ejemplo, OpenShift, Cloud Foundry, etc.) que brindara un conjunto integral de servicios operativos y de seguridad necesarios para clústeres distribuidos, por ejemplo, identidad basada en PKI, RBAC y gestión de acceso de usuarios, secretos y gestión de claves entre proveedores de nube, malla de servicios de múltiples clústeres, registros de auditoría y observabilidad, o seguridad de aplicação y redes.
     
  • Anthos (Google), Azure Arc (Microsoft) y Rancher son estaciones de administración de múltiples clústeres y paquetes de múltiples servicios diferentes; nuestro análisis fue que estos no habrían resuelto los requisitos operativos, de escalamiento, de seguridad y de múltiples inquilinos que teníamos para los servicios de aplicação e infraestructura en múltiples clústeres.
     
  • Tuvimos que construir nuestro propio plano de control distribuido para nuestro PaaS administrado que está construido sobre Kubernetes. Comenzamos con Kubernetes básico y luego realizamos cambios significativos para brindar los servicios de plataforma que necesitaban nuestros equipos de DevOps y SRE. Además, tuvimos que construir un plano de control para administrar grandes cantidades de clústeres distribuidos y brindar multi-tenencia en una infraestructura heterogénea (en el borde, nuestra red y múltiples proveedores de nube).

Kubernetes para la gestión de aplicaciones: Por qué y cómo

Elegimos Kubernetes (K8s) como el núcleo de nuestra plataforma para administrar aplicações distribuidas, ya que proporciona un amplio conjunto de funcionalidades sin ser demasiado prescriptivo, lo que nos da flexibilidad para innovar en cuestiones que creemos que son importantes para nuestros clientes. Utilizamos esto como base sobre la cual comenzar a construir nuestro servicio y, con la creciente popularidad de K8s, también es más fácil encontrar desarrolladores y operadores que estén familiarizados con él.

Dicho esto, implementar y administrar una gran cantidad de clústeres de Kubernetes de nivel de producción en un entorno híbrido (múltiples nubes, POP de red y ubicaciones de borde) no es muy fácil, ya que no existen soluciones listas para usar para Kubernetes que puedan:

  1. Armonizar los recursos de infraestructura heterogéneos con agrupamiento automatizado, escalamiento y aprovisionamiento sin intervención; esto fue especialmente doloroso en el borde y en nuestros PoP de red.
  2. Proporcionar conectividad confiable y de alto rendimiento en distintas ubicaciones, especialmente al cruzar proveedores de nube y provenir de ubicaciones periféricas.
  3. Resuelva el problema de seguridad de los datos en tránsito, los datos en reposo, los secretos, las claves y la red... todo respaldado por una identidad PKI uniforme que funciona en el borde, la red y la nube.
  4. Proporcionar una verdadera multitenencia (aislamiento de inquilinos y garantías de seguridad) con la capacidad de ejecutar cargas de trabajo de producción y desarrollo para las necesidades internas y del cliente en los mismos clústeres.
  5. Proporcionar observabilidad y operaciones en clústeres distribuidos que se vinculan con políticas e intenciones centralizadas, sin la necesidad de crear registros complejos ni recopilar métricas.

Después de varias pruebas de concepto con múltiples proveedores de nube y plataformas de código abierto como GKE, AKS, EKS y RKE, así como OpenShift y Cloud Foundry, nos dimos cuenta de que ninguno de ellos podía cumplir con los cinco requisitos anteriores. Como resultado, decidimos construir nuestro propio PaaS (comenzando con Kubernetes “básico” e hicimos varias adiciones) para identidad, redes, seguridad, multitenencia, registro, métricas, etc. Si bien utilizamos Kubernetes para satisfacer nuestras necesidades internas, tuvimos que tomar algunas decisiones difíciles, como no exponer estos clústeres de Kubernetes directamente a nuestros usuarios y/o clientes internos para ejecutar sus cargas de trabajo (hablaremos más sobre esto más adelante, ya que la multitenencia era un objetivo clave para nosotros).

Además de varias características nuevas que necesitábamos agregar, también existía la necesidad de ejecutar nuestras cargas de trabajo/servicios junto con las cargas de trabajo de los clientes en muchas ubicaciones en el borde, nuestra red y nubes públicas/privadas. Esto significó que tuvimos que desarrollar capacidades adicionales para administrar múltiples clústeres en múltiples entornos… todos conectados mediante nuestra red global y nuestros gateways de aplicação distribuidas para brindar conectividad a nivel de aplicación y de confianza cero en todos estos clústeres.

La parte difícil: Multi-inquilino y multi-clúster para Kubernetes

Desarrollar y operar aplicações que se ejecuten en un único clúster de Kubernetes no es una tarea trivial, incluso si se utiliza un clúster administrado por un proveedor de nube. Es por esto que es común que los equipos de DevOps y SRE minimicen sus gastos generales y no se ocupen de las complejidades de muchos clústeres. Es bastante común ver equipos que construyen un gran clúster de Kubernetes y colocan todo tipo de recursos dentro del mismo clúster. Si bien esto parece excelente porque puede simplificar las operaciones y ejecutar el clúster para lograr la máxima eficiencia y costo computacionales, no es la mejor idea por varias razones. En primer lugar, las necesidades de las cargas de trabajo de producción son muy diferentes a las de desarrollo y pruebas y a las de preparación: las cargas de trabajo de desarrollo inestables pueden causar problemas potencialmente para las cargas de trabajo de producción más estables.

Además de las necesidades de cargas de trabajo variadas, las limitaciones de seguridad y aislamiento de K8 son otro factor que impulsa la creación de múltiples clústeres. Un enfoque típico para resolver la seguridad y el aislamiento de recursos de K8 es crear clústeres independientes para cada inquilino utilizando un modelo de múltiples inquilinos. Si bien esto puede ser posible hacerlo en la nube, no es posible en el borde ejecutar múltiples clústeres. Los sitios de borde tienen limitaciones de recursos de procesamiento y almacenamiento y un ancho de banda de red restringido para enviar registros y métricas de cada clúster adicional a la nube central.

Para abordar el problema de múltiples clústeres de Kubernetes, evaluamos Rancher para la administración centralizada de nuestros clústeres de Kubernetes (cuando comenzamos, Anthos y Azure Arc no existían) y KubeFed. Los dos enfoques disponibles en ese momento eran (y siguen siendo la misma situación hoy en día):

  1. La administración de múltiples clústeres (por ejemplo, Rancher) desde una consola central nos habría dado la capacidad de implementar múltiples clústeres en cualquier ubicación y realizar operaciones de administración del ciclo de vida, como actualizaciones, reversiones, etc. Algunos de estos sistemas también brindaron la capacidad de abordar un clúster individual con automatización para la configuración y el despliegue de aplicações.
     
  2. Otro enfoque es implementar un plano de control de federación de clústeres de Kubernetes (KubeFed), lo que puede hacer que varios clústeres físicos parezcan un solo clúster. Este proyecto apenas estaba comenzando cuando lo analizamos y aún hoy se encuentra sólo en la etapa alfa.

Después del reciente anuncio de GCP Anthos y Azure Arc, reevaluamos nuestra decisión original de construir un plano de control distribuido y la conclusión fue que incluso estas dos nuevas ofertas no podrían haber resuelto dos problemas críticos con los clústeres distribuidos. Las dos capacidades clave que necesitábamos para nuestra plataforma eran:

  1. Administrar múltiples clústeres como una flota para resolver el problema de realizar operaciones en todos los clústeres o en un grupo lógico de ellos (operaciones como configuración, implementación, métricas, etc.). Esto es fundamental ya que queremos reducir la sobrecarga operativa de nuestros equipos de SRE, mejorar la capacidad de depuración de nuestro DevOps y mejorar la escalabilidad de nuestro sistema.
     
  2. Capacidad de dividir un clúster físico individual de Kubernetes para multiinquilino sin necesidad de crear clústeres físicos: esto es especialmente crítico en entornos con recursos limitados donde no queremos agregar nuevos clústeres físicos solo para multiinquilino

Para resolver estos dos problemas, tuvimos que idear una nueva técnica (el plano de control distribuido) para resolver la sobrecarga operativa de “múltiples” clústeres y brindar un equivalente de “múltiples clústeres” para múltiples inquilinos en entornos con recursos limitados.

Plano de control distribuido: Cómo logramos Kubernetes multiclúster

Nuestro equipo de plataforma decidió construir un plano de control distribuido para Kubernetes que expone las API de Kubernetes para el uso de nuestro equipo, sin embargo, estas API provienen de clústeres "virtuales" que solo existen en nuestro plano de control: un servidor de API K8s virtual (vK8s) para un clúster K8s virtual (como se muestra en la Figura 1 ). Este plano de control asigna la intención del usuario a múltiples clústeres físicos de Kubernetes que se ejecutan en nuestro borde, nuestros POP de red y ubicaciones de nube pública. Estos clústeres físicos solo son accesibles para nuestro plano de control distribuido y no para ningún usuario o inquilino individual.

plano de control-01
Figura 1: Plano de control distribuido

Este plano de control proporciona a cada inquilino uno o más clústeres de aplicação "virtuales" donde pueden implementar sus aplicação y, según la configuración, el plano de control las replicará y administrará en múltiples clústeres físicos de Kubernetes. Además de las operaciones de configuración e implementación, las operaciones de monitoreo también siguen este clúster “virtual” sin la necesidad de construir herramientas para recopilar y analizar datos de múltiples clústeres físicos.

Tomemos una aplicação de interfaz de usuario de ejemplo llamada productpage, donde la intención del usuario es ejecutarla distribuida en 3 ubicaciones: pa2-par, ny8-nyc y ams9-ams con 2 réplicas en cada una de ellas. A medida que el usuario crea un objeto vK8s y lo adjunta a un clúster virtual, este aprovisiona inmediatamente un servidor API vK8s que se puede usar con kubectl estándar.

Como siguiente paso, el usuario descarga kubeconfig para este clúster virtual y crea un yaml estándar para describir una implementación de K8s para productpage.

Después de la creación de la especificación de implementación, el usuario puede proceder a crear una implementación en este clúster virtual:

Ahora, si el usuario verifica su implementación, verá que se han iniciado 6 réplicas con 2 en cada ubicación (pa2-par, ny8-nyc y ams9-ams).

La siguiente salida muestra 2 pods ejecutándose en cada ubicación con mapeo a un nodo físico particular

Este sencillo ejemplo demuestra lo trivial que es obtener la replicación de múltiples clústeres de cualquier aplicación en minutos sin ninguna carga de instalación ni administración. Además de mapear la intención, el plano de control distribuido también proporciona capacidad de observación para el clúster virtual y no para cada clúster individual.

Control distribuido y gestión centralizada para múltiples inquilinos

Como puede ver en la Figura 2 , nuestro plano de administración centralizado se ejecuta en dos proveedores de nube pública (una región cada uno): uno en AWS y otro en Azure (para redundancia). Este plano de administración permite que nuestro SRE cree inquilinos con multitenencia estricta; por ejemplo, un equipo de desarrollo que trabaja en nuestro servicio VoltMesh puede ser un inquilino y un equipo de soluciones de clientes que trabaja en POC de clientes puede ser su propio inquilino con su propio conjunto de usuarios.

Figura 2: Multi-tenencia y multi-clúster

Cada uno de estos inquilinos puede crear muchos espacios de nombres y asignar un grupo de usuarios para colaborar en estos espacios de nombres. Estos espacios de nombres no son espacios de nombres de Kubernetes; son un límite de aislamiento en nuestra plataforma con reglas RBAC y políticas IAM para los usuarios.

Cuando un usuario dentro de un espacio de nombres desea crear un clúster de aplicação , crea un objeto vK8s y eso, a su vez, crea un servidor API vK8s en nuestro plano de administración. Al utilizar este objeto vK8s, el usuario puede crear implementaciones, conjuntos con estado, PVC, etc. y el plano de control garantizará que estas operaciones ocurran en uno o varios clústeres físicos, en función de los sitios asociados con el objeto vK8s.

Dado que cada inquilino y usuario utiliza operaciones estándar de K8s sin ninguna modificación, el sistema puede ser compatible con varias herramientas populares entre los operadores, por ejemplo, Spinnaker, Helm, Jenkins, etc.

Ganancias obtenidas de un plano de control distribuido

La gran ventaja de un plano de control distribuido es que ha resuelto la sobrecarga operativa de nuestros equipos de SRE y DevOps. Ahora pueden realizar operaciones (configuración, implementación, monitoreo, políticas, etc.) en un clúster virtual y el plano de control lo mapeará automáticamente en múltiples clústeres físicos. Además de la simplificación operativa para múltiples clústeres, el plano de control también ha resuelto el problema de seguridad y aislamiento para múltiples inquilinos.

Este plano de control distribuido también ha mejorado la productividad de los desarrolladores que desean agregar nuevas funciones a nuestra plataforma: no tienen que crear una nueva automatización cada vez que agregan nuevas funciones que afectan la configuración o las operaciones en múltiples clústeres. Utilizan el modelo de configuración basado en intenciones y el plano de control sabe lo que hay que hacer. Además, pueden seguir interactuando con este objeto de clúster distribuido y múltiple (Kubernetes virtual) usando kubectl y no otra CLI.

Después de ejecutar esto en nuestros entornos de desarrollo, prueba, ensayo y producción durante más de un año, nos dimos cuenta de que este plano de control distribuido globalmente (que se ejecuta en nuestros POP de red) también brinda importantes ventajas de escala, rendimiento y confiabilidad, algo que no habíamos imaginado por completo durante nuestros inicios. Cubriremos este hallazgo en nuestra próxima presentación de KubeCon y como una publicación de blog separada en las próximas semanas.

Continuará…

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. El siguiente paso es Global Service Mesh para aplicaciones distribuidas