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
| Backend | Service | Best For |
|---|---|---|
| AWS Cloud Map | AWS Cloud Map + ECS Metadata | AWS ECS, EKS, EC2 |
| Azure Discovery | Azure DNS Private Zones + Table Storage | Azure VMs, AKS, ACI |
| Consul | HashiCorp Consul | Kubernetes, 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
- Create a Cloud Map Namespace:
aws servicediscovery create-private-dns-namespace \
--name hdds.local \
--vpc vpc-12345678
- Create a Service:
aws servicediscovery create-service \
--name hdds-participants \
--namespace-id ns-12345678 \
--dns-config "NamespaceId=ns-12345678,DnsRecords=[{Type=A,TTL=60}]"
- 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
- Create DNS Private Zone:
az network private-dns zone create \
--resource-group myResourceGroup \
--name hdds.private.azure.local
- 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
- Start Consul Agent:
consul agent -dev -client=0.0.0.0
- 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
| Variable | Backend | Purpose |
|---|---|---|
HDDS_CLOUD_MAP_NAMESPACE | AWS | Cloud Map namespace name |
HDDS_CLOUD_MAP_SERVICE | AWS | Cloud Map service name |
AWS_REGION | AWS | AWS region |
HDDS_AZURE_DNS_ZONE | Azure | DNS Private Zone name |
HDDS_AZURE_TABLE_STORAGE | Azure | Table Storage connection string |
HDDS_CONSUL_ADDR | Consul | Consul HTTP API address |
HDDS_CONSUL_DATACENTER | Consul | Consul 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
| Scenario | Recommended Backend |
|---|---|
| AWS ECS/EKS only | AWS Cloud Map |
| Azure VMs/AKS only | Azure Discovery |
| Multi-cloud / hybrid | Consul |
| On-premises Kubernetes | Consul or K8s Discovery |
| Service mesh required | Consul |
| Simplest setup | K8s Discovery (DNS only) |
Comparison with K8s Discovery
| Feature | Cloud Discovery | K8s Discovery |
|---|---|---|
| Dependencies | reqwest, serde | None (std only) |
| Async | Yes | No (background thread) |
| Multi-cluster | Yes | No |
| Service mesh | Consul only | No |
| Health checks | Yes | No |
| Metadata storage | Yes | No |
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
- Use TLS for all cloud API connections
- Restrict IAM/RBAC to minimum required permissions
- Use private endpoints (AWS PrivateLink, Azure Private Endpoints)
- Enable audit logging on cloud services
- Rotate credentials regularly
Next Steps
- Kubernetes Discovery - Simpler DNS-based K8s discovery
- Security - DDS Security plugins
- QoS Policies - Configure QoS for cloud