Skip to main content

Cloud Discovery

Experimental Feature

Cloud Discovery is an experimental feature in HDDS v1.0. The API may change in future releases. Use in production at your own risk.

DDS discovery in cloud environments where UDP multicast is unavailable.

Overview

Standard DDS uses UDP multicast for automatic peer discovery, which is typically not available in cloud environments (AWS, Azure, GCP). HDDS provides Cloud Discovery backends that use cloud-native services for participant registration and discovery.

Supported Backends

BackendServiceBest For
AWS Cloud MapAWS Cloud Map + ECS MetadataAWS ECS, EKS, EC2
Azure DiscoveryAzure DNS Private Zones + Table StorageAzure VMs, AKS, ACI
ConsulHashiCorp ConsulKubernetes, on-prem, hybrid

Architecture

┌─────────────────────────────────────────────────────────────┐
│ Cloud Environment │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Node A │ │ Node B │ │ Node C │ │
│ │ HDDS │ │ HDDS │ │ HDDS │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ Cloud Discovery │ │
│ │ (CloudDiscovery) │ │
│ ├────────────────────────┤ │
│ │ • register_participant │ │
│ │ • discover_participants│ │
│ │ • deregister_participant│ │
│ │ • health_check │ │
│ └───────────┬────────────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────────┐ ┌─────────┐ │
│ │ AWS │ │ Azure │ │ Consul │ │
│ │Cloud │ │ DNS + │ │ Service │ │
│ │ Map │ │ Table │ │ Catalog │ │
│ └──────┘ └──────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────┘

Feature Flag

Cloud Discovery requires the cloud-discovery feature:

[dependencies]
hdds = { path = "../hdds/crates/hdds", features = ["cloud-discovery"] }

CloudDiscovery Trait

All backends implement the common CloudDiscovery trait:

pub trait CloudDiscovery: Send + Sync {
/// Register this participant with the cloud discovery service
async fn register_participant(&self, info: &ParticipantInfo) -> Result<(), Error>;

/// Discover other participants in the same domain
async fn discover_participants(&self) -> Result<Vec<ParticipantInfo>, Error>;

/// Deregister this participant (cleanup on shutdown)
async fn deregister_participant(&self, guid: [u8; 16]) -> Result<(), Error>;

/// Health check (optional, for service mesh integrations)
async fn health_check(&self) -> Result<bool, Error>;
}

AWS Cloud Map

Features

  • ECS Task Metadata - Auto-detect task IP from ECS metadata endpoint
  • Cloud Map Registration - Register service instances with attributes
  • DNS Discovery - Resolve peers via DNS SRV records
  • HTTP Discovery - Alternative via Cloud Map DiscoverInstances API

AWS Setup

  1. Create a Cloud Map Namespace:
aws servicediscovery create-private-dns-namespace \
--name hdds.local \
--vpc vpc-12345678
  1. Create a Service:
aws servicediscovery create-service \
--name hdds-participants \
--namespace-id ns-12345678 \
--dns-config "NamespaceId=ns-12345678,DnsRecords=[{Type=A,TTL=60}]"
  1. IAM Permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"servicediscovery:RegisterInstance",
"servicediscovery:DeregisterInstance",
"servicediscovery:DiscoverInstances",
"servicediscovery:GetInstancesHealthStatus"
],
"Resource": "*"
}
]
}

Rust API

use hdds::discovery::cloud::AwsCloudMap;

// Create AWS Cloud Map discovery
let discovery = AwsCloudMap::new(
"hdds-namespace", // Cloud Map namespace
"hdds-participants", // Service name
"us-east-1", // AWS region
)?;

// Register participant
discovery.register_participant(&participant_info).await?;

// Discover peers
let peers = discovery.discover_participants().await?;

// Cleanup on shutdown
discovery.deregister_participant(my_guid).await?;

ECS Task Definition

{
"containerDefinitions": [
{
"name": "dds-app",
"image": "my-dds-app:latest",
"environment": [
{"name": "AWS_REGION", "value": "us-east-1"},
{"name": "HDDS_CLOUD_MAP_NAMESPACE", "value": "hdds-namespace"},
{"name": "HDDS_CLOUD_MAP_SERVICE", "value": "hdds-participants"}
],
"portMappings": [
{"containerPort": 7400, "protocol": "udp"},
{"containerPort": 7411, "protocol": "udp"}
]
}
],
"networkMode": "awsvpc"
}

Azure Discovery

Features

  • Azure Instance Metadata - Auto-detect VM/container IP from IMDS
  • DNS Private Zones - DNS SRV/TXT records for participants
  • Table Storage - Persistent participant registry (optional)
  • Service Bus Topics - Real-time announcements (optional)

Azure Setup

  1. Create DNS Private Zone:
az network private-dns zone create \
--resource-group myResourceGroup \
--name hdds.private.azure.local
  1. Create Table Storage (optional):
az storage table create \
--name hddsparticipants \
--account-name mystorageaccount

Rust API

use hdds::discovery::cloud::AzureDiscovery;

// Basic DNS-based discovery
let discovery = AzureDiscovery::new("hdds.private.azure.local")?;

