Ir al contenido

Blog ·

Una palabra de capacidad para un comando viejo

Si una ronda añade un campo protobuf, un agente viejo falla de forma ruidosa. Si solo cambia lo que significa un indicador, responde de forma plausible y mal.

Por Provibr

Nuestro agente se ejecuta dentro de la red del propio cliente y marca hacia fuera, hacia nosotros. Se actualiza solo, pero no al instante y no siempre, de modo que en cualquier momento dado la flota es un abanico de versiones y la plataforma tiene que saber qué puede hacer cada una.

Lo sabe porque el agente lo dice. En cada sesión el agente envía una lista de palabras cortas, una por capacidad, y la plataforma rechaza un comando cuya palabra falta en lugar de enviarlo y esperar que salga bien.

Esta ronda añadió la tercera palabra de esas para los contenedores de Proxmox, y es la primera en la que la pregunta interesante no era si añadirla, sino qué habría pasado sin ella.

Por qué existen las palabras

El mecanismo protege frente a una propiedad concreta de protobuf: un campo desconocido dentro de un oneof se descarta.

Cuando una ronda añade un comando nuevo como un campo nuevo, un agente anterior a esa ronda analiza el mensaje, no reconoce el número de campo, lo tira y se queda con un ProxmoxCommand sin ningún comando dentro. Y entonces dice exactamente eso. El mensaje es honesto y completamente inútil: quien opera ve una queja sobre un sobre vacío y la causa está a cuatro capas de distancia, en un desajuste de versiones que nadie mencionó.

Así que la plataforma rechaza antes. Si la palabra falta, el comando no llega a salir, y el rechazo nombra la capacidad y la versión del agente. Es un resultado peor que el comando funcionando y mucho mejor que el comando fallando de una manera que cuesta una tarde de rastreo.

En cualquiera de los dos casos es un fallo ruidoso. Resulta que eso importa.

La tercera palabra no es un campo nuevo

El cambio de esta ronda fue que un contenedor ya puede mostrar su hardware. El comando que lo hace, GetHardware, no es nuevo. Todo agente, hasta los del trabajo temprano sobre el ciclo de vida de las máquinas virtuales, conoce el mensaje y sabe responderlo.

Lo que cambió es un indicador junto a él que dice a qué clase de recurso se refiere el identificador. Un agente anterior a esta ronda recibe ese indicador, no lo conoce y lo tira, exactamente como protobuf manda. Después hace lo que ha hecho siempre con una petición de hardware: le pide a Proxmox la configuración de la máquina por la ruta de QEMU.

Nada está vacío. Nada se queja. El agente cree que le han hecho una pregunta que entiende, y la responde.

Eso aterriza de dos maneras, y ninguna de las dos es ruidosa. Si Proxmox no tiene nada en ese identificador bajo la ruta de máquina virtual, al cliente se le dice que una máquina no existe, hablando de un contenedor que está funcionando delante de él. Y si sí vuelve una configuración y se le entrega al analizador construido para máquinas virtuales, la respuesta no está vacía: está mal.

La respuesta equivocada es concreta y tiene buena pinta

Los dos formatos de configuración son lo bastante parecidos para analizarse y lo bastante distintos para importar. Una máquina virtual escribe su primera tarjeta de red como un modelo y una dirección MAC unidos por un signo igual. Un contenedor escribe primero un nombre de interfaz y después la MAC en un campo con clave aparte.

El analizador de máquinas virtuales toma el primer par de clave y valor como el modelo y la dirección. Ante la línea de un contenedor, informa por tanto de una tarjeta de red cuyo modelo es name y cuya dirección MAC es ETH0.

Eso es una fila de aspecto plausible en una tabla. Tiene un modelo, tiene una dirección, se dibuja sin ninguna advertencia. Es la razón por la que la ruta de contenedor necesitaba su propio analizador, y es justo la clase de defecto que nadie comunica, porque no hay nada en él que comunicar. Alguien mira una pantalla, piensa que la columna del modelo es rara y sigue adelante.

Así que un comando que ya existe es una clase de cambio más peligrosa que un comando nuevo. El nuevo falla en el sobre, en público. Este falla en el significado, en privado.

Por qué no ensanchar nada y añadir una línea en su lugar

La alternativa evidente es ensanchar la palabra que ya existe. Hay una palabra que dice que el agente entiende siquiera la ruta de contenedor, y habría costado un carácter de trabajo hacer que significara también lo nuevo.

