Skip to content

Commit 4399726

Browse files
authored
outbound: Mock the original destination address in ingress-mode (#942)
The ingress-mode outbound proxy currently does not work as expected: resolutions are performed for each unique endpoint so that a service with 10 endpoints would manifest as 10 distinct balancers (with 20 resolutions). While we should ultimately rework the outbound stack to have target types that prevent this problem (i.e. by removing the original destination address from the Logical target type), this change implements a hack to avoid the observed cardinality issues: In ingress-mode, the original destination address is now mocked out with an IP address of 0.0.0.0 so that only a single cache entry is created per logical destination.
1 parent 77e2016 commit 4399726

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

linkerd/app/outbound/src/ingress.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use linkerd_app_core::{
33
config::{ProxyConfig, ServerConfig},
44
detect, discovery_rejected, drain, errors, http_request_l5d_override_dst_addr, http_tracing,
55
io, profiles, svc, tls,
6-
transport::{self, listen},
6+
transport::{self, listen, OrigDstAddr},
77
Addr, AddrMatch, Error,
88
};
99
use std::convert::TryFrom;
@@ -104,8 +104,10 @@ impl Outbound<()> {
104104
// Note that the router service is always ready, so the `FailFast` layer
105105
// need not use a `SpawnReady` to drive the service to ready.
106106
.push(svc::NewRouter::layer(TargetPerRequest::accept))
107+
.push(http::NewNormalizeUri::layer())
107108
.push_on_response(
108109
svc::layers()
110+
.push(http::MarkAbsoluteForm::layer())
109111
.push(svc::ConcurrencyLimit::layer(max_in_flight_requests))
110112
.push(svc::FailFast::layer("HTTP Server", dispatch_timeout))
111113
.push(self.runtime.metrics.http_errors.clone())
@@ -117,8 +119,6 @@ impl Outbound<()> {
117119
.push(http::BoxResponse::layer()),
118120
)
119121
.check_new_service::<http::Accept, http::Request<_>>()
120-
.push(http::NewNormalizeUri::layer())
121-
.check_new_service::<http::Accept, http::Request<_>>()
122122
.instrument(|a: &http::Accept| debug_span!("http", v = %a.protocol))
123123
.check_new_service::<http::Accept, http::Request<_>>()
124124
.push(http::NewServeHttp::layer(
@@ -150,7 +150,7 @@ struct AllowHttpProfile(AddrMatch);
150150
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
151151
struct Target {
152152
dst: Addr,
153-
accept: http::Accept,
153+
version: http::Version,
154154
}
155155

156156
#[derive(Clone)]
@@ -173,11 +173,18 @@ impl svc::stack::Predicate<Target> for AllowHttpProfile {
173173
// === impl Target ===
174174

175175
impl From<(Option<profiles::Receiver>, Target)> for http::Logical {
176-
fn from((p, Target { accept, .. }): (Option<profiles::Receiver>, Target)) -> Self {
176+
fn from((profile, Target { dst, version }): (Option<profiles::Receiver>, Target)) -> Self {
177+
// XXX This is a hack to fix caching when an dst-override is set.
178+
let orig_dst = if let Some(a) = dst.socket_addr() {
179+
OrigDstAddr(a)
180+
} else {
181+
OrigDstAddr(([0, 0, 0, 0], dst.port()).into())
182+
};
183+
177184
Self {
178-
profile: p,
179-
orig_dst: accept.orig_dst,
180-
protocol: accept.protocol,
185+
orig_dst,
186+
profile,
187+
protocol: version,
181188
}
182189
}
183190
}
@@ -194,10 +201,11 @@ impl<B> svc::stack::RecognizeRoute<http::Request<B>> for TargetPerRequest {
194201
type Key = Target;
195202

196203
fn recognize(&self, req: &http::Request<B>) -> Result<Self::Key, Error> {
204+
let dst =
205+
http_request_l5d_override_dst_addr(req).unwrap_or_else(|_| self.0.orig_dst.0.into());
197206
Ok(Target {
198-
accept: self.0,
199-
dst: http_request_l5d_override_dst_addr(req)
200-
.unwrap_or_else(|_| self.0.orig_dst.0.into()),
207+
dst,
208+
version: self.0.protocol,
201209
})
202210
}
203211
}

linkerd/proxy/http/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub use self::{
2929
detect::DetectHttp,
3030
glue::{HyperServerSvc, UpgradeBody},
3131
header_from_target::NewHeaderFromTarget,
32-
normalize_uri::NewNormalizeUri,
32+
normalize_uri::{MarkAbsoluteForm, NewNormalizeUri},
3333
override_authority::{CanOverrideAuthority, NewOverrideAuthority},
3434
retain::Retain,
3535
server::NewServeHttp,

0 commit comments

Comments
 (0)