// With Table Storage for persistence
let discovery = AzureDiscovery::new("hdds.private.azure.local")?
.with_table_storage("hddsparticipants", "<connection_string>");

// With Service Bus for real-time updates
let discovery = AzureDiscovery::new("hdds.private.azure.local")?
.with_service_bus("<connection_string>");

// Register and discover
discovery.register_participant(&participant_info).await?;
let peers = discovery.discover_participants().await?;

AKS Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: dds-app
spec:
template:
spec:
containers:
- name: app
image: my-dds-app:latest
env:
- name: HDDS_AZURE_DNS_ZONE
value: hdds.private.azure.local
- name: HDDS_AZURE_TABLE_STORAGE
valueFrom:
secretKeyRef:
name: azure-storage
key: connection-string
ports:
- containerPort: 7400
protocol: UDP
- containerPort: 7411
protocol: UDP

Consul Discovery

Features

  • Service Registration - Register participant as Consul service
  • Health Checks - HTTP/TCP health check endpoints
  • KV Store - Store participant metadata (GUID, domain, locators)
  • Blocking Queries - Efficient long-poll for real-time discovery

Consul Setup

  1. Start Consul Agent:
consul agent -dev -client=0.0.0.0
  1. For Production (Kubernetes):
helm install consul hashicorp/consul --set global.name=consul

Rust API

use hdds::discovery::cloud::ConsulDiscovery;

// Basic Consul discovery
let discovery = ConsulDiscovery::new("http://consul.service.consul:8500")?;

// With datacenter and health check
let discovery = ConsulDiscovery::new("http://localhost:8500")?
.with_datacenter("dc1")
.with_health_check_port(8080);

// Register and discover
discovery.register_participant(&participant_info).await?;
let peers = discovery.discover_participants().await?;

Service Registration Example

When registering, HDDS creates a Consul service like:

{
"Name": "hdds-participant",
"ID": "hdds-01aa0001-c0a80164-00000001",
"Tags": ["dds", "domain-0"],
"Address": "192.168.1.100",
"Port": 7411,
"Meta": {
"guid": "01aa0001c0a8016400000001000001c1",
"domain_id": "0",
"locators": "[...]"
},
"Check": {
"TCP": "192.168.1.100:7411",
"Interval": "10s",
"Timeout": "5s",
"DeregisterCriticalServiceAfter": "1m"
}
}

Kubernetes with Consul Connect

apiVersion: apps/v1
kind: Deployment
metadata:
name: dds-app
spec:
template:
metadata:
annotations:
consul.hashicorp.com/connect-inject: "true"
spec:
containers:
- name: app
image: my-dds-app:latest
env:
- name: HDDS_CONSUL_ADDR
value: "http://localhost:8500"
ports:
- containerPort: 7400
protocol: UDP
- containerPort: 7411
protocol: UDP

Environment Variables

VariableBackendPurpose
HDDS_CLOUD_MAP_NAMESPACEAWSCloud Map namespace name
HDDS_CLOUD_MAP_SERVICEAWSCloud Map service name
AWS_REGIONAWSAWS region
HDDS_AZURE_DNS_ZONEAzureDNS Private Zone name
HDDS_AZURE_TABLE_STORAGEAzureTable Storage connection string
HDDS_CONSUL_ADDRConsulConsul HTTP API address
HDDS_CONSUL_DATACENTERConsulConsul datacenter name

ParticipantInfo Structure

All backends exchange participant information using this structure:

pub struct ParticipantInfo {
/// Participant GUID (16 bytes)
pub guid: [u8; 16],

/// Participant name
pub name: String,

/// Domain ID
pub domain_id: u32,

/// Unicast locators (IP + port)
pub locators: Vec<Locator>,

/// Custom metadata (key-value pairs)
pub metadata: HashMap<String, String>,
}

Choosing a Backend

ScenarioRecommended Backend
AWS ECS/EKS onlyAWS Cloud Map
Azure VMs/AKS onlyAzure Discovery
Multi-cloud / hybridConsul
On-premises KubernetesConsul or K8s Discovery
Service mesh requiredConsul
Simplest setupK8s Discovery (DNS only)

Comparison with K8s Discovery

FeatureCloud DiscoveryK8s Discovery
Dependenciesreqwest, serdeNone (std only)
AsyncYesNo (background thread)
Multi-clusterYesNo
Service meshConsul onlyNo
Health checksYesNo
Metadata storageYesNo

Troubleshooting

AWS Cloud Map

# Check registered instances
aws servicediscovery list-instances --service-id srv-12345678

# Test DNS resolution
dig +short hdds-participants.hdds.local

Azure

# Check DNS Private Zone records
az network private-dns record-set list \
--resource-group myResourceGroup \
--zone-name hdds.private.azure.local

# Check Table Storage
az storage entity list --table-name hddsparticipants

Consul

# List registered services
consul catalog services

# Get service instances
consul catalog nodes -service=hdds-participant

# Check health status
consul health checks hdds-participant

Security Considerations

  1. Use TLS for all cloud API connections
  2. Restrict IAM/RBAC to minimum required permissions
  3. Use private endpoints (AWS PrivateLink, Azure Private Endpoints)
  4. Enable audit logging on cloud services
  5. Rotate credentials regularly

Next Steps