diff --git a/linkerd/app/admin/src/server.rs b/linkerd/app/admin/src/server.rs index 2c543ca824..2f606d6ec4 100644 --- a/linkerd/app/admin/src/server.rs +++ b/linkerd/app/admin/src/server.rs @@ -40,6 +40,7 @@ pub struct Admin { tracing: trace::Handle, ready: Readiness, shutdown_tx: mpsc::UnboundedSender<()>, + enable_shutdown: bool, #[cfg(feature = "pprof")] pprof: Option, } @@ -51,12 +52,14 @@ impl Admin { metrics: M, ready: Readiness, shutdown_tx: mpsc::UnboundedSender<()>, + enable_shutdown: bool, tracing: trace::Handle, ) -> Self { Self { metrics: metrics::Serve::new(metrics), ready, shutdown_tx, + enable_shutdown, tracing, #[cfg(feature = "pprof")] @@ -140,6 +143,13 @@ impl Admin { } fn shutdown(&self) -> Response { + if !self.enable_shutdown { + return Response::builder() + .status(StatusCode::NOT_FOUND) + .header(http::header::CONTENT_TYPE, "text/plain") + .body("shutdown endpoint is not enabled\n".into()) + .expect("builder with known status code must not fail"); + } if self.shutdown_tx.send(()).is_ok() { Response::builder() .status(StatusCode::OK) @@ -315,7 +325,7 @@ mod tests { let (_, t) = trace::Settings::default().build(); let (s, _) = mpsc::unbounded_channel(); - let admin = Admin::new((), r, s, t); + let admin = Admin::new((), r, s, true, t); macro_rules! call { () => {{ let r = Request::builder() diff --git a/linkerd/app/admin/src/stack.rs b/linkerd/app/admin/src/stack.rs index 910341f65b..7f36f5d392 100644 --- a/linkerd/app/admin/src/stack.rs +++ b/linkerd/app/admin/src/stack.rs @@ -24,6 +24,7 @@ pub struct Config { pub metrics_retain_idle: Duration, #[cfg(feature = "pprof")] pub enable_profiling: bool, + pub enable_shutdown: bool, } pub struct Task { @@ -100,7 +101,7 @@ impl Config { let (ready, latch) = crate::server::Readiness::new(); #[cfg_attr(not(feature = "pprof"), allow(unused_mut))] - let admin = crate::server::Admin::new(report, ready, shutdown, trace); + let admin = crate::server::Admin::new(report, ready, shutdown, self.enable_shutdown, trace); #[cfg(feature = "pprof")] let admin = admin.with_profiling(self.enable_profiling); diff --git a/linkerd/app/src/env.rs b/linkerd/app/src/env.rs index 32ee39a092..f0a2115222 100644 --- a/linkerd/app/src/env.rs +++ b/linkerd/app/src/env.rs @@ -105,6 +105,8 @@ pub const ENV_ADMIN_LISTEN_ADDR: &str = "LINKERD2_PROXY_ADMIN_LISTEN_ADDR"; pub const ENV_METRICS_RETAIN_IDLE: &str = "LINKERD2_PROXY_METRICS_RETAIN_IDLE"; +pub const ENV_SHUTDOWN_ENDPOINT_ENABLED: &str = "LINKERD2_PROXY_SHUTDOWN_ENDPOINT_ENABLED"; + const ENV_INGRESS_MODE: &str = "LINKERD2_PROXY_INGRESS_MODE"; const ENV_INBOUND_HTTP_QUEUE_CAPACITY: &str = "LINKERD2_PROXY_INBOUND_HTTP_QUEUE_CAPACITY"; @@ -397,6 +399,8 @@ pub fn parse_config(strings: &S) -> Result let control_receive_limits = control::mk_receive_limits(strings)?; + let shutdown_endpoint_enabled = parse(strings, ENV_SHUTDOWN_ENDPOINT_ENABLED, parse_bool); + // DNS let resolv_conf_path = strings.get(ENV_RESOLV_CONF); @@ -773,6 +777,7 @@ pub fn parse_config(strings: &S) -> Result // configuration. #[cfg(feature = "pprof")] enable_profiling: true, + enable_shutdown: shutdown_endpoint_enabled?.unwrap_or_default(), }; let dns = dns::Config {