-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgraceful_shutdown.rs
More file actions
111 lines (100 loc) · 4.91 KB
/
Copy pathgraceful_shutdown.rs
File metadata and controls
111 lines (100 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use indoc::formatdoc;
use snafu::{ResultExt, Snafu};
use stackable_operator::{
builder::pod::{PodBuilder, container::ContainerBuilder},
k8s_openapi::api::core::v1::{ExecAction, LifecycleHandler},
shared::time::Duration,
};
use crate::crd::{DruidRole, security::DruidTlsSecurity};
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("Failed to set terminationGracePeriod"))]
SetTerminationGracePeriod {
source: stackable_operator::builder::pod::Error,
},
}
pub fn add_graceful_shutdown_config(
role: &DruidRole,
tls_security: &DruidTlsSecurity,
graceful_shutdown_timeout: Option<Duration>,
pod_builder: &mut PodBuilder,
druid_builder: &mut ContainerBuilder,
) -> Result<(), Error> {
// This must be always set by the merge mechanism, as we provide a default value,
// users can not disable graceful shutdown.
if let Some(termination_grace_period) = graceful_shutdown_timeout {
match role {
DruidRole::Coordinator
| DruidRole::Broker
| DruidRole::Historical
| DruidRole::Router => {
pod_builder
.termination_grace_period(&termination_grace_period)
.context(SetTerminationGracePeriodSnafu)?;
}
DruidRole::MiddleManager => {
pod_builder
.termination_grace_period(&termination_grace_period)
.context(SetTerminationGracePeriodSnafu)?;
let (protocol, port) = if tls_security.tls_enabled() {
("https", role.get_https_port())
} else {
("http", role.get_http_port())
};
let middle_manager_host = format!("{protocol}://127.0.0.1:{port}");
let debug_message =
"$(date --utc +%FT%T,%3N) INFO [stackable_lifecycle_pre_stop] -";
let sleep_interval = 2;
// The middle manager can be terminated gracefully by disabling it, meaning
// the overlord will not send any new tasks and it will terminate after
// all tasks are finished or the termination grace period is exceeded.
// See: https://druid.apache.org/docs/latest/operations/rolling-updates/#rolling-restart-graceful-termination-based
// The DRUID_PID is set in the crd/src/lib.rs `main_container_start_command` method.
druid_builder.lifecycle_pre_stop(LifecycleHandler {
exec: Some(ExecAction {
command: Some(vec![
"/bin/bash".to_string(),
"-x".to_string(),
"-euo".to_string(),
"pipefail".to_string(),
"-c".to_string(),
formatdoc!(r#"
log() {{
echo "{debug_message} $1" >> /proc/$(cat /tmp/DRUID_PID)/fd/1 2>&1
}}
response=$(curl -v --fail --insecure -X POST {middle_manager_host}/druid/worker/v1/disable)
log "Disable middle manager to stop overlord from sending tasks: $response"
end_time_seconds=$(date --date="+{termination_grace_period_seconds} seconds" '+%s')
while :
do
current_time_seconds=$(date '+%s')
log "Check if termination grace period ({termination_grace_period_seconds} seconds) is reached..."
if [ $current_time_seconds -gt $end_time_seconds ]
then
log "The termination grace period is reached!"
break
fi
tasks=$(curl -v --fail --insecure -X GET {middle_manager_host}/druid/worker/v1/tasks)
log "Check if all tasks are finished... Running: $tasks"
if [ $tasks = "[]" ]
then
log "All tasks finished!"
break
fi
log "Sleeping {sleep_interval} seconds..."
log ""
sleep {sleep_interval}
done
log "All done!"
"#,
termination_grace_period_seconds = termination_grace_period.as_secs()
),
]),
}),
..Default::default()
});
}
}
}
Ok(())
}