No, no he perdido la cabeza. Unicornio es el nombre en código interno de Couchbase Autonomous Operator 2.0.0. Para un lanzamiento de esta envergadura queríamos algo mítico y fantástico que resumiera el esfuerzo y la pasión que se ha puesto en él. También es ligeramente divertido dar a la dirección una plataforma en la que tienen ¡para hablar de unicornios y duendecillos! Para subrayar la dificultad de este lanzamiento, nos centraremos en un aspecto clave del Operador: Los recursos personalizados de Kubernetes. Los recursos personalizados son la base de todo lo que hace Operator.
Esta entrada forma parte de una serie de blogs técnicos que profundizan en el funcionamiento interno de Operator. Este blog se centrará en ir de A a B. Parece sencillo, ¿verdad? (O vago...) Como verán, fue todo menos eso. Definiremos lo que queremos decir con esto, examinaremos los retos técnicos y, por último, llegaremos a la conclusión de por qué decidimos hacer lo que hicimos.
Desde el equipo de desarrollo hasta usted, el usuario final, esperamos que tenga una experiencia de uso tan buena como la que hemos tenido creándola.
¿De A a B con CRD?
¿Qué queremos decir con esto? En primer lugar, veamos por qué necesitamos una B. Operator 1.x gestiona clusters Couchbase con un único objeto de configuración, un recurso personalizado en terminología de Kubernetes. Este enfoque tiene sus ventajas -todo se controla de forma centralizada-, pero también tiene sus inconvenientes: para realizar cualquier cambio en el clúster es necesario tener acceso a todos los aspectos del mismo.
Me gusta el primer enfoque, y se lo digo al equipo todo el tiempo:
Sin embargo, ante todo proporcionamos un servicio empresarial. La seguridad debe ser una preocupación primordial, desde la capa de red hasta los procesos empresariales que existen durante la vida útil de un clúster.
Separación de preocupaciones
Un requisito empresarial claro era que un usuario pudiera crear un cubo de datos privado y utilizarlo. Ese mismo usuario no debería poder hacer nada más. No debía permitirse escalar el clúster, ya que esto podría causar interrupciones a otros usuarios. Nuestros objetivos eran, por tanto:
- Definición de roles en Kubernetes
- Los usuarios pueden gestionar cubos y procesar datos sin afectar a otros usuarios
- Los administradores pueden modificar la topología del cluster según las necesidades
Además de ofrecer fuertes garantías de seguridad, los roles separan las preocupaciones. Los usuarios finales sólo necesitan saber cómo manipular documentos y ejecutar consultas N1QL. Las principales preocupaciones de los administradores son el cumplimiento de las normas de seguridad, la utilización de los recursos y el coste. Sin embargo, hay una contrapartida. Limitar el conocimiento a dominios específicos también erige barreras entre esos dominios. La solución necesita flexibilidad para ofrecer la posibilidad de elegir donde existen barreras.
Descomposición personalizada de recursos
La clave para alcanzar nuestros objetivos es Kubernetes RBAC. Kubernetes RBAC permite a usuarios específicos realizar acciones específicas en tipos de recursos específicos. Avanzamos hacia nuestro objetivo dividiendo nuestro recurso de clúster monolítico Couchbase en tipos de recursos separados de clúster central y cubo. Cada tipo de recurso puede tener un conjunto separado de usuarios que están autorizados a utilizarlos.
Otra consideración con la que tenemos que lidiar es cómo el hecho de poder configurar un aspecto del clúster puede comprometer otro. Operator 2.0 introduce la gestión de la replicación entre centros de datos (XDCR). Estaría bien permitir a los usuarios de buckets configurar sus propias estrategias de replicación. Para configurar una replicación es necesario conectarse a un clúster remoto. Esto requiere credenciales que están configuradas con secretos Kubernetes. Al conceder a un usuario acceso a los secretos, se revelan todas las contraseñas y claves privadas TLS del espacio de nombres.
Por lo tanto, consideramos cualquier que requiere el acceso a los secretos como una operación "sólo para administradores". Esto ayuda a limitar el alcance entre los dominios de conocimiento lo mejor que podemos.
Agregación de recursos personalizada
La configuración de un cluster de Couchbase está ahora distribuida a través de muchos recursos diferentes. Estos son controlados por muchas personas diferentes con roles específicos. El Operador, sin embargo, necesita ver el imagen completa para crear y gestionar el clúster.
Por defecto, y sin que sea culpa suya, Operator 2.0 actúa de forma ingenua. Cuando empieza a monitorizar un cluster de Couchbase, también monitorizará cualquier recurso de bucket que encuentre. Se crea un único cluster lógico a partir de la agregación de estos recursos de cluster y de bucket. Si creas otro cluster, también encontrará y agregará los mismos recursos de bucket. Es posible que no desee este comportamiento, y Kubernetes proporciona el camino de nuevo.
Para cada tipo de recurso que se agrega, hay un selector de etiqueta correspondiente que se puede configurar. Este selector de etiquetas permite controlar exactamente qué recursos se agregan. Sólo los recursos con las etiquetas correspondientes serán seleccionados por el Operador.
La salida
Ahora sabemos que descomponer el recurso del cluster Couchbase es algo bueno. Aunque hacer esto no está exento de fallos, los beneficios los superan.
Kubernetes proporciona primitivas que nos ayudan a lograr nuestro objetivo con RBAC y selección de etiquetas. Nuestro viaje de A a B será fácil, ¿verdad? Piénsalo de nuevo.
Limitaciones de la plataforma
En un mundo perfecto, el Operador funcionaría en todas las versiones de Kubernetes disponibles. Sin embargo probablemente cierto para futuras versiones de Kubernetes que mantengan la compatibilidad con versiones anteriores. Yo digo probablemente porque pueden introducirse extensiones incompatibles con una aplicación escrita antes de su lanzamiento. Por este motivo, cada versión de Operator tiene una ventana de versiones de Kubernetes certificadas.
Las versiones certificadas de Kubernetes tienen un límite superior e inferior. Los límites están fuera de nuestro alcance. Solo podemos certificar si un proveedor de la nube admite una versión determinada. En el momento de redactar este documento, Google Kubernetes Engine (GKE) solo admite las versiones 1.14 y 1.15 de Kubernetes. El Operador está certificado en Amazon Elastic Kubernetes Service (EKS), Microsoft Azure Kubernetes Service (AKS) y Red Hat OpenShift Container Platform (OCP). Una vez más, estamos limitados por el conjunto común de versiones de Kubernetes compatibles entre todos plataformas.
El límite inferior para CAO 2.0.0 era Kubernetes 1.13.
Versionado personalizado de recursos
Kubernetes 1.13 introdujo definiciones de recursos personalizados (CRD) versionadas. Esto permite a Kubernetes ser consciente de los diferentes formatos de recursos personalizados. Esto suena perfecto para nuestras necesidades, pero el diablo está en los detalles.
El versionado CRD sólo almacena recursos como una única versión. Cuando definimos una v1 y una v2 de un tipo de recurso, Kubernetes almacena todos los recursos como una única versión, por ejemplo, v2. Los ganchos de conversión de recursos personalizados nos proporcionan una forma de convertir el recurso v2 almacenado en un recurso v1 cuando un cliente accede al recurso con la API v1. La conversión está diseñada para tomar un recurso y devolver otro, realizando únicamente operaciones sencillas. Para el Operador, convertir entre una configuración de cluster monolítica y una modular, es un paso demasiado lejos.
Otra preocupación era que con Kubernetes 1.13, la conversión CRD era una característica de grado alfa. Soy un fan de todo lo que proporciona una experiencia de usuario (UX) más fluida. Los usuarios, sin embargo, son menos entusiastas con la habilitación de características de grado alfa a través de la reconfiguración intrusiva de la API de Kubernetes. En general, solo empezamos a utilizar las funciones cuando las API están disponibles de forma general, normalmente en la fase beta.
El problema final era que el versionado CRD en Kubernetes 1.13 solo soportaba un único esquema JSON. Esto significa que cuando se instala, un clúster v2 Couchbase CRD podría soportar ambos tipos de recursos personalizados v1 y v2, pero cualquier actualización de un recurso v1 fallaría porque la validación contra el único esquema v2 fallaría.
Nunca llueve, diluvia
A primera vista, parece que estamos atascados. Una buena idea es imposible de conseguir sin empezar de nuevo. No podemos utilizar la conversión CRD porque no está disponible y no está diseñada para lo que queremos. No podemos ejecutar simultáneamente distintas versiones de Operator porque sólo admite un único esquema. Pero soy británico:

Si sólo se admite una única versión de un recurso personalizado, que así sea, lo actualizamos todo de una vez. Lo que nos deja el proceso de conversión.
¿Ya estamos cerca?
En realidad, sí. La clave del éxito es simple. Lee un viejo recurso de cluster Couchbase v1-este no es validado-entonces escribe un nuevo recurso de cluster Couchbase v2, y cualquier recurso de bucket que requiera-estos son validados.
Como ya se ha dicho, la experiencia del usuario es muy importante, por lo que proporcionamos una para realizar la conversión para usted. Como era de esperar, esto utiliza selectores de etiquetas y va a lo seguro. No se habilitan nuevas características -todas las nuevas características son opcionales- por lo que las configuraciones existentes de XDCR y Couchbase RBAC no se ven afectadas por el proceso de actualización.
La llegada
¡Por fin hemos llegado a la B! De alguna manera, a través de la adversidad, fuimos capaces de pasar de un modelo de configuración monolítico a uno modular. Hemos sido capaces de definir un proceso de actualización en línea casi sin fisuras. Ahora el poder está en sus manos para explorar las posibilidades que ofrece CAO 2.0.
Como siempre, ustedes han elegido las direcciones que hemos tomado y ustedes elegirán las direcciones que tomemos. Esperamos sus comentarios, sugerencias y -me atrevería a decir- críticas.
Es el viaje, no el destino
He pasado un enorme de tiempo dedicado a la documentación técnica de esta versión (y espero de verdad que disfrútalo). En lugar de un blog árido y demasiado técnico, pensé que era necesario un cambio, de ahí la interminable analogía. Lo que he intentado expresar son todos los retos técnicos y las compensaciones a las que nos enfrentamos como equipo para alcanzar estos hitos. Lo que puede parecer una simple novedad desde el punto de vista del marketing del producto, es mucho más complejo bajo el capó.
Al emprender estas complicadas tareas en su nombre -y ser sincero al respecto- espero sinceramente que aprecie el trabajo que conllevan. Espero que nuestra historia resuene con otros también. Kubernetes solo puede mejorar para todos a medida que estas ideas se perfeccionen e incorporen. Todavía tenemos un largo camino por recorrer, pero gracias por acompañarnos en este viaje.