Kubernetes operator for Dingo Cardano nodes
2.8K
A Kubernetes operator for Dingo, the Go Cardano node. It manages the full lifecycle of Cardano relays and block producers — including KES/operational-certificate monitoring and rotation, Mithril bootstrap, topology (with external relays), and active/standby failover — aimed at secure, production mainnet block production for enterprise stake pool operators.
Status: early development (
v1alpha1). The API may change.
DingoNode runs as a relay or a blockProducer.dingo mithril sync
(native Go client, no external binary)./keys volume with mode 0600, sets the CARDANO_SHELLEY_*
env, and surfaces KES period / opcert state from the node's metrics. A
delivered bundle is validated (opcert signature, pool binding, KES-key
binding, counter, KES period) before the operator rolls the pod onto it; a
refused bundle sets KeysValid=False and Degraded=True and is not rolled
out. The live pod keeps its staged keys when the Secret changes. Any later pod
recreation stages the Secret's current contents, so fix a refused bundle
rather than leaving it in place.blockProducer.nodeToClient.enabled, the
operator reads the pool's authoritative opcert counter from the node over
node-to-client local-state-query, publishes it as
status.opcert.onChainCounter, and refuses a delivered certificate numbered
below it (the chain would reject blocks forged with it). It fails open: an
unreachable or unsynced node falls back to the operator's own last accepted
counter, and the OnChainCounterAvailable condition says which applies.
Reaching the port also needs the label
dingo.blinklabs.io/node-to-client=allowed on the client pod — see the
NetworkPolicy note below.MonitorOnly, Assisted, or full Auto issuance via a
pluggable cold-signer (Bursa) that keeps cold keys out of the cluster.SingleActive (default) or ActiveStandby with fenced,
lease-based promotion so exactly one node ever forges.dingo.blinklabs.io/node-to-client=allowed, and its namespace too when it is
not the node's own. That label is the only way in — peers named in
topology.relayRefs get the node-to-node port (3001) and nothing else. Dingo
also binds node-to-client to loopback until
blockProducer.nodeToClient.enabled is set, so both the listener and the
policy have to be opened deliberately.Install the operator via its Helm chart (published to GHCR as an OCI artifact):
helm install dingo-operator \
oci://ghcr.io/blinklabs-io/helm-charts/charts/dingo-operator \
--namespace dingo-operator-system --create-namespace
The chart installs the DingoNode CRD, the operator Deployment, RBAC, and
(optionally) a PodMonitor. See the chart in
blinklabs-io/helm-charts.
Create a namespace and a relay:
kubectl create namespace cardano
kubectl apply -f config/samples/dingo_v1alpha1_dingonode_relay.yaml
kubectl get dn -n cardano
For a block producer, first create a Secret with your pool credentials in cardano-cli text-envelope form, then apply the sample:
kubectl create secret generic producer-pool-keys -n cardano \
--from-file=vrf.skey --from-file=kes.skey --from-file=opcert.cert
kubectl apply -f config/samples/dingo_v1alpha1_dingonode_blockproducer.yaml
DingoNode at a glanceapiVersion: dingo.blinklabs.io/v1alpha1
kind: DingoNode
spec:
role: blockProducer # relay | blockProducer
network: mainnet
storageMode: core
mithril: { enabled: true }
topology:
relayRefs: [relay]
externalRelays:
- { address: relay.example.com, port: 3001, valency: 1, trustable: true }
blockProducer:
keys: { secretRef: producer-pool-keys }
rotation: { mode: MonitorOnly, renewBeforePeriods: 8 }
ha: { strategy: SingleActive, failover: Automatic }
See CLAUDE.md for the design summary, rotation/HA models, delivery roadmap, and the upstream issues that unlock full automation, and AGENTS.md for coding and review standards.
make manifests generate # regenerate CRDs, RBAC, deepcopy
make build # build the operator binary
make test # run tests (uses envtest)
make lint # golangci-lint + nilaway + modernize
make run # run the operator against the current kubecontext
Requires Go 1.26+. A local Cardano devnet for end-to-end testing lives in the
Dingo repo under
internal/test/devnet/.
Apache-2.0. See LICENSE.
Content type
Image
Digest
sha256:f92758c20…
Size
20.2 MB
Last updated
about 18 hours ago
docker pull blinklabs/dingo-operator:main