Skip to content

Commit 58da2d4

Browse files
johanotmurali-reddy
authored andcommitted
Fix for network policy connection refused issue (#461) (#471)
* Instead of clearing the iptables firewall chains for each resync, new chains are now generated side-by-side with the existing ones. * Chain naming now has an addition component, version, which ensures chain name uniqueness. * Existing cleanup procedure for stale iptables rules will handle garbage collection of unused chains.
1 parent 7c21815 commit 58da2d4

File tree

1 file changed

+21
-26
lines changed

1 file changed

+21
-26
lines changed

pkg/controllers/netpol/network_policy_controller.go

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ func (npc *NetworkPolicyController) Sync() error {
206206
defer npc.mu.Unlock()
207207

208208
start := time.Now()
209+
syncVersion := string(start.UnixNano())
209210
defer func() {
210211
endTime := time.Since(start)
211212
if npc.MetricsEnabled {
@@ -214,7 +215,7 @@ func (npc *NetworkPolicyController) Sync() error {
214215
glog.V(1).Infof("sync iptables took %v", endTime)
215216
}()
216217

217-
glog.V(1).Info("Starting periodic sync of iptables")
218+
glog.V(1).Info("Starting sync of iptables")
218219

219220
if npc.v1NetworkPolicy {
220221
npc.networkPoliciesInfo, err = npc.buildNetworkPoliciesInfo()
@@ -229,12 +230,12 @@ func (npc *NetworkPolicyController) Sync() error {
229230
}
230231
}
231232

232-
activePolicyChains, activePolicyIpSets, err := npc.syncNetworkPolicyChains()
233+
activePolicyChains, activePolicyIpSets, err := npc.syncNetworkPolicyChains(syncVersion)
233234
if err != nil {
234235
return errors.New("Aborting sync. Failed to sync network policy chains: " + err.Error())
235236
}
236237

237-
activePodFwChains, err := npc.syncPodFirewallChains()
238+
activePodFwChains, err := npc.syncPodFirewallChains(syncVersion)
238239
if err != nil {
239240
return errors.New("Aborting sync. Failed to sync pod firewalls: " + err.Error())
240241
}
@@ -252,7 +253,7 @@ func (npc *NetworkPolicyController) Sync() error {
252253
// is used for matching destination ip address. Each ingress rule in the network
253254
// policyspec is evaluated to set of matching pods, which are grouped in to a
254255
// ipset used for source ip addr matching.
255-
func (npc *NetworkPolicyController) syncNetworkPolicyChains() (map[string]bool, map[string]bool, error) {
256+
func (npc *NetworkPolicyController) syncNetworkPolicyChains(version string) (map[string]bool, map[string]bool, error) {
256257

257258
activePolicyChains := make(map[string]bool)
258259
activePolicyIpSets := make(map[string]bool)
@@ -266,7 +267,7 @@ func (npc *NetworkPolicyController) syncNetworkPolicyChains() (map[string]bool,
266267
for _, policy := range *npc.networkPoliciesInfo {
267268

268269
// ensure there is a unique chain per network policy in filter table
269-
policyChainName := networkPolicyChainName(policy.namespace, policy.name)
270+
policyChainName := networkPolicyChainName(policy.namespace, policy.name, version)
270271
err := iptablesCmdHandler.NewChain("filter", policyChainName)
271272
if err != nil && err.(*iptables.Error).ExitStatus() != 1 {
272273
return nil, nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
@@ -305,18 +306,12 @@ func (npc *NetworkPolicyController) syncNetworkPolicyChains() (map[string]bool,
305306
glog.Errorf("failed to refresh targetDestPodIpSet: " + err.Error())
306307
}
307308

308-
// TODO use iptables-restore to better implement the logic, than flush and add rules
309-
err = iptablesCmdHandler.ClearChain("filter", policyChainName)
310-
if err != nil && err.(*iptables.Error).ExitStatus() != 1 {
311-
return nil, nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
312-
}
313-
314-
err = npc.processIngressRules(policy, targetDestPodIpSetName, activePolicyIpSets)
309+
err = npc.processIngressRules(policy, targetDestPodIpSetName, activePolicyIpSets, version)
315310
if err != nil {
316311
return nil, nil, err
317312
}
318313

319-
err = npc.processEgressRules(policy, targetSourcePodIpSetName, activePolicyIpSets)
314+
err = npc.processEgressRules(policy, targetSourcePodIpSetName, activePolicyIpSets, version)
320315
if err != nil {
321316
return nil, nil, err
322317
}
@@ -328,7 +323,7 @@ func (npc *NetworkPolicyController) syncNetworkPolicyChains() (map[string]bool,
328323
}
329324

330325
func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo,
331-
targetDestPodIpSetName string, activePolicyIpSets map[string]bool) error {
326+
targetDestPodIpSetName string, activePolicyIpSets map[string]bool, version string) error {
332327

333328
// From network policy spec: "If field 'Ingress' is empty then this NetworkPolicy does not allow any traffic "
334329
// so no whitelist rules to be added to the network policy
@@ -341,7 +336,7 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo
341336
return fmt.Errorf("Failed to initialize iptables executor due to: %s", err.Error())
342337
}
343338

344-
policyChainName := networkPolicyChainName(policy.namespace, policy.name)
339+
policyChainName := networkPolicyChainName(policy.namespace, policy.name, version)
345340

346341
// run through all the ingress rules in the spec and create iptable rules
347342
// in the chain for the network policy
@@ -466,7 +461,7 @@ func (npc *NetworkPolicyController) processIngressRules(policy networkPolicyInfo
466461
}
467462

468463
func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
469-
targetSourcePodIpSetName string, activePolicyIpSets map[string]bool) error {
464+
targetSourcePodIpSetName string, activePolicyIpSets map[string]bool, version string) error {
470465

471466
// From network policy spec: "If field 'Ingress' is empty then this NetworkPolicy does not allow any traffic "
472467
// so no whitelist rules to be added to the network policy
@@ -479,7 +474,7 @@ func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
479474
return fmt.Errorf("Failed to initialize iptables executor due to: %s", err.Error())
480475
}
481476

482-
policyChainName := networkPolicyChainName(policy.namespace, policy.name)
477+
policyChainName := networkPolicyChainName(policy.namespace, policy.name, version)
483478

484479
// run through all the egress rules in the spec and create iptable rules
485480
// in the chain for the network policy
@@ -600,7 +595,7 @@ func (npc *NetworkPolicyController) processEgressRules(policy networkPolicyInfo,
600595
return nil
601596
}
602597

603-
func (npc *NetworkPolicyController) syncPodFirewallChains() (map[string]bool, error) {
598+
func (npc *NetworkPolicyController) syncPodFirewallChains(version string) (map[string]bool, error) {
604599

605600
activePodFwChains := make(map[string]bool)
606601

@@ -623,7 +618,7 @@ func (npc *NetworkPolicyController) syncPodFirewallChains() (map[string]bool, er
623618
}
624619

625620
// ensure pod specific firewall chain exist for all the pods that need ingress firewall
626-
podFwChainName := podFirewallChainName(pod.namespace, pod.name)
621+
podFwChainName := podFirewallChainName(pod.namespace, pod.name, version)
627622
err = iptablesCmdHandler.NewChain("filter", podFwChainName)
628623
if err != nil && err.(*iptables.Error).ExitStatus() != 1 {
629624
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
@@ -703,7 +698,7 @@ func (npc *NetworkPolicyController) syncPodFirewallChains() (map[string]bool, er
703698
for _, policy := range *npc.networkPoliciesInfo {
704699
if _, ok := policy.targetPods[pod.ip]; ok {
705700
comment := "run through nw policy " + policy.name
706-
policyChainName := networkPolicyChainName(policy.namespace, policy.name)
701+
policyChainName := networkPolicyChainName(policy.namespace, policy.name, version)
707702
args := []string{"-m", "comment", "--comment", comment, "-j", policyChainName}
708703
exists, err := iptablesCmdHandler.Exists("filter", podFwChainName, args...)
709704
if err != nil {
@@ -747,7 +742,7 @@ func (npc *NetworkPolicyController) syncPodFirewallChains() (map[string]bool, er
747742
}
748743

749744
// ensure pod specific firewall chain exist for all the pods that need egress firewall
750-
podFwChainName := podFirewallChainName(pod.namespace, pod.name)
745+
podFwChainName := podFirewallChainName(pod.namespace, pod.name, version)
751746
err = iptablesCmdHandler.NewChain("filter", podFwChainName)
752747
if err != nil && err.(*iptables.Error).ExitStatus() != 1 {
753748
return nil, fmt.Errorf("Failed to run iptables command: %s", err.Error())
@@ -801,7 +796,7 @@ func (npc *NetworkPolicyController) syncPodFirewallChains() (map[string]bool, er
801796
for _, policy := range *npc.networkPoliciesInfo {
802797
if _, ok := policy.targetPods[pod.ip]; ok {
803798
comment := "run through nw policy " + policy.name
804-
policyChainName := networkPolicyChainName(policy.namespace, policy.name)
799+
policyChainName := networkPolicyChainName(policy.namespace, policy.name, version)
805800
args := []string{"-m", "comment", "--comment", comment, "-j", policyChainName}
806801
exists, err := iptablesCmdHandler.Exists("filter", podFwChainName, args...)
807802
if err != nil {
@@ -1302,14 +1297,14 @@ func (npc *NetworkPolicyController) buildBetaNetworkPoliciesInfo() (*[]networkPo
13021297
return &NetworkPolicies, nil
13031298
}
13041299

1305-
func podFirewallChainName(namespace, podName string) string {
1306-
hash := sha256.Sum256([]byte(namespace + podName))
1300+
func podFirewallChainName(namespace, podName string, version string) string {
1301+
hash := sha256.Sum256([]byte(namespace + podName + version))
13071302
encoded := base32.StdEncoding.EncodeToString(hash[:])
13081303
return "KUBE-POD-FW-" + encoded[:16]
13091304
}
13101305

1311-
func networkPolicyChainName(namespace, policyName string) string {
1312-
hash := sha256.Sum256([]byte(namespace + policyName))
1306+
func networkPolicyChainName(namespace, policyName string, version string) string {
1307+
hash := sha256.Sum256([]byte(namespace + policyName + version))
13131308
encoded := base32.StdEncoding.EncodeToString(hash[:])
13141309
return "KUBE-NWPLCY-" + encoded[:16]
13151310
}

0 commit comments

Comments
 (0)