]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/cephadm: only check haproxy frontend_port conflicts on VIP
authorAdam King <adking@redhat.com>
Fri, 11 Aug 2023 18:00:31 +0000 (14:00 -0400)
committerAdam King <adking@redhat.com>
Thu, 31 Aug 2023 17:36:15 +0000 (13:36 -0400)
If we know what IP the frontend_port will be binding
to, we can pass that down through the port_ips mapping
so cephadm will only check if that port on that specific
VIP if in use. This allows multiple haproxy daemons
to be bound to the same port on different VIPs on the
same host.

Note that you still must use a different monitor port
for the two different ingress services as that port
is bound to on the actual IP of the host. Only the
frontend port can be the same for haproxies on the
same host as long as the VIP is different.

Fixes: https://tracker.ceph.com/issues/57614
Signed-off-by: Adam King <adking@redhat.com>
(cherry picked from commit 640af155986ac85d12367f43ac45b682a9fa9415)

Conflicts:
src/pybind/mgr/cephadm/tests/test_services.py

src/pybind/mgr/cephadm/services/ingress.py
src/pybind/mgr/cephadm/tests/test_services.py

index 95cff4bad194460c234f9a0be18f73982c133921..720a0bf305c5726b89d1f5ed9409f342cc03179c 100644 (file)
@@ -169,6 +169,10 @@ class IngressService(CephService):
         if spec.enable_haproxy_protocol:
             server_opts.append("send-proxy-v2")
         logger.debug("enabled default server opts: %r", server_opts)
+        ip = '*' if spec.virtual_ips_list else str(spec.virtual_ip).split('/')[0] or daemon_spec.ip or '*'
+        frontend_port = daemon_spec.ports[0] if daemon_spec.ports else spec.frontend_port
+        if ip != '*' and frontend_port:
+            daemon_spec.port_ips = {str(frontend_port): ip}
         haproxy_conf = self.mgr.template.render(
             'services/ingress/haproxy.cfg.j2',
             {
@@ -178,8 +182,8 @@ class IngressService(CephService):
                 'servers': servers,
                 'user': spec.monitor_user or 'admin',
                 'password': password,
-                'ip': "*" if spec.virtual_ips_list else str(spec.virtual_ip).split('/')[0] or daemon_spec.ip or '*',
-                'frontend_port': daemon_spec.ports[0] if daemon_spec.ports else spec.frontend_port,
+                'ip': ip,
+                'frontend_port': frontend_port,
                 'monitor_port': daemon_spec.ports[1] if daemon_spec.ports else spec.monitor_port,
                 'local_host_ip': host_ip,
                 'default_server_opts': server_opts,
index e2c6fed9c735329806be321414716d53e18b8766..3350f2951b98a26fcaec887eb183743affe0d8ec 100644 (file)
@@ -2023,6 +2023,44 @@ class TestIngressService:
 
                 assert haproxy_generated_conf[0] == haproxy_expected_conf
 
+    @patch("cephadm.serve.CephadmServe._run_cephadm")
+    def test_haproxy_port_ips(self, _run_cephadm, cephadm_module: CephadmOrchestrator):
+        _run_cephadm.side_effect = async_side_effect(('{}', '', 0))
+
+        with with_host(cephadm_module, 'test', addr='1.2.3.7'):
+            cephadm_module.cache.update_host_networks('test', {
+                '1.2.3.0/24': {
+                    'if0': ['1.2.3.4/32']
+                }
+            })
+
+            # Check the ingress with multiple VIPs
+            s = RGWSpec(service_id="foo", placement=PlacementSpec(count=1),
+                        rgw_frontend_type='beast')
+
+            ip = '1.2.3.100'
+            frontend_port = 8089
+
+            ispec = IngressSpec(service_type='ingress',
+                                service_id='test',
+                                backend_service='rgw.foo',
+                                frontend_port=frontend_port,
+                                monitor_port=8999,
+                                monitor_user='admin',
+                                monitor_password='12345',
+                                keepalived_password='12345',
+                                virtual_ip=f"{ip}/24")
+            with with_service(cephadm_module, s) as _, with_service(cephadm_module, ispec) as _:
+                # generate the haproxy conf based on the specified spec
+                haproxy_daemon_spec = cephadm_module.cephadm_services['ingress'].prepare_create(
+                    CephadmDaemonDeploySpec(
+                        host='test',
+                        daemon_type='haproxy',
+                        daemon_id='ingress',
+                        service_name=ispec.service_name()))
+
+                assert haproxy_daemon_spec.port_ips == {str(frontend_port): ip}
+
     @patch("cephadm.serve.CephadmServe._run_cephadm")
     @patch("cephadm.services.nfs.NFSService.fence_old_ranks", MagicMock())
     @patch("cephadm.services.nfs.NFSService.run_grace_tool", MagicMock())