Skip to content

Commit 4c6e19f

Browse files
committed
feat(ipset): consolidate ipset usage across controllers
Before this, we had 2 different ways to interact with ipsets, through the handler interface which had the best handling for IPv6 because NPC heavily utilizes it, and through the ipset struct which mostly repeated the handler logic, but didn't handle some key things. NPC utilized the handler functions and NSC / NRC mostly utilized the old ipset struct functions. This caused a lot of duplication between the two groups of functions and also caused issues with proper IPv6 handling. This commit consolidates the two sets of usage into just the handler interface. This greatly simplifies how the controllers interact with ipsets and it also reduces the logic complexity on the ipset side. This also fixes up some inconsistency with how we handled IPv6 ipset names. ipset likes them to be prefixed with inet6:, but we weren't always doing this in a way that made sense and was consistent across all functions in the ipset struct.
1 parent c62e1b7 commit 4c6e19f

File tree

4 files changed

+94
-232
lines changed

4 files changed

+94
-232
lines changed

pkg/controllers/netpol/network_policy_controller_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,10 @@ func (ips *fakeIPSet) Sets() map[string]*utils.Set {
749749
return nil
750750
}
751751

752+
func (ips *fakeIPSet) Name(name string) string {
753+
return name
754+
}
755+
752756
func TestNetworkPolicyController(t *testing.T) {
753757
testCases := []tNetPolConfigTestCase{
754758
{

pkg/controllers/proxy/network_services_controller.go

+23-39
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ const (
7171
svcSchedFlagsAnnotation = "kube-router.io/service.schedflags"
7272

7373
// All IPSET names need to be less than 31 characters in order for the Kernel to accept them. Keep in mind that the
74-
// actual formulation for this may be inet6:<setNameBase> depending on ip family so that means that these base names
75-
// actually need to be less than 25 characters
74+
// actual formulation for this may be inet6:<setNameBase> depending on ip family, plus when we change ipsets we use
75+
// a swap operation that adds a hyphen to the end, so that means that these base names actually need to be less than
76+
// 24 characters
7677
localIPsIPSetName = "kube-router-local-ips"
7778
serviceIPPortsSetName = "kube-router-svip-prt"
7879
serviceIPsIPSetName = "kube-router-svip"
@@ -120,11 +121,6 @@ type NetworkServicesController struct {
120121
ipsetMutex *sync.Mutex
121122
fwMarkMap map[uint32]string
122123

123-
// Map of ipsets that we use.
124-
localIPsIPSets map[v1.IPFamily]*utils.Set
125-
serviceIPPortsIPSet map[v1.IPFamily]*utils.Set
126-
serviceIPsIPSet map[v1.IPFamily]*utils.Set
127-
128124
svcLister cache.Indexer
129125
epSliceLister cache.Indexer
130126
podLister cache.Indexer
@@ -399,34 +395,27 @@ func (nsc *NetworkServicesController) setupIpvsFirewall() error {
399395
- create ipsets
400396
- create firewall rules
401397
*/
402-
403398
var err error
404-
var ipset *utils.Set
405399

406-
// Remember ipsets for use in syncIpvsFirewall
407-
nsc.localIPsIPSets = make(map[v1.IPFamily]*utils.Set)
408-
nsc.serviceIPPortsIPSet = make(map[v1.IPFamily]*utils.Set)
409-
nsc.serviceIPsIPSet = make(map[v1.IPFamily]*utils.Set)
410-
for family, ipSetHandler := range nsc.ipSetHandlers {
400+
// Initialize some blank ipsets with the correct names in order to use them in the iptables below. We don't need
401+
// to retain references to them, because we'll use the handler to refresh them later in syncIpvsFirewall
402+
for _, ipSetHandler := range nsc.ipSetHandlers {
411403
// Create ipset for local addresses.
412-
ipset, err = ipSetHandler.Create(localIPsIPSetName, utils.TypeHashIP, utils.OptionTimeout, "0")
404+
_, err = ipSetHandler.Create(localIPsIPSetName, utils.TypeHashIP, utils.OptionTimeout, "0")
413405
if err != nil {
414406
return fmt.Errorf("failed to create ipset: %s - %v", localIPsIPSetName, err)
415407
}
416-
nsc.localIPsIPSets[family] = ipset
417408

418409
// Create 2 ipsets for services. One for 'ip' and one for 'ip,port'
419-
ipset, err = ipSetHandler.Create(serviceIPsIPSetName, utils.TypeHashIP, utils.OptionTimeout, "0")
410+
_, err = ipSetHandler.Create(serviceIPsIPSetName, utils.TypeHashIP, utils.OptionTimeout, "0")
420411
if err != nil {
421412
return fmt.Errorf("failed to create ipset: %s - %v", serviceIPsIPSetName, err)
422413
}
423-
nsc.serviceIPsIPSet[family] = ipset
424414

425-
ipset, err = ipSetHandler.Create(serviceIPPortsSetName, utils.TypeHashIPPort, utils.OptionTimeout, "0")
415+
_, err = ipSetHandler.Create(serviceIPPortsSetName, utils.TypeHashIPPort, utils.OptionTimeout, "0")
426416
if err != nil {
427417
return fmt.Errorf("failed to create ipset: %s - %v", serviceIPPortsSetName, err)
428418
}
429-
nsc.serviceIPPortsIPSet[family] = ipset
430419
}
431420

432421
// Setup a custom iptables chain to explicitly allow input traffic to ipvs services only.
@@ -612,16 +601,13 @@ func (nsc *NetworkServicesController) syncIpvsFirewall() error {
612601

613602
for family, addrs := range addrsMap {
614603
// Convert addrs from a slice of net.IP to a slice of string
615-
localIPsSets := make([]string, 0, len(addrs))
604+
localIPsSets := make([][]string, 0, len(addrs))
616605
for _, addr := range addrs {
617-
localIPsSets = append(localIPsSets, addr.String())
606+
localIPsSets = append(localIPsSets, []string{addr.String(), utils.OptionTimeout, "0"})
618607
}
619608

620609
// Refresh the family specific IPSet with the slice of strings
621-
err = nsc.localIPsIPSets[family].Refresh(localIPsSets)
622-
if err != nil {
623-
return fmt.Errorf("failed to sync ipset: %s", err.Error())
624-
}
610+
nsc.ipSetHandlers[family].RefreshSet(localIPsIPSetName, localIPsSets, utils.TypeHashIP)
625611
}
626612

627613
// Populate service ipsets.
@@ -630,8 +616,8 @@ func (nsc *NetworkServicesController) syncIpvsFirewall() error {
630616
return errors.New("Failed to list IPVS services: " + err.Error())
631617
}
632618

633-
serviceIPsSets := make(map[v1.IPFamily][]string)
634-
serviceIPPortsIPSets := make(map[v1.IPFamily][]string)
619+
serviceIPsSets := make(map[v1.IPFamily][][]string)
620+
serviceIPPortsIPSets := make(map[v1.IPFamily][][]string)
635621

636622
for _, ipvsService := range ipvsServices {
637623
var address net.IP
@@ -667,24 +653,22 @@ func (nsc *NetworkServicesController) syncIpvsFirewall() error {
667653
family = v1.IPv6Protocol
668654
}
669655

670-
serviceIPsSets[family] = append(serviceIPsSets[family], address.String())
656+
serviceIPsSets[family] = append(serviceIPsSets[family], []string{address.String(), utils.OptionTimeout, "0"})
671657

672658
ipvsAddressWithPort := fmt.Sprintf("%s,%s:%d", address, protocol, port)
673-
serviceIPPortsIPSets[family] = append(serviceIPPortsIPSets[family], ipvsAddressWithPort)
659+
serviceIPPortsIPSets[family] = append(serviceIPPortsIPSets[family],
660+
[]string{ipvsAddressWithPort, utils.OptionTimeout, "0"})
674661

675662
}
676663

677-
for family := range nsc.ipSetHandlers {
678-
serviceIPsIPSet := nsc.serviceIPsIPSet[family]
679-
err = serviceIPsIPSet.Refresh(serviceIPsSets[family])
680-
if err != nil {
681-
return fmt.Errorf("failed to sync ipset: %v", err)
682-
}
664+
for family, setHandler := range nsc.ipSetHandlers {
665+
setHandler.RefreshSet(serviceIPsIPSetName, serviceIPsSets[family], utils.TypeHashIP)
666+
667+
setHandler.RefreshSet(serviceIPPortsSetName, serviceIPPortsIPSets[family], utils.TypeHashIPPort)
683668

684-
serviceIPPortsIPSet := nsc.serviceIPPortsIPSet[family]
685-
err = serviceIPPortsIPSet.Refresh(serviceIPPortsIPSets[family])
669+
err := setHandler.Restore()
686670
if err != nil {
687-
return fmt.Errorf("failed to sync ipset: %v", err)
671+
return fmt.Errorf("could not save ipset for service firewall: %v", err)
688672
}
689673
}
690674

pkg/controllers/routing/network_routes_controller.go

+14-40
Original file line numberDiff line numberDiff line change
@@ -963,8 +963,8 @@ func (nrc *NetworkRoutingController) syncNodeIPSets() error {
963963
nodes := nrc.nodeLister.List()
964964

965965
// Collect active PodCIDR(s) and NodeIPs from nodes
966-
currentPodCidrs := make(map[v1core.IPFamily][]string)
967-
currentNodeIPs := make(map[v1core.IPFamily][]string)
966+
currentPodCidrs := make(map[v1core.IPFamily][][]string)
967+
currentNodeIPs := make(map[v1core.IPFamily][][]string)
968968
for _, obj := range nodes {
969969
node := obj.(*v1core.Node)
970970
podCIDRs := getPodCIDRsFromAllNodeSources(node)
@@ -978,26 +978,28 @@ func (nrc *NetworkRoutingController) syncNodeIPSets() error {
978978
klog.Warningf("Wasn't able to parse pod CIDR %s for node %s, skipping", cidr, node.Name)
979979
}
980980
if ip.To4() != nil {
981-
currentPodCidrs[v1core.IPv4Protocol] = append(currentPodCidrs[v1core.IPv4Protocol], cidr)
981+
currentPodCidrs[v1core.IPv4Protocol] = append(currentPodCidrs[v1core.IPv4Protocol],
982+
[]string{cidr, utils.OptionTimeout, "0"})
982983
} else {
983-
currentPodCidrs[v1core.IPv6Protocol] = append(currentPodCidrs[v1core.IPv6Protocol], cidr)
984+
currentPodCidrs[v1core.IPv6Protocol] = append(currentPodCidrs[v1core.IPv6Protocol],
985+
[]string{cidr, utils.OptionTimeout, "0"})
984986
}
985987
}
986988

987-
var ipv4Addrs, ipv6Addrs []string
989+
var ipv4Addrs, ipv6Addrs [][]string
988990
intExtNodeIPsv4, intExtNodeIPsv6 := utils.GetAllNodeIPs(node)
989991
if err != nil {
990992
klog.Errorf("Failed to find a node IP, cannot add to node ipset which could affect routing: %v", err)
991993
continue
992994
}
993995
for _, nodeIPv4s := range intExtNodeIPsv4 {
994996
for _, nodeIPv4 := range nodeIPv4s {
995-
ipv4Addrs = append(ipv4Addrs, nodeIPv4.String())
997+
ipv4Addrs = append(ipv4Addrs, []string{nodeIPv4.String(), utils.OptionTimeout, "0"})
996998
}
997999
}
9981000
for _, nodeIPv6s := range intExtNodeIPsv6 {
9991001
for _, nodeIPv6 := range nodeIPv6s {
1000-
ipv6Addrs = append(ipv6Addrs, nodeIPv6.String())
1002+
ipv6Addrs = append(ipv6Addrs, []string{nodeIPv6.String(), utils.OptionTimeout, "0"})
10011003
}
10021004
}
10031005
currentNodeIPs[v1core.IPv4Protocol] = append(currentNodeIPs[v1core.IPv4Protocol], ipv4Addrs...)
@@ -1006,41 +1008,13 @@ func (nrc *NetworkRoutingController) syncNodeIPSets() error {
10061008

10071009
// Syncing Pod subnet ipset entries
10081010
for family, ipSetHandler := range nrc.ipSetHandlers {
1009-
psSet := ipSetHandler.Get(podSubnetsIPSetName)
1010-
if psSet == nil {
1011-
klog.Infof("Creating missing ipset \"%s\"", podSubnetsIPSetName)
1012-
_, err = ipSetHandler.Create(podSubnetsIPSetName, utils.OptionTimeout, "0")
1013-
if err != nil {
1014-
return fmt.Errorf("ipset \"%s\" not found in controller instance",
1015-
podSubnetsIPSetName)
1016-
}
1017-
psSet = ipSetHandler.Get(podSubnetsIPSetName)
1018-
if nil == psSet {
1019-
return fmt.Errorf("failed to get ipsethandler for ipset \"%s\"", podSubnetsIPSetName)
1020-
}
1021-
}
1022-
err = psSet.Refresh(currentPodCidrs[family])
1023-
if err != nil {
1024-
return fmt.Errorf("failed to sync Pod Subnets ipset: %s", err)
1025-
}
1011+
ipSetHandler.RefreshSet(podSubnetsIPSetName, currentPodCidrs[family], utils.TypeHashNet)
10261012

1027-
// Syncing Node Addresses ipset entries
1028-
naSet := ipSetHandler.Get(nodeAddrsIPSetName)
1029-
if naSet == nil {
1030-
klog.Infof("Creating missing ipset \"%s\"", nodeAddrsIPSetName)
1031-
_, err = ipSetHandler.Create(nodeAddrsIPSetName, utils.OptionTimeout, "0")
1032-
if err != nil {
1033-
return fmt.Errorf("ipset \"%s\" not found in controller instance",
1034-
nodeAddrsIPSetName)
1035-
}
1036-
naSet = ipSetHandler.Get(nodeAddrsIPSetName)
1037-
if nil == naSet {
1038-
return fmt.Errorf("failed to get ipsethandler for ipset \"%s\"", nodeAddrsIPSetName)
1039-
}
1040-
}
1041-
err = naSet.Refresh(currentNodeIPs[family])
1013+
ipSetHandler.RefreshSet(nodeAddrsIPSetName, currentNodeIPs[family], utils.TypeHashIP)
1014+
1015+
err = ipSetHandler.Restore()
10421016
if err != nil {
1043-
return fmt.Errorf("failed to sync Node Addresses ipset: %s", err)
1017+
return fmt.Errorf("failed to sync pod subnets / node addresses ipsets: %v", err)
10441018
}
10451019
}
10461020
return nil

0 commit comments

Comments
 (0)