From 7a6c5281e0d75c54e298ce68b2a8b54eefc5f0f9 Mon Sep 17 00:00:00 2001 From: Damien Ciabrini Date: Fri, 16 Jul 2021 14:22:39 +0000 Subject: [PATCH] haproxy: frontend/backend syntax in config Ability to generate haproxy config with the frontend/backend sections rather than the old listen section. This allows the generation of complex configs, such as for example giving priority to local backends when routing traffic. Make the new syntax configurable via a new hiera key `haproxy_backend_syntax`. The frontend and backend config of each service can be further tweaked via additional keys tripleo::haproxy::::frontend_options and tripleo::haproxy::::backend_options By default, keep the current 'listen' syntax. Tested with capability disabled, the haproxy config generated for undercloud and ha overcloud doesn't change. Tested with capability enabled, tempest smoke test passed. Closes-Bug: #1941617 Change-Id: Ieb36f90c6709934aa3aa6668d3929bff872c30f5 --- lib/puppet/functions/merge_hash_values.rb | 30 + manifests/haproxy.pp | 758 ++++++++++++------ manifests/haproxy/endpoint.pp | 69 +- manifests/haproxy/horizon_endpoint.pp | 55 +- manifests/haproxy/stats.pp | 37 +- ...oxy-frontend-backend-e3719b323e84fd2c.yaml | 12 + spec/defines/tripleo_haproxy_endpoint_spec.rb | 25 + spec/fixtures/hieradata/default.yaml | 4 + 8 files changed, 702 insertions(+), 288 deletions(-) create mode 100644 lib/puppet/functions/merge_hash_values.rb create mode 100644 releasenotes/notes/haproxy-frontend-backend-e3719b323e84fd2c.yaml diff --git a/lib/puppet/functions/merge_hash_values.rb b/lib/puppet/functions/merge_hash_values.rb new file mode 100644 index 000000000..7d332d362 --- /dev/null +++ b/lib/puppet/functions/merge_hash_values.rb @@ -0,0 +1,30 @@ +# This function merges two hashes and concatenate the values of +# identical keys +# +# Example: +# $frontend = { 'option' => [ 'tcpka', 'tcplog' ], +# 'timeout client' => '90m' } +# $backend = { 'option' => [ 'httpchk' ], +# 'timeout server' => '90m' } +# +# Using this function: +# $merge = merge_hash_values($frontend, $backend) +# +# Would return: +# $merge = { 'option' => [ 'tcpka', 'tcplog', 'httpchk' ], +# 'timeout client' => '90m', +# 'timeout server' => '90m' } +# + +Puppet::Functions.create_function(:'merge_hash_values') do + dispatch :merge_hash_values do + param 'Hash', :hash1 + param 'Hash', :hash2 + return_type 'Hash' + end + + def merge_hash_values(hash1, hash2) + hh = hash1.merge(hash2) {|k, v1, v2| (v2 + v1).uniq()} + return hh + end +end diff --git a/manifests/haproxy.pp b/manifests/haproxy.pp index 261ff0de6..c4d087e56 100644 --- a/manifests/haproxy.pp +++ b/manifests/haproxy.pp @@ -108,6 +108,11 @@ # Can be a string or an array. # Defaults to undef # +# [*use_backend_syntax*] +# (optional) When set to true, generate a config with frontend and +# backend sections, otherwise use listen sections. +# Defaults to hiera('haproxy_backend_syntax', false) +# # [*haproxy_stats_user*] # Username for haproxy stats authentication. # A string. @@ -296,6 +301,14 @@ # Hash to pass to the mysql haproxy listen stanza to be deepmerged with the other options # Defaults to {} # +# [*mysql_custom_frontend_options*] +# Hash to pass to the mysql haproxy frontend stanza to be deepmerged with the other options +# Defaults to {} +# +# [*mysql_custom_backend_options*] +# Hash to pass to the mysql haproxy backend stanza to be deepmerged with the other options +# Defaults to {} +# # [*rabbitmq*] # (optional) Enable or not RabbitMQ binding # Defaults to false @@ -544,110 +557,113 @@ class tripleo::haproxy ( $controller_virtual_ip, $public_virtual_ip, - $haproxy_service_manage = true, - $haproxy_global_maxconn = 20480, - $haproxy_default_maxconn = 4096, - $haproxy_default_timeout = [ 'http-request 10s', 'queue 2m', 'connect 10s', 'client 2m', 'server 2m', 'check 10s' ], - $haproxy_listen_bind_param = [ 'transparent' ], - $haproxy_member_options = [ 'check', 'inter 2000', 'rise 2', 'fall 5' ], - $haproxy_log_address = '/dev/log', - $haproxy_log_facility = 'local0', - $activate_httplog = false, - $haproxy_globals_override = {}, - $haproxy_defaults_override = {}, - $haproxy_lb_mode_longrunning = 'leastconn', - $haproxy_daemon = true, - $haproxy_socket_access_level = 'user', - $haproxy_stats_user = 'admin', - $haproxy_stats_password = undef, - $haproxy_stats_bind_address = undef, - $manage_firewall = hiera('tripleo::firewall::manage_firewall', true), - $controller_hosts = hiera('controller_node_ips'), - $controller_hosts_names = hiera('controller_node_names', undef), - $service_certificate = undef, - $use_internal_certificates = false, - $internal_certificates_specs = {}, - $enable_internal_tls = hiera('enable_internal_tls', false), - $ssl_cipher_suite = '!SSLv2:kEECDH:kRSA:kEDH:kPSK:+3DES:!aNULL:!eNULL:!MD5:!EXP:!RC4:!SEED:!IDEA:!DES', - $ssl_options = 'no-sslv3 no-tlsv10', - $ca_bundle = '/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt', - $crl_file = undef, - $haproxy_stats_certificate = undef, - $haproxy_stats = true, - $keystone_admin = hiera('keystone_enabled', false), - $keystone_public = hiera('keystone_enabled', false), - $neutron = hiera('neutron_api_enabled', false), - $cinder = hiera('cinder_api_enabled', false), - $manila = hiera('manila_api_enabled', false), - $glance_api = hiera('glance_api_enabled', false), - $nova_osapi = hiera('nova_api_enabled', false), - $placement = hiera('placement_enabled', false), - $nova_metadata = hiera('nova_metadata_enabled', false), - $nova_novncproxy = hiera('nova_vnc_proxy_enabled', false), - $aodh = hiera('aodh_api_enabled', false), - $barbican = hiera('barbican_api_enabled', false), - $ceph_grafana = hiera('ceph_grafana_enabled', false), - $ceph_dashboard = hiera('ceph_grafana_enabled', false), - $gnocchi = hiera('gnocchi_api_enabled', false), - $mistral = hiera('mistral_api_enabled', false), - $swift_proxy_server = hiera('swift_proxy_enabled', false), - $heat_api = hiera('heat_api_enabled', false), - $heat_cfn = hiera('heat_api_cfn_enabled', false), - $horizon = hiera('horizon_enabled', false), - $ironic = hiera('ironic_api_enabled', false), - $ironic_inspector = hiera('ironic_inspector_enabled', false), - $octavia = hiera('octavia_api_enabled', false), - $designate = hiera('designate_api_enabled', false), - $metrics_qdr = hiera('metrics_qdr_enabled', false), - $mysql = hiera('mysql_enabled', false), - $mysql_clustercheck = false, - $mysql_max_conn = undef, - $mysql_member_options = undef, - $mysql_custom_listen_options = {}, - $rabbitmq = false, - $etcd = hiera('etcd_enabled', false), - $docker_registry = hiera('enable_docker_registry', false), - $redis = hiera('redis_enabled', false), - $redis_password = undef, - $zaqar_api = hiera('zaqar_api_enabled', false), - $ceph_rgw = hiera('ceph_rgw_enabled', false), - $ovn_dbs = hiera('ovn_dbs_enabled', false), - $ovn_dbs_manage_lb = false, - $zaqar_ws = hiera('zaqar_api_enabled', false), - $aodh_network = hiera('aodh_api_network', undef), - $barbican_network = hiera('barbican_api_network', false), - $ceph_rgw_network = hiera('ceph_rgw_network', undef), - $cinder_network = hiera('cinder_api_network', undef), - $designate_network = hiera('designate_api_network', undef), - $metrics_qdr_network = hiera('metrics_qdr_network', undef), - $docker_registry_network = hiera('docker_registry_network', undef), - $glance_api_network = hiera('glance_api_network', undef), - $gnocchi_network = hiera('gnocchi_api_network', undef), - $heat_api_network = hiera('heat_api_network', undef), - $ceph_grafana_network = hiera('ceph_grafana_network', undef), - $ceph_dashboard_network = hiera('ceph_dashboard_network', undef), - $heat_cfn_network = hiera('heat_api_cfn_network', undef), - $horizon_network = hiera('horizon_network', undef), - $ironic_inspector_network = hiera('ironic_inspector_network', undef), - $ironic_network = hiera('ironic_api_network', undef), - $keystone_admin_network = hiera('keystone_admin_api_network', undef), - $keystone_public_network = hiera('keystone_public_api_network', undef), - $keystone_sticky_sessions = hiera('keystone_sticky_sessions', false), - $keystone_session_cookie = hiera('keystone_session_cookie,', 'KEYSTONESESSION'), - $manila_network = hiera('manila_api_network', undef), - $mistral_network = hiera('mistral_api_network', undef), - $neutron_network = hiera('neutron_api_network', undef), - $nova_metadata_network = hiera('nova_metadata_network', undef), - $nova_novncproxy_network = hiera('nova_vnc_proxy_network', hiera('nova_libvirt_network', undef)), - $nova_osapi_network = hiera('nova_api_network', undef), - $placement_network = hiera('placement_network', undef), - $octavia_network = hiera('octavia_api_network', undef), - $ovn_dbs_network = hiera('ovn_dbs_network', undef), - $etcd_network = hiera('etcd_network', undef), - $swift_proxy_server_network = hiera('swift_proxy_network', undef), - $zaqar_api_network = hiera('zaqar_api_network', undef), - $zaqar_ws_timeout_tunnel = hiera('zaqar_ws_timeout_tunnel', '14400'), - $service_ports = {} + $use_backend_syntax = hiera('haproxy_backend_syntax', false), + $haproxy_service_manage = true, + $haproxy_global_maxconn = 20480, + $haproxy_default_maxconn = 4096, + $haproxy_default_timeout = [ 'http-request 10s', 'queue 2m', 'connect 10s', 'client 2m', 'server 2m', 'check 10s' ], + $haproxy_listen_bind_param = [ 'transparent' ], + $haproxy_member_options = [ 'check', 'inter 2000', 'rise 2', 'fall 5' ], + $haproxy_log_address = '/dev/log', + $haproxy_log_facility = 'local0', + $activate_httplog = false, + $haproxy_globals_override = {}, + $haproxy_defaults_override = {}, + $haproxy_lb_mode_longrunning = 'leastconn', + $haproxy_daemon = true, + $haproxy_socket_access_level = 'user', + $haproxy_stats_user = 'admin', + $haproxy_stats_password = undef, + $haproxy_stats_bind_address = undef, + $manage_firewall = hiera('tripleo::firewall::manage_firewall', true), + $controller_hosts = hiera('controller_node_ips'), + $controller_hosts_names = hiera('controller_node_names', undef), + $service_certificate = undef, + $use_internal_certificates = false, + $internal_certificates_specs = {}, + $enable_internal_tls = hiera('enable_internal_tls', false), + $ssl_cipher_suite = '!SSLv2:kEECDH:kRSA:kEDH:kPSK:+3DES:!aNULL:!eNULL:!MD5:!EXP:!RC4:!SEED:!IDEA:!DES', + $ssl_options = 'no-sslv3 no-tlsv10', + $ca_bundle = '/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt', + $crl_file = undef, + $haproxy_stats_certificate = undef, + $haproxy_stats = true, + $keystone_admin = hiera('keystone_enabled', false), + $keystone_public = hiera('keystone_enabled', false), + $neutron = hiera('neutron_api_enabled', false), + $cinder = hiera('cinder_api_enabled', false), + $manila = hiera('manila_api_enabled', false), + $glance_api = hiera('glance_api_enabled', false), + $nova_osapi = hiera('nova_api_enabled', false), + $placement = hiera('placement_enabled', false), + $nova_metadata = hiera('nova_metadata_enabled', false), + $nova_novncproxy = hiera('nova_vnc_proxy_enabled', false), + $aodh = hiera('aodh_api_enabled', false), + $barbican = hiera('barbican_api_enabled', false), + $ceph_grafana = hiera('ceph_grafana_enabled', false), + $ceph_dashboard = hiera('ceph_grafana_enabled', false), + $gnocchi = hiera('gnocchi_api_enabled', false), + $mistral = hiera('mistral_api_enabled', false), + $swift_proxy_server = hiera('swift_proxy_enabled', false), + $heat_api = hiera('heat_api_enabled', false), + $heat_cfn = hiera('heat_api_cfn_enabled', false), + $horizon = hiera('horizon_enabled', false), + $ironic = hiera('ironic_api_enabled', false), + $ironic_inspector = hiera('ironic_inspector_enabled', false), + $octavia = hiera('octavia_api_enabled', false), + $designate = hiera('designate_api_enabled', false), + $metrics_qdr = hiera('metrics_qdr_enabled', false), + $mysql = hiera('mysql_enabled', false), + $mysql_clustercheck = false, + $mysql_max_conn = undef, + $mysql_member_options = undef, + $mysql_custom_listen_options = {}, + $mysql_custom_frontend_options = {}, + $mysql_custom_backend_options = {}, + $rabbitmq = false, + $etcd = hiera('etcd_enabled', false), + $docker_registry = hiera('enable_docker_registry', false), + $redis = hiera('redis_enabled', false), + $redis_password = undef, + $zaqar_api = hiera('zaqar_api_enabled', false), + $ceph_rgw = hiera('ceph_rgw_enabled', false), + $ovn_dbs = hiera('ovn_dbs_enabled', false), + $ovn_dbs_manage_lb = false, + $zaqar_ws = hiera('zaqar_api_enabled', false), + $aodh_network = hiera('aodh_api_network', undef), + $barbican_network = hiera('barbican_api_network', false), + $ceph_rgw_network = hiera('ceph_rgw_network', undef), + $cinder_network = hiera('cinder_api_network', undef), + $designate_network = hiera('designate_api_network', undef), + $metrics_qdr_network = hiera('metrics_qdr_network', undef), + $docker_registry_network = hiera('docker_registry_network', undef), + $glance_api_network = hiera('glance_api_network', undef), + $gnocchi_network = hiera('gnocchi_api_network', undef), + $heat_api_network = hiera('heat_api_network', undef), + $ceph_grafana_network = hiera('ceph_grafana_network', undef), + $ceph_dashboard_network = hiera('ceph_dashboard_network', undef), + $heat_cfn_network = hiera('heat_api_cfn_network', undef), + $horizon_network = hiera('horizon_network', undef), + $ironic_inspector_network = hiera('ironic_inspector_network', undef), + $ironic_network = hiera('ironic_api_network', undef), + $keystone_admin_network = hiera('keystone_admin_api_network', undef), + $keystone_public_network = hiera('keystone_public_api_network', undef), + $keystone_sticky_sessions = hiera('keystone_sticky_sessions', false), + $keystone_session_cookie = hiera('keystone_session_cookie,', 'KEYSTONESESSION'), + $manila_network = hiera('manila_api_network', undef), + $mistral_network = hiera('mistral_api_network', undef), + $neutron_network = hiera('neutron_api_network', undef), + $nova_metadata_network = hiera('nova_metadata_network', undef), + $nova_novncproxy_network = hiera('nova_vnc_proxy_network', hiera('nova_libvirt_network', undef)), + $nova_osapi_network = hiera('nova_api_network', undef), + $placement_network = hiera('placement_network', undef), + $octavia_network = hiera('octavia_api_network', undef), + $ovn_dbs_network = hiera('ovn_dbs_network', undef), + $etcd_network = hiera('etcd_network', undef), + $swift_proxy_server_network = hiera('swift_proxy_network', undef), + $zaqar_api_network = hiera('zaqar_api_network', undef), + $zaqar_ws_timeout_tunnel = hiera('zaqar_ws_timeout_tunnel', '14400'), + $service_ports = {} ) { $default_service_ports = { aodh_api_port => 8042, @@ -789,13 +805,18 @@ class tripleo::haproxy ( } - $default_listen_options = { - 'option' => [ 'httpchk', 'httplog', ], + $default_frontend_options = { + 'option' => [ 'httplog', ], 'http-request' => [ 'set-header X-Forwarded-Proto https if { ssl_fc }', 'set-header X-Forwarded-Proto http if !{ ssl_fc }', 'set-header X-Forwarded-Port %[dst_port]'], } + $default_backend_options = { + 'option' => [ 'httpchk' ], + } + $default_listen_options = merge_hash_values($default_frontend_options, + $default_backend_options) Tripleo::Haproxy::Endpoint { haproxy_listen_bind_param => $haproxy_listen_bind_param, member_options => $haproxy_member_options, @@ -803,6 +824,8 @@ class tripleo::haproxy ( use_internal_certificates => $use_internal_certificates, internal_certificates_specs => $internal_certificates_specs, listen_options => $default_listen_options, + frontend_options => $default_frontend_options, + backend_options => $default_backend_options, manage_firewall => $manage_firewall, } @@ -830,23 +853,30 @@ class tripleo::haproxy ( } } - $keystone_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ] + $keystone_frontend_opts = { + 'option' => [ 'httplog' ] } + $keystone_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ] + } + $keystone_listen_opts = merge_hash_values($keystone_frontend_opts, + $keystone_backend_opts) if $keystone_admin { # NOTE(jaosorior): Given that the admin endpoint is in the same vhost # nowadays as the public/internal one. We can just loadbalance towards the # same IP. ::tripleo::haproxy::endpoint { 'keystone_admin': - internal_ip => hiera('keystone_admin_api_vip', $controller_virtual_ip), - service_port => $ports[keystone_public_api_port], - haproxy_port => $ports[keystone_admin_api_port], - ip_addresses => hiera('keystone_public_api_node_ips', $controller_hosts_real), - server_names => hiera('keystone_public_api_node_names', $controller_hosts_names_real), - mode => 'http', - listen_options => merge($default_listen_options, $keystone_listen_opts), - service_network => $keystone_admin_network, - member_options => union($haproxy_member_options, $internal_tls_member_options), + internal_ip => hiera('keystone_admin_api_vip', $controller_virtual_ip), + service_port => $ports[keystone_public_api_port], + haproxy_port => $ports[keystone_admin_api_port], + ip_addresses => hiera('keystone_public_api_node_ips', $controller_hosts_real), + server_names => hiera('keystone_public_api_node_names', $controller_hosts_names_real), + mode => 'http', + listen_options => merge($default_listen_options, $keystone_listen_opts), + frontend_options => merge($default_frontend_options, $keystone_frontend_opts), + backend_options => merge($default_backend_options, $keystone_backend_opts), + service_network => $keystone_admin_network, + member_options => union($haproxy_member_options, $internal_tls_member_options), } } @@ -859,6 +889,8 @@ class tripleo::haproxy ( server_names => hiera('keystone_public_api_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $keystone_listen_opts), + frontend_options => merge($default_frontend_options, $keystone_frontend_opts), + backend_options => $keystone_backend_opts, public_ssl_port => $ports[keystone_public_api_ssl_port], service_network => $keystone_public_network, sticky_sessions => $keystone_sticky_sessions, @@ -868,10 +900,15 @@ class tripleo::haproxy ( } if $neutron { - $neutron_listen_opts = { - 'balance' => $haproxy_lb_mode_longrunning, - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ] + $neutron_frontend_opts = { + 'option' => [ 'httplog' ] } + $neutron_backend_opts = { + 'balance' => $haproxy_lb_mode_longrunning, + 'option' => [ 'httpchk GET /healthcheck' ] + } + $neutron_listen_opts = merge_hash_values($neutron_frontend_opts, + $neutron_backend_opts) ::tripleo::haproxy::endpoint { 'neutron': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('neutron_api_vip', $controller_virtual_ip), @@ -880,6 +917,8 @@ class tripleo::haproxy ( server_names => hiera('neutron_api_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $neutron_listen_opts), + frontend_options => merge($default_frontend_options, $neutron_frontend_opts), + backend_options => merge($default_backend_options, $neutron_backend_opts), public_ssl_port => $ports[neutron_api_ssl_port], service_network => $neutron_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -887,10 +926,15 @@ class tripleo::haproxy ( } if $cinder { - $cinder_listen_opts = { - 'balance' => $haproxy_lb_mode_longrunning, - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ] + $cinder_frontend_opts = { + 'option' => [ 'httplog' ], } + $cinder_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + 'balance' => $haproxy_lb_mode_longrunning, + } + $cinder_listen_opts = merge_hash_values($cinder_frontend_opts, + $cinder_backend_opts) ::tripleo::haproxy::endpoint { 'cinder': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('cinder_api_vip', $controller_virtual_ip), @@ -899,6 +943,8 @@ class tripleo::haproxy ( server_names => hiera('cinder_api_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $cinder_listen_opts), + frontend_options => merge($default_frontend_options, $cinder_frontend_opts), + backend_options => merge($default_backend_options, $cinder_backend_opts), public_ssl_port => $ports[cinder_api_ssl_port], service_network => $cinder_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -906,9 +952,14 @@ class tripleo::haproxy ( } if $manila { - $manila_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], + $manila_frontend_opts = { + 'option' => [ 'httplog' ], } + $manila_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + } + $manila_listen_opts = merge_hash_values($manila_frontend_opts, + $manila_backend_opts) ::tripleo::haproxy::endpoint { 'manila': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('manila_api_vip', $controller_virtual_ip), @@ -917,6 +968,8 @@ class tripleo::haproxy ( server_names => hiera('manila_api_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $manila_listen_opts), + frontend_options => merge($default_frontend_options, $manila_frontend_opts), + backend_options => merge($default_backend_options, $manila_backend_opts), public_ssl_port => $ports[manila_api_ssl_port], service_network => $manila_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -924,9 +977,14 @@ class tripleo::haproxy ( } if $glance_api { - $glance_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], + $glance_frontend_opts = { + 'option' => [ 'httplog' ], } + $glance_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + } + $glance_listen_opts = merge_hash_values($glance_frontend_opts, + $glance_backend_opts) ::tripleo::haproxy::endpoint { 'glance_api': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('glance_api_vip', $controller_virtual_ip), @@ -936,6 +994,8 @@ class tripleo::haproxy ( public_ssl_port => $ports[glance_api_ssl_port], mode => 'http', listen_options => merge($default_listen_options, $glance_listen_opts), + frontend_options => merge($default_frontend_options, $glance_frontend_opts), + backend_options => merge($default_backend_options, $glance_backend_opts), service_network => $glance_api_network, member_options => union($haproxy_member_options, $internal_tls_member_options), } @@ -943,46 +1003,61 @@ class tripleo::haproxy ( if $ceph_grafana { ::tripleo::haproxy::endpoint { 'ceph_grafana': - internal_ip => hiera('ceph_dashboard_vip', $controller_virtual_ip), - service_port => $ports[ceph_grafana_port], - ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), - server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), - mode => 'http', - public_ssl_port => $ports[ceph_grafana_ssl_port], - listen_options => merge($default_listen_options, { + internal_ip => hiera('ceph_dashboard_vip', $controller_virtual_ip), + service_port => $ports[ceph_grafana_port], + ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), + server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), + mode => 'http', + public_ssl_port => $ports[ceph_grafana_ssl_port], + listen_options => merge($default_listen_options, { 'option' => [ 'httpchk HEAD /', 'httplog' ], 'balance' => 'source', }), - service_network => $ceph_grafana_network, - member_options => union($haproxy_member_options, $internal_tls_member_options), + frontend_options => $default_frontend_options, + backend_options => merge($default_backend_options, { + 'option' => [ 'httpchk HEAD /' ], + 'balance' => 'source', + }), + service_network => $ceph_grafana_network, + member_options => union($haproxy_member_options, $internal_tls_member_options), } ::tripleo::haproxy::endpoint { 'ceph_prometheus': - internal_ip => hiera('ceph_grafana_vip', $controller_virtual_ip), - service_port => $ports[ceph_prometheus_port], - ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), - server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), - mode => 'http', - public_ssl_port => $ports[ceph_prometheus_ssl_port], - listen_options => merge($default_listen_options, { + internal_ip => hiera('ceph_grafana_vip', $controller_virtual_ip), + service_port => $ports[ceph_prometheus_port], + ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), + server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), + mode => 'http', + public_ssl_port => $ports[ceph_prometheus_ssl_port], + listen_options => merge($default_listen_options, { 'option' => [ 'httpchk GET /metrics', 'httplog' ], 'balance' => 'source', }), - service_network => $ceph_grafana_network, - member_options => $haproxy_member_options, + frontend_options => $default_frontend_options, + backend_options => merge($default_backend_options, { + 'option' => [ 'httpchk GET /metrics' ], + 'balance' => 'source', + }), + service_network => $ceph_grafana_network, + member_options => $haproxy_member_options, } ::tripleo::haproxy::endpoint { 'ceph_alertmanager': - internal_ip => hiera('ceph_grafana_vip', $controller_virtual_ip), - service_port => $ports[ceph_alertmanager_port], - ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), - server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), - mode => 'http', - public_ssl_port => $ports[ceph_alertmanager_ssl_port], - listen_options => merge($default_listen_options, { + internal_ip => hiera('ceph_grafana_vip', $controller_virtual_ip), + service_port => $ports[ceph_alertmanager_port], + ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), + server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), + mode => 'http', + public_ssl_port => $ports[ceph_alertmanager_ssl_port], + listen_options => merge($default_listen_options, { 'option' => [ 'httpchk GET /', 'httplog' ], 'balance' => 'source', }), - service_network => $ceph_grafana_network, - member_options => $haproxy_member_options, + frontend_options => $default_frontend_options, + backend_options => merge($default_backend_options, { + 'option' => [ 'httpchk GET /' ], + 'balance' => 'source', + }), + service_network => $ceph_grafana_network, + member_options => $haproxy_member_options, } } @@ -992,20 +1067,25 @@ class tripleo::haproxy ( } else { $ceph_dashboard_tls_member_options = [] } + $ceph_dashboard_backend_opts = { + 'option' => [ 'httpchk HEAD /' ], + 'balance' => 'source', + 'http-check' => 'expect rstatus 2[0-9][0-9]', + } + $ceph_dashboard_listen_opts = merge_hash_values($default_frontend_options, + $ceph_dashboard_backend_opts) ::tripleo::haproxy::endpoint { 'ceph_dashboard': - internal_ip => hiera('ceph_dashboard_vip', $controller_virtual_ip), - service_port => $ports[ceph_dashboard_port], - ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), - server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), - mode => 'http', - public_ssl_port => $ports[ceph_dashboard_ssl_port], - listen_options => merge($default_listen_options, { - 'option' => [ 'httpchk HEAD /', 'httplog' ], - 'balance' => 'source', - 'http-check' => 'expect rstatus 2[0-9][0-9]', - }), - service_network => $ceph_dashboard_network, - member_options => union($haproxy_member_options, $ceph_dashboard_tls_member_options), + internal_ip => hiera('ceph_dashboard_vip', $controller_virtual_ip), + service_port => $ports[ceph_dashboard_port], + ip_addresses => hiera('ceph_grafana_node_ips', $controller_hosts_real), + server_names => hiera('ceph_grafana_node_names', $controller_hosts_names_real), + mode => 'http', + public_ssl_port => $ports[ceph_dashboard_ssl_port], + listen_options => merge($default_listen_options, $ceph_dashboard_listen_opts), + frontend_options => $default_frontend_options, + backend_options => merge($default_backend_options, $ceph_dashboard_backend_opts), + service_network => $ceph_dashboard_network, + member_options => union($haproxy_member_options, $ceph_dashboard_tls_member_options), } } @@ -1048,18 +1128,23 @@ class tripleo::haproxy ( } else { $nova_metadata_server_names_real = hiera('nova_metadata_node_names', $controller_hosts_names_real) } + $nova_metadata_backend_opts = { + 'balance' => 'source', + 'hash-type' => 'consistent', + } + $nova_metadata_listen_opts = merge_hash_values($default_listen_options, + $nova_metadata_backend_opts) ::tripleo::haproxy::endpoint { 'nova_metadata': - internal_ip => hiera('nova_metadata_vip', $controller_virtual_ip), - service_port => $ports[nova_metadata_port], - ip_addresses => hiera('nova_metadata_node_ips', $controller_hosts_real), - server_names => $nova_metadata_server_names_real, - mode => 'http', - service_network => $nova_metadata_network, - member_options => union($haproxy_member_options, $internal_tls_member_options), - listen_options => merge($default_listen_options, { - 'balance' => 'source', - 'hash-type' => 'consistent', - }), + internal_ip => hiera('nova_metadata_vip', $controller_virtual_ip), + service_port => $ports[nova_metadata_port], + ip_addresses => hiera('nova_metadata_node_ips', $controller_hosts_real), + server_names => $nova_metadata_server_names_real, + mode => 'http', + service_network => $nova_metadata_network, + member_options => union($haproxy_member_options, $internal_tls_member_options), + listen_options => merge($default_listen_options, $nova_metadata_listen_opts), + frontend_options => $default_frontend_options, + backend_options => merge($default_backend_options, $nova_metadata_backend_opts), } } @@ -1079,6 +1164,15 @@ class tripleo::haproxy ( } else { $novncproxy_server_names_real = hiera('nova_vnc_proxy_node_names', $controller_hosts_names_real) } + $nova_vncproxy_frontend_opts = { + 'option' => [ 'tcpka', 'tcplog' ], + } + $nova_vncproxy_backend_opts = { + 'balance' => 'source', + 'timeout' => [ 'tunnel 1h' ], + } + $nova_vncproxy_listen_opts = merge_hash_values($nova_vncproxy_frontend_opts, + $nova_vncproxy_backend_opts) ::tripleo::haproxy::endpoint { 'nova_novncproxy': public_virtual_ip => $public_virtual_ip, internal_ip => $nova_vnc_proxy_vip, @@ -1086,11 +1180,9 @@ class tripleo::haproxy ( ip_addresses => hiera('nova_vnc_proxy_node_ips', $controller_hosts_real), server_names => $novncproxy_server_names_real, mode => 'http', - listen_options => merge($default_listen_options, { - 'option' => [ 'tcpka', 'tcplog' ], - 'balance' => 'source', - 'timeout' => [ 'tunnel 1h' ], - }), + listen_options => merge($default_listen_options, $nova_vncproxy_listen_opts), + frontend_options => merge($default_frontend_options, $nova_vncproxy_frontend_opts), + backend_options => merge($default_backend_options, $nova_vncproxy_backend_opts), public_ssl_port => $ports[nova_novnc_ssl_port], service_network => $nova_novncproxy_network, member_options => union($haproxy_member_options_real, $internal_tls_member_options, $novncproxy_ssl_member_options), @@ -1098,9 +1190,14 @@ class tripleo::haproxy ( } if $aodh { - $aodh_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], + $aodh_frontend_opts = { + 'option' => [ 'httplog' ], } + $aodh_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + } + $aodh_listen_opts = merge_hash_values($aodh_frontend_opts, + $aodh_backend_opts) ::tripleo::haproxy::endpoint { 'aodh': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('aodh_api_vip', $controller_virtual_ip), @@ -1109,6 +1206,8 @@ class tripleo::haproxy ( server_names => hiera('aodh_api_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $aodh_listen_opts), + frontend_options => merge($default_frontend_options, $aodh_frontend_opts), + backend_options => merge($default_backend_options, $aodh_backend_opts), public_ssl_port => $ports[aodh_api_ssl_port], service_network => $aodh_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -1116,9 +1215,14 @@ class tripleo::haproxy ( } if $barbican { - $barbican_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], + $barbican_frontend_opts = { + 'option' => [ 'httplog' ], } + $barbican_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + } + $barbican_listen_opts = merge_hash_values($barbican_frontend_opts, + $barbican_backend_opts) ::tripleo::haproxy::endpoint { 'barbican': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('barbican_api_vip', $controller_virtual_ip), @@ -1129,6 +1233,8 @@ class tripleo::haproxy ( service_network => $barbican_network, mode => 'http', listen_options => merge($default_listen_options, $barbican_listen_opts), + frontend_options => merge($default_frontend_options, $barbican_frontend_opts), + backend_options => merge($default_backend_options, $barbican_backend_opts), member_options => union($haproxy_member_options, $internal_tls_member_options), } } @@ -1163,12 +1269,17 @@ class tripleo::haproxy ( } if $swift_proxy_server { - $swift_proxy_server_listen_options = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], - 'balance' => $haproxy_lb_mode_longrunning, + $swift_proxy_server_frontend_options = { + 'option' => [ 'httplog' ], 'timeout client' => '2m', + } + $swift_proxy_server_backend_options = { + 'option' => [ 'httpchk GET /healthcheck' ], + 'balance' => $haproxy_lb_mode_longrunning, 'timeout server' => '2m', } + $swift_proxy_server_listen_options = merge_hash_values($swift_proxy_server_frontend_options, + $swift_proxy_server_backend_options) ::tripleo::haproxy::endpoint { 'swift_proxy_server': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('swift_proxy_vip', $controller_virtual_ip), @@ -1177,6 +1288,8 @@ class tripleo::haproxy ( server_names => hiera('swift_proxy_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $swift_proxy_server_listen_options), + frontend_options => merge($default_frontend_options, $swift_proxy_server_frontend_options), + backend_options => merge($default_backend_options, $swift_proxy_server_backend_options), public_ssl_port => $ports[swift_proxy_ssl_port], service_network => $swift_proxy_server_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -1197,11 +1310,14 @@ class tripleo::haproxy ( $heat_ssl_options = { 'rsprep' => "^Location:\\ http://${public_virtual_ip}(.*) Location:\\ https://${public_virtual_ip}\\1", } - $heat_options = merge($default_listen_options, $heat_ssl_options, $heat_timeout_options) + $heat_listen_options = merge($default_listen_options, $heat_ssl_options, $heat_timeout_options) + $heat_frontend_options = merge($default_frontend_options, $heat_ssl_options, $heat_timeout_options) } else { - $heat_options = merge($default_listen_options, $heat_timeout_options) + $heat_listen_options = merge($default_listen_options, $heat_timeout_options) + $heat_frontend_options = merge($default_frontend_options, $heat_timeout_options) } - $heat_options_real = merge($heat_options, $heat_durability_options) + $heat_listen_options_real = merge($heat_listen_options, $heat_durability_options) + $heat_frontend_options_real = merge($heat_frontend_options, $heat_durability_options) if $heat_api { ::tripleo::haproxy::endpoint { 'heat_api': @@ -1211,7 +1327,8 @@ class tripleo::haproxy ( ip_addresses => $heat_ip_addresses, server_names => hiera('heat_api_node_names', $controller_hosts_names_real), mode => 'http', - listen_options => $heat_options_real, + listen_options => $heat_listen_options_real, + frontend_options => $heat_frontend_options_real, public_ssl_port => $ports[heat_api_ssl_port], service_network => $heat_api_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -1226,7 +1343,8 @@ class tripleo::haproxy ( ip_addresses => $heat_ip_addresses, server_names => hiera('heat_api_node_names', $controller_hosts_names_real), mode => 'http', - listen_options => $heat_options_real, + listen_options => $heat_listen_options_real, + frontend_options => $heat_frontend_options_real, public_ssl_port => $ports[heat_cfn_ssl_port], service_network => $heat_cfn_network, member_options => union($haproxy_member_options, $internal_tls_member_options), @@ -1250,9 +1368,14 @@ class tripleo::haproxy ( } if $ironic { - $ironic_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], + $ironic_frontend_opts = { + 'option' => [ 'httplog' ], } + $ironic_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + } + $ironic_listen_opts = merge_hash_values($ironic_frontend_opts, + $ironic_backend_opts) ::tripleo::haproxy::endpoint { 'ironic': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('ironic_api_vip', $controller_virtual_ip), @@ -1260,6 +1383,8 @@ class tripleo::haproxy ( ip_addresses => hiera('ironic_api_node_ips', $controller_hosts_real), server_names => hiera('ironic_api_node_names', $controller_hosts_names_real), mode => 'http', + frontend_options => merge($default_frontend_options, $ironic_frontend_opts), + backend_options => merge($default_backend_options, $ironic_backend_opts), listen_options => merge($default_listen_options, $ironic_listen_opts), public_ssl_port => $ports[ironic_api_ssl_port], service_network => $ironic_network, @@ -1268,6 +1393,15 @@ class tripleo::haproxy ( } if $ironic_inspector { + $ironic_inspector_frontend_opts = { + 'option' => [ 'httplog' ], + } + $ironic_inspector_backend_opts = { + 'option' => [ 'httpchk' ], + 'balance' => $haproxy_lb_mode_longrunning + } + $ironic_inspector_listen_opts = merge_hash_values($ironic_inspector_frontend_opts, + $ironic_inspector_backend_opts) # NOTE(tkajinam): Ironic-inspector doesn't provide healthcheck API ::tripleo::haproxy::endpoint { 'ironic-inspector': public_virtual_ip => $public_virtual_ip, @@ -1278,16 +1412,21 @@ class tripleo::haproxy ( public_ssl_port => $ports[ironic_inspector_ssl_port], service_network => $ironic_inspector_network, mode => 'http', - listen_options => merge($default_listen_options, { - 'balance' => $haproxy_lb_mode_longrunning - }), + listen_options => merge($default_listen_options, $ironic_inspector_listen_opts), + frontend_options => merge($default_frontend_options, $ironic_inspector_frontend_opts), + backend_options => merge($default_backend_options, $ironic_inspector_backend_opts), } } if $designate { - $designate_listen_opts = { - 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], + $designate_frontend_opts = { + 'option' => [ 'httplog' ], } + $designate_backend_opts = { + 'option' => [ 'httpchk GET /healthcheck' ], + } + $designate_listen_opts = merge_hash_values($designate_frontend_opts, + $designate_backend_opts) ::tripleo::haproxy::endpoint { 'designate': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('designate_api_vip', $controller_virtual_ip), @@ -1296,6 +1435,8 @@ class tripleo::haproxy ( server_names => hiera('designate_api_node_names', $controller_hosts_names_real), mode => 'http', listen_options => merge($default_listen_options, $designate_listen_opts), + frontend_options => merge($default_frontend_options, $designate_frontend_opts), + backend_options => merge($default_backend_options, $designate_backend_opts), public_ssl_port => $ports[designate_api_ssl_port], service_network => $designate_network, } @@ -1305,13 +1446,29 @@ class tripleo::haproxy ( $metrics_bind_opts = { "${public_virtual_ip}:${ports[metrics_qdr_port]}" => $haproxy_listen_bind_param, } - haproxy::listen { 'metrics_qdr': - bind => $metrics_bind_opts, - options => { - 'option' => [ 'tcp-check', 'tcplog' ], - 'tcp-check' => ["connect port ${ports[metrics_qdr_port]}"], - }, - collect_exported => false, + if $use_backend_syntax { + haproxy::frontend { 'metrics_qdr': + bind => $metrics_bind_opts, + options => { 'default_backend' => 'metrics_qdr_be' }, + collect_exported => false, + } + haproxy::backend { 'metrics_qdr_be': + options => { + 'option' => [ 'tcp-check', 'tcplog' ], + 'tcp-check' => ["connect port ${ports[metrics_qdr_port]}"], + }, + } + $metrics_qdr_service = 'metrics_qdr_be' + } else { + haproxy::listen { 'metrics_qdr': + bind => $metrics_bind_opts, + options => { + 'option' => [ 'tcp-check', 'tcplog' ], + 'tcp-check' => ["connect port ${ports[metrics_qdr_port]}"], + }, + collect_exported => false, + } + $metrics_qdr_service = 'metrics_qdr' } # Note(mmagr): while MetricsQdr service runs on all overcloud nodes, we need load balancing # only on controllers as those are only QDRs forming mesh (listening on connection @@ -1321,7 +1478,7 @@ class tripleo::haproxy ( # MetricsQdr will be refactored (split to QDR running on controller or on other node) # to better integrate, but for now we need this hack to enable the feature haproxy::balancermember { 'metrics_qdr': - listening_service => 'metrics_qdr', + listening_service => $metrics_qdr_service, ports => $ports[metrics_qdr_port], ipaddresses => hiera('pacemaker_node_ips', $controller_hosts_real), server_names => hiera('pacemaker_node_names', $controller_hosts_names_real), @@ -1331,25 +1488,34 @@ class tripleo::haproxy ( } if $mysql_clustercheck { - $mysql_listen_options = { - 'option' => [ 'tcpka', 'httpchk', 'tcplog' ], + $mysql_frontend_opts = { + 'option' => [ 'tcpka', 'tcplog' ], 'timeout client' => '90m', - 'timeout server' => '90m', - 'stick-table' => 'type ip size 1000', - 'stick' => 'on dst', 'maxconn' => $mysql_max_conn } + $mysql_backend_opts = { + 'option' => [ 'tcpka', 'httpchk' ], + 'stick-table' => 'type ip size 1000', + 'stick' => 'on dst', + 'timeout server' => '90m', + } + $mysql_listen_opts = merge_hash_values($mysql_frontend_opts, + $mysql_backend_opts) if $mysql_member_options { $mysql_member_options_real = $mysql_member_options } else { $mysql_member_options_real = ['backup', 'port 9200', 'on-marked-down shutdown-sessions', 'check', 'inter 1s'] } } else { - $mysql_listen_options = { + $mysql_frontend_opts = { 'timeout client' => '90m', - 'timeout server' => '90m', 'maxconn' => $mysql_max_conn } + $mysql_backend_opts = { + 'timeout server' => '90m', + } + $mysql_listen_opts = merge_hash_values($mysql_frontend_opts, + $mysql_backend_opts) if $mysql_member_options { $mysql_member_options_real = $mysql_member_options } else { @@ -1363,13 +1529,28 @@ class tripleo::haproxy ( } else { $mysql_server_names_real = hiera('mysql_node_names', $controller_hosts_names_real) } - haproxy::listen { 'mysql': - bind => $mysql_bind_opts, - options => deep_merge($mysql_listen_options, $mysql_custom_listen_options), - collect_exported => false, + if $use_backend_syntax { + haproxy::frontend { 'mysql': + bind => $mysql_bind_opts, + options => deep_merge($mysql_frontend_opts, + { 'default_backend' => 'mysql_be' }, + $mysql_custom_frontend_options), + collect_exported => false, + } + haproxy::backend { 'mysql_be': + options => deep_merge($mysql_backend_opts, $mysql_custom_backend_options), + } + $mysql_service = 'mysql_be' + } else { + haproxy::listen { 'mysql': + bind => $mysql_bind_opts, + options => deep_merge($mysql_listen_opts, $mysql_custom_listen_options), + collect_exported => false, + } + $mysql_service = 'mysql' } haproxy::balancermember { 'mysql-backup': - listening_service => 'mysql', + listening_service => $mysql_service, ports => '3306', ipaddresses => hiera('mysql_node_ips', $controller_hosts_real), server_names => $mysql_server_names_real, @@ -1387,16 +1568,31 @@ class tripleo::haproxy ( } if $rabbitmq { - haproxy::listen { 'rabbitmq': - bind => $rabbitmq_bind_opts, - options => { - 'option' => [ 'tcpka', 'tcplog' ], - 'timeout' => [ 'client 0', 'server 0' ], - }, - collect_exported => false, + if $use_backend_syntax { + haproxy::frontend { 'rabbitmq': + bind => $rabbitmq_bind_opts, + collect_exported => false, + } + haproxy::backend { 'rabbitmq_be': + options => { + 'option' => [ 'tcpka', 'tcplog' ], + 'timeout' => [ 'client 0', 'server 0' ], + }, + } + $rabbitmq_service = 'rabbitmq_be' + } else { + haproxy::listen { 'rabbitmq': + bind => $rabbitmq_bind_opts, + options => { + 'option' => [ 'tcpka', 'tcplog' ], + 'timeout' => [ 'client 0', 'server 0' ], + }, + collect_exported => false, + } + $rabbitmq_service = 'rabbitmq' } haproxy::balancermember { 'rabbitmq': - listening_service => 'rabbitmq', + listening_service => $rabbitmq_service, ports => '5672', ipaddresses => hiera('rabbitmq_node_ips', $controller_hosts_real), server_names => hiera('rabbitmq_node_names', $controller_hosts_names_real), @@ -1414,6 +1610,9 @@ class tripleo::haproxy ( member_options => union($haproxy_member_options, $internal_tls_member_options), listen_options => { 'balance' => 'source', + }, + backend_options => { + 'balance' => 'source', } } } @@ -1457,17 +1656,33 @@ class tripleo::haproxy ( 'send QUIT\r\n', 'expect string +OK'] $redis_tcp_check_options = $redis_tcp_check_connect_options + $redis_tcp_check_common_options - haproxy::listen { 'redis': - bind => $redis_bind_opts, - options => { - 'balance' => 'first', - 'option' => [ 'tcp-check', 'tcplog', ], - 'tcp-check' => $redis_tcp_check_options, - }, - collect_exported => false, + if $use_backend_syntax { + haproxy::frontend { 'redis': + bind => $redis_bind_opts, + collect_exported => false, + } + haproxy::backend { 'redis_be': + options => { + 'balance' => 'first', + 'option' => [ 'tcp-check', 'tcplog', ], + 'tcp-check' => $redis_tcp_check_options, + }, + } + $redis_service = 'redis_be' + } else { + haproxy::listen { 'redis': + bind => $redis_bind_opts, + options => { + 'balance' => 'first', + 'option' => [ 'tcp-check', 'tcplog', ], + 'tcp-check' => $redis_tcp_check_options, + }, + collect_exported => false, + } + $redis_service = 'redis' } haproxy::balancermember { 'redis': - listening_service => 'redis', + listening_service => $redis_service, ports => '6379', ipaddresses => hiera('redis_node_ips', $controller_hosts_real), server_names => hiera('redis_node_names', $controller_hosts_names_real), @@ -1501,6 +1716,12 @@ class tripleo::haproxy ( } if $ceph_rgw { + $ceph_rgw_backend_opts = { + 'option' => [ 'httpchk GET /swift/healthcheck' ], + 'balance' => $haproxy_lb_mode_longrunning + } + $ceph_rgw_listen_opts = merge_hash_values($default_frontend_options, + $ceph_rgw_backend_opts) ::tripleo::haproxy::endpoint { 'ceph_rgw': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('ceph_rgw_vip', $controller_virtual_ip), @@ -1510,21 +1731,24 @@ class tripleo::haproxy ( mode => 'http', public_ssl_port => $ports[ceph_rgw_ssl_port], service_network => $ceph_rgw_network, - listen_options => merge($default_listen_options, { - 'option' => [ 'httpchk GET /swift/healthcheck', 'httplog' ], - 'balance' => $haproxy_lb_mode_longrunning - } - ), + listen_options => merge($default_listen_options, $ceph_rgw_listen_opts), + frontend_options => $default_frontend_options, + backend_options => merge($default_backend_options, $ceph_rgw_backend_opts), member_options => union($haproxy_member_options, $internal_tls_member_options), } } if $octavia { - $octavia_listen_opts = { + $octavia_frontend_opts = { + 'option' => [ 'httplog' ], + } + $octavia_backend_opts = { 'hash-type' => 'consistent', 'option' => [ 'httpchk GET /healthcheck', 'httplog' ], 'balance' => 'source', } + $octavia_listen_opts = merge_hash_values($octavia_frontend_opts, + $octavia_backend_opts) ::tripleo::haproxy::endpoint { 'octavia': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('octavia_api_vip', $controller_virtual_ip), @@ -1536,6 +1760,8 @@ class tripleo::haproxy ( mode => 'http', member_options => union($haproxy_member_options, $internal_tls_member_options), listen_options => merge($default_listen_options, $octavia_listen_opts), + frontend_options => merge($default_frontend_options, $octavia_frontend_opts), + backend_options => $octavia_backend_opts, } } @@ -1545,13 +1771,17 @@ class tripleo::haproxy ( # We only configure ovn_dbs_vip in haproxy if HA for OVN DB servers is # disabled. # If HA is enabled, pacemaker configures the OVN DB servers accordingly. - $ovn_db_listen_options = { + $ovn_db_frontend_opts = { 'option' => [ 'tcpka', 'tcplog' ], 'timeout client' => '90m', + } + $ovn_db_backend_opts = { 'timeout server' => '90m', 'stick-table' => 'type ip size 1000', 'stick' => 'on dst', } + $ovn_db_listen_opts = merge_hash_values($ovn_db_frontend_opts, + $ovn_db_backend_opts) ::tripleo::haproxy::endpoint { 'ovn_nbdb': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('ovn_dbs_vip', $controller_virtual_ip), @@ -1560,7 +1790,9 @@ class tripleo::haproxy ( server_names => hiera('ovn_dbs_node_names', $controller_hosts_names_real), service_network => $ovn_dbs_network, public_ssl_port => $ports[ovn_nbdb_ssl_port], - listen_options => $ovn_db_listen_options, + listen_options => $ovn_db_listen_opts, + frontend_options => $ovn_db_frontend_opts, + backend_options => $ovn_db_backend_opts, mode => 'tcp' } ::tripleo::haproxy::endpoint { 'ovn_sbdb': @@ -1571,12 +1803,29 @@ class tripleo::haproxy ( server_names => hiera('ovn_dbs_node_names', $controller_hosts_names_real), service_network => $ovn_dbs_network, public_ssl_port => $ports[ovn_sbdb_ssl_port], - listen_options => $ovn_db_listen_options, + listen_options => $ovn_db_listen_opts, + frontend_options => $ovn_db_frontend_opts, + backend_options => $ovn_db_backend_opts, mode => 'tcp' } } if $zaqar_ws { + $zaqar_ws_frontend_opts = { + # NOTE(jaosorior): Websockets have more overhead in establishing + # connections than regular HTTP connections. Also, since it begins + # as an HTTP connection and then "upgrades" to a TCP connection, some + # timeouts get overridden by others at certain times of the connection. + # The following values were taken from the following site: + # http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/ + 'timeout' => ['connect 5s', 'client 25s'], + 'http-request' => [join(['set-header Host %[dst]:', $ports[zaqar_ws_port]])], + } + $zaqar_ws_backend_opts = { + 'timeout' => ['server 25s', regsubst('tunnel Xs', 'X', $zaqar_ws_timeout_tunnel)], + } + $zaqar_ws_listen_opts = merge_hash_values($zaqar_ws_frontend_opts, + $zaqar_ws_backend_opts) ::tripleo::haproxy::endpoint { 'zaqar_ws': public_virtual_ip => $public_virtual_ip, internal_ip => hiera('zaqar_ws_vip', $controller_virtual_ip), @@ -1585,16 +1834,9 @@ class tripleo::haproxy ( server_names => hiera('zaqar_ws_node_names', $controller_hosts_names_real), mode => 'http', haproxy_listen_bind_param => [], # We don't use a transparent proxy here - listen_options => { - # NOTE(jaosorior): Websockets have more overhead in establishing - # connections than regular HTTP connections. Also, since it begins - # as an HTTP connection and then "upgrades" to a TCP connection, some - # timeouts get overridden by others at certain times of the connection. - # The following values were taken from the following site: - # http://blog.haproxy.com/2012/11/07/websockets-load-balancing-with-haproxy/ - 'timeout' => ['connect 5s', 'client 25s', 'server 25s', regsubst('tunnel Xs', 'X', $zaqar_ws_timeout_tunnel)], - 'http-request' => [join(['set-header Host %[dst]:', $ports[zaqar_ws_port]])], - }, + listen_options => $zaqar_ws_listen_opts, + frontend_options => $zaqar_ws_frontend_opts, + backend_options => $zaqar_ws_backend_opts, public_ssl_port => $ports[zaqar_ws_ssl_port], service_network => $zaqar_api_network, } diff --git a/manifests/haproxy/endpoint.pp b/manifests/haproxy/endpoint.pp index 46682fd13..68790b6e6 100644 --- a/manifests/haproxy/endpoint.pp +++ b/manifests/haproxy/endpoint.pp @@ -28,6 +28,11 @@ # Options for the balancer member, specified after the server declaration. # These should go in the member's configuration block. # +# [*use_backend_syntax*] +# (optional) When set to true, generate a config with frontend and +# backend sections, otherwise use listen sections. +# Defaults to hiera('haproxy_backend_syntax', false) +# # [*haproxy_port*] # An alternative port, on which haproxy will listen for incoming requests. # Defaults to service_port. @@ -65,6 +70,14 @@ # HAproxy terms, the frontend). # defaults to {'option' => []} # +# [*frontend_options*] +# Options specified for the frontend service's configuration block +# defaults to {'option' => []} +# +# [*backend_options*] +# Options specified for the service's backend configuration block +# defaults to {'option' => []} +# # [*public_ssl_port*] # The port used for the public proxy endpoint if it differs from the default # one. This is used only if SSL is enabled, and it's used in order to avoid @@ -119,6 +132,7 @@ define tripleo::haproxy::endpoint ( $internal_ip, $service_port, $member_options, + $use_backend_syntax = hiera('haproxy_backend_syntax', false), $haproxy_port = undef, $base_service_name = undef, $ip_addresses = hiera("${name}_node_ips", undef), @@ -129,6 +143,12 @@ define tripleo::haproxy::endpoint ( $listen_options = { 'option' => [], }, + $frontend_options = { + 'option' => [], + }, + $backend_options = { + 'option' => [], + }, $public_ssl_port = undef, $public_certificate = undef, $use_internal_certificates = false, @@ -160,6 +180,8 @@ define tripleo::haproxy::endpoint ( } # Let users override the options on a per-service basis $custom_options = hiera("tripleo::haproxy::${name}::options", undef) + $custom_frontend_options = hiera("tripleo::haproxy::${name}::frontend_options", undef) + $custom_backend_options = hiera("tripleo::haproxy::${name}::backend_options", undef) $custom_bind_options_public = delete(any2array(hiera("tripleo::haproxy::${name}::public_bind_options", undef)), undef).flatten() $custom_bind_options_internal = delete(any2array(hiera("tripleo::haproxy::${name}::internal_bind_options", undef)), undef).flatten() if $public_virtual_ip { @@ -173,13 +195,16 @@ define tripleo::haproxy::endpoint ( 'option' => 'forwardfor', } $listen_options_precookie = merge($tls_listen_options, $listen_options, $custom_options) + $frontend_options_precookie = merge($tls_listen_options, $frontend_options, $custom_frontend_options) } else { $listen_options_precookie = merge($listen_options, $custom_options) + $frontend_options_precookie = merge($frontend_options, $custom_frontend_options) } $public_bind_opts = list_to_hash(suffix(any2array($public_virtual_ip), ":${public_ssl_port}"), union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate], $custom_bind_options_public)) } else { $listen_options_precookie = merge($listen_options, $custom_options) + $frontend_options_precookie = merge($frontend_options, $custom_frontend_options) $public_bind_opts = list_to_hash(suffix(any2array($public_virtual_ip), ":${haproxy_port_real}"), union($haproxy_listen_bind_param, $custom_bind_options_public)) } @@ -187,14 +212,17 @@ define tripleo::haproxy::endpoint ( # internal service only $public_bind_opts = {} $listen_options_precookie = merge($listen_options, $custom_options) + $frontend_options_precookie = merge($frontend_options, $custom_frontend_options) } if $sticky_sessions { $cookie_options = { 'cookie' => "${session_cookie} insert indirect nocache", } $listen_options_real = merge($listen_options_precookie, $cookie_options) + $frontend_options_real = merge($frontend_options_precookie, $cookie_options) } else { $listen_options_real = $listen_options_precookie + $frontend_options_real = $frontend_options_precookie } if $use_internal_certificates { if !$service_network { @@ -231,22 +259,45 @@ define tripleo::haproxy::endpoint ( 'acl' => "acl Auth${name} http_auth(${authorized_userlist})", 'http-request' => "auth realm ${name} if !Auth${name}", } - Haproxy::Listen[$name] { - require => Tripleo::Haproxy::Userlist[$authorized_userlist], + if $use_backend_syntax { + Haproxy::Frontend[$name] { + require => Tripleo::Haproxy::Userlist[$authorized_userlist], + } + } else { + Haproxy::Listen[$name] { + require => Tripleo::Haproxy::Userlist[$authorized_userlist], + } } } else { $access_rules = {} } $_real_options = merge($listen_options_real, $access_rules) + $_real_frontend_options = merge($frontend_options_real, $access_rules, + { 'default_backend' => "${name}_be" }) $bind_opts = merge($internal_bind_opts, $public_bind_opts) - haproxy::listen { "${name}": - bind => $bind_opts, - collect_exported => false, - mode => $mode, - options => $_real_options, + if $use_backend_syntax { + haproxy::frontend { "${name}": + bind => $bind_opts, + collect_exported => false, + mode => $mode, + options => $_real_frontend_options, + } + haproxy::backend { "${name}_be": + mode => $mode, + options => merge($backend_options, $custom_backend_options), + } + $listening_service = "${name}_be" + } else { + haproxy::listen { "${name}": + bind => $bind_opts, + collect_exported => false, + mode => $mode, + options => $_real_options, + } + $listening_service = "${name}" } if $sticky_sessions { hash(zip($ip_addresses_real, $server_names_real)).each | $ip, $server | { @@ -254,7 +305,7 @@ define tripleo::haproxy::endpoint ( # which is a reserved character to reference manifests $non_colon_ip = regsubst($ip, ':', '-', 'G') haproxy::balancermember { "${name}_${non_colon_ip}_${server}": - listening_service => $name, + listening_service => $listening_service, ports => $service_port_real, ipaddresses => $ip, server_names => $server, @@ -263,7 +314,7 @@ define tripleo::haproxy::endpoint ( } } else { haproxy::balancermember { "${name}": - listening_service => $name, + listening_service => $listening_service, ports => $service_port_real, ipaddresses => $ip_addresses_real, server_names => $server_names_real, diff --git a/manifests/haproxy/horizon_endpoint.pp b/manifests/haproxy/horizon_endpoint.pp index 05e5d20cb..43f2acf34 100644 --- a/manifests/haproxy/horizon_endpoint.pp +++ b/manifests/haproxy/horizon_endpoint.pp @@ -36,6 +36,11 @@ # If this service is internal only this should be ommitted. # Defaults to undef. # +# [*use_backend_syntax*] +# (optional) When set to true, generate a config with frontend and +# backend sections, otherwise use listen sections. +# Defaults to hiera('haproxy_backend_syntax', false) +# # [*haproxy_listen_bind_param*] # A list of params to be added to the HAProxy listener bind directive. # Defaults to undef. @@ -77,6 +82,7 @@ class tripleo::haproxy::horizon_endpoint ( $server_names, $member_options, $public_virtual_ip, + $use_backend_syntax = hiera('haproxy_backend_syntax', false), $haproxy_listen_bind_param = undef, $public_certificate = undef, $use_internal_certificates = false, @@ -86,6 +92,8 @@ class tripleo::haproxy::horizon_endpoint ( ) { # Let users override the options on a per-service basis $custom_options = hiera('tripleo::haproxy::horizon::options', undef) + $custom_frontend_options = hiera('tripleo::haproxy::horizon::frontend_options', undef) + $custom_backend_options = hiera('tripleo::haproxy::horizon::backend_options', undef) $custom_bind_options_public = delete(any2array(hiera('tripleo::haproxy::horizon::public_bind_options', undef)), undef).flatten() $custom_bind_options_internal = delete(any2array(hiera('tripleo::haproxy::horizon::internal_bind_options', undef)), undef).flatten() # service exposed to the public network @@ -120,26 +128,30 @@ class tripleo::haproxy::horizon_endpoint ( "${public_virtual_ip}:80" => union($haproxy_listen_bind_param, $custom_bind_options_public), "${public_virtual_ip}:443" => union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate], $custom_bind_options_public), } - $horizon_options = merge({ - 'cookie' => 'SERVERID insert indirect nocache', + $horizon_frontend_options = { 'rsprep' => '^Location:\ http://(.*) Location:\ https://\1', # NOTE(jaosorior): We always redirect to https for the public_virtual_ip. 'redirect' => 'scheme https code 301 if !{ ssl_fc }', - 'option' => [ 'forwardfor', 'httpchk' ], + 'option' => [ 'forwardfor' ], 'http-request' => [ 'set-header X-Forwarded-Proto https if { ssl_fc }', 'set-header X-Forwarded-Proto http if !{ ssl_fc }'], - }, $custom_options) + } } else { $horizon_bind_opts = { "${internal_ip}:80" => union($haproxy_listen_bind_param, $custom_bind_options_internal), "${public_virtual_ip}:80" => union($haproxy_listen_bind_param, $custom_bind_options_public), } - $horizon_options = merge({ - 'cookie' => 'SERVERID insert indirect nocache', - 'option' => [ 'forwardfor', 'httpchk' ], - }, $custom_options) + $horizon_frontend_options = { + 'option' => [ 'forwardfor' ], + } } + $horizon_backend_options = { + 'cookie' => 'SERVERID insert indirect nocache', + 'option' => [ 'httpchk' ], + } + $horizon_options = merge_hash_values($horizon_backend_options, + $horizon_frontend_options) if $use_internal_certificates { # Use SSL port if TLS in the internal network is enabled. @@ -148,18 +160,33 @@ class tripleo::haproxy::horizon_endpoint ( $backend_port = '80' } - haproxy::listen { 'horizon': - bind => $horizon_bind_opts, - options => $horizon_options, - mode => 'http', - collect_exported => false, + if $use_backend_syntax { + haproxy::frontend { 'horizon': + bind => $horizon_bind_opts, + options => merge($horizon_frontend_options, + { default_backend => 'horizon_be' }, + $custom_frontend_options), + mode => 'http', + collect_exported => false, + } + haproxy::backend { 'horizon_be': + options => merge($horizon_backend_options, $custom_backend_options), + mode => 'http', + } + } else { + haproxy::listen { 'horizon': + bind => $horizon_bind_opts, + options => merge($horizon_options, $custom_options), + mode => 'http', + collect_exported => false, + } } hash(zip($ip_addresses, $server_names)).each | $ip, $server | { # We need to be sure the IP (IPv6) don't have colons # which is a reserved character to reference manifests $non_colon_ip = regsubst($ip, ':', '-', 'G') haproxy::balancermember { "horizon_${non_colon_ip}_${server}": - listening_service => 'horizon', + listening_service => 'horizon_be', ports => $backend_port, ipaddresses => $ip, server_names => $server, diff --git a/manifests/haproxy/stats.pp b/manifests/haproxy/stats.pp index d6526b48c..0ce55404d 100644 --- a/manifests/haproxy/stats.pp +++ b/manifests/haproxy/stats.pp @@ -24,6 +24,11 @@ # IP Address(es) on which the stats interface is listening on. # Can be a string or a list of ip addresses # +# [*use_backend_syntax*] +# (optional) When set to true, generate a config with frontend and +# backend sections, otherwise use listen sections. +# Defaults to hiera('haproxy_backend_syntax', false) +# # [*port*] # Port on which to listen to for haproxy stats web interface # Defaults to '1993' @@ -47,6 +52,7 @@ class tripleo::haproxy::stats ( $haproxy_listen_bind_param, $ip, + $use_backend_syntax = hiera('haproxy_backend_syntax', false), $port = '1993', $password = undef, $certificate = undef, @@ -66,12 +72,29 @@ class tripleo::haproxy::stats ( } else { $stats_config = $stats_base } - haproxy::listen { 'haproxy.stats': - bind => $haproxy_stats_bind_opts, - mode => 'http', - options => { - 'stats' => $stats_config, - }, - collect_exported => false, + if $use_backend_syntax { + haproxy::frontend { 'haproxy.stats': + bind => $haproxy_stats_bind_opts, + mode => 'http', + options => { + 'stats' => $stats_config, + }, + collect_exported => false, + } + haproxy::backend { 'haproxy.stats_be': + mode => 'http', + options => { + 'stats' => $stats_config, + }, + } + } else { + haproxy::listen { 'haproxy.stats': + bind => $haproxy_stats_bind_opts, + mode => 'http', + options => { + 'stats' => $stats_config, + }, + collect_exported => false, + } } } diff --git a/releasenotes/notes/haproxy-frontend-backend-e3719b323e84fd2c.yaml b/releasenotes/notes/haproxy-frontend-backend-e3719b323e84fd2c.yaml new file mode 100644 index 000000000..767d7daba --- /dev/null +++ b/releasenotes/notes/haproxy-frontend-backend-e3719b323e84fd2c.yaml @@ -0,0 +1,12 @@ +--- +features: + - | + Haproxy configuration file can now use the frontend and backend + keywords to describe a service, rather than using the listen + keyword. The new format can be enabled via hiera parameter + `haproxy_backend_syntax`. When enabled, any frontend or backend + configuration can be overriden on a per service-basis via new + hiera keys `tripleo::haproxy::::frontend_options` and + `tripleo::haproxy::::frontend_options`. The original + hiera key `tripleo::haproxy::::options` has no effect + on the frontend and backend sections. diff --git a/spec/defines/tripleo_haproxy_endpoint_spec.rb b/spec/defines/tripleo_haproxy_endpoint_spec.rb index bcca6a44d..6e12fb76f 100644 --- a/spec/defines/tripleo_haproxy_endpoint_spec.rb +++ b/spec/defines/tripleo_haproxy_endpoint_spec.rb @@ -75,6 +75,31 @@ describe 'tripleo::haproxy::endpoint' do ) end end + + context 'with frontend/backend sections' do + before :each do + params.merge!({ + :use_backend_syntax => true, + }) + end + it 'should configure haproxy' do + is_expected.to compile.with_all_deps + is_expected.to contain_haproxy__frontend('neutron').with( + :collect_exported => false, + :bind => { "10.0.0.1:9696" => ["transparent"], + "192.168.0.1:9696" => ["transparent"] }, + :options => {'option' => [], + 'timeout client' => '90m', + 'default_backend' => 'neutron_be', + }, + ) + is_expected.to contain_haproxy__backend('neutron_be').with( + :options => {'option' => [], + 'timeout server' => '90m', + }, + ) + end + end end on_supported_os.each do |os, facts| diff --git a/spec/fixtures/hieradata/default.yaml b/spec/fixtures/hieradata/default.yaml index 75a77cdd2..cce31af8a 100644 --- a/spec/fixtures/hieradata/default.yaml +++ b/spec/fixtures/hieradata/default.yaml @@ -202,6 +202,10 @@ tripleo::dynamic_stuff::haproxy_endpoints: tripleo::haproxy::neutron::options: 'timeout client': '90m' 'timeout server': '90m' +tripleo::haproxy::neutron::frontend_options: + 'timeout client': '90m' +tripleo::haproxy::neutron::backend_options: + 'timeout server': '90m' tripleo::haproxy_basic_auth::haproxy_endpoints: starwars: