diff --git a/internal-dns/src/config.rs b/internal-dns/src/config.rs index 8318337f6d..29a718c2fa 100644 --- a/internal-dns/src/config.rs +++ b/internal-dns/src/config.rs @@ -64,7 +64,7 @@ use crate::names::{ServiceName, BOUNDARY_NTP_DNS_NAME, DNS_ZONE}; use anyhow::{anyhow, ensure}; use core::fmt; use dns_service_client::types::{DnsConfigParams, DnsConfigZone, DnsRecord}; -use omicron_common::address::CLICKHOUSE_TCP_PORT; +use omicron_common::address::{CLICKHOUSE_ADMIN_PORT, CLICKHOUSE_TCP_PORT}; use omicron_common::api::external::Generation; use omicron_uuid_kinds::{OmicronZoneUuid, SledUuid}; use std::collections::BTreeMap; @@ -411,6 +411,9 @@ impl DnsConfigBuilder { /// this zone, and `http_port` is the associated port for that service. The /// native service is added automatically, using its default port. /// + /// For `ClickhouseServer` zones we also need to add a + /// `ClickhouseAdminServer` service. + /// /// # Errors /// /// This fails if the provided `http_service` is not for a ClickHouse @@ -435,6 +438,45 @@ impl DnsConfigBuilder { ServiceName::ClickhouseNative, &zone, CLICKHOUSE_TCP_PORT, + )?; + + if http_service == ServiceName::ClickhouseServer { + self.service_backend_zone( + ServiceName::ClickhouseAdminServer, + &zone, + CLICKHOUSE_ADMIN_PORT, + )?; + } + + Ok(()) + } + + /// Higher-level shorthand for adding a ClickhouseKeeper zone with several + /// services. + /// + /// # Errors + /// + /// This fails if the provided `http_service` is not for a ClickhouseKeeper + /// replica server. It also fails if the given zone has already been added + /// to the configuration. + pub fn host_zone_clickhouse_keeper( + &mut self, + zone_id: OmicronZoneUuid, + underlay_address: Ipv6Addr, + service: ServiceName, + port: u16, + ) -> anyhow::Result<()> { + anyhow::ensure!( + service == ServiceName::ClickhouseKeeper, + "This method is only valid for ClickHouse keeper servers, \ + but we were provided the service '{service:?}'", + ); + let zone = self.host_zone(zone_id, underlay_address)?; + self.service_backend_zone(service, &zone, port)?; + self.service_backend_zone( + ServiceName::ClickhouseAdminKeeper, + &zone, + CLICKHOUSE_ADMIN_PORT, ) } @@ -546,6 +588,14 @@ mod test { #[test] fn display_srv_service() { assert_eq!(ServiceName::Clickhouse.dns_name(), "_clickhouse._tcp",); + assert_eq!( + ServiceName::ClickhouseAdminKeeper.dns_name(), + "_clickhouse-admin-keeper._tcp", + ); + assert_eq!( + ServiceName::ClickhouseAdminServer.dns_name(), + "_clickhouse-admin-server._tcp", + ); assert_eq!( ServiceName::ClickhouseKeeper.dns_name(), "_clickhouse-keeper._tcp", diff --git a/internal-dns/src/names.rs b/internal-dns/src/names.rs index 78db87fbab..ae4885c980 100644 --- a/internal-dns/src/names.rs +++ b/internal-dns/src/names.rs @@ -25,6 +25,10 @@ pub const DNS_ZONE_EXTERNAL_TESTING: &str = "oxide-dev.test"; pub enum ServiceName { /// The HTTP interface to a single-node ClickHouse server. Clickhouse, + /// The HTTP interface for managing clickhouse keepers + ClickhouseAdminKeeper, + /// The HTTP interface for managing replicated clickhouse servers + ClickhouseAdminServer, /// The native TCP interface to a ClickHouse server. /// /// NOTE: This is used for either single-node or a replicated cluster. @@ -55,6 +59,8 @@ impl ServiceName { fn service_kind(&self) -> &'static str { match self { ServiceName::Clickhouse => "clickhouse", + ServiceName::ClickhouseAdminKeeper => "clickhouse-admin-keeper", + ServiceName::ClickhouseAdminServer => "clickhouse-admin-server", ServiceName::ClickhouseNative => "clickhouse-native", ServiceName::ClickhouseKeeper => "clickhouse-keeper", ServiceName::ClickhouseServer => "clickhouse-server", @@ -82,6 +88,8 @@ impl ServiceName { pub fn dns_name(&self) -> String { match self { ServiceName::Clickhouse + | ServiceName::ClickhouseAdminKeeper + | ServiceName::ClickhouseAdminServer | ServiceName::ClickhouseNative | ServiceName::ClickhouseKeeper | ServiceName::ClickhouseServer diff --git a/nexus/reconfigurator/execution/src/dns.rs b/nexus/reconfigurator/execution/src/dns.rs index 3de715495b..52c593a8e6 100644 --- a/nexus/reconfigurator/execution/src/dns.rs +++ b/nexus/reconfigurator/execution/src/dns.rs @@ -301,7 +301,22 @@ pub fn blueprint_internal_dns_config( } BlueprintZoneType::ClickhouseKeeper( blueprint_zone_type::ClickhouseKeeper { address, .. }, - ) => (ServiceName::ClickhouseKeeper, address.port()), + ) => { + // Add the Clickhouse keeper service and `clickhouse-admin` + // service used for managing the keeper. We continue below so we + // don't fall through and call `host_zone_with_one_backend`. + dns_builder + .host_zone_clickhouse_keeper( + zone.id, + zone.underlay_address, + ServiceName::ClickhouseKeeper, + address.port(), + ) + .map_err(|e| Error::InternalError { + internal_message: e.to_string(), + })?; + continue 'all_zones; + } BlueprintZoneType::CockroachDb( blueprint_zone_type::CockroachDb { address, .. }, ) => (ServiceName::Cockroach, address.port()),