question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Discovery-First Config - Cannot completely disable Eureka

See original GitHub issue

Describe the bug

A microservice deployed on Kubernetes throws an incorrect exception on startup. A check against Eureka:Client:ServiceUrl is performed even if eureka is disabled (i.e. Eureka:Client:ShouldRegisterWithEureka and Eureka:Client:ShouldFetchRegistry are both false). I’ve also set Spring:Cloud:Config:Discovery:Enabled to false just to avoid the eureka client being injected but the result is the same, the application keeps crashing. The only way to fix it is to overwrite the Eureka:Client:ServiceUrl specifying a url that does not contain localhost.

This is the log from the application Pod:

System.InvalidOperationException: Eureka URL http://localhost:8761/eureka/ is not valid in containerized or cloud environments. Please configure Eureka:Client:ServiceUrl with a non-localhost address or add a service binding.
at Steeltoe.Discovery.Eureka.EurekaPostConfigurer.UpdateConfiguration(IConfiguration config, EurekaServiceInfo si, EurekaClientOptions clientOptions)
at Steeltoe.Discovery.Eureka.EurekaDiscoveryClientExtension.<>c__DisplayClass9_0.<ConfigureEurekaServices>b__0(EurekaClientOptions options)
at Microsoft.Extensions.Options.PostConfigureOptions`1.PostConfigure(String name, TOptions options)
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0()
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at System.Lazy`1.get_Value()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
at Microsoft.Extensions.Options.OptionsMonitor`1.get_CurrentValue()
at Steeltoe.Discovery.Eureka.EurekaDiscoveryClient.EurekaHttpClientInternal.get_Config()
at Steeltoe.Discovery.Eureka.Transport.EurekaHttpClient.Initialize(IDictionary`2 headers, ILoggerFactory logFactory)
at Steeltoe.Discovery.Eureka.EurekaDiscoveryClient.EurekaHttpClientInternal..ctor(IOptionsMonitor`1 config, ILoggerFactory logFactory, IHttpClientHandlerProvider handlerProvider)
at Steeltoe.Discovery.Eureka.EurekaDiscoveryClient..ctor(IOptionsMonitor`1 clientConfig, IOptionsMonitor`1 instConfig, EurekaApplicationInfoManager appInfoManager, IEurekaHttpClient httpClient, ILoggerFactory logFactory, IHttpClientHandlerProvider handlerProvider)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Steeltoe.Discovery.Eureka.EurekaDiscoveryClientExtension.<>c.<AddEurekaServices>b__10_0(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Steeltoe.Discovery.Client.DiscoveryApplicationBuilderExtensions.UseDiscoveryClient(IApplicationBuilder app)
at MyService.Startup.Configure(IApplicationBuilder app, IHostEnvironment env) in /app/Startup.cs:line 177
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass13_0.<UseStartup>b__2(IApplicationBuilder app)
at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)

Steps to reproduce

Steps to reproduce the behavior:

  1. deploy a config-server instance on a Kubernetes cluster (it should be accesible from a service named “config-server” at port 8888)
  2. create an aspnetcore 3.1 application with the following specs:

Project dependencies:

<PackageReference Include="Steeltoe.Discovery.ClientCore" Version="3.0.2" />
<PackageReference Include="Steeltoe.Discovery.Eureka" Version="3.0.2" />
<PackageReference Include="Steeltoe.Discovery.Kubernetes" Version="3.0.2" />
<PackageReference Include="Steeltoe.Extensions.Configuration.ConfigServerCore" Version="3.0.2" />
<PackageReference Include="Steeltoe.Extensions.Configuration.KubernetesCore" Version="3.0.2" />
<PackageReference Include="Steeltoe.Management.EndpointBase" Version="3.0.2" />
<PackageReference Include="Steeltoe.Management.EndpointCore" Version="3.0.2" />
<PackageReference Include="Steeltoe.Management.KubernetesCore" Version="3.0.2" />

Application code:

namespace Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args)
        {
            var startupLoggerFactory = new LoggerFactory().AddConsole();

            return Host.CreateDefaultBuilder(args)
                .AddKubernetesConfiguration(null, startupLoggerFactory)
                .AddConfigServer(startupLoggerFactory)
                .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
        }
    }
    
    public class Startup
    {
        private IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDiscoveryClient(Configuration);
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseDiscoveryClient();
        }
    }
}

Application configuration:

//appsettings.json
{
    "Spring": {
        "Cloud": {
            "Config": {
                "Discovery": {
                    "Enabled": true,
                    "ServiceId": "config-server"
                },
                "FailFast": true
            },
            "Kubernetes": {
                "Enabled":  false
            }
        }
    },
    "Eureka": {
        "Client": {
            "ServiceUrl": "http://localhost:8761/eureka/"
        }
    }
}
//appsettings.Kubernetes.json
{
    "Spring": {
        "Cloud": {
            "Config": {
                "Uri": "http://config-server:8888",
                "Discovery": {
                    "Enabled": false
                }
            },
            "Kubernetes": {
                "Enabled": true
            }
        }
    },
    "Eureka": {
        "Client": {
            "ShouldRegisterWithEureka": false,
            "ShouldFetchRegistry": false
        }
    }
}
  1. deploy the aspnetcore microservice on kubernetes and set ASPNETCORE_ENVIRONMENT=Kubernetes

Expected behavior

I would like to be able to disable the eureka client completely to avoid application startup crashes if eureka-server is not deployed in Kubernetes (and it probably won’t be due to native service discovery capabilities). Spring allows to disable eureka completely using the following property in the application.yml:

eureka:
  client:
    enabled: false

To disable the Eureka Discovery Client, you can set eureka.client.enabled to false. Eureka Discovery Client will also be disabled when spring.cloud.discovery.enabled is set to false.

I would like to have the same option to disable any Eureka integration (discovery, health check, etc…) through configuration thus skipping any check for incorrect eureka client configurations or errors due to missing eureka-server.

Note: I have multiple configuration to support multiple deployments so I cannot simply remove the eureka dependency from the project.

Environment:

  • Steeltoe Version: 3.0.2
  • Platform: Kubernetes (Client Version: v1.18.1, Server Version: v1.19.7)
  • OS: Windows (Minikube)
  • .NET Version: .NET Core 3.1

Additional context or links

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
TimHesscommented, May 20, 2021

@DaviGia if the original complaint (Eureka appears active when it shouldn’t be) is still present then we need to get to the bottom of that to determine if there’s a bug to fix (I think you’ve provided enough info, somebody just needs to find the time to look into it). The additional settings would technically be an enhancement, but I don’t feel strongly about needing to separate the two items at this time.

edit: the labels aren’t exclusive, why not both?

1reaction
TimHesscommented, Jul 7, 2021

@DaviGia sorry for the delay and bummer of an answer here, but I missed the key to the problem: "Spring:Cloud:Config:Discovery:Enabled": true. Which is valid, I was just looking at the Discovery code and not thinking about discovery-first Config Server…

The reason this is the key is twofold:

So… it looks like we already needed to completely re-implement ConfigServerDiscoveryService anyway, and what you’re seeing is just symptoms of a larger problem

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to selectively disable Eureka discovery client with ...
To disable the Eureka Discovery Client, you can set eureka.client.enabled to false. Eureka Discovery Client will also be disabled when spring.
Read more >
Spring Cloud – Disable Discovery Clients with Profiles
In this tutorial, we'll look at how to disable Spring Cloud's Discovery Clients using profiles. This can be useful in situations where we ......
Read more >
Eureka client local cache doesn't refresh in a "discovery ...
I have the same problem. I run a eureka-server and config-server. Now I have a service with a config client in discovery first...
Read more >
1. Service Discovery: Eureka Clients
See EurekaInstanceConfigBean and EurekaClientConfigBean for more details of the configurable options. To disable the Eureka Discovery Client you can set eureka.
Read more >
Quick Guide to Microservices with Spring Boot 2, Eureka ...
Guide to building microservices with Spring Boot and Spring Cloud. Using components like Spring Cloud Netflix, Gateway and OpenFeign.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found