Skip to content

Commit c17dba5

Browse files
committed
MGMT-21485: Enable dpu-host mode that matches DPF requirements
This commit introduces OVN_NODE_MODE environment variable to enable per-node feature enforcement, particularly for DPU host mode where certain features must be disabled regardless of cluster-wide configuration. - Move feature toggles from ConfigMap (004-config.yaml) to startup scripts - ConfigMap values cannot be reliably overridden per-node, but script logic can be conditional - Implement OVN_NODE_MODE-based conditional feature enablement in node startup script - Update control-plane scripts to handle moved parameters - Add 'dpu-host' mode that automatically disables incompatible features: - Egress IP and related features (egress firewall, egress QoS, egress service) - Multicast support - Multi-external gateway support - Multi-network policies and admin network policies - Network segmentation features - Set gateway_interface='derive-from-mgmt-port' for DPU host nodes - Add ovnkube_node_mode='--ovnkube-node-mode dpu-host' flag From bindata/network/ovn-kubernetes/*/004-config.yaml: - enable-egress-ip=true - enable-egress-firewall=true - enable-egress-qos=true - enable-egress-service=true - enable-multicast=true - enable-multi-external-gateway=true Note: HyperShift hosted cluster ConfigMap (managed/004-config.yaml) retains egress feature flags as DPU host mode is not supported in hosted cluster configurations. - Add conditional blocks based on OVN_NODE_MODE - Full mode (default): All features enabled as configured - DPU host mode: Incompatible features force-disabled - Rename egress_ip_enable_flag to egress_features_enable_flag for clarity - Always-enabled features: Direct CLI flags (cleaner implementation) - --enable-egress-ip=true, --enable-egress-firewall=true, etc. - --enable-multicast, --enable-multi-external-gateway=true - Conditional features: Script variables (matching original ConfigMap logic) - multi_network_enabled_flag, network_segmentation_enabled_flag - multi_network_policy_enabled_flag, admin_network_policy_enabled_flag - Maintain backward compatibility for existing deployments - Add comprehensive TestOVNKubernetesScriptLibCombined test covering: - DPU host mode feature gating and disabling - Full mode with multi-network features enabled/disabled - Non-mode-gated features (route advertisements, DNS resolver, etc.) - Gateway interface variable usage validation - Multi-external gateway and egress features flag behavior across modes - Add TestOVNKubernetesControlPlaneFlags test covering: - Always-enabled features validation (direct CLI flags) - Conditional features validation (script variables) - Multi-network enablement logic (OVN_MULTI_NETWORK_ENABLE or OVN_NETWORK_SEGMENTATION_ENABLE) - Network segmentation logic validation - Remove redundant individual test functions after consolidation - Update existing config rendering tests for new ConfigMap content - Update test assertions to use correct flag names (egress_features_enable_flag) - Create docs/ovn_node_mode.md with detailed technical explanation - Update docs/operands.md with OVN-Kubernetes node modes section - Update docs/architecture.md with per-node configuration explanation - Update README.md with DPU host mode support information - Add implementation details, feature mapping tables, and migration notes - Document multi-external gateway as disabled feature in DPU host mode - Update all references to use correct flag names ConfigMap-based feature control cannot be overridden per-node, making it impossible to disable features on specific node types (like DPU hosts) while keeping them enabled cluster-wide. Moving the logic to startup scripts allows the same cluster configuration to work across heterogeneous node types. This change ensures that DPU host nodes automatically have incompatible features disabled, preventing runtime failures and enabling mixed-mode cluster deployments. - Existing clusters continue to work without changes - Default behavior (full mode) remains unchanged - Control-plane components maintain identical functionality - Migration is automatic during upgrade process - No manual intervention required - HyperShift hosted clusters unaffected (DPU host mode not supported)
1 parent b864c3d commit c17dba5

File tree

12 files changed

+527
-211
lines changed

12 files changed

+527
-211
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ OVNKubernetes supports the following configuration options, all of which are opt
157157
* `egressIPConfig`: holds the configuration for EgressIP options.
158158
* `reachabilityTotalTimeoutSeconds`: Set EgressIP node reachability total timeout in seconds, 0 means disable reachability check and the default is 1 second.
159159

160+
#### DPU Host Mode Support
161+
162+
OVN-Kubernetes supports specialized hardware deployments such as DPU (Data Processing Unit) hosts through the `OVN_NODE_MODE` environment variable. In `dpu-host` mode, certain features are automatically disabled on those nodes regardless of cluster-wide configuration:
163+
164+
- Egress IP and related features (egress firewall, egress QoS, egress service)
165+
- Multicast support
166+
- Multi-external gateway support
167+
- Multi-network policies and admin network policies
168+
- Network segmentation features
169+
170+
This per-node feature enforcement is implemented through conditional logic in the startup scripts, allowing the same cluster configuration to work across heterogeneous node types. For detailed information about node modes and the technical implementation, see `docs/ovn_node_mode.md`.
171+
160172
These configuration flags are only in the Operator configuration object.
161173

162174
Example from the `manifests/cluster-network-03-config.yml` file:

bindata/network/ovn-kubernetes/common/008-script-lib.yaml

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -515,13 +515,35 @@ data:
515515

516516
echo "I$(date "+%m%d %H:%M:%S.%N") - starting ovnkube-node"
517517

518+
# enable egress ip, egress firewall, egress qos, egress service
519+
egress_features_enable_flag="--enable-egress-ip=true --enable-egress-firewall=true --enable-egress-qos=true --enable-egress-service=true"
520+
init_ovnkube_controller="--init-ovnkube-controller ${K8S_NODE}"
521+
multi_external_gateway_enable_flag="--enable-multi-external-gateway=true"
522+
gateway_interface=br-ex
518523

519-
if [ "{{.OVN_NODE_MODE}}" == "dpu-host" ]; then
520-
// this is required for the dpu-host mode to configure right gateway interface
521-
// https://github.com/ovn-kubernetes/ovn-kubernetes/pull/5327/files
522-
gateway_interface=derive-from-mgmt-port
523-
else
524-
gateway_interface=br-ex
524+
# enable multicast
525+
enable_multicast_flag="--enable-multicast"
526+
527+
# Use OVN_NODE_MODE environment variable, default to "full" if not set
528+
OVN_NODE_MODE=${OVN_NODE_MODE:-full}
529+
# We check only dpu-host mode and not smart-nic mode here as currently we do not support it yet
530+
# Once we support it, we will need to check for it here and add relevant code.
531+
if [ "${OVN_NODE_MODE}" == "dpu-host" ]; then
532+
# this is required for the dpu-host mode to configure right gateway interface
533+
# https://github.com/ovn-kubernetes/ovn-kubernetes/pull/5327/files
534+
gateway_interface="derive-from-mgmt-port"
535+
ovnkube_node_mode="--ovnkube-node-mode dpu-host"
536+
# disable egress ip for dpu-host mode as it is not supported
537+
egress_features_enable_flag=""
538+
539+
# disable multicast for dpu-host mode as it is not supported
540+
enable_multicast_flag=""
541+
542+
# disable init-ovnkube-controller for dpu-host mode as it is not supported
543+
init_ovnkube_controller=""
544+
545+
# disable multi-external-gateway for dpu-host mode as it is not supported
546+
multi_external_gateway_enable_flag=""
525547
fi
526548

527549
if [ "{{.OVN_GATEWAY_MODE}}" == "shared" ]; then
@@ -567,12 +589,12 @@ data:
567589
fi
568590

569591
multi_network_enabled_flag=
570-
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" == "true" ]]; then
592+
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" == "true" && "${OVN_NODE_MODE}" != "dpu-host" ]]; then
571593
multi_network_enabled_flag="--enable-multi-network"
572594
fi
573595

574596
network_segmentation_enabled_flag=
575-
if [[ "{{.OVN_NETWORK_SEGMENTATION_ENABLE}}" == "true" ]]; then
597+
if [[ "{{.OVN_NETWORK_SEGMENTATION_ENABLE}}" == "true" && "${OVN_NODE_MODE}" != "dpu-host" ]]; then
576598
multi_network_enabled_flag="--enable-multi-network"
577599
network_segmentation_enabled_flag="--enable-network-segmentation"
578600
fi
@@ -593,12 +615,12 @@ data:
593615
fi
594616

595617
multi_network_policy_enabled_flag=
596-
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
618+
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true"&& "${OVN_NODE_MODE}" != "dpu-host" ]]; then
597619
multi_network_policy_enabled_flag="--enable-multi-networkpolicy"
598620
fi
599621

600622
admin_network_policy_enabled_flag=
601-
if [[ "{{.OVN_ADMIN_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
623+
if [[ "{{.OVN_ADMIN_NETWORK_POLICY_ENABLE}}" == "true" && "${OVN_NODE_MODE}" != "dpu-host" ]]; then
602624
admin_network_policy_enabled_flag="--enable-admin-network-policy"
603625
fi
604626

@@ -663,17 +685,15 @@ data:
663685
fi
664686

665687
exec /usr/bin/ovnkube \
666-
--init-ovnkube-controller "${K8S_NODE}" \
688+
${init_ovnkube_controller} \
667689
--init-node "${K8S_NODE}" \
668690
--config-file=/run/ovnkube-config/ovnkube.conf \
669691
--ovn-empty-lb-events \
670692
--loglevel "${log_level}" \
671693
--inactivity-probe="${OVN_CONTROLLER_INACTIVITY_PROBE}" \
672694
${gateway_mode_flags} \
673695
${node_mgmt_port_netdev_flags} \
674-
{{- if eq .OVN_NODE_MODE "dpu-host" }}
675-
--ovnkube-node-mode dpu-host \
676-
{{- end }}
696+
${ovnkube_node_mode} \
677697
--metrics-bind-address "127.0.0.1:${metrics_port}" \
678698
--ovn-metrics-bind-address "127.0.0.1:${ovn_metrics_port}" \
679699
--metrics-enable-pprof \
@@ -689,7 +709,7 @@ data:
689709
${admin_network_policy_enabled_flag} \
690710
${dns_name_resolver_enabled_flag} \
691711
${network_observability_enabled_flag} \
692-
--enable-multicast \
712+
${enable_multicast_flag} \
693713
--zone ${K8S_NODE} \
694714
--enable-interconnect \
695715
--acl-logging-rate-limit "{{.OVNPolicyAuditRateLimit}}" \
@@ -702,5 +722,7 @@ data:
702722
${ovn_v4_masquerade_subnet_opt} \
703723
${ovn_v6_masquerade_subnet_opt} \
704724
${ovn_v4_transit_switch_subnet_opt} \
705-
${ovn_v6_transit_switch_subnet_opt}
725+
${ovn_v6_transit_switch_subnet_opt} \
726+
${egress_features_enable_flag} \
727+
${multi_external_gateway_enable_flag}
706728
}

bindata/network/ovn-kubernetes/managed/004-config.yaml

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,9 @@ data:
3333
dns-service-name="dns-default"
3434

3535
[ovnkubernetesfeature]
36-
enable-egress-ip=true
37-
enable-egress-firewall=true
38-
enable-egress-qos=true
39-
enable-egress-service=true
4036
{{- if .ReachabilityNodePort }}
4137
egressip-node-healthcheck-port={{.ReachabilityNodePort}}
4238
{{- end }}
43-
{{- if .OVN_MULTI_NETWORK_ENABLE }}
44-
enable-multi-network=true
45-
{{- end }}
4639
{{- if .OVN_NETWORK_SEGMENTATION_ENABLE }}
4740
{{- if not .OVN_MULTI_NETWORK_ENABLE }}
4841
enable-multi-network=true
@@ -52,13 +45,6 @@ data:
5245
{{- if .OVN_PRE_CONF_UDN_ADDR_ENABLE }}
5346
enable-preconfigured-udn-addresses=true
5447
{{- end }}
55-
{{- if .OVN_MULTI_NETWORK_POLICY_ENABLE }}
56-
enable-multi-networkpolicy=true
57-
{{- end }}
58-
{{- if .OVN_ADMIN_NETWORK_POLICY_ENABLE }}
59-
enable-admin-network-policy=true
60-
{{- end }}
61-
enable-multi-external-gateway=true
6248
{{- if .DNS_NAME_RESOLVER_ENABLE }}
6349
enable-dns-name-resolver=true
6450
{{- end }}
@@ -147,13 +133,6 @@ data:
147133
enable-preconfigured-udn-addresses=true
148134
{{- end }}
149135
{{- end }}
150-
{{- if .OVN_MULTI_NETWORK_POLICY_ENABLE }}
151-
enable-multi-networkpolicy=true
152-
{{- end }}
153-
{{- if .OVN_ADMIN_NETWORK_POLICY_ENABLE }}
154-
enable-admin-network-policy=true
155-
{{- end }}
156-
enable-multi-external-gateway=true
157136
{{- if .DNS_NAME_RESOLVER_ENABLE }}
158137
enable-dns-name-resolver=true
159138
{{- end }}

bindata/network/ovn-kubernetes/managed/ovnkube-control-plane.yaml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,13 @@ spec:
184184
# will rollout control plane pods as well
185185
network_segmentation_enabled_flag=
186186
multi_network_enabled_flag=
187-
if [[ "{{.OVN_NETWORK_SEGMENTATION_ENABLE}}" == "true" ]]; then
187+
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" == "true" ]]; then
188188
multi_network_enabled_flag="--enable-multi-network"
189+
fi
190+
if [[ "{{.OVN_NETWORK_SEGMENTATION_ENABLE}}" == "true" ]]; then
191+
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" != "true" ]]; then
192+
multi_network_enabled_flag="--enable-multi-network"
193+
fi
189194
network_segmentation_enabled_flag="--enable-network-segmentation"
190195
fi
191196
@@ -199,6 +204,18 @@ spec:
199204
preconfigured_udn_addresses_enable_flag="--enable-preconfigured-udn-addresses"
200205
fi
201206
207+
# Enable multi-network policy if configured (control-plane always full mode)
208+
multi_network_policy_enabled_flag=
209+
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
210+
multi_network_policy_enabled_flag="--enable-multi-networkpolicy"
211+
fi
212+
213+
# Enable admin network policy if configured (control-plane always full mode)
214+
admin_network_policy_enabled_flag=
215+
if [[ "{{.OVN_ADMIN_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
216+
admin_network_policy_enabled_flag="--enable-admin-network-policy"
217+
fi
218+
202219
echo "I$(date "+%m%d %H:%M:%S.%N") - ovnkube-control-plane - start ovnkube --init-cluster-manager ${K8S_NODE}"
203220
exec /usr/bin/ovnkube \
204221
--enable-interconnect \
@@ -220,7 +237,15 @@ spec:
220237
${multi_network_enabled_flag} \
221238
${network_segmentation_enabled_flag} \
222239
${route_advertisements_enable_flag} \
223-
${preconfigured_udn_addresses_enable_flag}
240+
${preconfigured_udn_addresses_enable_flag} \
241+
--enable-egress-ip=true \
242+
--enable-egress-firewall=true \
243+
--enable-egress-qos=true \
244+
--enable-egress-service=true \
245+
--enable-multicast \
246+
--enable-multi-external-gateway=true \
247+
${multi_network_policy_enabled_flag} \
248+
${admin_network_policy_enabled_flag}
224249
volumeMounts:
225250
- mountPath: /run/ovnkube-config/
226251
name: ovnkube-config

bindata/network/ovn-kubernetes/managed/ovnkube-node.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ spec:
394394
value: "{{.OVN_CONTROLLER_INACTIVITY_PROBE}}"
395395
- name: OVN_KUBE_LOG_LEVEL
396396
value: "4"
397+
- name: OVN_NODE_MODE
398+
value: "{{.OVN_NODE_MODE}}"
397399
{{ if .NetFlowCollectors }}
398400
- name: NETFLOW_COLLECTORS
399401
value: "{{.NetFlowCollectors}}"

bindata/network/ovn-kubernetes/self-hosted/004-config.yaml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,13 @@ data:
3636
dns-service-name="dns-default"
3737

3838
[ovnkubernetesfeature]
39-
enable-egress-ip=true
40-
enable-egress-firewall=true
41-
enable-egress-qos=true
42-
enable-egress-service=true
39+
4340
{{- if .ReachabilityTotalTimeoutSeconds }}
4441
egressip-reachability-total-timeout={{.ReachabilityTotalTimeoutSeconds}}
4542
{{- end }}
4643
{{- if .ReachabilityNodePort }}
4744
egressip-node-healthcheck-port={{.ReachabilityNodePort}}
4845
{{- end }}
49-
{{- if .OVN_MULTI_NETWORK_ENABLE }}
50-
enable-multi-network=true
51-
{{- end }}
5246
{{- if .OVN_NETWORK_SEGMENTATION_ENABLE }}
5347
{{- if not .OVN_MULTI_NETWORK_ENABLE }}
5448
enable-multi-network=true
@@ -61,10 +55,6 @@ data:
6155
{{- if .OVN_MULTI_NETWORK_POLICY_ENABLE }}
6256
enable-multi-networkpolicy=true
6357
{{- end }}
64-
{{- if .OVN_ADMIN_NETWORK_POLICY_ENABLE }}
65-
enable-admin-network-policy=true
66-
{{- end }}
67-
enable-multi-external-gateway=true
6858
{{- if .DNS_NAME_RESOLVER_ENABLE }}
6959
enable-dns-name-resolver=true
7060
{{- end }}

bindata/network/ovn-kubernetes/self-hosted/ovnkube-control-plane.yaml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,13 @@ spec:
135135
# will rollout control plane pods as well
136136
network_segmentation_enabled_flag=
137137
multi_network_enabled_flag=
138-
if [[ "{{.OVN_NETWORK_SEGMENTATION_ENABLE}}" == "true" ]]; then
138+
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" == "true" ]]; then
139139
multi_network_enabled_flag="--enable-multi-network"
140+
fi
141+
if [[ "{{.OVN_NETWORK_SEGMENTATION_ENABLE}}" == "true" ]]; then
142+
if [[ "{{.OVN_MULTI_NETWORK_ENABLE}}" != "true" ]]; then
143+
multi_network_enabled_flag="--enable-multi-network"
144+
fi
140145
network_segmentation_enabled_flag="--enable-network-segmentation"
141146
fi
142147

@@ -149,6 +154,18 @@ spec:
149154
if [[ "{{.OVN_PRE_CONF_UDN_ADDR_ENABLE}}" == "true" ]]; then
150155
preconfigured_udn_addresses_enable_flag="--enable-preconfigured-udn-addresses"
151156
fi
157+
158+
# Enable multi-network policy if configured (control-plane always full mode)
159+
multi_network_policy_enabled_flag=
160+
if [[ "{{.OVN_MULTI_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
161+
multi_network_policy_enabled_flag="--enable-multi-networkpolicy"
162+
fi
163+
164+
# Enable admin network policy if configured (control-plane always full mode)
165+
admin_network_policy_enabled_flag=
166+
if [[ "{{.OVN_ADMIN_NETWORK_POLICY_ENABLE}}" == "true" ]]; then
167+
admin_network_policy_enabled_flag="--enable-admin-network-policy"
168+
fi
152169

153170
if [ "{{.OVN_GATEWAY_MODE}}" == "shared" ]; then
154171
gateway_mode_flags="--gateway-mode shared"
@@ -178,7 +195,15 @@ spec:
178195
${network_segmentation_enabled_flag} \
179196
${gateway_mode_flags} \
180197
${route_advertisements_enable_flag} \
181-
${preconfigured_udn_addresses_enable_flag}
198+
${preconfigured_udn_addresses_enable_flag} \
199+
--enable-egress-ip=true \
200+
--enable-egress-firewall=true \
201+
--enable-egress-qos=true \
202+
--enable-egress-service=true \
203+
--enable-multicast \
204+
--enable-multi-external-gateway=true \
205+
${multi_network_policy_enabled_flag} \
206+
${admin_network_policy_enabled_flag}
182207
volumeMounts:
183208
- mountPath: /run/ovnkube-config/
184209
name: ovnkube-config

bindata/network/ovn-kubernetes/self-hosted/ovnkube-node.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,8 @@ spec:
538538
value: "{{.OVN_CONTROLLER_INACTIVITY_PROBE}}"
539539
- name: OVN_KUBE_LOG_LEVEL
540540
value: "4"
541+
- name: OVN_NODE_MODE
542+
value: "{{.OVN_NODE_MODE}}"
541543
{{ if .NetFlowCollectors }}
542544
- name: NETFLOW_COLLECTORS
543545
value: "{{.NetFlowCollectors}}"

docs/architecture.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ The Network operator needs to make sure that the input configuration doesn't cha
141141

142142
The persisted configuration must **make all defaults explicit**. This protects against inadvertent code changes that could destabilize an existing cluster.
143143

144+
### Per-Node Configuration
145+
146+
For certain specialized deployments (e.g., DPU host nodes), some features need to be disabled on a per-node basis even when enabled cluster-wide. Since ConfigMap values cannot be reliably overridden per-node, the CNO implements per-node feature enforcement through conditional logic in the startup scripts.
147+
148+
The `OVN_NODE_MODE` environment variable is injected into `ovnkube-node` pods and consumed by the startup script (`008-script-lib.yaml`) to conditionally enable or disable features based on the node's operational mode. This ensures that unsupported features are deterministically disabled on specialized hardware regardless of cluster-wide configuration.
149+
144150
## Egress Router
145151

146152
**Input:** `EgressRouter.network.operator.openshift.io`

docs/operands.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,26 @@ configuration object (which in turn is copied there from the
9393
configuration) is "`OVNKubernetes`". If the specified network type is
9494
not "`OVNKubernetes`", the CNO will not render any network plugin.
9595

96+
### OVN-Kubernetes Node Modes
97+
98+
OVN-Kubernetes supports different node operational modes through the `OVN_NODE_MODE`
99+
environment variable. This allows per-node feature enforcement, particularly for
100+
specialized hardware like DPU (Data Processing Unit) hosts where certain features
101+
must be disabled.
102+
103+
The startup script (`008-script-lib.yaml`) contains conditional logic that adjusts
104+
feature enablement based on the node mode:
105+
106+
- **`full` mode (default)**: All features enabled as configured
107+
- **`dpu-host` mode**: Certain features like egress IP, multicast, multi-network
108+
policies, and admin network policies are automatically disabled regardless of
109+
cluster-wide configuration
110+
111+
This approach was necessary because ConfigMap values (`004-config.yaml`) cannot be
112+
reliably overridden on a per-node basis, but startup script logic can be conditional.
113+
114+
For detailed information, see `docs/ovn_node_mode.md`.
115+
96116
## Multus
97117

98118
Multus is deployed as long as `.spec.disableMultiNetwork` is not set.

0 commit comments

Comments
 (0)