Skip to content

Using containerized Consul for service discovery #11740

@bart-vmware

Description

@bart-vmware

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I'm trying to use HashiCorp Consul for DNS-based service discovery in an Aspire Starter App. In doing so, I identified the following limitations:

Expected Behavior

Being able to use Consul DNS for service discovery.

Steps To Reproduce

I'm using the following code to start the container from AppHost:

public static class ConsulDistributedApplicationBuilderExtensions
{
    public static IResourceBuilder<ConsulResource> AddConsulContainer(
        this IDistributedApplicationBuilder builder, [ResourceName] string name)
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentNullException.ThrowIfNull(name);

        var consul = new ConsulResource(name);

        return builder.AddResource(consul)
            .WithImage("hashicorp/consul", "latest")
            .WithImageRegistry("docker.io")
            .WithHttpEndpoint(8500, isProxied: false)
            .WithHttpHealthCheck("http://localhost:8500/")
            .WithUrl("http://localhost:8500/v1/agent/services", "Services JSON")
            .WithUrl("http://localhost:8500/v1/agent/checks", "Checks JSON")
            .WithEndpoint("dns-tcp", ea =>
            {
                ea.Protocol = ProtocolType.Tcp;
                ea.Port = 53;
                ea.TargetPort = 8600;
                ea.IsProxied = false;
            })
            .WithEndpoint("dns-udp", ea =>
            {
                // TODO: Why does dashboard show tcp?
                ea.Protocol = ProtocolType.Udp;
                ea.Port = 53;
                ea.TargetPort = 8600;
                ea.IsProxied = false;
            });
    }
}

public sealed class ConsulResource(string name)
    : ContainerResource(name);

From the app, I'm using the following:

builder.Services.AddDnsSrvServiceEndpointProvider(
    options => options.QuerySuffix = "service.consul");

To make this work, I patched the Aspire sources here, which is obviously not a permanent solution:

// PATCH-START: Change DNS query to work with Consul.
//var srvQuery = $"_{portName}._tcp.{query.ServiceName}.{_querySuffix}";  // example: _default._tcp.fortune-service.service.consul
var srvQuery = $"_{query.ServiceName}._tcp.{_querySuffix}";               // example: _fortune-service._tcp.service.consul
// PATCH-END: Change DNS query to work with Consul.
// PATCH-START: Use the Consul DNS server, instead of the local machine.
//public DnsResolver(TimeProvider timeProvider, ILogger<DnsResolver> logger) : this(timeProvider, logger, OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() ? ResolvConf.GetOptions() : NetworkInfo.GetOptions())
public DnsResolver(TimeProvider timeProvider, ILogger<DnsResolver> logger) : this(timeProvider, logger, new ResolverOptions([new IPEndPoint(IPAddress.Parse("127.0.0.1"), 53)]))
// PATCH-END: Use the Consul DNS server, instead of the local machine.

Exceptions (if any)

No response

.NET Version info

.NET SDK:
 Version:           9.0.305
 Commit:            3fc74f3529
 Workload version:  9.0.300-manifests.6fcb754b
 MSBuild version:   17.14.21+8929ca9e3

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.26100
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\9.0.305\

.NET workloads installed:
There are no installed workloads to display.
Configured to use loose manifests when installing new manifests.

Host:
  Version:      9.0.9
  Architecture: x64
  Commit:       893c2ebbd4

.NET SDKs installed:
  8.0.414 [C:\Program Files\dotnet\sdk]
  9.0.110 [C:\Program Files\dotnet\sdk]
  9.0.205 [C:\Program Files\dotnet\sdk]
  9.0.305 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 9.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 9.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Anything else?

I'm interested in opening a PR to enable Consul support, but would like some guidance on how to expose these capabilities. Perhaps make ResolverOptions public, and offer a template property for the DNS query somewhere?

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-service-discoveryneeds-area-labelAn area label is needed to ensure this gets routed to the appropriate area owners

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions