Skip to content

Commit 40e0cf4

Browse files
authored
feat(outbound)!: disable 'hostname' label (#3606)
The 'hostname' label value is derived from the request URI and can be influenced by applications. If a client uses a high cardinality of hostname values, this leads to the proxy exporting many metrics and ultimately exhausting resources. This change disables the 'hostname' label by default. A new field is outed to the HTTP and TLS route parameters, `export_hostname_labels`, which can be used to enable the 'hostname' label; however, this type is not yet configurable. Changes are required to the proxy API and, ultimately, the policy controller, to make this field configurable. When the hostname is not exported, an empty label value is used. BREAKING: The 'hostname' label is now disabled by default.
1 parent 570fc11 commit 40e0cf4

File tree

10 files changed

+250
-54
lines changed

10 files changed

+250
-54
lines changed

linkerd/app/outbound/src/http/logical/policy/route.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl<B, T> svc::ExtractParam<metrics::labels::Route, http::Request<B>> for Http<
174174
metrics::labels::Route::new(
175175
self.params.parent_ref.clone(),
176176
self.params.route_ref.clone(),
177-
req.uri(),
177+
self.params.params.export_hostname_labels.then(|| req.uri()),
178178
)
179179
}
180180
}
@@ -187,10 +187,9 @@ impl<T> metrics::MkStreamLabel for Http<T> {
187187
fn mk_stream_labeler<B>(&self, req: &::http::Request<B>) -> Option<Self::StreamLabel> {
188188
let parent = self.params.parent_ref.clone();
189189
let route = self.params.route_ref.clone();
190+
let uri = self.params.params.export_hostname_labels.then(|| req.uri());
190191
Some(metrics::LabelHttpRsp::from(metrics::labels::Route::new(
191-
parent,
192-
route,
193-
req.uri(),
192+
parent, route, uri,
194193
)))
195194
}
196195
}
@@ -240,7 +239,7 @@ impl<B, T> svc::ExtractParam<metrics::labels::Route, http::Request<B>> for Grpc<
240239
metrics::labels::Route::new(
241240
self.params.parent_ref.clone(),
242241
self.params.route_ref.clone(),
243-
req.uri(),
242+
self.params.params.export_hostname_labels.then(|| req.uri()),
244243
)
245244
}
246245
}
@@ -253,10 +252,9 @@ impl<T> metrics::MkStreamLabel for Grpc<T> {
253252
fn mk_stream_labeler<B>(&self, req: &::http::Request<B>) -> Option<Self::StreamLabel> {
254253
let parent = self.params.parent_ref.clone();
255254
let route = self.params.route_ref.clone();
255+
let uri = self.params.params.export_hostname_labels.then(|| req.uri());
256256
Some(metrics::LabelGrpcRsp::from(metrics::labels::Route::new(
257-
parent,
258-
route,
259-
req.uri(),
257+
parent, route, uri,
260258
)))
261259
}
262260
}

linkerd/app/outbound/src/http/logical/policy/route/metrics/labels.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,10 @@ pub enum Error {
5959
// === impl Route ===
6060

6161
impl Route {
62-
pub fn new(parent: ParentRef, route: RouteRef, uri: &http::uri::Uri) -> Self {
62+
pub fn new(parent: ParentRef, route: RouteRef, uri: Option<&http::uri::Uri>) -> Self {
6363
let hostname = uri
64-
.host()
65-
.map(str::as_bytes)
66-
.map(dns::Name::try_from_ascii)
67-
.and_then(Result::ok);
64+
.and_then(http::uri::Uri::host)
65+
.and_then(|h| dns::Name::try_from_ascii(h.as_bytes()).ok());
6866

6967
Self {
7068
parent,

linkerd/app/outbound/src/http/logical/policy/route/metrics/test_util.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ pub async fn send_assert_incremented(
1414
send: impl FnOnce(SendResponse),
1515
) {
1616
handle.allow(1);
17-
assert_eq!(counter.get(), 0);
17+
let init = counter.get();
1818
svc.ready().await.expect("ready");
1919
let mut call = svc.call(req);
2020
let (_req, tx) = tokio::select! {
2121
_ = (&mut call) => unreachable!(),
2222
res = handle.next_request() => res.unwrap(),
2323
};
24-
assert_eq!(counter.get(), 0);
24+
assert_eq!(counter.get(), init);
2525
send(tx);
2626
if let Ok(mut rsp) = call.await {
2727
if !rsp.body().is_end_stream() {
@@ -30,7 +30,7 @@ pub async fn send_assert_incremented(
3030
let _ = rsp.body_mut().trailers().await;
3131
}
3232
}
33-
assert_eq!(counter.get(), 1);
33+
assert_eq!(counter.get(), init + 1);
3434
}
3535

3636
pub type Handle = tower_test::mock::Handle<http::Request<BoxBody>, http::Response<BoxBody>>;

0 commit comments

Comments
 (0)