Browse Source

Merge "Ensure only affected services are updated on Pod/NetworkPolicy events"

Zuul 1 month ago
parent
commit
8ca54e2592

+ 6
- 0
kuryr_kubernetes/controller/drivers/base.py View File

@@ -251,6 +251,8 @@ class PodSecurityGroupsDriver(DriverBase):
251 251
         """Create security group rules for a pod.
252 252
 
253 253
         :param pod: dict containing Kubernetes Pod object
254
+        :return: a list containing podSelectors of CRDs
255
+        that had security group rules created
254 256
         """
255 257
         raise NotImplementedError()
256 258
 
@@ -258,6 +260,8 @@ class PodSecurityGroupsDriver(DriverBase):
258 260
         """Delete security group rules for a pod
259 261
 
260 262
         :param pod: dict containing Kubernetes Pod object
263
+        :return: a list containing podSelectors of CRDs
264
+        that had security group rules deleted
261 265
         """
262 266
         raise NotImplementedError()
263 267
 
@@ -265,6 +269,8 @@ class PodSecurityGroupsDriver(DriverBase):
265 269
         """Update security group rules for a pod
266 270
 
267 271
         :param pod: dict containing Kubernetes Pod object
272
+        :return: a list containing podSelectors of CRDs
273
+        that had security group rules updated
268 274
         """
269 275
         raise NotImplementedError()
270 276
 

+ 10
- 3
kuryr_kubernetes/controller/drivers/network_policy_security_groups.py View File

@@ -215,6 +215,7 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
215 215
 
216 216
     def create_sg_rules(self, pod):
217 217
         LOG.debug("Creating sg rule for pod: %s", pod['metadata']['name'])
218
+        crd_pod_selectors = []
218 219
         knp_crds = driver_utils.get_kuryrnetpolicy_crds()
219 220
         for crd in knp_crds.get('items'):
220 221
             crd_selector = crd['spec'].get('podSelector')
@@ -225,11 +226,13 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
225 226
             if i_matched or e_matched:
226 227
                 driver_utils.patch_kuryr_crd(crd, i_rules,
227 228
                                              e_rules, crd_selector)
229
+                crd_pod_selectors.append(crd_selector)
230
+        return crd_pod_selectors
228 231
 
229 232
     def delete_sg_rules(self, pod):
230 233
         LOG.debug("Deleting sg rule for pod: %s", pod['metadata']['name'])
231 234
         pod_ip = driver_utils.get_pod_ip(pod)
232
-
235
+        crd_pod_selectors = []
233 236
         knp_crds = driver_utils.get_kuryrnetpolicy_crds()
234 237
         for crd in knp_crds.get('items'):
235 238
             crd_selector = crd['spec'].get('podSelector')
@@ -264,11 +267,15 @@ class NetworkPolicySecurityGroupsDriver(base.PodSecurityGroupsDriver):
264 267
             if matched:
265 268
                 driver_utils.patch_kuryr_crd(crd, i_rules, e_rules,
266 269
                                              crd_selector)
270
+                crd_pod_selectors.append(crd_selector)
271
+        return crd_pod_selectors
267 272
 
268 273
     def update_sg_rules(self, pod):
269 274
         LOG.debug("Updating sg rule for pod: %s", pod['metadata']['name'])
270
-        self.delete_sg_rules(pod)
271
-        self.create_sg_rules(pod)
275
+        crd_pod_selectors = []
276
+        crd_pod_selectors.extend(self.delete_sg_rules(pod))
277
+        crd_pod_selectors.extend(self.create_sg_rules(pod))
278
+        return crd_pod_selectors
272 279
 
273 280
     def delete_namespace_sg_rules(self, namespace):
274 281
         ns_name = namespace['metadata']['name']

+ 18
- 0
kuryr_kubernetes/controller/drivers/utils.py View File

@@ -405,3 +405,21 @@ def get_services(namespace):
405 405
                       'namespace %s', namespace)
406 406
         raise
407 407
     return services
408
+
409
+
410
+def service_matches_affected_pods(service, pod_selectors):
411
+    """Returns if the service is affected by the pod selectors
412
+
413
+    Checks if the service selector matches the labelSelectors of
414
+    NetworkPolicies.
415
+
416
+    param service: k8s service
417
+    param pod_selectors: a list of kubernetes labelSelectors
418
+    return: True if the service is selected by any of the labelSelectors
419
+            and False otherwise.
420
+    """
421
+    svc_selector = service['spec'].get('selector')
422
+    for selector in pod_selectors:
423
+        if match_selector(selector, svc_selector):
424
+            return True
425
+    return False

