Configure Consul clustering
Use the Microsoft.Orleans.Clustering.Consul package to store Orleans membership records in the Consul key/value store.
Every silo and client in a cluster must use:
Configure a silo
Section titled “Configure a silo”Configure ConsulClusteringOptions with the Consul address and, when Consul ACLs are enabled, an ACL token:
var builder = Host.CreateApplicationBuilder(args);
var consulAddress = new Uri( builder.Configuration["Consul:Address"] ?? throw new InvalidOperationException("Consul:Address isn't configured."));var consulToken = builder.Configuration["Consul:Token"];
builder.UseOrleans(siloBuilder =>{ siloBuilder .Configure<ClusterOptions>(options => { options.ServiceId = "orders"; options.ClusterId = "production"; }) .UseConsulSiloClustering(options => { options.ConfigureConsulClient(consulAddress, consulToken); options.KvRootFolder = "orleans/orders"; });});
await builder.Build().RunAsync();Configure a client
Section titled “Configure a client”Configure Orleans clients with the same Consul settings and cluster identity:
var builder = Host.CreateApplicationBuilder(args);
var consulAddress = new Uri( builder.Configuration["Consul:Address"] ?? throw new InvalidOperationException("Consul:Address isn't configured."));var consulToken = builder.Configuration["Consul:Token"];
builder.UseOrleansClient(clientBuilder =>{ clientBuilder .Configure<ClusterOptions>(options => { options.ServiceId = "orders"; options.ClusterId = "production"; }) .UseConsulClientClustering(options => { options.ConfigureConsulClient(consulAddress, consulToken); options.KvRootFolder = "orleans/orders"; });});
await builder.Build().RunAsync();Inspect membership data
Section titled “Inspect membership data”The provider stores each cluster beneath one Consul key/value prefix:
<KvRootFolder>/orleans/<ClusterId>when ConsulClusteringOptions.KvRootFolder is configured.orleans/<ClusterId>whenKvRootFolderisn’t configured.
ServiceId isn’t part of this prefix. Don’t reuse the same KvRootFolder and ClusterId for different services, because their membership records would share one keyspace.
Under the cluster prefix, the provider maintains:
| Key | Purpose |
|---|---|
version | The integer membership table version. Consul’s ModifyIndex for this key is the compare-and-set ETag. |
<silo-address> | The silo registration, including its host name, gateway port, start time, status, silo name, and failure-detector votes. |
<silo-address>/iamalive | The silo’s periodic IAmAlive timestamp. |
Membership reads use Consul’s consistent mode to return coherent snapshots of registrations and the table version. Single-silo reads query the silo’s registration and timestamp prefix and validate that the table version’s ETag remains unchanged across the read. Retried reads wait 100 ms after a version change and honor cancellation. Insertions and status updates use a Consul transaction to atomically compare-and-set the registration and table version. A conflicting row or table ETag returns a failed update so the caller can refresh its membership view. Other transaction failures surface as exceptions containing Consul’s operation error details.
Each silo owns its periodic IAmAlive updates throughout its registered lifetime. Each update performs one native write to that silo’s iamalive key, retaining the registration fields, row ETag, and table version. The write honors cancellation and propagates storage failures. Membership reads include the separately published timestamp for liveness diagnostics; row and table concurrency checks use only canonical membership tokens.
Cleanup removes Dead registrations whose start time, IAmAlive timestamp, and failure-detector votes all precede the cutoff. It compares the registration and timestamp keys atomically and retains the table version, preserving entries changed by concurrent writers.
The IAmAlive timestamp supports diagnostics and startup recovery. Silos probe one another for failure detection, as described in Cluster membership.
Orleans clients list the cluster prefix and select active registrations with a nonzero gateway port. If a client discovers no gateways, inspect the exact prefix used by the client and silos, then compare registration status, gateway ports, and advertised-address reachability.
Use the Consul KV command to list or inspect the records:
consul kv get -keys -recurse <cluster-prefix>consul kv get -detailed -recurse <cluster-prefix>The detailed output includes each key’s value and ModifyIndex. Treat the layout as a diagnostic implementation detail. Don’t manually edit or delete membership keys while any silo from that cluster might still be running.
Production considerations
Section titled “Production considerations”- Run Consul in a highly available configuration and follow the Consul production deployment guidance.
- Enable Consul ACLs and TLS. Supply tokens using workload identity, a secret store, or the platform’s protected configuration mechanism; don’t embed tokens in source or images.
- Restrict network access so only authorized silos and clients can reach the Consul API.
- Give the Orleans identity only the permissions required for its key/value prefix.
- Use a distinct
ClusterIdand key/value root for environments that must remain isolated. - Monitor Consul availability, request latency, leadership changes, storage capacity, and ACL or TLS failures.
- Test cluster startup and recovery while Consul is degraded or unavailable. Avoid synchronized, unbounded retries.
Consul membership data coordinates cluster discovery and liveness. It doesn’t contain grain application state and doesn’t replace a grain storage provider. For provider selection criteria, see Topology, networking, and clustering.
