Probar un grupo de central en Docker¶
Redundancia explica cómo está construido un grupo de central, y Un grupo de central en servidores separados explica cómo desplegarlo. Esta página trata de verlo funcionar con sus propios ojos: en una sola máquina, a partir de contenedores, en diez minutos y sin alquilar un solo servidor.
El banco es desechable. En él se puede — y se debe — hacer lo que no se hace en una instalación en servicio: matar procesos en pleno vuelo y ver qué sale de ello.
Qué hace falta¶
- Docker con compose — no hay nada más que instalar.
- Una clave de licencia. La necesita cada proceso: los dos central y los dos streamers.
- Una imagen con el grupo de central. El laboratorio necesita una compilación cuya consola tenga la sección Clúster → Central. Si esa sección no está, la imagen es anterior al grupo de central y el banco no se montará.
- Los puertos 8081 y 8082 libres en la máquina local.
De qué está hecho el banco¶
Cinco contenedores:
- postgres — una base de datos para todo el grupo.
- central-a y central-b — dos instancias del plano de control sobre esa base, con consolas en los puertos 8081 y 8082.
- streamer-1 y streamer-2 — dos streamers repartidos entre las instancias: el primero va a central-a, el segundo a central-b.
Repartir los streamers entre instancias no es un adorno, es el sentido del banco. La imagen del «ahora mismo» es una sola para el grupo, y todo el parque debe verse desde cualquiera de las dos direcciones, aunque las máquinas reporten a instancias distintas.
Descargue el docker-compose.yaml en un directorio vacío. Abajo están las partes por las que fue escrito; el resto es fontanería corriente.
La primera instancia declara los cuatro roles, migrate incluido:
central:
admin_keys:
- lab-admin-key
roles: [run, migrate, layouter, stats]
advertise_url: http://central-a
La segunda es la misma sin migrate: el esquema lo aplica un solo proceso, o dos lanzan las migraciones a la carrera.
central:
admin_keys:
- lab-admin-key
roles: [run, layouter, stats]
advertise_url: http://central-b
Los roles layouter y stats los declaran las dos, y eso no es un arranque doble: un rol es una declaración, y al ejecutor lo elige un mandato.
A un streamer no se le da la dirección de una instancia sino la lista de direcciones del grupo; el orden es el orden de preferencia:
managed_by:
name: streamer-1
url:
- http://central-a
- http://central-b
join_token: ${JOIN_TOKEN}
El segundo streamer tiene la misma lista en orden inverso.
Levantarlo¶
El banco no se monta con un solo docker compose up: la ventana de unión la abre un central vivo, y el token de unión solo existe después de que arranque.
Primero la base de datos y las dos instancias del plano de control:
export CATENA_VERSION=latest
export LICENSE_KEY='su clave'
docker compose up -d postgres central-a central-b
Espere a que la consola se abra en http://127.0.0.1:8081 y entre como admin con la contraseña pass. En el primer inicio de sesión la consola pide crear una cuenta nominal — créela.
Abra Clúster → Streamers, pulse Permitir unión y copie el token de unión. Levante los streamers con él:
JOIN_TOKEN=jt-... docker compose up -d streamer-1 streamer-2
Las dos máquinas aparecen en la lista de streamers en segundos. Cierre después la ventana de unión — el parque está montado.
Cree unos cuantos streams para que el clúster tenga algo que colocar. La entrada syntetic es el generador incorporado; el banco no necesita ninguna fuente externa:
for i in 1 2 3 4 5 6; do
curl -s -X PUT -H 'Authorization: Bearer lab-admin-key' \
-H 'Content-Type: application/json' \
-d '{"inputs":[{"syntetic":{}}]}' \
"http://127.0.0.1:8081/central/api-v4/streams/configs/cam$i"
done
El grupo entero¶
Abra Clúster → Central.