+ 16
- 1
kuryr_kubernetes/controller/handlers/pod_label.py View File

@@ -39,9 +39,11 @@ class PodLabelHandler(k8s_base.ResourceEventHandler):
39 39
         super(PodLabelHandler, self).__init__()
40 40
         self._drv_project = drivers.PodProjectDriver.get_instance()
41 41
         self._drv_sg = drivers.PodSecurityGroupsDriver.get_instance()
42
+        self._drv_svc_sg = drivers.ServiceSecurityGroupsDriver.get_instance()
42 43
         self._drv_vif_pool = drivers.VIFPoolDriver.get_instance(
43 44
             specific_driver='multi_pool')
44 45
         self._drv_vif_pool.set_vif_driver()
46
+        self._drv_lbaas = drivers.LBaaSDriver.get_instance()
45 47
 
46 48
     def on_present(self, pod):
47 49
         if driver_utils.is_host_network(pod) or not self._has_pod_state(pod):
@@ -57,13 +59,16 @@ class PodLabelHandler(k8s_base.ResourceEventHandler):
57 59
         if current_pod_labels == previous_pod_labels:
58 60
             return
59 61
 
60
-        self._drv_sg.update_sg_rules(pod)
62
+        crd_pod_selectors = self._drv_sg.update_sg_rules(pod)
61 63
 
62 64
         project_id = self._drv_project.get_project(pod)
63 65
         security_groups = self._drv_sg.get_security_groups(pod, project_id)
64 66
         self._drv_vif_pool.update_vif_sgs(pod, security_groups)
65 67
         self._set_pod_labels(pod, current_pod_labels)
66 68
 
69
+        services = driver_utils.get_services(pod['metadata']['namespace'])
70
+        self._update_services(services, crd_pod_selectors, project_id)
71
+
67 72
     def _get_pod_labels(self, pod):
68 73
         try:
69 74
             annotations = pod['metadata']['annotations']
@@ -94,3 +99,13 @@ class PodLabelHandler(k8s_base.ResourceEventHandler):
94 99
         except KeyError:
95 100
             return False
96 101
         return True
102
+
103
+    def _update_services(self, services, crd_pod_selectors, project_id):
104
+        for service in services.get('items'):
105
+            if (service['metadata']['name'] == 'kubernetes' or not
106
+                    driver_utils.service_matches_affected_pods(
107
+                        service, crd_pod_selectors)):
108
+                continue
109
+            sgs = self._drv_svc_sg.get_security_groups(service,
110
+                                                       project_id)
111
+            self._drv_lbaas.update_lbaas_sg(service, sgs)

+ 11
- 2
kuryr_kubernetes/controller/handlers/policy.py View File

@@ -85,7 +85,8 @@ class NetworkPolicyHandler(k8s_base.ResourceEventHandler):
85 85
             for service in services.get('items'):
86 86
                 # TODO(ltomasbo): Skip other services that are not affected
87 87
                 # by the policy
88
-                if service['metadata']['name'] == 'kubernetes':
88
+                if (service['metadata']['name'] == 'kubernetes' or not
89
+                        self._is_service_affected(service, pods_to_update)):
89 90
                     continue
90 91
                 sgs = self._drv_svc_sg.get_security_groups(service,
91 92
                                                            project_id)
@@ -119,7 +120,8 @@ class NetworkPolicyHandler(k8s_base.ResourceEventHandler):
119 120
             services = driver_utils.get_services(
120 121
                 policy['metadata']['namespace'])
121 122
             for service in services.get('items'):
122
-                if service['metadata']['name'] == 'kubernetes':
123
+                if (service['metadata']['name'] == 'kubernetes' or not
124
+                        self._is_service_affected(service, pods_to_update)):
123 125
                     continue
124 126
                 sgs = self._drv_svc_sg.get_security_groups(service,
125 127
                                                            project_id)
@@ -138,3 +140,10 @@ class NetworkPolicyHandler(k8s_base.ResourceEventHandler):
138 140
         if utils.has_limit(sg_quota):
139 141
             return utils.is_available('security_groups', sg_quota, sg_func)
140 142
         return True
