Skip to content

Commit 8352a60

Browse files
chore: Follow-ups to the containerdebug log collection (#892)
* chore: Follow-ups to the containerdebug log collection * chore: Create the containerdebug log directory via the environment variable * fix: Do not hard-code the environment variable name "FILE_LOG_DIRECTORY"
1 parent 9de8e41 commit 8352a60

4 files changed

Lines changed: 33 additions & 15 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
- Add `/ready` endpoint to the operator Deployment, which reports the CRD installation status ([#868]).
1414
- Webservers now have a default affinity to the OPA Pods when OPA authorization is configured ([#872]).
1515
- The logs of the `containerdebug` process are now collected by the Vector agent and forwarded to
16-
the Vector aggregator ([#888]).
16+
the Vector aggregator ([#888], [#892]).
1717

1818
### Changed
1919

@@ -112,6 +112,7 @@
112112
[#886]: https://github.com/stackabletech/airflow-operator/pull/886
113113
[#887]: https://github.com/stackabletech/airflow-operator/pull/887
114114
[#888]: https://github.com/stackabletech/airflow-operator/pull/888
115+
[#892]: https://github.com/stackabletech/airflow-operator/pull/892
115116

116117
## [26.7.0] - 2026-07-21
117118

‎rust/operator-binary/src/controller/build/properties/env_vars.rs‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{collections::BTreeSet, str::FromStr};
22

3+
use const_format::concatcp;
34
use stackable_operator::{
45
constant,
56
crd::{authentication::oidc, git_sync},
@@ -15,7 +16,8 @@ use stackable_operator::{
1516
use crate::{
1617
controller::{ValidatedCluster, ValidatedLogging},
1718
crd::{
18-
AirflowExecutor, AirflowRole, HTTP_PORT, LOG_CONFIG_DIR, TEMPLATE_LOCATION, TEMPLATE_NAME,
19+
AirflowExecutor, AirflowRole, FILE_LOG_DIRECTORY, FILE_LOG_MAX_FILES,
20+
FILE_LOG_ROTATION_PERIOD, HTTP_PORT, LOG_CONFIG_DIR, TEMPLATE_LOCATION, TEMPLATE_NAME,
1921
authentication::{
2022
AirflowAuthenticationClassResolved, AirflowClientAuthenticationDetailsResolved,
2123
},
@@ -77,9 +79,6 @@ constant!(ADMIN_PASSWORD_SECRET_KEY: SecretKey = "adminUser.password");
7779

7880
constant!(PYTHONPATH: EnvVarName = "PYTHONPATH");
7981

80-
constant!(FILE_LOG_DIRECTORY: EnvVarName = "FILE_LOG_DIRECTORY");
81-
constant!(FILE_LOG_ROTATION_PERIOD: EnvVarName = "FILE_LOG_ROTATION_PERIOD");
82-
constant!(FILE_LOG_MAX_FILES: EnvVarName = "FILE_LOG_MAX_FILES");
8382
constant!(STACKABLE_POST_HOOK: EnvVarName = "_STACKABLE_POST_HOOK");
8483

8584
/// Return environment variables to be applied to the statefulsets for the scheduler, webserver (and worker,
@@ -188,9 +187,11 @@ pub fn build_airflow_statefulset_envs(
188187
// other telemetry-based process in it would log into the same directory and the Vector
189188
// agent would label its events with `container: containerdebug`.
190189
env_vars = env_vars
190+
// The directory must be exactly one level below the log directory, because the Vector
191+
// agent derives the container name from that path segment.
191192
.with_value(
192193
&FILE_LOG_DIRECTORY,
193-
format!("{STACKABLE_LOG_DIR}/containerdebug"),
194+
concatcp!(STACKABLE_LOG_DIR, "/containerdebug"),
194195
)
195196
.with_value(&FILE_LOG_ROTATION_PERIOD, "hourly")
196197
.with_value(&FILE_LOG_MAX_FILES, "2")
@@ -536,9 +537,6 @@ mod tests {
536537
let _ = *AIRFLOW_WEBSERVER_ENABLE_PROXY_FIX;
537538
let _ = *AIRFLOW_WEBSERVER_EXPOSE_CONFIG;
538539
let _ = *AIRFLOW_WEBSERVER_PROXY_FIX_X_FOR;
539-
let _ = *FILE_LOG_DIRECTORY;
540-
let _ = *FILE_LOG_MAX_FILES;
541-
let _ = *FILE_LOG_ROTATION_PERIOD;
542540
let _ = *FORWARDED_ALLOW_IPS;
543541
let _ = *PYTHONPATH;
544542
let _ = *STACKABLE_POST_HOOK;

‎rust/operator-binary/src/controller/build/volumes.rs‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,9 @@ pub fn create_volumes(
3232
name: LOG_VOLUME_NAME.to_string(),
3333
empty_dir: Some(EmptyDirVolumeSource {
3434
medium: None,
35-
// Only the Airflow log files are budgeted here. The `containerdebug` files in this
36-
// volume are rotated by time, which bounds their number but not their size, so they
37-
// are an unbudgeted writer. They stay negligible at the default INFO level and a 30
38-
// minute loop, but raising `FILE_LOG_LEVEL` via `envOverrides` can exceed the limit,
39-
// which makes the kubelet evict the Pod.
35+
// Only the Airflow log files are budgeted. The `containerdebug` files in this
36+
// volume are rotated by time, not by size, so they have no budget; raising
37+
// `FILE_LOG_LEVEL` via `envOverrides` can therefore evict the Pod.
4038
size_limit: Some(product_logging::framework::calculate_log_volume_size_limit(
4139
&[MAX_LOG_FILES_SIZE],
4240
)),

‎rust/operator-binary/src/crd/mod.rs‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{collections::BTreeSet, ops::Deref, str::FromStr};
22

3+
use indoc::formatdoc;
34
use serde::{Deserialize, Serialize};
45
use snafu::{ResultExt, Snafu};
56
use stackable_operator::{
@@ -38,6 +39,7 @@ use stackable_operator::{
3839
status::condition::{ClusterCondition, HasStatusCondition},
3940
utils::{COMMON_BASH_TRAP_FUNCTIONS, crds::raw_object_list_schema},
4041
v2::{
42+
builder::pod::container::EnvVarName,
4143
config_overrides::KeyValueConfigOverrides,
4244
flask_config_writer::{FlaskAppConfigOptions, PythonType},
4345
product_logging::framework::STACKABLE_LOG_DIR,
@@ -84,6 +86,14 @@ pub const CONFIG_PATH: &str = "/stackable/app/config";
8486
pub const LOG_CONFIG_DIR: &str = "/stackable/app/log_config";
8587
pub const AIRFLOW_HOME: &str = "/stackable/airflow";
8688

89+
// The `stackable-telemetry` variables which configure the file logs of the `containerdebug`
90+
// process. They are set on the Airflow container in `env_vars`, and the start command below
91+
// references the directory as a shell variable, so that an `envOverrides` entry for it takes
92+
// effect in both places.
93+
constant!(pub FILE_LOG_DIRECTORY: EnvVarName = "FILE_LOG_DIRECTORY");
94+
constant!(pub FILE_LOG_MAX_FILES: EnvVarName = "FILE_LOG_MAX_FILES");
95+
constant!(pub FILE_LOG_ROTATION_PERIOD: EnvVarName = "FILE_LOG_ROTATION_PERIOD");
96+
8797
constant!(pub TEMPLATE_VOLUME_NAME: VolumeName = "airflow-executor-pod-template");
8898
pub const TEMPLATE_LOCATION: &str = "/templates";
8999
pub const TEMPLATE_NAME: &str = "airflow_executor_pod_template.yaml";
@@ -776,7 +786,15 @@ impl Deref for AirflowRole {
776786
}
777787

778788
fn container_debug_command() -> String {
779-
format!("containerdebug --output={STACKABLE_LOG_DIR}/containerdebug-state.json --loop &")
789+
// The log directory is created here, because `FILE_LOG_MAX_FILES` makes the telemetry library
790+
// prune old log files before it creates the first one, which complains about the directory not
791+
// existing yet.
792+
formatdoc!(
793+
r#"
794+
mkdir --parents "${file_log_directory}" || true
795+
containerdebug --output={STACKABLE_LOG_DIR}/containerdebug-state.json --loop &"#,
796+
file_log_directory = FILE_LOG_DIRECTORY.as_ref(),
797+
)
780798
}
781799

782800
#[derive(Clone, Debug, Deserialize, JsonSchema, PartialEq, Serialize)]
@@ -1029,6 +1047,9 @@ mod tests {
10291047
let _ = *WORKER_ROLE_NAME;
10301048
let _ = *DAG_PROCESSOR_ROLE_NAME;
10311049
let _ = *TRIGGERER_ROLE_NAME;
1050+
let _ = *FILE_LOG_DIRECTORY;
1051+
let _ = *FILE_LOG_MAX_FILES;
1052+
let _ = *FILE_LOG_ROTATION_PERIOD;
10321053
let _ = *TEMPLATE_VOLUME_NAME;
10331054
let _ = *LISTENER_PVC_NAME;
10341055
let _ = *METRICS_CONTAINER_NAME;

0 commit comments

Comments
 (0)