Eso rechazaría todo comando de contenedor de todo agente que no se haya actualizado todavía, incluidos los que hoy funcionan a la perfección. Una flota que ahora mismo está sirviendo contenedores se quedaría a oscuras para una capacidad que tiene de verdad, porque le cambiamos por debajo lo que significaba nuestra palabra.

Una palabra es una promesa sobre lo que se ha construido, y la promesa tiene que conservar su significado mientras siga habiendo alguien que la sostenga. Añadir una tercera palabra cuesta una constante en cada lado y rechaza exactamente los comandos que hay que rechazar, y nada más. Además pone el razonamiento en un sitio donde una persona lo va a encontrar, que es junto a la constante y no en un mensaje de confirmación.

Los dos lados son dos constantes, una en el código Rust y otra en el TypeScript compartido, y cada una nombra a la otra. Ese emparejamiento no es elegante, y todo intento de hacerlo elegante acaba en un paso de compilación entre dos lenguajes que tienen que poder leerse por separado.

El simulador dice dos de las tres a propósito

Hay un agente simulado que nos permite gobernar la pasarela sin hipervisor, y también anuncia las palabras de contenedor.

Anuncia dos de ellas. Dice que conoce la ruta de contenedor y dice que lee el hardware de un contenedor, y a propósito no reclama la tercera, porque reinstalar un contenedor es algo que no sabe hacer.

Merece la pena decirlo porque un simulador que lo reclama todo es un simulador que vuelve imposible de probar cualquier camino de rechazo. Y lo contrario importa igual de tanto: sin la palabra de hardware la pasarela habría rechazado, correctamente, y la comprobación habría medido en silencio un rechazo en lugar de una respuesta. Un banco de pruebas que miente sobre sus propias capacidades produce resultados en verde sobre la cosa equivocada.

Lo que dejaríamos por escrito

  1. Protobuf tira los campos desconocidos en silencio, así que un comando nuevo llega a un agente viejo como un sobre vacío.
  2. Rechace antes de enviar. Un rechazo que nombra la capacidad y la versión gana a una queja llegada de cuatro capas más abajo.
  3. El cambio sin campo nuevo es el peligroso. No se tira nada, así que nada se queja.
  4. El modo de fallo que interesa es el ruidoso. Una respuesta plausible y equivocada no se comunica jamás.
  5. Dos formatos de configuración que se analizan los dos son peores que dos que no.
  6. Nunca ensanche una palabra de capacidad existente. Es una promesa en manos de agentes a los que no se puede llegar.
  7. Una palabra de más cuesta una constante en cada lado, y rechaza solo lo que hay que rechazar.
  8. Ponga el razonamiento junto a la constante, que es donde va a estar de pie la persona siguiente.
  9. Un simulador tiene que declinar lo que no sabe hacer, o todo camino de rechazo se vuelve imposible de probar.
  10. Un banco de pruebas que reclama de más produce resultados en verde sobre la cosa equivocada.

Para que quede claro qué es esto: una tercera palabra de capacidad para los contenedores de Proxmox, añadida junto a un cambio que no introdujo ningún campo de protocolo nuevo, con el razonamiento anotado contra las dos constantes y el agente simulado anunciando dos de las tres; la ronda llevó el módulo de pruebas de contenedores de treinta y cinco pruebas a treinta y nueve, con el formato y el destino de publicación limpios, y terminó con los paquetes compartidos en 5347 en verde, la pasarela en 1467, las herramientas del agente simulado en 489 y el conjunto de pruebas web en 4593, sin fallos, más cincuenta comprobaciones de navegador en verde en dos idiomas. Sin demostrar: nada de esto se ejecutó contra un Proxmox real, así que el comportamiento de un agente más antiguo ante un identificador de contenedor queda establecido a partir de los dos formatos de configuración y del analizador, y no observado, y la cadena en funcionamiento se ejercitó contra nuestro propio simulador.

Del trabajo de plataforma en Provibr. Lo que ocurre cuando dos rondas van a por el mismo número de campo está en dos rondas, un mismo número de campo, la ronda que enseñó al agente lo que es un contenedor está en reinstalar un contenedor es reemplazarlo, y cómo decide un agente si fiarse siquiera de una compilación nueva está en una actualización firmada que se rechaza sola.

Empiece con un host y un agente

Cree una cuenta, instale el agente con un solo comando y conecte su primer host de Proxmox. El periodo de prueba dura 14 días y no pide ningún dato de pago.