La tabla tiene dos filas — el grupo entero — y cualquier instancia la muestra igual: el registro está en la base de datos común.
- Los roles reclamados son casi iguales en las dos:
migratesolo lo declaracentral-a, todo lo demás lo declaran ambas máquinas. - Los mandatos en curso solo están rellenos en una fila. Esa es la respuesta a «quién manda aquí»: nadie manda, hay titulares de mandatos concretos.
- La segunda fila dice ninguno: solo atiende peticiones. Una instancia así no es una reserva ni está dormida: responde por completo a la consola, al API y a los streamers; simplemente ahora mismo no es ella la que hace el trabajo de fondo.
En su banco los mandatos pueden quedar de otra manera — los dos en una máquina o uno en cada una. Los mandatos son independientes y su disposición depende de quién llegó primero; aquí no hay disposición incorrecta.
El parque se ve desde cualquier dirección¶
Sin salir de la instancia, abra Clúster → Streamers.

Las dos máquinas están en el aire, aunque a esta instancia solo le reporta una de ellas. La otra manda su sincronización al vecino y se ve aquí porque la imagen del «ahora mismo» es una sola para el grupo: una instancia sin el mandato stats llega a ella por la red, justamente por esa dirección anunciada.
Abra la misma página en http://127.0.0.1:8082 y verá lo mismo. Esa es la comprobación para la que los streamers están repartidos entre instancias.
Matamos al titular del mandato¶
Ahora aquello por lo que el banco es desechable. Mate la instancia que tiene los mandatos — en las capturas de arriba es central-b:
docker compose stop central-b
Vuelva a Clúster → Central en la instancia viva y espere unos segundos.

Han cambiado tres cosas:
- La fila de la instancia matada no ha desaparecido, está marcada: «en silencio: lo más probable es que el proceso haya muerto». El grupo recuerda su composición, no solo a los vivos.
- Los mandatos se han mudado a la instancia viva. Nadie los ha entregado: un mandato vive en una conexión propia con PostgreSQL y se libera con la muerte de esa sesión, y el vecino viene a por el liberado por su cuenta.
- El número de época ha crecido. Crece en cada cambio de titular y viaja con cada escritura: una instancia que despierta y ya no es la titular recibe un rechazo en la escritura, en lugar de estropear la colocación a posteriori.
La mudanza tarda segundos. No hay que confirmarla a mano, ni con qué.
El aire no se ha enterado¶
Abra Streams.

Los seis streams siguen. La mitad vive en el streamer que reportaba a la instancia matada: pasó a la segunda dirección de su lista tras una petición fallida, y central ni siquiera llegó a darlo por perdido.
Exactamente por eso la segunda dirección de la lista es obligatoria. Quítela, repita el experimento y minuto y medio después verá cómo el layouter mueve streams desde una máquina viva, porque dejó de dar señales de vida.
Devolvemos la instancia¶
docker compose start central-b
La fila vuelve a encenderse, pero no hay mudanza de vuelta — y eso es una decisión, no algo por terminar.
- Los mandatos se quedan en la instancia viva. No hay nada que ganar quitándoselos: el titular está trabajando, y un cambio de titular cuesta una nueva encarnación de la imagen del «ahora mismo».
- El streamer se queda en la dirección a la que se fue. Mientras esa dirección responda, no hay nada que ganar cambiándola; el orden de la lista es una preferencia de partida, no una vinculación permanente.
Se puede devolver la disposición original con un reinicio — para eso el banco es desechable —, pero en producción no hace falta: el grupo funciona en cualquier disposición.
Retiramos el banco¶
docker compose down -v
La opción -v retira también los volúmenes: la base de datos, el estado de los streamers y su identidad en el clúster. Sin ella el siguiente arranque hereda un estado medio ajeno.
Qué no muestra este banco¶
- Un fallo de la base de datos. Aquí es única y sin réplica: mátela y la gestión se detendrá por completo mientras el aire sigue. Es cierto, pero la redundancia de la base es tarea de la propia base.
- La red. Todos los contenedores están en una misma red de docker, sin pérdidas ni latencia entre ellos.
- La carga. Seis streams sintéticos no dicen nada sobre cómo se comporta el grupo en un parque real.
- El punto de entrada del operador. En el banco hay dos, uno por instancia; en producción hace falta una sola dirección con conmutación.