Envoy failed to route your request because it couldn’t find a suitable upstream cluster to send it to, despite receiving a valid request from the client.
Here’s why that can happen, and how to fix it:
1. Missing or Incorrectly Configured service_name in the Virtual Host
This is the most common culprit. Envoy uses the service_name in your virtual host configuration to match incoming requests to the correct upstream cluster. If it’s misspelled, missing, or doesn’t match the HOST header of your request, Envoy will throw this error.
-
Diagnosis: Check your Envoy configuration file (typically
envoy.yamlor a file included in it). Look for thevirtual_hostssection.static_resources: listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 10000 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http route_config: name: route_config_0 virtual_hosts: - name: some_service_vhost domains: ["my-api.example.com"] # THIS is what you're looking for: routes: - match: { prefix: "/" } route: cluster: my_app_clusterNow, look at your actual HTTP request’s
HOSTheader. Does it match any of thedomainsin yourvirtual_hosts? If not, or if there’s nodomainssection and you’re expecting a specific host, Envoy won’t know whichvirtual_hostto use. -
Fix: Ensure the
domainsin yourvirtual_hostsaccurately reflect theHOSTheader your clients are sending. If you want to match any host for a given virtual host, you can use*as the domain.virtual_hosts: - name: some_service_vhost domains: ["my-api.example.com", "*.example.com"] # Added wildcard routes: - match: { prefix: "/" } route: cluster: my_app_clusterOr, if you have no specific domain requirements and want this virtual host to catch everything not matched by other virtual hosts:
virtual_hosts: - name: default_catchall_vhost domains: ["*"] # Catches any host routes: - match: { prefix: "/" } route: cluster: my_app_clusterThis works because Envoy uses the
domainslist to find the firstvirtual_hostthat matches the incoming request’sHOSTheader.
2. The cluster Name in the Route Doesn’t Exist
Even if Envoy selects the correct virtual_host, it still needs a cluster defined that matches the cluster name specified in the route.
-
Diagnosis: In your
envoy.yaml, within theroute_configfor the relevantvirtual_host, you’ll see aroutewith aclusterfield.route: cluster: my_app_cluster # This name must exist in static_resources.clustersNow, scroll down to the
static_resources.clusterssection and verify that a cluster with the exact namemy_app_clusteris defined.static_resources: clusters: - name: my_app_cluster # <-- This must match the route's cluster name connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: my_app_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: 10.0.0.1, port_value: 8080 } -
Fix: Either rename the
clusterin your route to match an existing cluster, or create/rename the cluster definition instatic_resources.clustersto match the name used in the route.# ... in route_config ... route: cluster: my_existing_app_cluster # Renamed to match a defined cluster # ... in static_resources.clusters ... clusters: - name: my_existing_app_cluster # <-- Now this matches # ... rest of cluster config ...This works because Envoy maintains a catalog of defined clusters by name. If a route references a cluster name not in this catalog, it has nowhere to send the request.
3. Wildcard Domains (*) in Virtual Hosts Without Specificity
If you have multiple virtual hosts, and one uses a broad wildcard domain like *, it can "catch" requests that were intended for a more specific virtual host if the wildcard is listed before the specific one in the configuration. Envoy processes virtual hosts in the order they appear.
-
Diagnosis: Examine the order of your
virtual_hostsinenvoy.yaml. If you see adomains: ["*"]entry, check if it appears before a more specific domain likedomains: ["api.example.com"].virtual_hosts: - name: catchall_vhost # This might be matching too early domains: ["*"] routes: - match: { prefix: "/" } route: cluster: fallback_cluster - name: specific_api_vhost # This might be skipped domains: ["api.example.com"] routes: - match: { prefix: "/" } route: cluster: api_cluster -
Fix: Reorder your
virtual_hostsso that the most specific domains appear first, followed by less specific ones, and finally the wildcard catch-all.virtual_hosts: - name: specific_api_vhost # Now this is checked first for api.example.com domains: ["api.example.com"] routes: - match: { prefix: "/" } route: cluster: api_cluster - name: catchall_vhost # This will only catch requests not matching api.example.com domains: ["*"] routes: - match: { prefix: "/" } route: cluster: fallback_clusterThis ensures Envoy attempts to match the most precise domain first. If a match is found, it uses that virtual host; otherwise, it proceeds to the next virtual host, including the wildcard.
4. Invalid Cluster Type or Configuration
While less common for "No Cluster Found," a malformed cluster definition can lead Envoy to discard it, effectively making it "not found." This could be due to incorrect endpoint addresses, invalid type settings, or missing required fields.
-
Diagnosis: Scrutinize the
static_resources.clusterssection for the cluster name referenced in your route. Ensure thetypeis valid (e.g.,STRICT_DNS,LOGICAL_DNS,STATIC,ORIGINAL_DST). Check thatload_assignmentorhostsfields are correctly populated with valid IP addresses and ports.# Example of a potentially problematic cluster config clusters: - name: my_broken_cluster connect_timeout: 0.25s type: INVALID_TYPE # <-- Invalid type # ... other fields ...Or:
clusters: - name: my_broken_cluster connect_timeout: 0.25s type: STRICT_DNS load_assignment: cluster_name: my_broken_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: "not_an_ip", port_value: 8080 } # <-- Invalid address -
Fix: Correct the
typefield to a valid option. Ensure IP addresses are valid and ports are numeric. ForSTRICT_DNSorLOGICAL_DNS, verify the DNS name resolves correctly. ForSTATICorORIGINAL_DST, ensure the addresses are correctly specified.clusters: - name: my_fixed_cluster connect_timeout: 0.25s type: STRICT_DNS # <-- Corrected type load_assignment: cluster_name: my_fixed_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: "192.168.1.100", port_value: 8080 } # <-- Valid addressEnvoy performs validation on cluster configurations during startup. If a cluster definition is invalid, Envoy might not register it at all, leading to the "No Cluster Found" error when a route attempts to use it.
5. Dynamic Configuration Not Loaded (if using EDS/Aggregated Discovery Service)
If you’re using dynamic configuration sources like EDS (Endpoint Discovery Service) or ADS (Aggregated Discovery Service) and your configuration server isn’t pushing cluster information, Envoy won’t know about the clusters.
-
Diagnosis: Check the Envoy logs for any errors related to connecting to the xDS server or receiving updates. Use
curlto inspect Envoy’s internal stats.curl -s http://localhost:9901/stats/prometheus | grep envoy_cluster_manager_sds_fetch_totalIf the
sds_fetch_totalcounters aren’t incrementing, Envoy isn’t successfully fetching configuration. Also, check the status of your xDS server (e.g., Istio’s Pilot, Consul, etc.). -
Fix: Ensure your xDS server is running, accessible from Envoy, and correctly configured to push the necessary cluster definitions. Verify network connectivity between Envoy and the xDS server.
# Example: Ensure your Istio ingress gateway pods are running and healthy kubectl get pods -n istio-systemThis works by Envoy establishing a gRPC connection to the xDS API server and subscribing to updates for cluster configurations. If this connection or the update process fails, Envoy’s cluster registry remains empty or incomplete.
6. Empty or Missing clusters Section in Static Configuration
In a purely static configuration, if the static_resources.clusters section is entirely missing or empty, Envoy has no clusters to reference, regardless of the routing rules.
-
Diagnosis: Open your
envoy.yamland look forstatic_resources. Does it contain aclusterskey? If so, is the list of clusters under it empty?static_resources: # clusters: [] # <-- This would be an empty cluster list # OR # This entire 'clusters' section is missing -
Fix: Add your cluster definitions under the
static_resources.clusterskey.static_resources: clusters: - name: my_app_cluster connect_timeout: 0.25s type: STRICT_DNS load_assignment: cluster_name: my_app_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: 10.0.0.1, port_value: 8080 } # ... other clusters ...Envoy needs a populated
clusterslist within its static resources to know what upstream services are available to route requests to.
The next error you’ll likely encounter if you’ve fixed this is a 503 Service Unavailable if the endpoints within your now-found cluster are unhealthy or unreachable.