143
+
144
+    def _is_service_affected(self, service, affected_pods):
145
+        svc_namespace = service['metadata']['namespace']
146
+        svc_selector = service['spec'].get('selector')
147
+        svc_pods = driver_utils.get_pods({'selector': svc_selector},
148
+                                         svc_namespace).get('items')
149
+        return any(pod in svc_pods for pod in affected_pods)

+ 9
- 6
kuryr_kubernetes/controller/handlers/vif.py View File

@@ -126,12 +126,13 @@ class VIFHandler(k8s_base.ResourceEventHandler):
126 126
                     changed = True
127 127
             if changed:
128 128
                 self._set_pod_state(pod, state)
129
-                self._drv_sg.create_sg_rules(pod)
129
+                crd_pod_selectors = self._drv_sg.create_sg_rules(pod)
130 130
 
131 131
                 if self._is_network_policy_enabled():
132 132
                     services = driver_utils.get_services(
133 133
                         pod['metadata']['namespace'])
134
-                    self._update_services(services, project_id)
134
+                    self._update_services(
135
+                        services, crd_pod_selectors, project_id)
135 136
 
136 137
     def on_deleted(self, pod):
137 138
         if driver_utils.is_host_network(pod):
@@ -139,7 +140,7 @@ class VIFHandler(k8s_base.ResourceEventHandler):
139 140
 
140 141
         services = driver_utils.get_services(pod['metadata']['namespace'])
141 142
         project_id = self._drv_project.get_project(pod)
142
-        self._drv_sg.delete_sg_rules(pod)
143
+        crd_pod_selectors = self._drv_sg.delete_sg_rules(pod)
143 144
         try:
144 145
             security_groups = self._drv_sg.get_security_groups(pod, project_id)
145 146
         except k_exc.ResourceNotReady:
@@ -158,7 +159,7 @@ class VIFHandler(k8s_base.ResourceEventHandler):
158 159
                 self._drv_vif_pool.release_vif(pod, vif, project_id,
159 160
                                                security_groups)
160 161
         if self._is_network_policy_enabled():
161
-            self._update_services(services, project_id)
162
+            self._update_services(services, crd_pod_selectors, project_id)
162 163
 
163 164
     @MEMOIZE
164 165
     def is_ready(self, quota):
@@ -208,9 +209,11 @@ class VIFHandler(k8s_base.ResourceEventHandler):
208 209
                       constants.K8S_ANNOTATION_LABEL: labels_annotation},
209 210
                      resource_version=pod['metadata']['resourceVersion'])
210 211
 
211
-    def _update_services(self, services, project_id):
212
+    def _update_services(self, services, crd_pod_selectors, project_id):
212 213
         for service in services.get('items'):
213
-            if service['metadata']['name'] == 'kubernetes':
214
+            if (service['metadata']['name'] == 'kubernetes' or not
215
+                    driver_utils.service_matches_affected_pods(
216
+                        service, crd_pod_selectors)):
214 217
                 continue
215 218
             sgs = self._drv_svc_sg.get_security_groups(service,
216 219
                                                        project_id)

+ 5
- 2
kuryr_kubernetes/tests/unit/controller/handlers/test_pod_label.py View File

@@ -32,7 +32,8 @@ class TestPodLabelHandler(test_base.TestCase):
32 32
         self._pod_link = mock.sentinel.pod_link
33 33
         self._pod = {
34 34
             'metadata': {'resourceVersion': self._pod_version,
35
-                         'selfLink': self._pod_link},
35
+                         'selfLink': self._pod_link,
36
+                         'namespace': 'default'},
36 37
             'status': {'phase': k_const.K8S_POD_STATUS_PENDING},
37 38
             'spec': {'hostNetwork': False,
38 39
                      'nodeName': 'hostname'}
@@ -72,7 +73,9 @@ class TestPodLabelHandler(test_base.TestCase):
72 73
         self.assertEqual(sg_driver, handler._drv_sg)
73 74
         self.assertEqual(vif_pool_driver, handler._drv_vif_pool)
74 75
 
75
-    def test_on_present(self):
76
+    @mock.patch('kuryr_kubernetes.controller.drivers.utils.get_services')
77
+    def test_on_present(self,  m_get_services):
78
+        m_get_services.return_value = {"items": []}
76 79
         self._has_pod_state.return_value = True
77 80
         self._get_pod_labels.return_value = {'test1': 'test'}
78 81
 

Loading…
Cancel
Save