Skip to content

Commit 77e8e1b

Browse files
committed
fetch kubelet config when initializing operators
1 parent 592fdc1 commit 77e8e1b

File tree

4 files changed

+41
-41
lines changed

4 files changed

+41
-41
lines changed

crates/stackable-operator/src/client.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ use tracing::trace;
2121

2222
use crate::{
2323
kvp::LabelSelectorExt,
24-
utils::cluster_info::{KubernetesClusterInfo, KubernetesClusterInfoOpts},
24+
utils::{
25+
cluster_info::{KubernetesClusterInfo, KubernetesClusterInfoOpts},
26+
kubelet,
27+
},
2528
};
2629

2730
pub type Result<T, E = Error> = std::result::Result<T, E>;
@@ -84,6 +87,9 @@ pub enum Error {
8487

8588
#[snafu(display("unable to create kubernetes client"))]
8689
CreateKubeClient { source: kube::Error },
90+
91+
#[snafu(display("unable to fetch kubelet config"))]
92+
KubeletConfig { source: kubelet::Error },
8793
}
8894

8995
/// This `Client` can be used to access Kubernetes.
@@ -651,7 +657,10 @@ pub async fn initialize_operator(
651657
.context(InferKubeConfigSnafu)?;
652658
let default_namespace = kubeconfig.default_namespace.clone();
653659
let client = kube::Client::try_from(kubeconfig).context(CreateKubeClientSnafu)?;
654-
let cluster_info = KubernetesClusterInfo::new(cluster_info_opts);
660+
let kubelet_config = kubelet::KubeletConfig::fetch(&client)
661+
.await
662+
.context(KubeletConfigSnafu)?;
663+
let cluster_info = KubernetesClusterInfo::new(&kubelet_config, cluster_info_opts);
655664

656665
Ok(Client::new(
657666
client,

crates/stackable-operator/src/utils/cluster_info.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
use std::str::FromStr;
2-
1+
use super::kubelet::KubeletConfig;
32
use crate::commons::networking::DomainName;
43

5-
const KUBERNETES_CLUSTER_DOMAIN_DEFAULT: &str = "cluster.local";
6-
74
/// Some information that we know about the Kubernetes cluster.
85
#[derive(Debug, Clone)]
96
pub struct KubernetesClusterInfo {
@@ -21,20 +18,19 @@ pub struct KubernetesClusterInfoOpts {
2118
}
2219

2320
impl KubernetesClusterInfo {
24-
pub fn new(cluster_info_opts: &KubernetesClusterInfoOpts) -> Self {
21+
pub fn new(
22+
kubelet_config: &KubeletConfig,
23+
cluster_info_opts: &KubernetesClusterInfoOpts,
24+
) -> Self {
2525
let cluster_domain = match &cluster_info_opts.kubernetes_cluster_domain {
2626
Some(cluster_domain) => {
2727
tracing::info!(%cluster_domain, "Using configured Kubernetes cluster domain");
2828

2929
cluster_domain.clone()
3030
}
3131
None => {
32-
// TODO(sbernauer): Do some sort of advanced auto-detection, see https://github.com/stackabletech/issues/issues/436.
33-
// There have been attempts of parsing the `/etc/resolv.conf`, but they have been
34-
// reverted. Please read on the linked issue for details.
35-
let cluster_domain = DomainName::from_str(KUBERNETES_CLUSTER_DOMAIN_DEFAULT)
36-
.expect("KUBERNETES_CLUSTER_DOMAIN_DEFAULT constant must a valid domain");
37-
tracing::info!(%cluster_domain, "Defaulting Kubernetes cluster domain as it has not been configured");
32+
let cluster_domain = kubelet_config.cluster_domain.clone();
33+
tracing::info!(%cluster_domain, "Using kubelet config cluster domain");
3834

3935
cluster_domain
4036
}
Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,70 @@
1+
use http;
12
use k8s_openapi::api::core::v1::Node;
23
use kube::{
34
Api,
45
api::{ListParams, ResourceExt},
56
client::Client,
67
};
78
use serde::Deserialize;
8-
use http;
9-
use snafu::{Snafu, ResultExt, OptionExt};
9+
use snafu::{OptionExt, ResultExt, Snafu};
10+
11+
use crate::commons::networking::DomainName;
1012

1113
#[derive(Debug, Snafu)]
1214
pub enum Error {
13-
1415
#[snafu(display("failed to list nodes"))]
15-
ListNodes {
16-
source: kube::Error,
17-
},
16+
ListNodes { source: kube::Error },
1817
#[snafu(display("failed to build proxy/configz request"))]
19-
ConfigzRequest {
20-
source: http::Error,
21-
},
18+
ConfigzRequest { source: http::Error },
2219

2320
#[snafu(display("failed to fetch kubelet config from node {node}"))]
24-
FetchNodeKubeletConfig {
25-
source: kube::Error,
26-
node: String,
27-
},
21+
FetchNodeKubeletConfig { source: kube::Error, node: String },
2822

2923
#[snafu(display("failed to fetch `kubeletconfig` JSON key from configz response"))]
3024
KubeletConfigJsonKey,
3125

3226
#[snafu(display("failed to deserialize kubelet config JSON"))]
33-
KubeletConfigJson {
34-
source: serde_json::Error,
35-
},
27+
KubeletConfigJson { source: serde_json::Error },
3628

3729
#[snafu(display("empty Kubernetes nodes list"))]
3830
EmptyKubernetesNodesList,
3931
}
4032

4133
#[derive(Debug, Deserialize)]
4234
#[serde(rename_all = "camelCase")]
43-
struct KubeletConfig {
44-
cluster_domain: String,
35+
pub struct KubeletConfig {
36+
pub cluster_domain: DomainName,
4537
}
4638

4739
impl KubeletConfig {
4840
pub async fn fetch(client: &Client) -> Result<Self, Error> {
4941
let api: Api<Node> = Api::all(client.clone());
50-
let nodes = api.list(&ListParams::default()).await.context(ListNodesSnafu)?;
42+
let nodes = api
43+
.list(&ListParams::default())
44+
.await
45+
.context(ListNodesSnafu)?;
5146
let node = nodes.iter().next().context(EmptyKubernetesNodesListSnafu)?;
5247

5348
let name = node.name_any();
5449

55-
// Query node stats by issuing a request to the admin endpoint.
56-
// See https://kubernetes.io/docs/reference/instrumentation/node-metrics/
50+
// Query kukbelet config
5751
let url = format!("/api/v1/nodes/{}/proxy/configz", name);
58-
let req = http::Request::get(url).body(Default::default()).context(ConfigzRequestSnafu)?;
52+
let req = http::Request::get(url)
53+
.body(Default::default())
54+
.context(ConfigzRequestSnafu)?;
5955

6056
// Deserialize JSON response as a JSON value. Alternatively, a type that
6157
// implements `Deserialize` can be used.
62-
let resp = client.request::<serde_json::Value>(req).await.context(FetchNodeKubeletConfigSnafu { node: name })?;
58+
let resp = client
59+
.request::<serde_json::Value>(req)
60+
.await
61+
.context(FetchNodeKubeletConfigSnafu { node: name })?;
6362

6463
// Our JSON value is an object so we can treat it like a dictionary.
6564
let summary = resp
6665
.get("kubeletconfig")
6766
.context(KubeletConfigJsonKeySnafu)?;
6867

69-
// The base JSON representation includes a lot of metrics, including
70-
// container metrics. Use a `NodeMetrics` type to deserialize only the
71-
// values we care about.
7268
serde_json::from_value::<KubeletConfig>(summary.to_owned()).context(KubeletConfigJsonSnafu)
7369
}
74-
7570
}

crates/stackable-operator/src/utils/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod bash;
22
pub mod cluster_info;
33
pub mod crds;
4-
mod kubelet;
4+
pub mod kubelet;
55
pub mod logging;
66
mod option;
77
mod url;

0 commit comments

Comments
 (0)