diff --git a/changelogs/unreleased/repmgr-guardrails.yml b/changelogs/unreleased/repmgr-guardrails.yml new file mode 100644 index 0000000000000000000000000000000000000000..0bafcd45e84e85379fe2f82acb458a96afcc1b29 --- /dev/null +++ b/changelogs/unreleased/repmgr-guardrails.yml @@ -0,0 +1,5 @@ +--- +title: Switch to enabling patroni by default with new patroni role +merge_request: 4851 +author: +type: changed diff --git a/doc/roles/README.md b/doc/roles/README.md index 052dc4a47d6cdb20af0e3108c0f4b9d783844d98..47b8f5609e45b9e6fc3c80a7201be27e149f0c86 100644 --- a/doc/roles/README.md +++ b/doc/roles/README.md @@ -113,6 +113,12 @@ Documentation on the usage of the PostgreSQL Roles can be found in [Configuring *By default, enables no other services.* +- **patroni_role** (`gitlab-ee`) + + Enables the PostgreSQL, patroni, and Consul services on the machine + + *By default, enables no other services.* + - **pgbouncer_role** (`gitlab-ee`) Enables the PgBouncer and Consul services on the machine diff --git a/files/gitlab-cookbooks/consul/libraries/consul_helper.rb b/files/gitlab-cookbooks/consul/libraries/consul_helper.rb index 85ee1c480f6aada21972fba5f17b43f21e0a234a..0b6ecbb539dee68a7918b1201d5530798497b4cd 100644 --- a/files/gitlab-cookbooks/consul/libraries/consul_helper.rb +++ b/files/gitlab-cookbooks/consul/libraries/consul_helper.rb @@ -102,8 +102,8 @@ class ConsulHelper end def postgresql_ha_solution - return 'repmgr' unless Gitlab['patroni']['enable'] - return 'patroni_standby_cluster' if Gitlab['patroni'].key?('standby_cluster') && Gitlab['patroni']['standby_cluster']['enable'] + return 'repmgr' unless node['patroni']['enable'] + return 'patroni_standby_cluster' if node['patroni'].key?('standby_cluster') && node['patroni']['standby_cluster']['enable'] 'patroni' end diff --git a/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb b/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb index cd4b8e0ccd1e4ece6b911a48130bdc73f82e99c7..b0a7cc2f551f869a9e2d8d95766d836f2dc65695 100644 --- a/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb +++ b/files/gitlab-cookbooks/gitlab/libraries/helpers/base_pg_helper.rb @@ -291,15 +291,15 @@ class BasePgHelper < BaseHelper # When Patroni is enabled, the configuration of PostgreSQL instance must be delegated to it. # PostgreSQL cookbook skips some of the steps that are must be done either during or after # Patroni bootstraping. - Gitlab['patroni']['enable'] && !Gitlab['repmgr']['enable'] + node['patroni']['enable'] && !Gitlab['repmgr']['enable'] end def config_dir - Gitlab['patroni']['enable'] ? node['patroni']['data_dir'] : node['postgresql']['data_dir'] + node['patroni']['enable'] ? node['patroni']['data_dir'] : node['postgresql']['data_dir'] end def postgresql_config - ::File.join(config_dir, "postgresql#{Gitlab['patroni']['enable'] ? '.base' : ''}.conf") + ::File.join(config_dir, "postgresql#{node['patroni']['enable'] ? '.base' : ''}.conf") end def postgresql_runtime_config diff --git a/files/gitlab-cookbooks/gitlab/recipes/default.rb b/files/gitlab-cookbooks/gitlab/recipes/default.rb index 5e76c9ead1f59d660f987c62bd82f7d48508729b..93ad661b7a7e885e4656990bedc3d370431bdcba 100644 --- a/files/gitlab-cookbooks/gitlab/recipes/default.rb +++ b/files/gitlab-cookbooks/gitlab/recipes/default.rb @@ -29,6 +29,10 @@ OmnibusHelper.check_deprecations OmnibusHelper.check_environment OmnibusHelper.check_locale +# Setup additional postgresql attributes +include_recipe 'postgresql::directory_locations' +OmnibusHelper.new(node).check_invalid_pg_ha + directory "/etc/gitlab" do owner "root" group "root" diff --git a/files/gitlab-cookbooks/package/libraries/config/gitlab.rb b/files/gitlab-cookbooks/package/libraries/config/gitlab.rb index e32148dc3aaaf32c2a045d98ba9a8b1d13c665f9..d3a0e2fe4e4e908669b2aa80da254a1168c5a50e 100644 --- a/files/gitlab-cookbooks/package/libraries/config/gitlab.rb +++ b/files/gitlab-cookbooks/package/libraries/config/gitlab.rb @@ -38,6 +38,7 @@ module Gitlab role('monitoring').use { MonitoringRole } role('postgres').use { PostgresRole } role('pgbouncer').use { PgbouncerRole } + role('patroni').use { PatroniRole } role('consul').use { ConsulRole } role('pages').use { PagesRole } diff --git a/files/gitlab-cookbooks/package/libraries/config/roles/patroni.rb b/files/gitlab-cookbooks/package/libraries/config/roles/patroni.rb new file mode 100644 index 0000000000000000000000000000000000000000..5d4ad09ee8e3fd362eeb5cdd80d1f336fcaca247 --- /dev/null +++ b/files/gitlab-cookbooks/package/libraries/config/roles/patroni.rb @@ -0,0 +1,23 @@ +# Copyright:: Copyright (c) 2021 GitLab Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module PatroniRole + def self.load_role + return unless Gitlab['patroni_role']['enable'] + + Services.enable_group('patroni_role') + end +end diff --git a/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb b/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb index a63efbcf30748d2d646de294e25def2160ee7f18..d285e5645b3c5e39cb302b7e1aa3514b017d6dd4 100644 --- a/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb +++ b/files/gitlab-cookbooks/package/libraries/config/roles/postgres.rb @@ -18,7 +18,7 @@ module PostgresRole def self.load_role return unless Gitlab['postgres_role']['enable'] - Gitlab['repmgr']['enable'] = true if !Gitlab['patroni']['enable'] && Gitlab['repmgr']['enable'].nil? + Gitlab['repmgr']['enable'] = true if !Gitlab['patroni']['enable'] && !Gitlab['patroni_role']['enable'] && Gitlab['repmgr']['enable'].nil? Services.enable_group('postgres_role') end end diff --git a/files/gitlab-cookbooks/package/libraries/config/services.rb b/files/gitlab-cookbooks/package/libraries/config/services.rb index 88bc36f2ba04922bad097e95af4f5f1ce44c6434..9fecb30bc2815cb3f5e33a7ca5ace804d33466db 100644 --- a/files/gitlab-cookbooks/package/libraries/config/services.rb +++ b/files/gitlab-cookbooks/package/libraries/config/services.rb @@ -29,11 +29,11 @@ module Services service 'gitaly', groups: [DEFAULT_GROUP, 'rails'] service 'redis', groups: [DEFAULT_GROUP, 'redis', 'redis_node'] service 'redis_exporter', groups: [DEFAULT_GROUP, 'redis', 'redis_node', 'monitoring'] - service 'postgresql', groups: [DEFAULT_GROUP, 'postgres', 'postgres_role'] + service 'postgresql', groups: [DEFAULT_GROUP, 'postgres', 'postgres_role', 'patroni_role'] service 'nginx', groups: [DEFAULT_GROUP, 'pages_role'] service 'prometheus', groups: [DEFAULT_GROUP, 'monitoring', 'monitoring_role'] service 'alertmanager', groups: [DEFAULT_GROUP, 'monitoring', 'monitoring_role'] - service 'postgres_exporter', groups: [DEFAULT_GROUP, 'monitoring', 'postgres', 'postgres_role'] + service 'postgres_exporter', groups: [DEFAULT_GROUP, 'monitoring', 'postgres', 'postgres_role', 'patroni_role'] service 'grafana', groups: [DEFAULT_GROUP, 'monitoring', 'monitoring_role'] service 'gitlab_pages', groups: ['pages_role'] service 'mailroom' @@ -55,8 +55,8 @@ module Services service 'pgbouncer', groups: %w(postgres pgbouncer_role) service 'pgbouncer_exporter', groups: %w(pgbouncer_role) service 'repmgrd', groups: %w(postgres postgres_role) - service 'patroni', groups: %w(postgres) - service 'consul', groups: %w(consul_role ha pgbouncer_role postgres_role) + service 'patroni', groups: %w(postgres patroni_role) + service 'consul', groups: %w(consul_role ha pgbouncer_role postgres_role patroni_role) service 'sidekiq_cluster', groups: ['sidekiq'] end end diff --git a/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb b/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb index c39df04a4cbe6fb698cf3dc6e91c0569d185302b..4290fc0e00373a3011f1bff3909c83cc85fd867f 100644 --- a/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb +++ b/files/gitlab-cookbooks/package/libraries/omnibus_helper.rb @@ -103,6 +103,21 @@ class OmnibusHelper LoggingHelper.note(msg) end + def check_invalid_pg_ha + return unless Services.enabled?('repmgr') && Services.enabled?('repmgrd') + + geo_pg_helper = GeoPgHelper.new(node) + pg_helper = PgHelper.new(node) + + main_db_version = pg_helper.database_version if Services.enabled?('postgresql') + geo_db_version = geo_pg_helper.database_version if Services.enabled?('geo_postgresql') + db_version = node['postgresql']['version'] || main_db_version || geo_db_version + + return unless db_version.nil? || db_version.to_f >= 12 + + raise 'The included Repmgr is not supported on PostgreSQL 12, please use Patroni: https://docs.gitlab.com/ee/administration/postgresql/replication_and_failover.html' + end + def self.utf8_variable?(var) ENV[var]&.downcase&.include?('utf-8') || ENV[var]&.downcase&.include?('utf8') end diff --git a/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb b/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb index 9015c36efebc5b760876695a5f8dc8b2fa595efb..5b24855a6eb4c452dca01d3b57ca4341372a7b40 100644 --- a/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb +++ b/files/gitlab-cookbooks/patroni/libraries/patroni_helper.rb @@ -77,7 +77,7 @@ class PatroniHelper < BaseHelper end def public_attributes - return {} unless Gitlab['patroni']['enable'] + return {} unless node['patroni']['enable'] { 'patroni' => { diff --git a/spec/chef/patroni/recipes/patroni_spec.rb b/spec/chef/patroni/recipes/patroni_spec.rb index 32a9d0dc2dba6e6dfffd843a8437b0920c41e22f..1668feb6a6a7694c59c52a9d10b7f26f73b65025 100644 --- a/spec/chef/patroni/recipes/patroni_spec.rb +++ b/spec/chef/patroni/recipes/patroni_spec.rb @@ -14,10 +14,46 @@ RSpec.describe 'patroni cookbook' do expect(chef_run).to include_recipe('patroni::disable') end + context 'when postgres_role is enabled' do + before do + stub_gitlab_rb(roles: %w(postgres_role)) + end + + it 'should be disabled while repmgr is enabled' do + expect(chef_run).to include_recipe('repmgr::enable') + expect(chef_run).to include_recipe('patroni::disable') + end + end + + context 'when patroni_role is enabled' do + before do + stub_gitlab_rb(roles: %w(patroni_role)) + end + + it 'should be enabled while repmgr is disabled' do + expect(chef_run).to include_recipe('repmgr::disable') + expect(chef_run).to include_recipe('patroni::enable') + end + end + + context 'when patroni_role and postgres_role is enabled' do + before do + stub_gitlab_rb(roles: %w(postgres_role patroni_role)) + end + + it 'should be enabled while repmgr is disabled' do + expect(chef_run).to include_recipe('repmgr::disable') + expect(chef_run).to include_recipe('patroni::enable') + end + end + context 'when repmgr is enabled' do before do stub_gitlab_rb( - roles: %w(postgres_role) + roles: %w(postgres_role), + repmgr: { + enable: true + } ) end @@ -30,10 +66,7 @@ RSpec.describe 'patroni cookbook' do context 'when enabled with default config' do before do stub_gitlab_rb( - roles: %w(postgres_role), - patroni: { - enable: true - }, + roles: %w(patroni_role), postgresql: { pgbouncer_user_password: '' } diff --git a/spec/chef/postgresql/resources/config_spec.rb b/spec/chef/postgresql/resources/config_spec.rb index 85f76feb2a45e2fb05c6ea4be4332ca79fe2ca74..43bcb053b2ada02257bf693f9785c7a2fbad3088 100644 --- a/spec/chef/postgresql/resources/config_spec.rb +++ b/spec/chef/postgresql/resources/config_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'postgresql_config' do end end - let(:chef_run) { runner.converge('test_postgresql::postgresql_config') } + let(:chef_run) { runner.converge('gitlab::config', 'test_postgresql::postgresql_config') } before do allow_any_instance_of(PgHelper).to receive(:postgresql_user).and_return('fakeuser')