okdload balancer using 1936 port http healthcheck #240

Merged
stremblay merged 7 commits from feat/okd_loadbalancer_betterhealthcheck into master 2026-03-10 17:45:52 +00:00
6 changed files with 37 additions and 30 deletions

View File

@@ -6,7 +6,10 @@ use harmony::{
data::{FileContent, FilePath}, data::{FileContent, FilePath},
modules::{ modules::{
inventory::HarmonyDiscoveryStrategy, inventory::HarmonyDiscoveryStrategy,
okd::{installation::OKDInstallationPipeline, ipxe::OKDIpxeScore}, okd::{
installation::OKDInstallationPipeline, ipxe::OKDIpxeScore,
load_balancer::OKDLoadBalancerScore,
},
}, },
score::Score, score::Score,
topology::HAClusterTopology, topology::HAClusterTopology,
@@ -32,6 +35,7 @@ async fn main() {
scores scores
.append(&mut OKDInstallationPipeline::get_all_scores(HarmonyDiscoveryStrategy::MDNS).await); .append(&mut OKDInstallationPipeline::get_all_scores(HarmonyDiscoveryStrategy::MDNS).await);
scores.push(Box::new(OKDLoadBalancerScore::new(&topology)));
harmony_cli::run(inventory, topology, scores, None) harmony_cli::run(inventory, topology, scores, None)
.await .await
.unwrap(); .unwrap();

View File

@@ -44,6 +44,7 @@ fn build_large_score() -> LoadBalancerScore {
], ],
listening_port: SocketAddr::V4(SocketAddrV4::new(ipv4!("192.168.0.0"), 49387)), listening_port: SocketAddr::V4(SocketAddrV4::new(ipv4!("192.168.0.0"), 49387)),
health_check: Some(HealthCheck::HTTP( health_check: Some(HealthCheck::HTTP(
Some(1993),
"/some_long_ass_path_to_see_how_it_is_displayed_but_it_has_to_be_even_longer" "/some_long_ass_path_to_see_how_it_is_displayed_but_it_has_to_be_even_longer"
.to_string(), .to_string(),
HttpMethod::GET, HttpMethod::GET,

View File

@@ -106,6 +106,7 @@ pub enum SSL {
#[derive(Debug, Clone, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize)]
pub enum HealthCheck { pub enum HealthCheck {
HTTP(String, HttpMethod, HttpStatusCode, SSL), /// HTTP(None, "/healthz/ready", HttpMethod::GET, HttpStatusCode::Success2xx, SSL::Disabled)
HTTP(Option<u16>, String, HttpMethod, HttpStatusCode, SSL),
TCP(Option<u16>), TCP(Option<u16>),
} }

View File

@@ -216,7 +216,15 @@ pub(crate) fn get_health_check_for_backend(
SSL::Other(other.to_string()) SSL::Other(other.to_string())
} }
}; };
Some(HealthCheck::HTTP(path, method, status_code, ssl))
let port = haproxy_health_check
.checkport
.content_string()
.parse::<u16>()
.ok();
debug!("Found haproxy healthcheck port {port:?}");
Some(HealthCheck::HTTP(port, path, method, status_code, ssl))
} }
_ => panic!("Received unsupported health check type {}", uppercase), _ => panic!("Received unsupported health check type {}", uppercase),
} }
@@ -251,7 +259,7 @@ pub(crate) fn harmony_load_balancer_service_to_haproxy_xml(
// frontend points to backend // frontend points to backend
let healthcheck = if let Some(health_check) = &service.health_check { let healthcheck = if let Some(health_check) = &service.health_check {
match health_check { match health_check {
HealthCheck::HTTP(path, http_method, _http_status_code, ssl) => { HealthCheck::HTTP(port, path, http_method, _http_status_code, ssl) => {
let ssl: MaybeString = match ssl { let ssl: MaybeString = match ssl {
SSL::SSL => "ssl".into(), SSL::SSL => "ssl".into(),
SSL::SNI => "sslni".into(), SSL::SNI => "sslni".into(),
@@ -267,6 +275,7 @@ pub(crate) fn harmony_load_balancer_service_to_haproxy_xml(
http_uri: path.clone().into(), http_uri: path.clone().into(),
interval: "2s".to_string(), interval: "2s".to_string(),
ssl, ssl,
checkport: MaybeString::from(port.map(|p| p.to_string())),
..Default::default() ..Default::default()
}; };

View File

@@ -41,6 +41,7 @@ impl OKDBootstrapLoadBalancerScore {
backend_servers: Self::topology_to_backend_server(topology, 6443), backend_servers: Self::topology_to_backend_server(topology, 6443),
listening_port: SocketAddr::new(private_ip, 6443), listening_port: SocketAddr::new(private_ip, 6443),
health_check: Some(HealthCheck::HTTP( health_check: Some(HealthCheck::HTTP(
None,
"/readyz".to_string(), "/readyz".to_string(),
HttpMethod::GET, HttpMethod::GET,
HttpStatusCode::Success2xx, HttpStatusCode::Success2xx,

View File

@@ -58,12 +58,12 @@ impl OKDLoadBalancerScore {
LoadBalancerService { LoadBalancerService {
backend_servers: Self::nodes_to_backend_server(topology, 80), backend_servers: Self::nodes_to_backend_server(topology, 80),
listening_port: SocketAddr::new(public_ip, 80), listening_port: SocketAddr::new(public_ip, 80),
health_check: Some(HealthCheck::TCP(None)), health_check: None,
}, },
LoadBalancerService { LoadBalancerService {
backend_servers: Self::nodes_to_backend_server(topology, 443), backend_servers: Self::nodes_to_backend_server(topology, 443),
listening_port: SocketAddr::new(public_ip, 443), listening_port: SocketAddr::new(public_ip, 443),
health_check: Some(HealthCheck::TCP(None)), health_check: None,
}, },
]; ];
@@ -71,12 +71,24 @@ impl OKDLoadBalancerScore {
LoadBalancerService { LoadBalancerService {
backend_servers: Self::nodes_to_backend_server(topology, 80), backend_servers: Self::nodes_to_backend_server(topology, 80),
listening_port: SocketAddr::new(public_ip, 80), listening_port: SocketAddr::new(public_ip, 80),
health_check: Some(HealthCheck::TCP(None)), health_check: Some(HealthCheck::HTTP(
Some(25001),
"/health?check=okd_router_1936,node_ready".to_string(),
HttpMethod::GET,
HttpStatusCode::Success2xx,
SSL::Default,
)),
}, },
LoadBalancerService { LoadBalancerService {
backend_servers: Self::nodes_to_backend_server(topology, 443), backend_servers: Self::nodes_to_backend_server(topology, 443),
listening_port: SocketAddr::new(public_ip, 443), listening_port: SocketAddr::new(public_ip, 443),
health_check: Some(HealthCheck::TCP(None)), health_check: Some(HealthCheck::HTTP(
Some(25001),
"/health?check=okd_router_1936,node_ready".to_string(),
HttpMethod::GET,
HttpStatusCode::Success2xx,
SSL::Default,
)),
}, },
LoadBalancerService { LoadBalancerService {
backend_servers: Self::control_plane_to_backend_server(topology, 22623), backend_servers: Self::control_plane_to_backend_server(topology, 22623),
@@ -87,6 +99,7 @@ impl OKDLoadBalancerScore {
backend_servers: Self::control_plane_to_backend_server(topology, 6443), backend_servers: Self::control_plane_to_backend_server(topology, 6443),
listening_port: SocketAddr::new(public_ip, 6443), listening_port: SocketAddr::new(public_ip, 6443),
health_check: Some(HealthCheck::HTTP( health_check: Some(HealthCheck::HTTP(
None,
"/readyz".to_string(), "/readyz".to_string(),
HttpMethod::GET, HttpMethod::GET,
HttpStatusCode::Success2xx, HttpStatusCode::Success2xx,
@@ -298,28 +311,6 @@ mod tests {
assert_eq!(private_service_22623.backend_servers.len(), 3); assert_eq!(private_service_22623.backend_servers.len(), 3);
} }
#[test]
fn test_private_service_port_6443_only_control_plane() {
let topology = create_test_topology();
let score = OKDLoadBalancerScore::new(&topology);
let private_service_6443 = score
.load_balancer_score
.private_services
.iter()
.find(|s| s.listening_port.port() == 6443)
.expect("Private service on port 6443 not found");
assert_eq!(private_service_6443.backend_servers.len(), 3);
assert!(
matches!(
private_service_6443.health_check,
Some(HealthCheck::HTTP(_, _, _, _))
),
"Expected HTTP health check for port 6443"
);
}
#[test] #[test]
fn test_all_backend_servers_have_correct_port() { fn test_all_backend_servers_have_correct_port() {
let topology = create_test_topology(); let topology = create_test_topology();