1
2
3
4
19
20 package ipvs
21
22 import (
23 "k8s.io/apimachinery/pkg/util/sets"
24 utilversion "k8s.io/apimachinery/pkg/util/version"
25 utilipset "k8s.io/kubernetes/pkg/proxy/ipvs/ipset"
26
27 "fmt"
28 "strings"
29
30 "k8s.io/klog/v2"
31 )
32
33 const (
34
35 MinIPSetCheckVersion = "6.0"
36
37 kubeLoopBackIPSetComment = "Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose"
38 kubeLoopBackIPSet = "KUBE-LOOP-BACK"
39
40 kubeClusterIPSetComment = "Kubernetes service cluster ip + port for masquerade purpose"
41 kubeClusterIPSet = "KUBE-CLUSTER-IP"
42
43 kubeExternalIPSetComment = "Kubernetes service external ip + port for masquerade and filter purpose"
44 kubeExternalIPSet = "KUBE-EXTERNAL-IP"
45
46 kubeExternalIPLocalSetComment = "Kubernetes service external ip + port with externalTrafficPolicy=local"
47 kubeExternalIPLocalSet = "KUBE-EXTERNAL-IP-LOCAL"
48
49 kubeLoadBalancerSetComment = "Kubernetes service lb portal"
50 kubeLoadBalancerSet = "KUBE-LOAD-BALANCER"
51
52 kubeLoadBalancerLocalSetComment = "Kubernetes service load balancer ip + port with externalTrafficPolicy=local"
53 kubeLoadBalancerLocalSet = "KUBE-LOAD-BALANCER-LOCAL"
54
55 kubeLoadBalancerFWSetComment = "Kubernetes service load balancer ip + port for load balancer with sourceRange"
56 kubeLoadBalancerFWSet = "KUBE-LOAD-BALANCER-FW"
57
58 kubeLoadBalancerSourceIPSetComment = "Kubernetes service load balancer ip + port + source IP for packet filter purpose"
59 kubeLoadBalancerSourceIPSet = "KUBE-LOAD-BALANCER-SOURCE-IP"
60
61 kubeLoadBalancerSourceCIDRSetComment = "Kubernetes service load balancer ip + port + source cidr for packet filter purpose"
62 kubeLoadBalancerSourceCIDRSet = "KUBE-LOAD-BALANCER-SOURCE-CIDR"
63
64 kubeNodePortSetTCPComment = "Kubernetes nodeport TCP port for masquerade purpose"
65 kubeNodePortSetTCP = "KUBE-NODE-PORT-TCP"
66
67 kubeNodePortLocalSetTCPComment = "Kubernetes nodeport TCP port with externalTrafficPolicy=local"
68 kubeNodePortLocalSetTCP = "KUBE-NODE-PORT-LOCAL-TCP"
69
70 kubeNodePortSetUDPComment = "Kubernetes nodeport UDP port for masquerade purpose"
71 kubeNodePortSetUDP = "KUBE-NODE-PORT-UDP"
72
73 kubeNodePortLocalSetUDPComment = "Kubernetes nodeport UDP port with externalTrafficPolicy=local"
74 kubeNodePortLocalSetUDP = "KUBE-NODE-PORT-LOCAL-UDP"
75
76 kubeNodePortSetSCTPComment = "Kubernetes nodeport SCTP port for masquerade purpose with type 'hash ip:port'"
77 kubeNodePortSetSCTP = "KUBE-NODE-PORT-SCTP-HASH"
78
79 kubeNodePortLocalSetSCTPComment = "Kubernetes nodeport SCTP port with externalTrafficPolicy=local with type 'hash ip:port'"
80 kubeNodePortLocalSetSCTP = "KUBE-NODE-PORT-LOCAL-SCTP-HASH"
81
82 kubeHealthCheckNodePortSetComment = "Kubernetes health check node port"
83 kubeHealthCheckNodePortSet = "KUBE-HEALTH-CHECK-NODE-PORT"
84
85 kubeIPVSSetComment = "Addresses on the ipvs interface"
86 kubeIPVSSet = "KUBE-IPVS-IPS"
87 )
88
89
90 type IPSetVersioner interface {
91
92 GetVersion() (string, error)
93 }
94
95
96 type IPSet struct {
97 utilipset.IPSet
98
99 activeEntries sets.Set[string]
100
101 handle utilipset.Interface
102 }
103
104
105 func NewIPSet(handle utilipset.Interface, name string, setType utilipset.Type, isIPv6 bool, comment string) *IPSet {
106 hashFamily := utilipset.ProtocolFamilyIPV4
107 if isIPv6 {
108 hashFamily = utilipset.ProtocolFamilyIPV6
109
110
111
112
113
114
115
116 if strings.HasPrefix(name, "KUBE-") {
117 name = strings.Replace(name, "KUBE-", "KUBE-6-", 1)
118 if len(name) > 31 {
119 klog.InfoS("Ipset name truncated", "ipSetName", name, "truncatedName", name[:31])
120 name = name[:31]
121 }
122 }
123 }
124 set := &IPSet{
125 IPSet: utilipset.IPSet{
126 Name: name,
127 SetType: setType,
128 HashFamily: hashFamily,
129 Comment: comment,
130 },
131 activeEntries: sets.New[string](),
132 handle: handle,
133 }
134 return set
135 }
136
137 func (set *IPSet) validateEntry(entry *utilipset.Entry) bool {
138 return entry.Validate(&set.IPSet)
139 }
140
141 func (set *IPSet) isEmpty() bool {
142 return set.activeEntries.Len() == 0
143 }
144
145 func (set *IPSet) getComment() string {
146 return fmt.Sprintf("\"%s\"", set.Comment)
147 }
148
149 func (set *IPSet) resetEntries() {
150 set.activeEntries = sets.New[string]()
151 }
152
153 func (set *IPSet) syncIPSetEntries() {
154 appliedEntries, err := set.handle.ListEntries(set.Name)
155 if err != nil {
156 klog.ErrorS(err, "Failed to list ip set entries")
157 return
158 }
159
160
161 currentIPSetEntries := sets.New[string]()
162 for _, appliedEntry := range appliedEntries {
163 currentIPSetEntries.Insert(appliedEntry)
164 }
165
166 if !set.activeEntries.Equal(currentIPSetEntries) {
167
168 for _, entry := range currentIPSetEntries.Difference(set.activeEntries).UnsortedList() {
169 if err := set.handle.DelEntry(entry, set.Name); err != nil {
170 if !utilipset.IsNotFoundError(err) {
171 klog.ErrorS(err, "Failed to delete ip set entry from ip set", "ipSetEntry", entry, "ipSet", set.Name)
172 }
173 } else {
174 klog.V(3).InfoS("Successfully deleted legacy ip set entry from ip set", "ipSetEntry", entry, "ipSet", set.Name)
175 }
176 }
177
178 for _, entry := range set.activeEntries.Difference(currentIPSetEntries).UnsortedList() {
179 if err := set.handle.AddEntry(entry, &set.IPSet, true); err != nil {
180 klog.ErrorS(err, "Failed to add ip set entry to ip set", "ipSetEntry", entry, "ipSet", set.Name)
181 } else {
182 klog.V(3).InfoS("Successfully added ip set entry to ip set", "ipSetEntry", entry, "ipSet", set.Name)
183 }
184 }
185 }
186 }
187
188 func ensureIPSet(set *IPSet) error {
189 if err := set.handle.CreateSet(&set.IPSet, true); err != nil {
190 klog.ErrorS(err, "Failed to make sure existence of ip set", "ipSet", set)
191 return err
192 }
193 return nil
194 }
195
196
197 func checkMinVersion(vstring string) bool {
198 version, err := utilversion.ParseGeneric(vstring)
199 if err != nil {
200 klog.ErrorS(err, "Got invalid version string", "versionString", vstring)
201 return false
202 }
203
204 minVersion, err := utilversion.ParseGeneric(MinIPSetCheckVersion)
205 if err != nil {
206 klog.ErrorS(err, "Got invalid version string", "versionString", MinIPSetCheckVersion)
207 return false
208 }
209 return !version.LessThan(minVersion)
210 }
211
View as plain text