Tutorial

Run a local cluster

Bring up a three-instance middleware cluster with Kiwi Vault, Redis, MongoDB and sample workers on one machine.

Distro Current 3 min read Updated

Prerequisites

  • Docker Desktop running
  • .NET SDK 8 and 9
  • Kiwi Launch and the Kiwi Vault repository built
  • Optional: Node.js 22.18 or newer, Python 3.11 or newer, JDK 17 and Maven for the extra-language workers

Note

Kiwi Distro is currently in private preview. Interfaces and behaviour described here can change before general availability. Contact Kiwify Labs for access.

The local cluster is a development and learning environment. It is launched with Kiwi Launch, which runs a dependency graph of tasks.

text
client / worker --HTTPS 8443--> nginx (L4 TLS pass-through) --> 3 x middleware (7001-7003 HTTP, 7401-7403 HTTPS)
                --HTTP 8080 (/ca)-->                                    |  Redis pub/sub between instances
                                              Kiwi Vault (CA, config store)   Redis   MongoDB   4 sample workers

What each part does#

  • Kiwi Vault is the configuration store (it holds the shared module settings for Redis and MongoDB, so each instance carries only a kiwiconfig:// connection string) and the PKI that issues each instance's TLS certificate from one root CA.
  • Redis provides the transaction cache and the peer message bus.
  • MongoDB stores data, secrets and feedback.
  • nginx does layer-4 TLS pass-through on 8443 so the Vault certificate reaches the client end to end, and serves the CA endpoint over HTTP on 8080.
  • Sample workers for .NET, Node.js, Python and Java register for a sample service in lazy mode (each is skipped, with a warning, if its toolchain is missing).

Run it#

powershell
dotnet <path-to>/Kiwify.Kiwi.Launch.Cli.dll apply  --script .\deploy\cluster\kiwi-cluster.launch.json
dotnet <path-to>/Kiwify.Kiwi.Launch.Cli.dll status -e <execution-id>
dotnet <path-to>/Kiwify.Kiwi.Launch.Cli.dll kill   -e <execution-id> --force
.\deploy\cluster\teardown-cluster.ps1

apply stages (builds and publishes every component and Kiwi Vault), starts MongoDB and Redis containers on named volumes (so data survives relaunches), starts Vault and bootstraps it, starts three middleware instances 8 seconds apart (so they do not hit Vault at once), starts nginx, bootstraps a super-admin client, service and worker profile, and launches the sample workers. Output is staged under %USERPROFILE%\kiwi-cluster\, which records every URL, id and key.

Try it#

With the staged bootstrap.json:

powershell
$bs = Get-Content "$env:USERPROFILE\kiwi-cluster\bootstrap.json" -Raw | ConvertFrom-Json
$h  = @{ Authorization = "Bearer $($bs.accessToken)" }
Invoke-RestMethod -Method Post "$($bs.lb)/client/api/request" -Headers $h -ContentType application/json `
  -Body '{"method":"clustersvc/progress","target":"any","params":{"Job":"demo"}}'
Invoke-RestMethod "$($bs.lb)/client/feedback?service_id=$($bs.serviceId)" -Headers $h

Or use the CLI, which is a Kiwi shell product:

powershell
kiwi distro signin --credentials-file "$env:USERPROFILE\kiwi-cluster\cli-creds.json"
kiwi distro list-services
kiwi distro list-workers --output json
kiwi distro request-method --method clustersvc/hello --target any --params-file params.json --output raw

The CLI token is cached under %LOCALAPPDATA%\kiwi\distro\.

Configuration#

Common parameters in the launch script: MW_INSTANCES (3), MW_BASE_PORT and MW_BASE_TLS (7000 and 7400), MONGO_PORT and REDIS_PORT (27017 and 6379), VAULT_HTTP and VAULT_HTTPS (5080 and 5443), LB_HTTP and LB_HTTPS (8080 and 8443) and CONFIGURATION (Debug, or Release for a faster middleware). If you change the instance count, update the instance parameters in the script too.

Notes and limits#

  • The database is reused across launches. teardown-cluster.ps1 -RemoveVolume wipes volumes, caches and bootstrap state for a clean slate.
  • After removing the volumes, if signin fails on TLS, delete the cached CA files in %LOCALAPPDATA%\kiwi\ca\ and ~\.kiwi\ca\ and retry.
  • The Vault connection string uses 127.0.0.1, not localhost, because the Vault client resolves localhost to IPv6 first while the server binds IPv4.
  • The launcher opens visible windows, so run it from a normal interactive terminal, not a service or CI.
  • The SideCar and HybridWorker are not started automatically; they need their own mapping or script configuration.

Expected result

  • Three middleware instances behind a load balancer, with workers registered for a sample service