Skip to content
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- The lifetime of auto generated TLS certificates is now configurable with the role and roleGroup
config property `requestedSecretLifetime`. This helps reducing frequent Pod restarts ([#619]).

### Fixed

- BREAKING: Use distinct ServiceAccounts for the Stacklets, so that multiple Stacklets can be
deployed in one namespace. Existing Stacklets will use the newly created ServiceAccounts after
restart ([#616]).

[#616]: https://github.com/stackabletech/hdfs-operator/pull/616
[#619]: https://github.com/stackabletech/hdfs-operator/pull/619

## [24.11.0] - 2024-11-18

Expand Down
25 changes: 7 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
snafu = "0.8"
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.82.0" }
stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "stackable-operator-0.83.0" }
product-config = { git = "https://github.com/stackabletech/product-config.git", tag = "0.7.0" }
strum = { version = "0.26", features = ["derive"] }
tokio = { version = "1.40", features = ["full"] }
Expand Down
24 changes: 24 additions & 0 deletions deploy/helm/hdfs-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -538,6 +542,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -840,6 +848,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -1104,6 +1116,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -1353,6 +1369,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -1621,6 +1641,10 @@ spec:
nullable: true
type: boolean
type: object
requestedSecretLifetime:
description: Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`. This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
nullable: true
type: string
resources:
default:
cpu:
Expand Down
20 changes: 20 additions & 0 deletions rust/crd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ pub struct CommonNodeConfig {
/// Time period Pods have to gracefully shut down, e.g. `30m`, `1h` or `2d`. Consult the operator documentation for details.
#[fragment_attrs(serde(default))]
pub graceful_shutdown_timeout: Option<Duration>,

/// Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`.
/// This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.
#[fragment_attrs(serde(default))]
pub requested_secret_lifetime: Option<Duration>,
}

/// Configuration for a rolegroup of an unknown type.
Expand Down Expand Up @@ -310,6 +315,13 @@ impl AnyNodeConfig {
AnyNodeConfig::JournalNode(node) => node.logging.enable_vector_agent,
}
}
pub fn requested_secret_lifetime(&self) -> Option<Duration> {
match self {
AnyNodeConfig::NameNode(node) => node.common.requested_secret_lifetime,
AnyNodeConfig::DataNode(node) => node.common.requested_secret_lifetime,
AnyNodeConfig::JournalNode(node) => node.common.requested_secret_lifetime,
}
}
}

#[derive(
Expand Down Expand Up @@ -1074,6 +1086,8 @@ pub struct NameNodeConfig {
}

impl NameNodeConfigFragment {
const DEFAULT_NAME_NODE_SECRET_LIFETIME: Duration = Duration::from_days_unchecked(7);

pub fn default_config(cluster_name: &str, role: &HdfsRole) -> Self {
Self {
resources: ResourcesFragment {
Expand All @@ -1098,6 +1112,7 @@ impl NameNodeConfigFragment {
common: CommonNodeConfigFragment {
affinity: get_affinity(cluster_name, role),
graceful_shutdown_timeout: Some(DEFAULT_NAME_NODE_GRACEFUL_SHUTDOWN_TIMEOUT),
requested_secret_lifetime: Some(Self::DEFAULT_NAME_NODE_SECRET_LIFETIME),
},
}
}
Expand Down Expand Up @@ -1208,6 +1223,8 @@ pub struct DataNodeConfig {
}

impl DataNodeConfigFragment {
const DEFAULT_DATA_NODE_SECRET_LIFETIME: Duration = Duration::from_days_unchecked(7);

pub fn default_config(cluster_name: &str, role: &HdfsRole) -> Self {
Self {
resources: ResourcesFragment {
Expand Down Expand Up @@ -1237,6 +1254,7 @@ impl DataNodeConfigFragment {
common: CommonNodeConfigFragment {
affinity: get_affinity(cluster_name, role),
graceful_shutdown_timeout: Some(DEFAULT_DATA_NODE_GRACEFUL_SHUTDOWN_TIMEOUT),
requested_secret_lifetime: Some(Self::DEFAULT_DATA_NODE_SECRET_LIFETIME),
},
}
}
Expand Down Expand Up @@ -1324,6 +1342,7 @@ pub struct JournalNodeConfig {
}

impl JournalNodeConfigFragment {
const DEFAULT_JOURNAL_NODE_SECRET_LIFETIME: Duration = Duration::from_days_unchecked(7);
pub fn default_config(cluster_name: &str, role: &HdfsRole) -> Self {
Self {
resources: ResourcesFragment {
Expand All @@ -1347,6 +1366,7 @@ impl JournalNodeConfigFragment {
common: CommonNodeConfigFragment {
affinity: get_affinity(cluster_name, role),
graceful_shutdown_timeout: Some(DEFAULT_JOURNAL_NODE_GRACEFUL_SHUTDOWN_TIMEOUT),
requested_secret_lifetime: Some(Self::DEFAULT_JOURNAL_NODE_SECRET_LIFETIME),
},
}
}
Expand Down
8 changes: 8 additions & 0 deletions rust/operator-binary/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Snafu, Debug, EnumDiscriminants)]
#[strum_discriminants(derive(IntoStaticStr))]
pub enum Error {
#[snafu(display("missing secret lifetime"))]
MissingSecretLifetime,

#[snafu(display("object has no namespace"))]
ObjectHasNoNamespace,

Expand Down Expand Up @@ -272,6 +275,11 @@ impl ContainerConfig {
.with_node_scope()
.with_format(SecretFormat::TlsPkcs12)
.with_tls_pkcs12_password(TLS_STORE_PASSWORD)
.with_auto_tls_cert_lifetime(
merged_config
.requested_secret_lifetime()
.context(MissingSecretLifetimeSnafu)?,
)
.build()
.context(BuildSecretVolumeSnafu {
volume_name: TLS_STORE_VOLUME_NAME,
Expand Down
8 changes: 8 additions & 0 deletions tests/templates/kuttl/kerberos/20-assert.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ metadata:
status:
readyReplicas: 2
replicas: 2
---
apiVersion: kuttl.dev/v1beta1
kind: TestAssert
timeout: 600
commands:
- script: kubectl -n $NAMESPACE get sts/hdfs-namenode-default -o yaml | yq -e '.spec.template.spec.volumes.[] | select(.name == "tls" and .ephemeral.volumeClaimTemplate.metadata.annotations."secrets.stackable.tech/backend.autotls.cert.lifetime" == "7d")'
- script: kubectl -n $NAMESPACE get sts/hdfs-datanode-default -o yaml | yq -e '.spec.template.spec.volumes.[] | select(.name == "tls" and .ephemeral.volumeClaimTemplate.metadata.annotations."secrets.stackable.tech/backend.autotls.cert.lifetime" == "1d")'
- script: kubectl -n $NAMESPACE get sts/hdfs-journalnode-default -o yaml | yq -e '.spec.template.spec.volumes.[] | select(.name == "tls" and .ephemeral.volumeClaimTemplate.metadata.annotations."secrets.stackable.tech/backend.autotls.cert.lifetime" == "2d")'
3 changes: 3 additions & 0 deletions tests/templates/kuttl/kerberos/20-install-hdfs.txt.j2
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ spec:
replicas: 2
dataNodes:
config:
requestedSecretLifetime: 1d
logging:
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
roleGroups:
Expand All @@ -56,3 +57,5 @@ spec:
roleGroups:
default:
replicas: 3
config:
requestedSecretLifetime: 2d
Loading