Skip to content

Commit aab04ad

Browse files
authored
Merge pull request #5321 from qinqon/udn-static-ips-default-network
Allow configuring static IP and MAC with primary UDNs.
2 parents 6082160 + d49c46c commit aab04ad

File tree

34 files changed

+1557
-222
lines changed

34 files changed

+1557
-222
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ jobs:
467467
- {"target": "node-ip-mac-migration", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv6", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-disabled"}
468468
- {"target": "node-ip-mac-migration", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
469469
- {"target": "compact-mode", "ha": "noHA", "gateway-mode": "local", "ipfamily": "ipv4", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-disabled"}
470-
- {"target": "multi-homing", "ha": "noHA", "gateway-mode": "local", "ipfamily": "dualstack", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
470+
- {"target": "multi-homing", "ha": "noHA", "gateway-mode": "local", "ipfamily": "dualstack", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones", "network-segmentation": "enable-network-segmentation"}
471471
- {"target": "multi-node-zones", "ha": "noHA", "gateway-mode": "local", "ipfamily": "ipv4", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-multi-node-zones", "num-workers": "3", "num-nodes-per-zone": "2"}
472472
- {"target": "external-gateway", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "2br", "ic": "ic-single-node-zones"}
473473
- {"target": "external-gateway", "ha": "noHA", "gateway-mode": "local", "ipfamily": "ipv4", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
@@ -513,6 +513,7 @@ jobs:
513513
TRAFFIC_FLOW_TESTS: "${{ matrix.traffic-flow-tests }}"
514514
ENABLE_ROUTE_ADVERTISEMENTS: "${{ matrix.routeadvertisements != '' }}"
515515
ADVERTISE_DEFAULT_NETWORK: "${{ matrix.routeadvertisements == 'advertise-default' }}"
516+
ENABLE_PRE_CONF_UDN_ADDR: "${{ ( ( matrix.target == 'multi-homing' && matrix.network-segmentation == 'enable-network-segmentation' ) || matrix.target == 'kv-live-migration' ) && matrix.ic == 'ic-single-node-zones' }}"
516517
steps:
517518

518519
- name: Install VRF kernel module

go-controller/cmd/ovn-k8s-cni-overlay/ovn-k8s-cni-overlay.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ func main() {
2020

2121
p := cni.NewCNIPlugin("")
2222
c.Action = func(_ *cli.Context) error {
23-
skel.PluginMain(
24-
p.CmdAdd,
25-
p.CmdCheck,
26-
p.CmdDel,
23+
skel.PluginMainFuncs(
24+
skel.CNIFuncs{
25+
Add: p.CmdAdd,
26+
Check: p.CmdCheck,
27+
Del: p.CmdDel,
28+
},
2729
version.All,
2830
bv.BuildString("ovn-k8s-cni-overlay"))
2931
return nil

go-controller/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
1111
github.com/bhendo/go-powershell v0.0.0-20190719160123-219e7fb4e41e
1212
github.com/cenkalti/backoff/v4 v4.3.0
13-
github.com/containernetworking/cni v1.1.2
13+
github.com/containernetworking/cni v1.2.3
1414
github.com/containernetworking/plugins v1.2.0
1515
github.com/coreos/go-iptables v0.6.0
1616
github.com/fsnotify/fsnotify v1.7.0
@@ -25,7 +25,7 @@ require (
2525
github.com/k8snetworkplumbingwg/govdpa v0.1.5-0.20230926073613-07c1031aea47
2626
github.com/k8snetworkplumbingwg/ipamclaims v0.5.0-alpha
2727
github.com/k8snetworkplumbingwg/multi-networkpolicy v1.0.1
28-
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.6.0
28+
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.7
2929
github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20230427090635-4929697df2dc
3030
github.com/mdlayher/arp v0.0.0-20220512170110-6706a2966875
3131
github.com/mdlayher/ndp v1.0.1

go-controller/go.sum

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNR
199199
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
200200
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
201201
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
202-
github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=
203-
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
202+
github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM=
203+
github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M=
204204
github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM=
205205
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
206206
github.com/containernetworking/plugins v1.2.0 h1:SWgg3dQG1yzUo4d9iD8cwSVh1VqI+bP7mkPDoSfP9VU=
@@ -498,8 +498,8 @@ github.com/k8snetworkplumbingwg/ipamclaims v0.5.0-alpha h1:b3iHeks/KTzhG2dNanaUZ
498498
github.com/k8snetworkplumbingwg/ipamclaims v0.5.0-alpha/go.mod h1:MGaMX1tJ7MlHDee4/xmqp3guQh+eDiuCLAauqD9K11Q=
499499
github.com/k8snetworkplumbingwg/multi-networkpolicy v1.0.1 h1:Egj1hEVYNXWFlKpgzAXxe/2o8VNiVcAJLrKzlinILQo=
500500
github.com/k8snetworkplumbingwg/multi-networkpolicy v1.0.1/go.mod h1:kEJ4WM849yNmXekuSXLRwb+LaZ9usC06O8JgoAIq+f4=
501-
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.6.0 h1:BT3ghAY0q7lWib9rz+tVXDFkm27dJV6SLCn7TunZwo4=
502-
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.6.0/go.mod h1:wxt2YWRVItDtaQmVSmaN5ubE2L1c9CiNoHQwSJnM8Ko=
501+
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.7 h1:z4P744DR+PIpkjwXSEc6TvN3L6LVzmUquFgmNm8wSUc=
502+
github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.7.7/go.mod h1:CM7HAH5PNuIsqjMN0fGc1ydM74Uj+0VZFhob620nklw=
503503
github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20230427090635-4929697df2dc h1:v6+jUd70AayPbIRgTYUNpnBLG5cBPTY0+10y80CZeMk=
504504
github.com/k8snetworkplumbingwg/sriovnet v1.2.1-0.20230427090635-4929697df2dc/go.mod h1:jyWzGe6ZtYiPq6ih6aXCOy6mZ49Y9mNyBOLBBXnli+k=
505505
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -603,7 +603,6 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
603603
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
604604
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
605605
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
606-
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
607606
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
608607
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
609608
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=

go-controller/pkg/allocator/pod/pod_annotation.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,35 @@ func allocatePodAnnotationWithTunnelID(
207207
return pod, podAnnotation, nil
208208
}
209209

210+
// validateStaticIPRequest checks if a static IP request can be honored when IPAM is enabled for the given network.
211+
func validateStaticIPRequest(netInfo util.NetInfo, network *nadapi.NetworkSelectionElement, ipamClaim *ipamclaimsapi.IPAMClaim, podDesc string) error {
212+
// Allow static IPs with IPAM only for primary networks with layer2 topology when EnablePreconfiguredUDNAddresses is enabled
213+
// Feature gate integration: EnablePreconfiguredUDNAddresses controls static IP allocation with IPAM
214+
if !util.IsPreconfiguredUDNAddressesEnabled() {
215+
// Feature is disabled, reject static IPs with IPAM
216+
return fmt.Errorf("cannot allocate a static IP request with IPAM for pod %s (custom network configuration disabled)", podDesc)
217+
}
218+
if !netInfo.IsPrimaryNetwork() {
219+
// Static IP requests with IPAM are only supported on primary networks
220+
return fmt.Errorf("cannot allocate a static IP request with IPAM for pod %s: only supported on primary networks", podDesc)
221+
}
222+
if netInfo.TopologyType() != types.Layer2Topology {
223+
// Static IP requests with IPAM are only supported on layer2 topology networks.
224+
// On other topologies, we cannot distinguish between already allocated IPs and
225+
// IPs excluded from allocation, making it impossible to safely honor static IP
226+
// requests when IPAM is enabled.
227+
return fmt.Errorf("cannot allocate a static IP request with IPAM for pod %s: layer2 topology is required, but network has topology %q", podDesc, netInfo.TopologyType())
228+
}
229+
if ipamClaim != nil && len(ipamClaim.Status.IPs) > 0 {
230+
for _, ipRequest := range network.IPRequest {
231+
if !util.IsItemInSlice(ipamClaim.Status.IPs, ipRequest) {
232+
return fmt.Errorf("cannot allocate a static IP request with IPAM for pod %q: the pod references an ipam claim with IPs not containing the requested IP %q", podDesc, ipRequest)
233+
}
234+
}
235+
}
236+
return nil
237+
}
238+
210239
// allocatePodAnnotationWithRollback allocates the PodAnnotation which includes
211240
// IPs, a mac address, routes, gateways and an ID. Returns the allocated pod
212241
// annotation and a pod with that annotation set. Returns a nil pod and the existing
@@ -330,13 +359,11 @@ func allocatePodAnnotationWithRollback(
330359
}
331360
hasIPAMClaim = ipamClaim != nil && len(ipamClaim.Status.IPs) > 0
332361
}
362+
333363
if hasIPAM && hasStaticIPRequest {
334-
// for now we can't tell apart already allocated IPs from IPs excluded
335-
// from allocation so we can't really honor static IP requests when
336-
// there is IPAM as we don't really know if the requested IP should not
337-
// be allocated or was already allocated by the same pod
338-
err = fmt.Errorf("cannot allocate a static IP request with IPAM for pod %s", podDesc)
339-
return
364+
if err = validateStaticIPRequest(netInfo, network, ipamClaim, podDesc); err != nil {
365+
return
366+
}
340367
}
341368

342369
// we need to update the annotation if it is missing IPs or MAC
@@ -348,6 +375,7 @@ func allocatePodAnnotationWithRollback(
348375
if hasIPRequest {
349376
tentative.IPs, err = util.ParseIPNets(network.IPRequest)
350377
if err != nil {
378+
klog.Warningf("Failed parsing IPRequest %+v for pod %s: %v", network.IPRequest, podDesc, err)
351379
return
352380
}
353381
} else if hasIPAMClaim {

0 commit comments

Comments
 (0)