This commit introduces the ability to configure health checks for load balancer backends located in remote availability zones through OVN Interconnect.
Key changes include: 1. Added new 'local' field to service monitor schema. 2. Extended ip_port_mappings syntax to support remote backends: - Added :remote:<az-name> suffix for health check targets 3. Modified controller logic to skip non-local monitors. 4. Enhanced northd to handle remote health check configuration. Signed-off-by: Alexandra Rukomoinikova <arukomoinikova@k2.cloud> --- controller/pinctrl.c | 2 +- northd/lb.c | 30 +++++++++++++++++++++++------- northd/lb.h | 9 +++++++-- northd/northd.c | 35 ++++++++++++++++++++++++++++------- ovn-nb.xml | 7 +++++++ ovn-sb.ovsschema | 5 +++-- ovn-sb.xml | 10 +++++++++- 7 files changed, 78 insertions(+), 20 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index d4f4da731..fcb04eadd 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -7048,7 +7048,7 @@ sync_svc_monitors(struct ovsdb_idl_txn *ovnsb_idl_txn, const struct sbrec_port_binding *pb = lport_lookup_by_name(sbrec_port_binding_by_name, sb_svc_mon->logical_port); - if (!pb) { + if (!pb || !sb_svc_mon->local) { continue; } diff --git a/northd/lb.c b/northd/lb.c index b11896cf1..15a0b8651 100644 --- a/northd/lb.c +++ b/northd/lb.c @@ -120,20 +120,29 @@ ovn_lb_vip_backends_health_check_init(const struct ovn_northd_lb *lb, } char *svc_mon_src_ip = NULL; + char *az_name = NULL; char *port_name = xstrdup(s); - char *p = strstr(port_name, ":"); - if (p) { - *p = 0; - p++; + + char *ip_part = strstr(port_name, ":"); + if (ip_part) { + *ip_part = '\0'; + ip_part++; + + char *remote_marker = strstr(ip_part, ":remote:"); + if (remote_marker) { + *remote_marker = '\0'; + az_name = remote_marker + 8; + } + struct sockaddr_storage svc_mon_src_addr; - if (!inet_parse_address(p, &svc_mon_src_addr)) { + if (!inet_parse_address(ip_part, &svc_mon_src_addr)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Invalid svc mon src IP %s", p); + VLOG_WARN_RL(&rl, "Invalid svc mon src IP %s", ip_part); } else { struct ds src_ip_s = DS_EMPTY_INITIALIZER; ss_format_address_nobracks(&svc_mon_src_addr, - &src_ip_s); + &src_ip_s); svc_mon_src_ip = ds_steal_cstr(&src_ip_s); } } @@ -144,6 +153,12 @@ ovn_lb_vip_backends_health_check_init(const struct ovn_northd_lb *lb, backend_nb->health_check = true; backend_nb->logical_port = xstrdup(port_name); backend_nb->svc_mon_src_ip = svc_mon_src_ip; + if (az_name) { + backend_nb->local_backend = false; + backend_nb->az_name = xstrdup(az_name); + } else { + backend_nb->local_backend = true; + } } free(port_name); } @@ -158,6 +173,7 @@ void ovn_northd_lb_vip_destroy(struct ovn_northd_lb_vip *vip) for (size_t i = 0; i < vip->n_backends; i++) { free(vip->backends_nb[i].logical_port); free(vip->backends_nb[i].svc_mon_src_ip); + free(vip->backends_nb[i].az_name); } free(vip->backends_nb); } diff --git a/northd/lb.h b/northd/lb.h index eb1942bd4..6de953cfc 100644 --- a/northd/lb.h +++ b/northd/lb.h @@ -88,8 +88,13 @@ struct ovn_northd_lb_vip { struct ovn_northd_lb_backend { bool health_check; - char *logical_port; /* Logical port to which the ip belong to. */ - char *svc_mon_src_ip; /* Source IP to use for monitoring. */ + /* Set to true if port locates in current ovn cluster. */ + bool local_backend; + /* Logical port to which the ip belong to. */ + char *logical_port; + char *svc_mon_src_ip; + /* Target az_name for service monitor. */ + char *az_name; }; struct ovn_northd_lb *ovn_northd_lb_create(const struct nbrec_load_balancer *); diff --git a/northd/northd.c b/northd/northd.c index a7be29619..c83348fe5 100644 --- a/northd/northd.c +++ b/northd/northd.c @@ -3730,13 +3730,28 @@ get_service_mon(const struct hmap *local_monitor_map, return NULL; } +static void +set_service_mon_options(const struct sbrec_service_monitor *sbrec_mon, + const struct smap *nb_hc_options, + const char *target_az_name) +{ + struct smap sb_svc_options = SMAP_INITIALIZER(&sb_svc_options); + + smap_clone(&sb_svc_options, nb_hc_options); + if (target_az_name) { + smap_add(&sb_svc_options, "az-name", target_az_name); + } + sbrec_service_monitor_set_options(sbrec_mon, &sb_svc_options); + smap_destroy(&sb_svc_options); +} + static struct service_monitor_info * create_or_get_service_mon(struct ovsdb_idl_txn *ovnsb_txn, struct hmap *local_monitor_map, struct hmap *ic_learned_monitor_map, const char *ip, const char *logical_port, uint16_t service_port, const char *protocol, - const char *chassis_name) + const char *chassis_name, bool local_backend) { struct service_monitor_info *mon_info = get_service_mon(local_monitor_map, ic_learned_monitor_map, @@ -3762,6 +3777,8 @@ create_or_get_service_mon(struct ovsdb_idl_txn *ovnsb_txn, sbrec_service_monitor_set_port(sbrec_mon, service_port); sbrec_service_monitor_set_logical_port(sbrec_mon, logical_port); sbrec_service_monitor_set_protocol(sbrec_mon, protocol); + sbrec_service_monitor_set_local(sbrec_mon, local_backend); + sbrec_service_monitor_set_ic_learned(sbrec_mon, false); if (chassis_name) { sbrec_service_monitor_set_chassis_name(sbrec_mon, chassis_name); } @@ -3803,7 +3820,8 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, struct ovn_port *op = ovn_port_find(ls_ports, backend_nb->logical_port); - if (!op || !lsp_is_enabled(op->nbsp)) { + if (backend_nb->local_backend && + (!op || !lsp_is_enabled(op->nbsp))) { continue; } @@ -3813,7 +3831,7 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, } const char *chassis_name = NULL; - if (op->sb->chassis) { + if (backend_nb->local_backend && op->sb->chassis) { chassis_name = op->sb->chassis->name; } @@ -3825,10 +3843,12 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, backend_nb->logical_port, backend->port, protocol, - chassis_name); + chassis_name, + backend_nb->local_backend); ovs_assert(mon_info); - sbrec_service_monitor_set_options( - mon_info->sbrec_mon, &lb_vip_nb->lb_health_check->options); + set_service_mon_options(mon_info->sbrec_mon, + &lb_vip_nb->lb_health_check->options, + backend_nb->az_name); struct eth_addr ea; if (!mon_info->sbrec_mon->src_mac || !eth_addr_from_string(mon_info->sbrec_mon->src_mac, &ea) || @@ -3845,7 +3865,8 @@ ovn_lb_svc_create(struct ovsdb_idl_txn *ovnsb_txn, backend_nb->svc_mon_src_ip); } - if ((!op->sb->n_up || !op->sb->up[0]) + if (backend_nb->local_backend && + (!op->sb->n_up || !op->sb->up[0]) && mon_info->sbrec_mon->status && !strcmp(mon_info->sbrec_mon->status, "online")) { sbrec_service_monitor_set_status(mon_info->sbrec_mon, diff --git a/ovn-nb.xml b/ovn-nb.xml index 4a7581807..674dfdc0c 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -2231,6 +2231,9 @@ Health checks are sent to this port with the specified source IP. For IPv6 square brackets must be used around IP address, e.g: <code><var>port_name</var>:<var>[sourc_ip]</var></code> + Remote endpoint: + Use the :remote:<code>az-name</code> syntax to create remote health + checks in a specific zone. </p> <p> @@ -2238,11 +2241,15 @@ defined as <code>10.0.0.4</code>=<code>sw0-p1:10.0.0.2</code> and <code>20.0.0.4</code>=<code>sw1-p1:20.0.0.2</code>, if the values given were suitable ports and IP addresses. + And remote endpoint: + <code>10.0.0.4</code>=<code>sw0-p1:10.0.0.2</code>:remote:az1, where + <code>sw0-p1</code> - logical port in <code>az1</code>. </p> <p> For IPv6 IP to port mappings might be defined as <code>[2001::1]</code>=<code>sw0-p1:[2002::1]</code>. + Remote endpoint: same as for IP. </p> </column> </group> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema index da1fd38e8..91763b7f8 100644 --- a/ovn-sb.ovsschema +++ b/ovn-sb.ovsschema @@ -1,7 +1,7 @@ { "name": "OVN_Southbound", - "version": "21.3.0", - "cksum": "3512532069 34910", + "version": "21.4.0", + "cksum": "1850884918 34956", "tables": { "SB_Global": { "columns": { @@ -517,6 +517,7 @@ "src_mac": {"type": "string"}, "src_ip": {"type": "string"}, "chassis_name": {"type": "string"}, + "local": {"type": "boolean"}, "ic_learned": {"type": "boolean"}, "status": { "type": {"key": {"type": "string", diff --git a/ovn-sb.xml b/ovn-sb.xml index f7eafd379..08b4892f5 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -4967,6 +4967,10 @@ tcp.flags = RST; The service can be an IPv4 TCP or UDP service. <code>ovn-controller</code> periodically sends out service monitor packets and updates the status of the service. + If the service monitor is not local, then ovn-ic creates a record about + it in the SBDB database, after which another OVN deployment creates a + record about the Service Monitor in its SBDB and the status is + propagated back to the initial record in the original availability zone. </p> <p> @@ -4981,7 +4985,7 @@ tcp.flags = RST; </p> <column name="ip"> - IP of the service to be monitored. Only IPv4 is supported. + IP of the service to be monitored. </column> <column name="protocol"> @@ -5010,6 +5014,10 @@ tcp.flags = RST; The name of the chassis where the logical port is bound. </column> + <column name="local"> + Set to true if backend locates on local ovn deployment. + </column> + <column name="ic_learned"> Set to true if the service monitor was propagated from another OVN deployment via ovn-ic management. -- 2.48.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev