From ecdc41a54f84ab5bdd161d12c25c04a3710f302c Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Mon, 29 Nov 2021 13:09:13 -0600 Subject: [PATCH 1/2] Rename postgres cookbook, deploy new replica fixes #361 closes #330 --- nodes/akkounts-1.json | 2 +- nodes/postgres-2.json | 10 +- roles/postgresql_client.rb | 2 +- roles/postgresql_primary.rb | 4 +- roles/postgresql_replica.rb | 6 +- site-cookbooks/kosmos-postgresql/.gitignore | 22 ---- site-cookbooks/kosmos-postgresql/Berksfile | 4 - site-cookbooks/kosmos-postgresql/CHANGELOG.md | 5 - site-cookbooks/kosmos-postgresql/LICENSE | 20 ---- site-cookbooks/kosmos-postgresql/README.md | 57 ---------- .../kosmos-postgresql/attributes/default.rb | 3 - site-cookbooks/kosmos-postgresql/chefignore | 104 ------------------ .../kosmos-postgresql/libraries/helpers.rb | 45 -------- site-cookbooks/kosmos-postgresql/metadata.rb | 25 ----- .../kosmos-postgresql/recipes/firewall.rb | 15 --- .../kosmos-postgresql/recipes/hostsfile.rb | 16 --- .../kosmos-postgresql/recipes/primary.rb | 33 ------ .../kosmos-postgresql/recipes/replica.rb | 56 ---------- .../kosmos-postgresql/resources/server.rb | 77 ------------- site-cookbooks/kosmos_kvm/recipes/host.rb | 25 +---- 20 files changed, 14 insertions(+), 517 deletions(-) delete mode 100644 site-cookbooks/kosmos-postgresql/.gitignore delete mode 100644 site-cookbooks/kosmos-postgresql/Berksfile delete mode 100644 site-cookbooks/kosmos-postgresql/CHANGELOG.md delete mode 100644 site-cookbooks/kosmos-postgresql/LICENSE delete mode 100644 site-cookbooks/kosmos-postgresql/README.md delete mode 100644 site-cookbooks/kosmos-postgresql/attributes/default.rb delete mode 100644 site-cookbooks/kosmos-postgresql/chefignore delete mode 100644 site-cookbooks/kosmos-postgresql/libraries/helpers.rb delete mode 100644 site-cookbooks/kosmos-postgresql/metadata.rb delete mode 100644 site-cookbooks/kosmos-postgresql/recipes/firewall.rb delete mode 100644 site-cookbooks/kosmos-postgresql/recipes/hostsfile.rb delete mode 100644 site-cookbooks/kosmos-postgresql/recipes/primary.rb delete mode 100644 site-cookbooks/kosmos-postgresql/recipes/replica.rb delete mode 100644 site-cookbooks/kosmos-postgresql/resources/server.rb diff --git a/nodes/akkounts-1.json b/nodes/akkounts-1.json index 93a1617..1168a2d 100644 --- a/nodes/akkounts-1.json +++ b/nodes/akkounts-1.json @@ -18,7 +18,7 @@ "recipes": [ "kosmos-base", "kosmos-base::default", - "kosmos-postgresql::hostsfile", + "kosmos_postgresql::hostsfile", "kosmos-akkounts", "kosmos-akkounts::default", "kosmos-akkounts::nginx", diff --git a/nodes/postgres-2.json b/nodes/postgres-2.json index cd48a8c..89bcc85 100644 --- a/nodes/postgres-2.json +++ b/nodes/postgres-2.json @@ -8,17 +8,17 @@ "automatic": { "fqdn": "postgres-2", "os": "linux", - "os_version": "5.4.0-64-generic", + "os_version": "5.4.0-77-generic", "hostname": "postgres-2", "ipaddress": "192.168.122.244", "roles": [ - "postgresql_replica" + "postgresql_primary" ], "recipes": [ "kosmos-base", "kosmos-base::default", - "kosmos-postgresql::replica", - "kosmos-postgresql::firewall", + "kosmos_postgresql::primary", + "kosmos_postgresql::firewall", "apt::default", "timezone_iii::default", "timezone_iii::debian", @@ -52,4 +52,4 @@ "recipe[kosmos-base]", "role[postgresql_primary]" ] -} +} \ No newline at end of file diff --git a/roles/postgresql_client.rb b/roles/postgresql_client.rb index 96b5418..f2fbb71 100644 --- a/roles/postgresql_client.rb +++ b/roles/postgresql_client.rb @@ -3,5 +3,5 @@ name "postgresql_client" run_list %w( - kosmos-postgresql::hostsfile + kosmos_postgresql::hostsfile ) diff --git a/roles/postgresql_primary.rb b/roles/postgresql_primary.rb index ba5e5be..58ef4b7 100644 --- a/roles/postgresql_primary.rb +++ b/roles/postgresql_primary.rb @@ -1,6 +1,6 @@ name "postgresql_primary" run_list %w( - kosmos-postgresql::primary - kosmos-postgresql::firewall + kosmos_postgresql::primary + kosmos_postgresql::firewall ) diff --git a/roles/postgresql_replica.rb b/roles/postgresql_replica.rb index 6d73f31..099291d 100644 --- a/roles/postgresql_replica.rb +++ b/roles/postgresql_replica.rb @@ -1,7 +1,7 @@ name "postgresql_replica" run_list %w( - kosmos-postgresql::hostsfile - kosmos-postgresql::replica - kosmos-postgresql::firewall + kosmos_postgresql::hostsfile + kosmos_postgresql::replica + kosmos_postgresql::firewall ) diff --git a/site-cookbooks/kosmos-postgresql/.gitignore b/site-cookbooks/kosmos-postgresql/.gitignore deleted file mode 100644 index 13e41c4..0000000 --- a/site-cookbooks/kosmos-postgresql/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -.vagrant -*~ -*# -.#* -\#*# -.*.sw[a-z] -*.un~ - -# Bundler -Gemfile.lock -gems.locked -bin/* -.bundle/* - -# test kitchen -.kitchen/ -.kitchen.local.yml - -# Chef -Berksfile.lock -.zero-knife.rb -Policyfile.lock.json diff --git a/site-cookbooks/kosmos-postgresql/Berksfile b/site-cookbooks/kosmos-postgresql/Berksfile deleted file mode 100644 index 0656a99..0000000 --- a/site-cookbooks/kosmos-postgresql/Berksfile +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true -source 'https://supermarket.chef.io' - -metadata diff --git a/site-cookbooks/kosmos-postgresql/CHANGELOG.md b/site-cookbooks/kosmos-postgresql/CHANGELOG.md deleted file mode 100644 index 20e9a6a..0000000 --- a/site-cookbooks/kosmos-postgresql/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# kosmos-postgresql CHANGELOG - -# 0.1.0 - -Initial release. diff --git a/site-cookbooks/kosmos-postgresql/LICENSE b/site-cookbooks/kosmos-postgresql/LICENSE deleted file mode 100644 index c150a1f..0000000 --- a/site-cookbooks/kosmos-postgresql/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2019-2020 Kosmos Developers - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/site-cookbooks/kosmos-postgresql/README.md b/site-cookbooks/kosmos-postgresql/README.md deleted file mode 100644 index 2541424..0000000 --- a/site-cookbooks/kosmos-postgresql/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# kosmos-postgresql - -## Usage - -### On the primary: - -Set the `postgresql_primary` role on the node - -### On the replica: - -Add the `postgresql_replica` role to the node's run list. Run Chef on the node -a first time. -After the initial Chef run on the replica, run Chef on the primary to add the -firewall rules and PostgreSQL access rules, then run Chef again on the replica -to set up replication. - -## Caveat - -[`firewall_rules`](https://github.com/chef-cookbooks/firewall/issues/134) and -[`postgresql_access`](https://github.com/sous-chefs/postgresql/issues/648) are -declared in recipes, not resources because of the way custom resources -work currently in Chef. See the `default.rb` and `replica.rb` recipes. - -The primary gives access to the `replication` db to the `replication` user -connecting from a replica, and replicas to the primary. For more information -about PostgreSQL client authentication, see the -[official docs](https://www.postgresql.org/docs/12/auth-pg-hba-conf.html) - -The primary opens up the PostgreSQL port (5432 TCP) to replicas, and replicas -to the primary. - -## TLS self-signed certificate - -A wildcard (`*.kosmos.org` certificate) was generated with the following -commands: - -``` -openssl req -new -nodes -text -out root.csr -keyout root.key \ - -subj "/CN=root.kosmos.org" -chmod og-rwx root.key -openssl x509 -req -in root.csr -text -days 3650 \ - -extfile /etc/ssl/openssl.cnf -extensions v3_ca \ - -signkey root.key -out root.crt -openssl req -new -nodes -text -out server.csr \ - -keyout server.key -subj "/CN=*.kosmos.org" -chmod og-rwx server.key -openssl x509 -req -in server.csr -text -days 1825 \ - -CA root.crt -CAkey root.key -CAcreateserial \ - -out server.crt -``` - -It is valid until May 12 2025. - -The content of `server.crt`, `server.key` and `root.crt` an stored in the -`postgresql` encrypted data bag. The root key is stored in LastPass -("Self-signed TLS root certificate"). `server.crt` & `server.key` are used by -the PostgreSQL server. diff --git a/site-cookbooks/kosmos-postgresql/attributes/default.rb b/site-cookbooks/kosmos-postgresql/attributes/default.rb deleted file mode 100644 index dec530f..0000000 --- a/site-cookbooks/kosmos-postgresql/attributes/default.rb +++ /dev/null @@ -1,3 +0,0 @@ -# This is set to false by default, and set to true in the server resource -# for replicas. -node.default['kosmos-postgresql']['ready_to_set_up_replica'] = false diff --git a/site-cookbooks/kosmos-postgresql/chefignore b/site-cookbooks/kosmos-postgresql/chefignore deleted file mode 100644 index 4439807..0000000 --- a/site-cookbooks/kosmos-postgresql/chefignore +++ /dev/null @@ -1,104 +0,0 @@ -# Put files/directories that should be ignored in this file when uploading -# to a chef-server or supermarket. -# Lines that start with '# ' are comments. - -# OS generated files # -###################### -.DS_Store -Icon? -nohup.out -ehthumbs.db -Thumbs.db - -# SASS # -######## -.sass-cache - -# EDITORS # -########### -\#* -.#* -*~ -*.sw[a-z] -*.bak -REVISION -TAGS* -tmtags -*_flymake.* -*_flymake -*.tmproj -.project -.settings -mkmf.log - -## COMPILED ## -############## -a.out -*.o -*.pyc -*.so -*.com -*.class -*.dll -*.exe -*/rdoc/ - -# Testing # -########### -.watchr -.rspec -spec/* -spec/fixtures/* -test/* -features/* -examples/* -Guardfile -Procfile -.kitchen* -kitchen.yml* -.rubocop.yml -spec/* -Rakefile -.travis.yml -.foodcritic -.codeclimate.yml - -# SCM # -####### -.git -*/.git -.gitignore -.gitmodules -.gitconfig -.gitattributes -.svn -*/.bzr/* -*/.hg/* -*/.svn/* - -# Berkshelf # -############# -Berksfile -Berksfile.lock -cookbooks/* -tmp - -# Bundler # -########### -vendor/* - -# Policyfile # -############## -Policyfile.rb -Policyfile.lock.json - -# Cookbooks # -############# -CONTRIBUTING* -CHANGELOG* -TESTING* - -# Vagrant # -########### -.vagrant -Vagrantfile diff --git a/site-cookbooks/kosmos-postgresql/libraries/helpers.rb b/site-cookbooks/kosmos-postgresql/libraries/helpers.rb deleted file mode 100644 index 7d3c397..0000000 --- a/site-cookbooks/kosmos-postgresql/libraries/helpers.rb +++ /dev/null @@ -1,45 +0,0 @@ -class Chef - class Recipe - def postgresql_primary - postgresql_primary = search(:node, "role:postgresql_primary AND chef_environment:#{node.chef_environment}").first - - unless postgresql_primary.nil? - primary_ip = ip_for(postgresql_primary) - - { hostname: postgresql_primary[:hostname], ipaddress: primary_ip } - end - end - - def postgresql_replicas - postgresql_replicas = [] - - search(:node, "role:postgresql_replica AND chef_environment:#{node.chef_environment}").each do |replica| - replica_ip = ip_for(replica) - - postgresql_replicas << { hostname: replica[:hostname], ipaddress: replica_ip } - end - - postgresql_replicas - end - - def ip_for(server_node) - if node.chef_environment == "development" - server_node['network']['interfaces']['eth1']['routes'].first['src'] - else - # If the server has a private Zerotier IP, use it - if server_node['knife_zero'] && server_node['knife_zero']['host'] && \ - server_node['knife_zero']['host'].start_with?("10.1.1.") - server_node['knife_zero']['host'] - else - server_node['ipaddress'] - end - end - end - - def postgresql_service_name - postgresql_version = "12" - - "postgresql@#{postgresql_version}-main" - end - end -end diff --git a/site-cookbooks/kosmos-postgresql/metadata.rb b/site-cookbooks/kosmos-postgresql/metadata.rb deleted file mode 100644 index 1b031b2..0000000 --- a/site-cookbooks/kosmos-postgresql/metadata.rb +++ /dev/null @@ -1,25 +0,0 @@ -name 'kosmos-postgresql' -maintainer 'Kosmos' -maintainer_email 'ops@5apps.com' -license 'MIT' -description 'Installs/Configures kosmos-postgresql' -long_description 'Installs/Configures kosmos-postgresql' -version '0.1.0' -chef_version '>= 12.14' if respond_to?(:chef_version) - -# The `issues_url` points to the location where issues for this cookbook are -# tracked. A `View Issues` link will be displayed on this cookbook's page when -# uploaded to a Supermarket. -# -# issues_url 'https://github.com//kosmos-postgresql/issues' - -# The `source_url` points to the development repository for this cookbook. A -# `View Source` link will be displayed on this cookbook's page when uploaded to -# a Supermarket. -# -# source_url 'https://github.com//kosmos-postgresql' - -depends "postgresql", ">= 7.0.0" -depends "build-essential" -depends "kosmos_encfs" -depends "hostsfile" diff --git a/site-cookbooks/kosmos-postgresql/recipes/firewall.rb b/site-cookbooks/kosmos-postgresql/recipes/firewall.rb deleted file mode 100644 index 7b9b380..0000000 --- a/site-cookbooks/kosmos-postgresql/recipes/firewall.rb +++ /dev/null @@ -1,15 +0,0 @@ -# -# Cookbook:: kosmos-postgresql -# Recipe:: firewall -# - -unless node.chef_environment == "development" - include_recipe "kosmos-base::firewall" - - firewall_rule "postgresql zerotier members" do - port 5432 - protocol :tcp - command :allow - source "10.1.1.0/24" - end -end diff --git a/site-cookbooks/kosmos-postgresql/recipes/hostsfile.rb b/site-cookbooks/kosmos-postgresql/recipes/hostsfile.rb deleted file mode 100644 index 265f563..0000000 --- a/site-cookbooks/kosmos-postgresql/recipes/hostsfile.rb +++ /dev/null @@ -1,16 +0,0 @@ -# -# Cookbook:: kosmos-postgresql -# Recipe:: hostsfile -# - -begin -primary_ip = postgresql_primary[:ipaddress] -rescue NoMethodError -end - -unless primary_ip.nil? - hostsfile_entry primary_ip do - hostname "pg.kosmos.local" - unique true - end -end diff --git a/site-cookbooks/kosmos-postgresql/recipes/primary.rb b/site-cookbooks/kosmos-postgresql/recipes/primary.rb deleted file mode 100644 index b3a7534..0000000 --- a/site-cookbooks/kosmos-postgresql/recipes/primary.rb +++ /dev/null @@ -1,33 +0,0 @@ -# -# Cookbook:: kosmos-postgresql -# Recipe:: primary -# - -postgresql_version = "12" -postgresql_service = "postgresql@#{postgresql_version}-main" - -service postgresql_service do - supports restart: true, status: true, reload: true -end - -postgresql_custom_server postgresql_version do - role "primary" -end - -postgresql_access "zerotier members" do - access_type "host" - access_db "all" - access_user "all" - access_addr "10.1.1.0/24" - access_method "md5" - notifies :reload, "service[#{postgresql_service}]", :immediately -end - -postgresql_access "zerotier members replication" do - access_type "host" - access_db "replication" - access_user "replication" - access_addr "10.1.1.0/24" - access_method "md5" - notifies :reload, "service[#{postgresql_service}]", :immediately -end diff --git a/site-cookbooks/kosmos-postgresql/recipes/replica.rb b/site-cookbooks/kosmos-postgresql/recipes/replica.rb deleted file mode 100644 index 6525948..0000000 --- a/site-cookbooks/kosmos-postgresql/recipes/replica.rb +++ /dev/null @@ -1,56 +0,0 @@ -# -# Cookbook:: kosmos-postgresql -# Recipe:: replica -# - -postgresql_version = "12" -postgresql_service = "postgresql@#{postgresql_version}-main" - -postgresql_custom_server postgresql_version do - role "replica" -end - -service postgresql_service do - supports restart: true, status: true, reload: true -end - -postgresql_data_bag_item = data_bag_item('credentials', 'postgresql') - -primary = postgresql_primary - -unless primary.nil? - # TODO - postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main" - - # FIXME get zerotier IP - execute "set up replication" do - command <<-EOF -systemctl stop #{postgresql_service} -mv #{postgresql_data_dir} #{postgresql_data_dir}.old -pg_basebackup -h pg.kosmos.local -U replication -D #{postgresql_data_dir} -R -chown -R postgres:postgres #{postgresql_data_dir} -systemctl start #{postgresql_service} - EOF - environment 'PGPASSWORD' => postgresql_data_bag_item['replication_password'] - sensitive true - not_if { ::File.exist? "#{postgresql_data_dir}/standby.signal" } - end - - postgresql_access "zerotier members" do - access_type "host" - access_db "all" - access_user "all" - access_addr "10.1.1.0/24" - access_method "md5" - notifies :reload, "service[#{postgresql_service}]", :immediately - end - - postgresql_access "zerotier members replication" do - access_type "host" - access_db "replication" - access_user "replication" - access_addr "10.1.1.0/24" - access_method "md5" - notifies :reload, "service[#{postgresql_service}]", :immediately - end -end diff --git a/site-cookbooks/kosmos-postgresql/resources/server.rb b/site-cookbooks/kosmos-postgresql/resources/server.rb deleted file mode 100644 index f71520e..0000000 --- a/site-cookbooks/kosmos-postgresql/resources/server.rb +++ /dev/null @@ -1,77 +0,0 @@ -resource_name :postgresql_custom_server - -property :postgresql_version, String, required: true, name_property: true -property :role, String, required: true # Can be primary or replica - -action :create do - postgresql_version = new_resource.postgresql_version - postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main" - postgresql_service = "postgresql@#{postgresql_version}-main" - postgresql_credentials = data_bag_item('credentials', 'postgresql') - - build_essential do - compile_time true - end - - package("libpq-dev") { action :nothing }.run_action(:install) - - chef_gem 'pg' do - compile_time true - end - - user "postgres" do - manage_home false - end - - postgresql_server_install "main" do - version postgresql_version - setup_repo true - password postgresql_credentials['server_password'] - action :install - end - - service postgresql_service do - supports restart: true, status: true, reload: true - action [:enable, :start] - end - - # This service is a dependency that will auto-start our cluster service on - # boot if it's enabled, so we disable it explicitly - service "postgresql" do - action :disable - end - - shared_buffers = if node['memory']['total'].to_i / 1024 < 1024 # > 1GB RAM - "128MB" - else # >= 1GB RAM, use 25% of total RAM - "#{node['memory']['total'].to_i / 1024 / 4}MB" - end - - additional_config = { - max_connections: 100, # default - shared_buffers: shared_buffers, - unix_socket_directories: "/var/run/postgresql", - dynamic_shared_memory_type: "posix", - timezone: "UTC", # default is GMT - listen_addresses: "0.0.0.0" - } - - additional_config[:promote_trigger_file] = "#{postgresql_data_dir}/failover.trigger" - - postgresql_server_conf "main" do - version postgresql_version - additional_config additional_config - notifies :reload, "service[#{postgresql_service}]", :delayed - end - - postgresql_user "replication" do - action :create - replication true - password postgresql_credentials['replication_password'] - end -end - -action_class do - # to use the data_dir helper - include PostgresqlCookbook::Helpers -end diff --git a/site-cookbooks/kosmos_kvm/recipes/host.rb b/site-cookbooks/kosmos_kvm/recipes/host.rb index a89f7eb..1d611bd 100644 --- a/site-cookbooks/kosmos_kvm/recipes/host.rb +++ b/site-cookbooks/kosmos_kvm/recipes/host.rb @@ -2,34 +2,13 @@ # Cookbook:: kosmos_kvm # Recipe:: host # -# The MIT License (MIT) -# -# Copyright:: 2020, Kosmos Developers -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. package %w(virtinst libvirt-daemon-system) directory "/var/lib/libvirt/images/base" do recursive true owner "libvirt-qemu" - group "root" + group "kvm" mode "0750" end @@ -37,7 +16,7 @@ end remote_file "/var/lib/libvirt/images/base/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.qcow2" do source "http://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64-disk-kvm.img" owner "libvirt-qemu" - group "root" + group "kvm" mode "0640" end From 91ffe75bc1ed4df8a0a6507d2acbcd63c0aa9be9 Mon Sep 17 00:00:00 2001 From: Sebastian Kippe Date: Mon, 29 Nov 2021 13:12:17 -0600 Subject: [PATCH 2/2] Add missing files --- clients/postgres-4.json | 4 + nodes/postgres-4.json | 57 ++++++++++ site-cookbooks/kosmos_postgresql/.gitignore | 22 ++++ site-cookbooks/kosmos_postgresql/Berksfile | 4 + site-cookbooks/kosmos_postgresql/CHANGELOG.md | 5 + site-cookbooks/kosmos_postgresql/LICENSE | 20 ++++ site-cookbooks/kosmos_postgresql/README.md | 57 ++++++++++ .../kosmos_postgresql/attributes/default.rb | 3 + site-cookbooks/kosmos_postgresql/chefignore | 104 ++++++++++++++++++ .../kosmos_postgresql/libraries/helpers.rb | 45 ++++++++ site-cookbooks/kosmos_postgresql/metadata.rb | 25 +++++ .../kosmos_postgresql/recipes/firewall.rb | 15 +++ .../kosmos_postgresql/recipes/hostsfile.rb | 16 +++ .../kosmos_postgresql/recipes/primary.rb | 33 ++++++ .../kosmos_postgresql/recipes/replica.rb | 56 ++++++++++ .../kosmos_postgresql/resources/server.rb | 78 +++++++++++++ 16 files changed, 544 insertions(+) create mode 100644 clients/postgres-4.json create mode 100644 nodes/postgres-4.json create mode 100644 site-cookbooks/kosmos_postgresql/.gitignore create mode 100644 site-cookbooks/kosmos_postgresql/Berksfile create mode 100644 site-cookbooks/kosmos_postgresql/CHANGELOG.md create mode 100644 site-cookbooks/kosmos_postgresql/LICENSE create mode 100644 site-cookbooks/kosmos_postgresql/README.md create mode 100644 site-cookbooks/kosmos_postgresql/attributes/default.rb create mode 100644 site-cookbooks/kosmos_postgresql/chefignore create mode 100644 site-cookbooks/kosmos_postgresql/libraries/helpers.rb create mode 100644 site-cookbooks/kosmos_postgresql/metadata.rb create mode 100644 site-cookbooks/kosmos_postgresql/recipes/firewall.rb create mode 100644 site-cookbooks/kosmos_postgresql/recipes/hostsfile.rb create mode 100644 site-cookbooks/kosmos_postgresql/recipes/primary.rb create mode 100644 site-cookbooks/kosmos_postgresql/recipes/replica.rb create mode 100644 site-cookbooks/kosmos_postgresql/resources/server.rb diff --git a/clients/postgres-4.json b/clients/postgres-4.json new file mode 100644 index 0000000..eed891f --- /dev/null +++ b/clients/postgres-4.json @@ -0,0 +1,4 @@ +{ + "name": "postgres-4", + "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu6fPxOZeKloF/EgYvU0k\nOwv8bJjsCQcWaMTPle5//mRTszA6PM2z9RI+Mfr45qxTlsL9pQY8WJOWF6QOK31x\nszuqcr7oOjtAhrLI8f/oNDEDjcx325FqG9gNKQEAD7d4zodh+PhDe6x7GIyIS7lG\nIcD5Zre9iDwv8FGLR+5GLqS8SJOPL/wJkQ8w+N0f8YDFw81kiTta5NLhAx3fMDs0\n2kmoNlbmKlNZTtLjCfCV+/pa9oY6wycjck3GvobiFE/4cWaNkeGlPc+uAwlfmrOv\nHy0tq1XBX/BCvE5kMXmhnMT23JXjm2s2PgCLgEVGAXilXk/T597KDm+z4oBpAQma\nnQIDAQAB\n-----END PUBLIC KEY-----\n" +} \ No newline at end of file diff --git a/nodes/postgres-4.json b/nodes/postgres-4.json new file mode 100644 index 0000000..77e5a0f --- /dev/null +++ b/nodes/postgres-4.json @@ -0,0 +1,57 @@ +{ + "name": "postgres-4", + "normal": { + "knife_zero": { + "host": "10.1.1.107" + } + }, + "automatic": { + "fqdn": "postgres-4", + "os": "linux", + "os_version": "5.4.0-91-generic", + "hostname": "postgres-4", + "ipaddress": "192.168.122.3", + "roles": [ + "postgresql_replica" + ], + "recipes": [ + "kosmos-base", + "kosmos-base::default", + "kosmos_postgresql::hostsfile", + "kosmos_postgresql::replica", + "kosmos_postgresql::firewall", + "apt::default", + "timezone_iii::default", + "timezone_iii::debian", + "ntp::default", + "ntp::apparmor", + "kosmos-base::systemd_emails", + "apt::unattended-upgrades", + "kosmos-base::firewall", + "kosmos-postfix::default", + "postfix::default", + "postfix::_common", + "postfix::_attributes", + "postfix::sasl_auth", + "hostname::default" + ], + "platform": "ubuntu", + "platform_version": "20.04", + "cloud": null, + "chef_packages": { + "chef": { + "version": "17.7.29", + "chef_root": "/opt/chef/embedded/lib/ruby/gems/3.0.0/gems/chef-17.7.29/lib", + "chef_effortless": null + }, + "ohai": { + "version": "17.7.8", + "ohai_root": "/opt/chef/embedded/lib/ruby/gems/3.0.0/gems/ohai-17.7.8/lib/ohai" + } + } + }, + "run_list": [ + "recipe[kosmos-base]", + "role[postgresql_replica]" + ] +} \ No newline at end of file diff --git a/site-cookbooks/kosmos_postgresql/.gitignore b/site-cookbooks/kosmos_postgresql/.gitignore new file mode 100644 index 0000000..13e41c4 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/.gitignore @@ -0,0 +1,22 @@ +.vagrant +*~ +*# +.#* +\#*# +.*.sw[a-z] +*.un~ + +# Bundler +Gemfile.lock +gems.locked +bin/* +.bundle/* + +# test kitchen +.kitchen/ +.kitchen.local.yml + +# Chef +Berksfile.lock +.zero-knife.rb +Policyfile.lock.json diff --git a/site-cookbooks/kosmos_postgresql/Berksfile b/site-cookbooks/kosmos_postgresql/Berksfile new file mode 100644 index 0000000..0656a99 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/Berksfile @@ -0,0 +1,4 @@ +# frozen_string_literal: true +source 'https://supermarket.chef.io' + +metadata diff --git a/site-cookbooks/kosmos_postgresql/CHANGELOG.md b/site-cookbooks/kosmos_postgresql/CHANGELOG.md new file mode 100644 index 0000000..1ffdd2a --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/CHANGELOG.md @@ -0,0 +1,5 @@ +# kosmos_postgresql CHANGELOG + +# 0.1.0 + +Initial release. diff --git a/site-cookbooks/kosmos_postgresql/LICENSE b/site-cookbooks/kosmos_postgresql/LICENSE new file mode 100644 index 0000000..c150a1f --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2019-2020 Kosmos Developers + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/site-cookbooks/kosmos_postgresql/README.md b/site-cookbooks/kosmos_postgresql/README.md new file mode 100644 index 0000000..9ea16a7 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/README.md @@ -0,0 +1,57 @@ +# kosmos_postgresql + +## Usage + +### On the primary: + +Set the `postgresql_primary` role on the node + +### On the replica: + +Add the `postgresql_replica` role to the node's run list. Run Chef on the node +a first time. +After the initial Chef run on the replica, run Chef on the primary to add the +firewall rules and PostgreSQL access rules, then run Chef again on the replica +to set up replication. + +## Caveat + +[`firewall_rules`](https://github.com/chef-cookbooks/firewall/issues/134) and +[`postgresql_access`](https://github.com/sous-chefs/postgresql/issues/648) are +declared in recipes, not resources because of the way custom resources +work currently in Chef. See the `default.rb` and `replica.rb` recipes. + +The primary gives access to the `replication` db to the `replication` user +connecting from a replica, and replicas to the primary. For more information +about PostgreSQL client authentication, see the +[official docs](https://www.postgresql.org/docs/12/auth-pg-hba-conf.html) + +The primary opens up the PostgreSQL port (5432 TCP) to replicas, and replicas +to the primary. + +## TLS self-signed certificate + +A wildcard (`*.kosmos.org` certificate) was generated with the following +commands: + +``` +openssl req -new -nodes -text -out root.csr -keyout root.key \ + -subj "/CN=root.kosmos.org" +chmod og-rwx root.key +openssl x509 -req -in root.csr -text -days 3650 \ + -extfile /etc/ssl/openssl.cnf -extensions v3_ca \ + -signkey root.key -out root.crt +openssl req -new -nodes -text -out server.csr \ + -keyout server.key -subj "/CN=*.kosmos.org" +chmod og-rwx server.key +openssl x509 -req -in server.csr -text -days 1825 \ + -CA root.crt -CAkey root.key -CAcreateserial \ + -out server.crt +``` + +It is valid until May 12 2025. + +The content of `server.crt`, `server.key` and `root.crt` an stored in the +`postgresql` encrypted data bag. The root key is stored in LastPass +("Self-signed TLS root certificate"). `server.crt` & `server.key` are used by +the PostgreSQL server. diff --git a/site-cookbooks/kosmos_postgresql/attributes/default.rb b/site-cookbooks/kosmos_postgresql/attributes/default.rb new file mode 100644 index 0000000..f3daf9b --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/attributes/default.rb @@ -0,0 +1,3 @@ +# This is set to false by default, and set to true in the server resource +# for replicas. +node.default['kosmos_postgresql']['ready_to_set_up_replica'] = false diff --git a/site-cookbooks/kosmos_postgresql/chefignore b/site-cookbooks/kosmos_postgresql/chefignore new file mode 100644 index 0000000..4439807 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/chefignore @@ -0,0 +1,104 @@ +# Put files/directories that should be ignored in this file when uploading +# to a chef-server or supermarket. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +examples/* +Guardfile +Procfile +.kitchen* +kitchen.yml* +.rubocop.yml +spec/* +Rakefile +.travis.yml +.foodcritic +.codeclimate.yml + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Bundler # +########### +vendor/* + +# Policyfile # +############## +Policyfile.rb +Policyfile.lock.json + +# Cookbooks # +############# +CONTRIBUTING* +CHANGELOG* +TESTING* + +# Vagrant # +########### +.vagrant +Vagrantfile diff --git a/site-cookbooks/kosmos_postgresql/libraries/helpers.rb b/site-cookbooks/kosmos_postgresql/libraries/helpers.rb new file mode 100644 index 0000000..7d3c397 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/libraries/helpers.rb @@ -0,0 +1,45 @@ +class Chef + class Recipe + def postgresql_primary + postgresql_primary = search(:node, "role:postgresql_primary AND chef_environment:#{node.chef_environment}").first + + unless postgresql_primary.nil? + primary_ip = ip_for(postgresql_primary) + + { hostname: postgresql_primary[:hostname], ipaddress: primary_ip } + end + end + + def postgresql_replicas + postgresql_replicas = [] + + search(:node, "role:postgresql_replica AND chef_environment:#{node.chef_environment}").each do |replica| + replica_ip = ip_for(replica) + + postgresql_replicas << { hostname: replica[:hostname], ipaddress: replica_ip } + end + + postgresql_replicas + end + + def ip_for(server_node) + if node.chef_environment == "development" + server_node['network']['interfaces']['eth1']['routes'].first['src'] + else + # If the server has a private Zerotier IP, use it + if server_node['knife_zero'] && server_node['knife_zero']['host'] && \ + server_node['knife_zero']['host'].start_with?("10.1.1.") + server_node['knife_zero']['host'] + else + server_node['ipaddress'] + end + end + end + + def postgresql_service_name + postgresql_version = "12" + + "postgresql@#{postgresql_version}-main" + end + end +end diff --git a/site-cookbooks/kosmos_postgresql/metadata.rb b/site-cookbooks/kosmos_postgresql/metadata.rb new file mode 100644 index 0000000..ad7ca14 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/metadata.rb @@ -0,0 +1,25 @@ +name 'kosmos_postgresql' +maintainer 'Kosmos' +maintainer_email 'ops@5apps.com' +license 'MIT' +description 'Installs/Configures kosmos_postgresql' +long_description 'Installs/Configures kosmos_postgresql' +version '0.1.0' +chef_version '>= 12.14' if respond_to?(:chef_version) + +# The `issues_url` points to the location where issues for this cookbook are +# tracked. A `View Issues` link will be displayed on this cookbook's page when +# uploaded to a Supermarket. +# +# issues_url 'https://github.com//kosmos_postgresql/issues' + +# The `source_url` points to the development repository for this cookbook. A +# `View Source` link will be displayed on this cookbook's page when uploaded to +# a Supermarket. +# +# source_url 'https://github.com//kosmos_postgresql' + +depends "postgresql", ">= 7.0.0" +depends "build-essential" +depends "kosmos_encfs" +depends "hostsfile" diff --git a/site-cookbooks/kosmos_postgresql/recipes/firewall.rb b/site-cookbooks/kosmos_postgresql/recipes/firewall.rb new file mode 100644 index 0000000..ebc3404 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/recipes/firewall.rb @@ -0,0 +1,15 @@ +# +# Cookbook:: kosmos_postgresql +# Recipe:: firewall +# + +unless node.chef_environment == "development" + include_recipe "kosmos-base::firewall" + + firewall_rule "postgresql zerotier members" do + port 5432 + protocol :tcp + command :allow + source "10.1.1.0/24" + end +end diff --git a/site-cookbooks/kosmos_postgresql/recipes/hostsfile.rb b/site-cookbooks/kosmos_postgresql/recipes/hostsfile.rb new file mode 100644 index 0000000..9000b67 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/recipes/hostsfile.rb @@ -0,0 +1,16 @@ +# +# Cookbook:: kosmos_postgresql +# Recipe:: hostsfile +# + +begin +primary_ip = postgresql_primary[:ipaddress] +rescue NoMethodError +end + +unless primary_ip.nil? + hostsfile_entry primary_ip do + hostname "pg.kosmos.local" + unique true + end +end diff --git a/site-cookbooks/kosmos_postgresql/recipes/primary.rb b/site-cookbooks/kosmos_postgresql/recipes/primary.rb new file mode 100644 index 0000000..de7466f --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/recipes/primary.rb @@ -0,0 +1,33 @@ +# +# Cookbook:: kosmos_postgresql +# Recipe:: primary +# + +postgresql_version = "12" +postgresql_service = "postgresql@#{postgresql_version}-main" + +service postgresql_service do + supports restart: true, status: true, reload: true +end + +postgresql_custom_server postgresql_version do + role "primary" +end + +postgresql_access "zerotier members" do + access_type "host" + access_db "all" + access_user "all" + access_addr "10.1.1.0/24" + access_method "md5" + notifies :reload, "service[#{postgresql_service}]", :immediately +end + +postgresql_access "zerotier members replication" do + access_type "host" + access_db "replication" + access_user "replication" + access_addr "10.1.1.0/24" + access_method "md5" + notifies :reload, "service[#{postgresql_service}]", :immediately +end diff --git a/site-cookbooks/kosmos_postgresql/recipes/replica.rb b/site-cookbooks/kosmos_postgresql/recipes/replica.rb new file mode 100644 index 0000000..b1dd345 --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/recipes/replica.rb @@ -0,0 +1,56 @@ +# +# Cookbook:: kosmos_postgresql +# Recipe:: replica +# + +postgresql_version = "12" +postgresql_service = "postgresql@#{postgresql_version}-main" + +postgresql_custom_server postgresql_version do + role "replica" +end + +service postgresql_service do + supports restart: true, status: true, reload: true +end + +postgresql_data_bag_item = data_bag_item('credentials', 'postgresql') + +primary = postgresql_primary + +unless primary.nil? + # TODO + postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main" + + # FIXME get zerotier IP + execute "set up replication" do + command <<-EOF +systemctl stop #{postgresql_service} +mv #{postgresql_data_dir} #{postgresql_data_dir}.old +pg_basebackup -h pg.kosmos.local -U replication -D #{postgresql_data_dir} -R +chown -R postgres:postgres #{postgresql_data_dir} +systemctl start #{postgresql_service} + EOF + environment 'PGPASSWORD' => postgresql_data_bag_item['replication_password'] + sensitive true + not_if { ::File.exist? "#{postgresql_data_dir}/standby.signal" } + end + + postgresql_access "zerotier members" do + access_type "host" + access_db "all" + access_user "all" + access_addr "10.1.1.0/24" + access_method "md5" + notifies :reload, "service[#{postgresql_service}]", :immediately + end + + postgresql_access "zerotier members replication" do + access_type "host" + access_db "replication" + access_user "replication" + access_addr "10.1.1.0/24" + access_method "md5" + notifies :reload, "service[#{postgresql_service}]", :immediately + end +end diff --git a/site-cookbooks/kosmos_postgresql/resources/server.rb b/site-cookbooks/kosmos_postgresql/resources/server.rb new file mode 100644 index 0000000..5d5fb1c --- /dev/null +++ b/site-cookbooks/kosmos_postgresql/resources/server.rb @@ -0,0 +1,78 @@ +resource_name :postgresql_custom_server +provides :postgresql_custom_server + +property :postgresql_version, String, required: true, name_property: true +property :role, String, required: true # Can be primary or replica + +action :create do + postgresql_version = new_resource.postgresql_version + postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main" + postgresql_service = "postgresql@#{postgresql_version}-main" + postgresql_credentials = data_bag_item('credentials', 'postgresql') + + build_essential do + compile_time true + end + + package("libpq-dev") { action :nothing }.run_action(:install) + + chef_gem 'pg' do + compile_time true + end + + user "postgres" do + manage_home false + end + + postgresql_server_install "main" do + version postgresql_version + setup_repo true + password postgresql_credentials['server_password'] + action :install + end + + service postgresql_service do + supports restart: true, status: true, reload: true + action [:enable, :start] + end + + # This service is a dependency that will auto-start our cluster service on + # boot if it's enabled, so we disable it explicitly + service "postgresql" do + action :disable + end + + shared_buffers = if node['memory']['total'].to_i / 1024 < 1024 # < 1GB RAM + "128MB" + else # >= 1GB RAM, use 50% of total RAM + "#{node['memory']['total'].to_i / 1024 / 2}MB" + end + + additional_config = { + max_connections: 200, # default + shared_buffers: shared_buffers, + unix_socket_directories: "/var/run/postgresql", + dynamic_shared_memory_type: "posix", + timezone: "UTC", # default is GMT + listen_addresses: "0.0.0.0" + } + + additional_config[:promote_trigger_file] = "#{postgresql_data_dir}/failover.trigger" + + postgresql_server_conf "main" do + version postgresql_version + additional_config additional_config + notifies :reload, "service[#{postgresql_service}]", :delayed + end + + postgresql_user "replication" do + action :create + replication true + password postgresql_credentials['replication_password'] + end +end + +action_class do + # to use the data_dir helper + include PostgresqlCookbook::Helpers +end