From 6af6404c6357a7003e1ca677756c529bb0da30a6 Mon Sep 17 00:00:00 2001 From: Maxim Likhachev Date: Sun, 27 Mar 2022 17:27:57 +0000 Subject: [PATCH] Greenplum provisioning Ansible role --- .ansible-lint | 8 ++ Makefile | 33 +++++ README.md | 93 ++++++++++++++ add-users.yml | 27 ++++ ansible.cfg | 26 ++++ ...-2.5.4+pivotal.2.build.3-gp6-rhel7-x86_64.gppkg | 1 + files/rpm/greenplum-db-6.7.0-rhel7-x86_64.rpm | 2 + inventory/sample/files/ssh/gpadmin | 89 +++++++++++++ inventory/sample/files/ssh/gpadmin.pub | 25 ++++ inventory/sample/files/ssh/provision | 89 +++++++++++++ inventory/sample/files/ssh/provision.pub | 25 ++++ inventory/sample/group_vars/all/all.yml | 68 ++++++++++ inventory/sample/hosts.ini | 10 ++ roles/common/defaults/main.yml | 8 ++ roles/common/handlers/main.yml | 12 ++ roles/common/tasks/dependencies.yml | 11 ++ roles/common/tasks/disks.yml | 65 ++++++++++ roles/common/tasks/firewall.yml | 9 ++ roles/common/tasks/kernel.yml | 24 ++++ roles/common/tasks/limits.yml | 25 ++++ roles/common/tasks/main.yml | 15 +++ roles/common/tasks/ssh.yml | 55 ++++++++ roles/common/tasks/sysctl.yml | 143 +++++++++++++++++++++ roles/common/tasks/timezone.yml | 6 + roles/common/tasks/users.yml | 25 ++++ roles/greenplum-master/defaults/main.yml | 16 +++ roles/greenplum-master/handlers/main.yml | 39 ++++++ roles/greenplum-master/tasks/extensions.yml | 93 ++++++++++++++ roles/greenplum-master/tasks/init.yml | 106 +++++++++++++++ roles/greenplum-master/tasks/main.yml | 46 +++++++ roles/greenplum-master/tasks/roles.yml | 29 +++++ .../templates/gpinitsystem_config.j2 | 71 ++++++++++ .../templates/greenplum.service.j2 | 29 +++++ .../templates/hostfile_gpinitsystem.j2 | 3 + roles/greenplum-segment/defaults/main.yml | 4 + roles/greenplum-segment/tasks/main.yml | 14 ++ roles/greenplum/defaults/main.yml | 15 +++ roles/greenplum/tasks/extensions-contrib.yml | 111 ++++++++++++++++ roles/greenplum/tasks/main.yml | 67 ++++++++++ roles/ntpd/defaults/main.yml | 8 ++ roles/ntpd/handlers/main.yml | 16 +++ roles/ntpd/tasks/main.yml | 17 +++ roles/ntpd/templates/ntp.conf.j2 | 60 +++++++++ roles/prometheus-exporter/defaults/main.yml | 19 +++ roles/prometheus-exporter/handlers/main.yml | 16 +++ roles/prometheus-exporter/tasks/main.yml | 27 ++++ .../templates/postgres_exporter.service.j2 | 27 ++++ site.yml | 46 +++++++ 48 files changed, 1773 insertions(+) create mode 100644 .ansible-lint create mode 100644 Makefile create mode 100644 README.md create mode 100644 add-users.yml create mode 100644 ansible.cfg create mode 100644 files/pkg/postgis-2.5.4+pivotal.2.build.3-gp6-rhel7-x86_64.gppkg create mode 100644 files/rpm/greenplum-db-6.7.0-rhel7-x86_64.rpm create mode 100644 inventory/sample/files/ssh/gpadmin create mode 100644 inventory/sample/files/ssh/gpadmin.pub create mode 100644 inventory/sample/files/ssh/provision create mode 100644 inventory/sample/files/ssh/provision.pub create mode 100644 inventory/sample/group_vars/all/all.yml create mode 100644 inventory/sample/hosts.ini create mode 100644 roles/common/defaults/main.yml create mode 100644 roles/common/handlers/main.yml create mode 100644 roles/common/tasks/dependencies.yml create mode 100644 roles/common/tasks/disks.yml create mode 100644 roles/common/tasks/firewall.yml create mode 100644 roles/common/tasks/kernel.yml create mode 100644 roles/common/tasks/limits.yml create mode 100644 roles/common/tasks/main.yml create mode 100644 roles/common/tasks/ssh.yml create mode 100644 roles/common/tasks/sysctl.yml create mode 100644 roles/common/tasks/timezone.yml create mode 100644 roles/common/tasks/users.yml create mode 100644 roles/greenplum-master/defaults/main.yml create mode 100644 roles/greenplum-master/handlers/main.yml create mode 100644 roles/greenplum-master/tasks/extensions.yml create mode 100644 roles/greenplum-master/tasks/init.yml create mode 100644 roles/greenplum-master/tasks/main.yml create mode 100644 roles/greenplum-master/tasks/roles.yml create mode 100644 roles/greenplum-master/templates/gpinitsystem_config.j2 create mode 100644 roles/greenplum-master/templates/greenplum.service.j2 create mode 100644 roles/greenplum-master/templates/hostfile_gpinitsystem.j2 create mode 100644 roles/greenplum-segment/defaults/main.yml create mode 100644 roles/greenplum-segment/tasks/main.yml create mode 100644 roles/greenplum/defaults/main.yml create mode 100644 roles/greenplum/tasks/extensions-contrib.yml create mode 100644 roles/greenplum/tasks/main.yml create mode 100644 roles/ntpd/defaults/main.yml create mode 100644 roles/ntpd/handlers/main.yml create mode 100644 roles/ntpd/tasks/main.yml create mode 100644 roles/ntpd/templates/ntp.conf.j2 create mode 100644 roles/prometheus-exporter/defaults/main.yml create mode 100644 roles/prometheus-exporter/handlers/main.yml create mode 100644 roles/prometheus-exporter/tasks/main.yml create mode 100644 roles/prometheus-exporter/templates/postgres_exporter.service.j2 create mode 100644 site.yml diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..ebfbeca --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,8 @@ +--- + +skip_list: + - empty-lines + - colons + - commas + - braces + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6d894bf --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +CLUSTER ?= sample +SSH_USER ?= $(USER) +SSH_KEY ?= $(USER)/.ssh/id_rsa + +PROVISION_USER ?= provision +VAULT_FILE ?= .ansible_vault + +ANSIBLE := ansible-playbook --user $(SSH_USER) --private-key $(SSH_KEY) --vault-password-file $(VAULT_FILE) --become --extra-vars "deploy_cluster=$(CLUSTER) provision_user=$(PROVISION_USER)" +ANSIBLE_CFG := ansible.cfg +HOSTS := inventory/$(CLUSTER)/hosts.ini + +help: ## Display this help. + @awk 'BEGIN { \ + FS = ":.*##"; \ + printf "\nUsage:\n make \033[36m\033[0m\n\nTargets:\n" \ + } \ + /^[a-zA-Z_-]+:.*?##/ { \ + printf " \033[36m%-10s\033[0m %s\n", $$1, $$2 \ + } \ + END { \ + print \ + }' \ + $(MAKEFILE_LIST) + + +install: provision ## Provision Greenplum cluster + +provision: ## Provision Greenplum cluster + ANSIBLE_CONFIG=$(ANSIBLE_CFG) $(ANSIBLE) -i $(HOSTS) site.yml + +users: ## Create extra users + ANSIBLE_CONFIG=$(ANSIBLE_CFG) $(ANSIBLE) -i $(HOSTS) add-users.yml + diff --git a/README.md b/README.md new file mode 100644 index 0000000..8efd526 --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# Deploy a Greenplum Cluster + +![Greenplum Logo](https://s3.amazonaws.com/greenplum.org/wp-content/uploads/2017/08/11004213/logo-greenplum.png) + +----- + +## Description + +This repository contains Ansible the following roles which could be used to +provision [Greenplum Database](https://greenplum.org/) cluster: + +- [common](roles/common) configures the servers according to [official reccomendations](https://gpdb.docs.pivotal.io/6-7/install_guide/prep_os.html). +- [ntpd](roles/ntpd) installs ntp server with the [Russian time pools](https://www.pool.ntp.org/zone/ru). +- [greenplum](roles/greenplum) installs the main greenplum package. +- [greenplum-segment](roles/greenplum-segment) creates necessary directory tree for proper segment node work. +- [greenplum-master](roles/greenplum-master) configures a master node and initializes the cluster. +- [prometheus-exporter](roles/prometheus-exporter/) uses [postgres_exporter](https://github.com/wrouesnel/postgres_exporter) to provide database metrics. + +## Requirements + +- [Ansible](https://ansible.com/) v2.9.x. +- GNU Make. + +## Hardware + +It is possible to install Greenplum cluster on one server which will be used as +master and segment. + +## Greenplum distributive and extensions + +### Greenplum installation package + +Greenplum RPM files should be placed into [files/rpm/](files/rpm/) directory. A +new Greenplum version can be downloaded from the +[official website](https://network.pivotal.io/products/pivotal-gpdb/#/releases/) +(it requires registration). + +### Greenplum modules and extensions + +All additional modules supported by default are listed on the +[Greenplum website](https://gpdb.docs.pivotal.io/6-4/ref_guide/modules/intro.html). + +By default this Ansible role installs **and adds them to default database template** +the following extensions. + +#### [hstore](https://gpdb.docs.pivotal.io/6-4/ref_guide/modules/hstore.html) + +It provides a data type for storing sets of key/value pairs within a single +PostgreSQL value. + +#### [PostGIS](https://gpdb.docs.pivotal.io/530/ref_guide/extensions/postGIS.html). + +PostGIS is a spatial database extension for PostgreSQL that allows GIS +(Geographic Information Systems) objects to be stored in the database. The +Greenplum Database PostGIS extension includes support for GiST-based R-Tree +spatial indexes and functions for analysis and processing of GIS objects. + +----- + +## Usage + +### 0. Make an inventory + +[Sample inventory](inventory/sample/) may be used as a sample cluster manifest. To +make a new cluster just copy this directory to another one and adjust variables +and hosts IP addresses: + +```sh +$ copy -r inventory/sample inventory/new-cluster +$ vim inventory/new_cluster/hosts.ini +$ vim inventory/new_cluster/group_vars/all/all.yml +``` + +----- + +### 1. Make the SSH key for a new user and upload it to remote servers + +```sh +$ ssh-keygen -C new_user@new_cluster -f inventory/new_cluster/files/ssh/new_user + +$ make users PROVISION_USER=new_user +``` + +This command creates user on remote servers, configures sudoers file and +uploads the SSH key. All further Ansible playbooks will be executed under this +user. + +### 2. Provision the Greenplum cluster + +```sh +$ make provision CLUSTER=new_cluster SSH_USER=new_user SSH_KEY=inventory/new_cluster/files/ssh/new_user +``` + diff --git a/add-users.yml b/add-users.yml new file mode 100644 index 0000000..61b099c --- /dev/null +++ b/add-users.yml @@ -0,0 +1,27 @@ +--- + +- hosts: greenplum_cluster + become: yes + tasks: + - name: Create user to deploy greenplum cluster + user: + name: "{{ provision_user }}" + comment: User for configuring greenplum cluster + shell: /bin/bash + + - name: Configure sudo for {{ provision_user }} user + copy: + dest: "/etc/sudoers.d/{{ provision_user }}" + content: "{{ provision_user }} ALL=(ALL) NOPASSWD: ALL" + + - name: Upload SSH Key + authorized_key: + user: "{{ provision_user }}" + key: "{{ lookup('file', '../inventory/' ~ deploy_cluster ~ '/files/ssh/' ~ provision_user ~ '.pub') }}" + state: present + + - name: Restart SSH service + service: + name: sshd + state: restarted + diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..9bd41c1 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,26 @@ +[ssh_connection] +pipelining=True +ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no + +[defaults] +strategy_plugins = plugins/mitogen/ansible_mitogen/plugins/strategy +force_valid_group_names = ignore + +force_color = 1 + +host_key_checking=False +gathering = smart +fact_caching = jsonfile +fact_caching_connection = /tmp +fact_caching_timeout = 7200 +stdout_callback = default +display_skipped_hosts = no +library = ./library +callback_whitelist = profile_tasks +roles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/roles +deprecation_warnings=False +inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds, .gpg + +[inventory] +ignore_patterns = artifacts, credentials + diff --git a/files/pkg/postgis-2.5.4+pivotal.2.build.3-gp6-rhel7-x86_64.gppkg b/files/pkg/postgis-2.5.4+pivotal.2.build.3-gp6-rhel7-x86_64.gppkg new file mode 100644 index 0000000..7995775 --- /dev/null +++ b/files/pkg/postgis-2.5.4+pivotal.2.build.3-gp6-rhel7-x86_64.gppkg @@ -0,0 +1 @@ +Sample package. diff --git a/files/rpm/greenplum-db-6.7.0-rhel7-x86_64.rpm b/files/rpm/greenplum-db-6.7.0-rhel7-x86_64.rpm new file mode 100644 index 0000000..7f73a09 --- /dev/null +++ b/files/rpm/greenplum-db-6.7.0-rhel7-x86_64.rpm @@ -0,0 +1,2 @@ +Greenplum packages can be found on the following page: +https://network.pivotal.io/products/pivotal-gpdb/#/releases/. diff --git a/inventory/sample/files/ssh/gpadmin b/inventory/sample/files/ssh/gpadmin new file mode 100644 index 0000000..43eb31e --- /dev/null +++ b/inventory/sample/files/ssh/gpadmin @@ -0,0 +1,89 @@ +$ANSIBLE_VAULT;1.1;AES256 +64386230616362663936343661373733396230393037623832376261306461393136386639356332 +3035646262386138636235636130663038633135666563300a353033393164306639326564383131 +62646333653339626466623935376463613437353363623238646363613134303936303462363765 +3366643930666464350a343137376333373062366333613839323537373763386233356437376363 +39653566616164346134306439633732343832643562633634396538373937626235383862643533 +65333865626661643262323938383566613166613061643261643861663962633738646564316664 +30306161663766656238376430653930386136386462643535373464623063383739386661636163 +61393235326166306438373839313231616139373235303266343237346165643366333964333035 +33666233303566383132386564393661313963616439623566353463623430646534303137656533 +39383435376235316563306530313763353832643966373730623834666436343665653839343334 +64343264663432303864366330373034653138333035363765366438326463643961323862656561 +36343233373439316362666138373137383861363732336165623837303662366332393137663131 +38636339663461373137663063356232353166323133616135346632333364653632623765313062 +61313562303365336233386565336561663263653761303138643962633536333262333037323330 +30633362333030633532316435653238303834336464636537623164336164383633346635323333 +39363231303531333338383861663230326239356463336339323537346563653861373433323433 +31333836633238656431343136623764363666303731353830393037613935373832353262386434 +34336239386637313266373339333737616234663461306431306666303066666631333134663462 +32613233366630386337656330626134316432333630373263643537633561303764663432343230 +31373930663961643233303132393762623637636461396438643531376263633236656332393762 +32383737633436323261363432346664633437646564643463636534393833383937356265346331 +63643762353332316563613031643236343131323037356231316362623935643262653239313964 +32396438353936323265393135333830386435613832613435616331383438336364373930313835 +65663462356664353137353439323437643365653532643961313433663736343465313339373632 +39336537373337643138303063383231653335613764383139373030656362353466356165393665 +61666330646130666636303736393731666531396136373665663564383066356564636634356535 +35646136313436643730343332643866643832353431366238613936623939343966646465393130 +63636433633033306663633530643161613532303438636261303563376335336363613634396533 +66323835393933653262376435383766656431306339626637356234366439653234633435323364 +61313839313131373239646336346231326462376661346637386662613266313637656536323762 +32623662633263366638376362626538643166656237646561313365303536303931633035323437 +63333764336330386631373837383135373838373962393830326466636539663461363263376661 +32616434626566343063393139333264326139393938386262333838313063353030386430326531 +61383532373065376363303264316361633732326130363463333230333765363864633330373032 +66396132643737326137623031626363366562663137386530393034303334306337393932356234 +33633064373263623631346632383333653332363236663335393465633933626664336433653837 +31353730363362393037393930303636626532366630306637393861356330636139356635343737 +63393336336130303064613033653431366361396161313163646432353964663831363266333031 +34396462356137333533386330333038666661326137396262393062313161616261383233613962 +61323966336662373030373032333062313361353063343134666232333838346162613538643631 +37316463346561383130383263633736313533616533653137353562373937623235346635363264 +61366233353233643663666230303736666232366262616564356435333463383165363962623739 +62373339343366626135653164343637326437343139313432373735383335373139643266326232 +30643832376466363430353032373730306163383633383361383233626330613131383966663831 +35613931646435303437343334656334393734316531396136633666623938376361336337616563 +61353862353161343661343635366436383230323261666162363062353833353738653433613332 +39636562393533356637616533323265636237316465386635386463356134653537623635626337 +61316531376637323062396565326462653130396134376232333433626161646162346564323061 +31636432616663633662323138313934653633346336626435393739353038636533393062613333 +32383038326635363766373466626637363166623466343062316336333136313264333935373138 +63613537623838376336623136313238383863316464666539326139356162633437356461353034 +38363066343134653234643634393663666562633337363337326165393437646331393932636337 +33653734613532656230346665643035366138323864396537653238383731363530666433376634 +35346165346264363964383032336630663138346465323330363635326437636633306638636462 +66306335663737663664336139626461303136343164636637663666363731373832353235363134 +39343331636333373935626533323635366239656639636135356438626635323766383264346565 +35643431396434346166386564396631643631356137356434656666396164306531666163653533 +35613461343634633635323964613330663462656165346563333631616438333732626166336166 +32663936313238336437306463616237366461336563346431363232356239363033623530633666 +30623036623637623230333134666431303065616533393239633964626435336561316439633632 +30386164346231616638653233663437356434663338393865393332643533393636663733336665 +66613330393939653161303661656566653835643563613661353939316563313439663434393066 +31333034303665623237356165313866323939356465313164366165316465376637656538373839 +38653238643231316531613239343964653763383935656562333933303865393661343839363865 +66313535356639393038356638356132616534656566333466616431633131336637613437613237 +61383638633134663439373430613761626565393762333130373938643238373664306161363931 +38383061393836646533396530626530646665393066393363366438333861333131613665656635 +30633061303630666166326433663635663365346161316339653535333530343563396137313236 +31633932303262396530373262393533333064616664666565303862616264623137356330663435 +65623263303632333865363733333131383465326566643963613963613931326631386437653131 +30616232356438613961373561653939343936616464323966306562613964316265623365303032 +37316462323231366339663831336231313331636338633262636563343039666636646663633830 +36306338333938353264643235643966373830353163313937313966336339376533633032633037 +65303961616365656538386639366532373433366366396231646236613063366333643166363836 +39396363383961386261653139346334623261383430313230663236633037333465613134636436 +31306132366436333364333736663934356237663531353732653331353938306331366263623436 +39666264353830383735623935323863333539653132316139373034356564363562323339353537 +34373439663166366134373966323339643239353938623836353134316433363639346432386166 +36303463333463333938353131316133346638336264633336646537383034373030353863656434 +63623638353035653035633865666133646637356333636266653333313037316639373832323462 +31346632376463313938653264366265333564303762313932333537396362333934656434373033 +31653335383461333063316137623866313064373365363663633134613364646332663933613037 +33333737313033393466303562653336656266636532646132306539373738323662393739386231 +34663731626162636262636638353766633262373835363065313730393266376133323464656564 +63303237343134393361313239316330663130333532656336396232666534326463343634653131 +61356664653331393135336435396462363263303562366562336362666532333263646336346233 +36363733383231353866636465356136396561306638336430636464326562383038326236353935 +66306433613761663264 diff --git a/inventory/sample/files/ssh/gpadmin.pub b/inventory/sample/files/ssh/gpadmin.pub new file mode 100644 index 0000000..d679a80 --- /dev/null +++ b/inventory/sample/files/ssh/gpadmin.pub @@ -0,0 +1,25 @@ +$ANSIBLE_VAULT;1.1;AES256 +33383862643130376538663834303564313838633431366333303564313737653563646263353163 +6132323836356232333366633863333732303236353566630a313664623630366564393662313335 +35386137636131623537303537343230343963346134633966343233383536663135366236383139 +6464383539613563660a323335323532333961333235346663373130326130316564346331616234 +30633266313539333165656634396161623463356163303435333035363937326135663762373366 +38393539363463383862316335393363346465393237366133633261323037613033363663666635 +32306435626161333332313037376634356338373433383936643838666130306530616438376264 +32623162613930353238623936366535643535356632636137656137636563373030373535343063 +38633731343630623633313932333462326266623965653533653563656166623464613138616139 +31383065363864623163653036373630636136393137393432636665323737323633386564336362 +31386138663863323538393964396137333537653637623838653633393935376361353963306166 +35616633633838303865393161613161353433346235313936323733656466376537326533636232 +63636163626634643033313332336638313135303830633433623330336162303031646331393238 +37313965663939383736323338386561636535633235306538366364363430363162383034646634 +35623332663934643135376336613039393831663135623561643336653263303861353466336132 +30663630636331626633393039373434653631306464336464623765636331323965643037303364 +37613436333939383434313133633562393037336265613863636430356331333861613065623739 +64393063393964336138323838303332613836323636376637616534663865313830646132613933 +31353262313136376637613438666439396138616266323765646230643937373331306561326630 +65356664383134313164326633333839366430383662636263376161616433626539353130343138 +30396535343364653738633164383138323066336636373932663432663065616432363934333362 +32383937616539363139323432376333363065366261616363313336353862653634336365373062 +37323839346336313030623266616465623462346134323965346162653866646561363934623235 +35326465613564353234 diff --git a/inventory/sample/files/ssh/provision b/inventory/sample/files/ssh/provision new file mode 100644 index 0000000..14256f6 --- /dev/null +++ b/inventory/sample/files/ssh/provision @@ -0,0 +1,89 @@ +$ANSIBLE_VAULT;1.1;AES256 +31373634383765343932613762623963663832646666623039386531616131633964616430363333 +6138663133313931333861383031356338323535353162660a393661303362616138353062626333 +31616263376362353538303466643563363038343034313333366336653832336263656636626362 +6436633539653935370a616530343536343936356165326638393933653038613666393437663834 +33663361376236356630663761393264646439643733303334663934353131356632376333646237 +32636362613839313038303835373930323535336666613239363538633462643734363533336631 +63323738353538653432326566633066656431303864626537636638333731303230656639653637 +33323766363332313363643264616338623863356239623533613431343439383937636330333437 +35363131623838313865623838356366663530633737396239376362336463383665323239356430 +32343532396638623435366135393866653430323961626230656339383563306639356235633339 +37633532376434653730663334656135336330346266313535636232336263633833373261646231 +65303638393462373538343836356661366363373739616133323636396663393461653831356138 +33303333313763383732343833343438333861343365316437613733363935626330383231653839 +65323434333661316632303736366237633939393630323164383239646464663266396665323166 +62653936656165616230393534393039653563343561633034353863383331346462653765363235 +62306564346536393065653332643934313339366332643637613137623935643062666331653335 +36393633353832383266333333333639663165386230333431336430333035333537346335383035 +38623938313739313736373834393661393136383131623365393639653736353464346139653261 +61646236363438336436326335316161373834333333313530326661333532653639303663626264 +65396165383365313364636536646261323638613262303462643539646338336231663663636165 +62303361656161366533613437323938663931623633623461373766353130653137666639656138 +66646664313037623932396637306533386466383162646631393739623538393134333366666435 +65376332323533313130303038663030323035656638623737626232613335623632396430646531 +32626461366438336561393436643236656636313833623934643761643165363833303338386133 +39383131616334356234383333303234333166326564396530643464643935393339343135366439 +66653530333761333632386230313730383364643735306435303462363336366531313538306662 +65643830393634663436386665633264643633663830336231653264356430326434626534306161 +36626165383638653639393437353833303764373735663731323534393062373137323962313737 +62363039613234616538373731623835663139616264373238383866373465343639353832643135 +63666264396333353330346364623061666433643338656266306261613430636565393437346430 +34633731643937666339613865363131636134623338613639363764333761353361353233383934 +34383136303061313064663630343363373637666338333033393933363063313735326332343962 +64313433616335626330343133316635396532373331623332666463623266366637326139643731 +38626634303363383532303438386665333864623330353366356236353530386461643939363430 +37366364656462393237623163336537643432313937343831396161336264386437643130616563 +61646365383630623532663833363838393961303165656437653564383732386531393364316565 +66666363383736666234666436623765623463316635653936613134303232306463633039326131 +37333766356166323465666264613166633936663838306536616333386366643062343066396231 +65653430666531303264316638656630326134346563643561386438366165656535316139356439 +63373864633961646534356139386363666138626362666435353130333935623964323337396361 +62653362636562346134376132613362383839643635353233393862663761616439363037366335 +65303565623139666337363266643033366536366539323438613364633566306339383833333634 +62336366383965353731393536366362376638343033383638663366396261396336313932613334 +65626330373063666563353061663337336366613731376661613665646538653934633339333833 +38313734363037336262383038636463356361626238633332386439363436323961366161643163 +34616161663364346166386135316161323466323233356638643238393762383261303562666466 +37636263303966326234373363363933373631613535623535323638383561643738336639373864 +30326162313165313039616166356365623561643862333763366363653132313861313334636665 +30386234346165636363393230346166666334616231633634393130373963623861643339643132 +35303835353031393964633238623666666366636561326264326231343065626663393632366564 +63643465616132356633373439653664333165643366306163633863333163663364663736343039 +33343238333630363334663730623265353339613362393830393138336437633561643162626232 +32623633363836333133303066383732396466363334653864643063386433623236393335643761 +62343931343533613030623435373766666364383536343836396233366131303064376265633563 +37623633626230613739623065386135393632323263383463353639393730663563663961616462 +37316263656233383465363065613836663261346133333838326566306337633735306338316234 +37333334333462616639643839663831363863313837616464376634613132326631656464393439 +36653962613866626161383734323865363632393430616435373366373838643762623534303433 +34353235646364313434633637373138306162333435353139613839633835626432383334646235 +63613964616430666337636363323133636632376538313733323863396265393762373836346366 +62393239333030313333383862383333643135646461363461663763323061616165623236663837 +65666461386536393763366631643338323336393936363330656361613331303465363731393135 +66396262643165653862646361393136643662626162666563356363353030383230396436326133 +36393762323937646662313130313433376437383863333137326139656337353332393831336333 +38663662356239396665653436613432363265353638393461643633623765616132633334343335 +39343830313062303263363061666635646133353639396335646632333830383564613636616161 +62363936306232633333393434616637363239656662316336653963323165343464343939333936 +38386230363034393637353864346438333965646536626532323261636566616162383330343831 +35336430373162383962653735373364356664313537616132323066323031336664376636653966 +38356361626161303561313335623433623539326236366465663662656364663833633138303239 +33333733326264336565323730313139363739373664613236303939323161653734626136343265 +32626565356130363965343535393933663566313131626532333332636565663335643762386262 +35346566376639633133303665376233393962386562386134303833396235376264373265623261 +65323531633932373334386437623661383238616366623936363130336638303437393630303735 +66306465316436333434356631643161613633366334353137336561343234666230633336316364 +66393461623232393333373561653033653333393438373965633862363335396433366664373966 +34333532396132653234623535363961633764643662656233383332643165393863383338343334 +33626132626638373537643961653461396362323731663438353735353237333833623735643466 +61346638663064623737363064366634363237363262623962356133303939346339393165336636 +64343266626363643465613537326464656233613131323035636333643166323264623965323334 +65383130363566376162376534616661343234613666636263666166313864376665356438616266 +30386430313363613438386532643337383261663361616436313539353139313035376236663735 +35646331396232626565623730336231666465383866323466396539653866313930396630633639 +31343135393533663462303463663039356632323132326530353331363634333130323834646330 +63633537653963663033643936626263376661623164356532613164656264623963616265356635 +66363934656363346530653932633236393265313937313130393533633631313439303363633663 +38383538663564363761353162366435333637353565303431323033373261383563303061623136 +32346532646534323530 diff --git a/inventory/sample/files/ssh/provision.pub b/inventory/sample/files/ssh/provision.pub new file mode 100644 index 0000000..4fe2f51 --- /dev/null +++ b/inventory/sample/files/ssh/provision.pub @@ -0,0 +1,25 @@ +$ANSIBLE_VAULT;1.1;AES256 +31616466353563373530653730633765303565303032656137383732333137396366626437336136 +3130316365633839343962643761306433336463346366660a313332633836356464356562313561 +31323930656239386539346539616561646433623835633830363961363933663931386665636539 +3964306531623661360a646464613630383263376231623566386339386162343834383463363564 +35393939636639343230653630663033366631386565383131663134326266353066623061363766 +65663363366638643761313339303635626235393261633937653934633764346665653335653835 +39313330303737643662366230626562643031316638303032333034363238306432396231346531 +35643036653631663830666564643030363839626333333431626466356232343066613731616133 +64316330663439363366323732363136303561326333353439346434383332316261616263303232 +32346438343332303932376564383263396237326436646135636430633761626538323735366664 +61656138383532666263656336396464666232663735623765623830613830316436376462653034 +64326436303933333639616537666561376464396633333539326466333230636162393162316633 +30613864626332316363613539616330643665303030343762323465326235643336316539366130 +64393733623730343865653162393330383761326666356339393162653732376161666131623331 +36633866356361386630336633356534303837393935356632333738653636326465376430303636 +63656138356238366438323332323263623133376435633662323261363336333136313732376433 +66383739386566646238316439316131323364613337313734623831623932376132346538366665 +32643365303262643331653664383436636636633934336636636166306436623039376566646437 +66373731393438366430336632326336633965653833653566306334303333356136336234623031 +65303166313936343530313932313034306463646530633235303265666136636632393564366536 +36643264643337323139633563366663363735393664396634386538643963383439656365373237 +66383435646534303739393462316334646566396436623465663064333665333363393237383339 +38323464376538656137663839313839333266346238643438313931303961333234366631333765 +30663335313738623365 diff --git a/inventory/sample/group_vars/all/all.yml b/inventory/sample/group_vars/all/all.yml new file mode 100644 index 0000000..5d9ae4a --- /dev/null +++ b/inventory/sample/group_vars/all/all.yml @@ -0,0 +1,68 @@ +--- + +timezone: UTC + +greenplum_group: gpadmin +greenplum_user: gpadmin +greenplum_user_id: 10000 +greenplum_user_profile_file: "~{{ greenplum_user }}/.bashrc" + +greenplum_sudo: false + +greenplum_master_port: 5432 + +greenplum_src_directory: /opt/src + +greenplum_data_directory: /opt/data +greenplum_master_directory: "{{ greenplum_data_directory }}/master" + +greenplum_postgis_databases: + - postgres + - template1 # enable PostGIS for all new databases by default + +greenplum_extensions: + - name: hstore + databases: + - template1 # enable hstore extencion for all new databases by default + +greenplum_config_directory: /opt/gpconfig + +# Maximum log file segments between automatic WAL checkpoints. +greenplum_check_point_segments: 8 + +#### Base number by which primary segment port numbers are calculated. +greenplum_port_base: 6000 + +#### Naming convention for utility-generated data directories. +greenplum_seg_prefix: gpseg + +postgres_exporter_enabled: true +postgres_exporter_host: "127.0.0.1:5432" +postgres_exporter_database: "postgres" +postgres_exporter_user: gpmon +postgres_exporter_password: password + +# - { contype: host|local, source: ::1, databases: "postgres,db1,db2", users: "admin,dev,qa", method: md5|ident|password|peer|trust|... } +greenplum_trusted_hosts: + - contype: host + source: 172.22.0.0/16 + databases: all + users: dev + method: md5 + + - contype: host + source: 127.0.0.1/32 + databases: all + users: "{{ postgres_exporter_user }}" + method: md5 + +# - { name: user, password: , superuser: true|false, groups: [group1, group2] } +greenplum_users: + - name: dev + superuser: true + password: password + + - name: "{{ postgres_exporter_user }}" + superuser: true + password: "{{ postgres_exporter_password }}" + diff --git a/inventory/sample/hosts.ini b/inventory/sample/hosts.ini new file mode 100644 index 0000000..5b1f5ee --- /dev/null +++ b/inventory/sample/hosts.ini @@ -0,0 +1,10 @@ +[all] + +greenplum_master ansible_host=10.2.3.4 greenplum_hostname=greenplum-cluster + +[greenplum_segments] +greenplum_master + +[greenplum_cluster] +greenplum_master + diff --git a/roles/common/defaults/main.yml b/roles/common/defaults/main.yml new file mode 100644 index 0000000..a38d58d --- /dev/null +++ b/roles/common/defaults/main.yml @@ -0,0 +1,8 @@ +--- + +greenplum_group: gpadmin +greenplum_user: gpadmin +greenplum_user_id: 10000 + +greenplum_sudo: false + diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml new file mode 100644 index 0000000..04c7d63 --- /dev/null +++ b/roles/common/handlers/main.yml @@ -0,0 +1,12 @@ +--- + +- name: enable rc.local + ansible.builtin.file: + path: /etc/rc.local + mode: 0744 + +- name: restart sshd + ansible.builtin.service: + name: sshd + state: restarted + diff --git a/roles/common/tasks/dependencies.yml b/roles/common/tasks/dependencies.yml new file mode 100644 index 0000000..b458c7a --- /dev/null +++ b/roles/common/tasks/dependencies.yml @@ -0,0 +1,11 @@ +--- + +- name: Install Greenplum dependencies and common packages + ansible.builtin.package: + state: present + name: + - xerces-c-devel + - python-psycopg2 + - python-ipaddress + - libzstd + diff --git a/roles/common/tasks/disks.yml b/roles/common/tasks/disks.yml new file mode 100644 index 0000000..4207782 --- /dev/null +++ b/roles/common/tasks/disks.yml @@ -0,0 +1,65 @@ +--- + +# +# XFS is the preferred data storage file system on Linux platforms. Use the +# mount command with the following recommended XFS mount options for RHEL and +# CentOS systems: +# +# rw,nodev,noatime,nobarrier,inode64 +# +# The nobarrier option is not supported on Ubuntu systems. Use only the +# options: +# +# rw,nodev,noatime,inode64 +# + +- name: disks | Set mount options for / + ansible.builtin.mount: + path: "/" + src: "UUID={{ ansible_mounts | json_query('[?mount == `/`] | [0].uuid') }}" + fstype: "xfs" + opts: "rw,nodev,noatime,nobarrier,inode64" + state: "present" + +- name: disks | Get all block devices + ansible.builtin.set_fact: + disks: "{{ disks|default([]) + [item.key] }}" + with_dict: "{{ ansible_devices }}" + when: item.key.startswith('sda') + +# +# Each disk device file should have a read-ahead (blockdev) value of 16384. +# + +- name: disks | Adjust block devices read-ahead settings + ansible.builtin.shell: "/sbin/blockdev --setra 16384 /dev/{{ item }}" + with_items: "{{ disks | default([]) }}" + tags: skip_ansible_lint + +- name: disks | Add blockdev command to rc.local file + ansible.builtin.lineinfile: + path: /etc/rc.local + line: "/sbin/blockdev --setra 16384 /dev/{{ item }}" + with_items: "{{ disks | default([]) }}" + notify: enable rc.local + +# +# The Linux disk I/O scheduler for disk access supports different policies, +# such as CFQ, AS, and deadline. +# +# The deadline scheduler option is recommended. To specify a scheduler +# until the next system reboot, run the following: +# + +- name: disks | Adjust block devices scheduler + ansible.builtin.shell: "echo deadline > /sys/block/{{ item }}/queue/scheduler" + tags: skip_ansible_lint + with_items: "{{ disks | default([]) }}" + +- name: disks | Adjust block devices scheduler during OS boot process + ansible.builtin.lineinfile: + path: /etc/rc.local + line: "echo deadline > /sys/block/{{ item }}/queue/scheduler" + with_items: "{{ disks | default([]) }}" + notify: enable rc.local + diff --git a/roles/common/tasks/firewall.yml b/roles/common/tasks/firewall.yml new file mode 100644 index 0000000..e9b2dc8 --- /dev/null +++ b/roles/common/tasks/firewall.yml @@ -0,0 +1,9 @@ +--- + +- name: Stop firewalld service + ansible.builtin.service: + name: firewalld + state: stopped + enabled: false + when: '"firewalld" in ansible_facts.services' + diff --git a/roles/common/tasks/kernel.yml b/roles/common/tasks/kernel.yml new file mode 100644 index 0000000..f86d9dc --- /dev/null +++ b/roles/common/tasks/kernel.yml @@ -0,0 +1,24 @@ +--- + +# +# Disable Transparent Huge Pages (THP) as it degrades Greenplum Database +# performance. RHEL 6.0 or higher enables THP by default. +# + +- name: kernel | Get current THP settings + ansible.builtin.shell: cat /sys/kernel/mm/*transparent_hugepage/enabled + changed_when: false + register: current_thp_mode + +- name: kernel | Show current THP settings + ansible.builtin.debug: var=current_thp_mode.stdout verbosity=2 + +- name: kernel | Disable Transparent Huge Pages + ansible.builtin.shell: "echo never > /sys/kernel/mm/transparent_hugepage/enabled" + tags: skip_ansible_lint + +- name: kernel | Disable Transparent Huge Pages by default + ansible.builtin.shell: 'grubby --update-kernel=ALL --args="transparent_hugepage=never"' + when: '"[never]" not in current_thp_mode.stdout' + tags: skip_ansible_lint + diff --git a/roles/common/tasks/limits.yml b/roles/common/tasks/limits.yml new file mode 100644 index 0000000..84c05c3 --- /dev/null +++ b/roles/common/tasks/limits.yml @@ -0,0 +1,25 @@ +--- + +# +# For Red Hat Enterprise Linux (RHEL) and CentOS systems, parameter values +# in the /etc/security/limits.d/90-nproc.conf file (RHEL/CentOS 6) or +# /etc/security/limits.d/20-nproc.conf file (RHEL/CentOS 7) override the values +# in the limits.conf file. Ensure that any parameters in the override file are +# set to the required value. +# + +- name: limits | Adjust PAM limits + community.general.pam_limits: + domain: '*' + limit_type: "{{ item.type }}" + limit_item: "{{ item.name }}" + value: "{{ item.value }}" + dest: "/etc/security/limits.d/20-nproc.conf" + loop_control: + label: "* {{ item.type }} {{ item.name }} {{ item.value }}" + loop: + - { type: 'soft', name: 'nofile', value: '524288' } + - { type: 'hard', name: 'nofile', value: '524288' } + - { type: 'soft', name: 'nproc', value: '131072' } + - { type: 'hard', name: 'nproc', value: '131072' } + diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml new file mode 100644 index 0000000..aba140e --- /dev/null +++ b/roles/common/tasks/main.yml @@ -0,0 +1,15 @@ +--- + +- name: Collect information about services + ansible.builtin.service_facts: + +- include: 'dependencies.yml' +- include: 'sysctl.yml' +- include: 'limits.yml' +- include: 'kernel.yml' +- include: 'disks.yml' +- include: 'timezone.yml' +- include: 'users.yml' +- include: 'firewall.yml' +- include: 'ssh.yml' + diff --git a/roles/common/tasks/ssh.yml b/roles/common/tasks/ssh.yml new file mode 100644 index 0000000..d0700c5 --- /dev/null +++ b/roles/common/tasks/ssh.yml @@ -0,0 +1,55 @@ +--- + +- name: Add current server IP addresses to /etc/hosts + ansible.builtin.lineinfile: + path: /etc/hosts + line: "127.0.0.1 {{ hostvars[item]['greenplum_hostname'] }} # {{ item }}" + with_items: "{{ groups['greenplum_cluster'] }}" + when: groups['greenplum_cluster'] | length == 1 + +- name: Add all Greenplum IP addresses to /etc/hosts + ansible.builtin.lineinfile: + path: /etc/hosts + line: > + "{{ hostvars[item]['ip_address'] if 'ip_address' in hostvars[item] else hostvars[item]['ansible_host'] }} {{ hostvars[item]['greenplum_hostname'] }} + # {{ item }}" + with_items: "{{ groups['greenplum_cluster'] }}" + when: item != inventory_hostname + +- name: ssh | Set proper MaxStartups value + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^MaxStartups' + line: 'MaxStartups 10:30:200' + notify: restart sshd + +- name: ssh | Set proper MaxSessions value + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^MaxSessions' + line: 'MaxSessions 200' + notify: restart sshd + +- name: Add public Greenplum SSH Key to authorized_key list + ansible.posix.authorized_key: + user: "{{ greenplum_user }}" + key: "{{ lookup('file', 'inventory/' ~ deploy_cluster ~ '/files/ssh/' ~ greenplum_user ~ '.pub') }}" + state: present + notify: restart sshd + +- name: Upload private Greenplum SSH Key + ansible.builtin.copy: + dest: "~{{ greenplum_user }}/.ssh/id_rsa" + src: "{{ 'inventory/' ~ deploy_cluster ~ '/files/ssh/' ~ greenplum_user }}" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + mode: 0600 + +- name: Upload public Greenplum SSH Key + ansible.builtin.copy: + dest: "~{{ greenplum_user }}/.ssh/id_rsa.pub" + src: "{{ 'inventory/' ~ deploy_cluster ~ '/files/ssh/' ~ greenplum_user ~ '.pub' }}" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + mode: 0600 + diff --git a/roles/common/tasks/sysctl.yml b/roles/common/tasks/sysctl.yml new file mode 100644 index 0000000..1927688 --- /dev/null +++ b/roles/common/tasks/sysctl.yml @@ -0,0 +1,143 @@ +--- + +- name: sysctl | Get PAGE_SIZE + ansible.builtin.shell: getconf PAGE_SIZE + register: page_size + changed_when: false + tags: skip_ansible_lint + +- name: Show PAGE_SIZE + ansible.builtin.debug: var=page_size.stdout verbosity=2 + +- name: sysctl | Get _PHYS_PAGES + ansible.builtin.shell: getconf _PHYS_PAGES + register: phys_pages + changed_when: false + tags: skip_ansible_lint + +- name: sysctl | Calculate optimal kernel_shmall value + ansible.builtin.set_fact: + kernel_shmall: "{{ (phys_pages.stdout|int / 2) | int }}" # kernel.shmall = _PHYS_PAGES / 2 # See Shared Memory Pages + +- name: Show kernel_shmall + ansible.builtin.debug: var=kernel_shmall verbosity=2 + +- name: sysctl | Calculate optimal kernel_shmmax value + ansible.builtin.set_fact: + kernel_shmmax: "{{ (kernel_shmall|int * page_size.stdout|int) }}" # kernel.shmmax = kernel.shmall * PAGE_SIZE + +- name: Show kernel_shmmax + ansible.builtin.debug: var="{{ kernel_shmmax }}" verbosity=2 + +- name: sysctl | Adjust sysctl settings + ansible.builtin.sysctl: + name: "{{ item.option }}" + value: "{{ item.value }}" + state: present + reload: true + loop_control: + label: "{{ item.option }} = {{ item.value }}" + loop: + - { option: 'kernel.shmall', value: '{{ kernel_shmall }}' } + - { option: 'kernel.shmmax', value: '{{ kernel_shmmax }}' } + - { option: 'kernel.shmmni', value: '4096' } + - { option: 'kernel.sem', value: '500 2048000 200 4096' } + - { option: 'kernel.sysrq', value: '1' } + - { option: 'kernel.core_uses_pid', value: '1' } + - { option: 'kernel.msgmnb', value: '65536' } + - { option: 'kernel.msgmax', value: '65536' } + - { option: 'kernel.msgmni', value: '2048' } + - { option: 'net.ipv4.tcp_syncookies', value: '1' } + - { option: 'net.ipv4.conf.default.accept_source_route', value: '0' } + - { option: 'net.ipv4.tcp_max_syn_backlog', value: '4096' } + - { option: 'net.ipv4.conf.all.arp_filter', value: '1' } + - { option: 'net.core.netdev_max_backlog', value: '10000' } + - { option: 'net.core.rmem_max', value: '2097152' } + - { option: 'net.core.wmem_max', value: '2097152' } + - { option: 'vm.swappiness', value: '10' } + - { option: 'vm.zone_reclaim_mode', value: '0' } + - { option: 'vm.dirty_expire_centisecs', value: '500' } + - { option: 'vm.dirty_writeback_centisecs', value: '100' } + + # The vm.overcommit_memory Linux kernel parameter is used by the OS to + # determine how much memory can be allocated to processes. For Greenplum + # Database, this parameter should always be set to 2. + - { option: 'vm.overcommit_memory', value: '2' } + + # vm.overcommit_ratio is the percent of RAM that is used for application + # processes and the remainder is reserved for the operating system. The default + # is 50 on Red Hat Enterprise Linux. + - { option: 'vm.overcommit_ratio', value: '95' } + + # To avoid port conflicts between Greenplum Database and other applications + # during Greenplum initialization, make a note of the port range specified by + # the operating system parameter net.ipv4.ip_local_port_range. When + # initializing Greenplum using the gpinitsystem cluster configuration file, do + # not specify Greenplum Database ports in that range. For example, if + # net.ipv4.ip_local_port_range = 10000 65535, set the Greenplum Database base + # port numbers to these values. + # + # PORT_BASE = 6000 + # MIRROR_PORT_BASE = 7000 + # + - { option: 'net.ipv4.ip_local_port_range', value: '10000 65535' } + +# Increase vm.min_free_kbytes to ensure PF_MEMALLOC requests from network +# and storage drivers are easily satisfied. This is especially critical on +# systems with large amounts of system memory. The default value is often far +# too low on these systems. +# +# Do not set vm.min_free_kbytes to higher than 5% of system memory as doing +# so might cause out of memory conditions. +# +- name: sysctl | Calculate optimal vm.min_free_kbytes value + ansible.builtin.set_fact: + vm_min_free_kbytes: "{{ (ansible_memtotal_mb|int * 1024 * 0.3) | int }}" + +- name: Show vm_min_free_kbytes + ansible.builtin.debug: var=vm_min_free_kbytes verbosity=2 + +# For host systems with more than 64GB of memory, these settings are recommended: +# +# vm.dirty_background_ratio = 0 +# vm.dirty_ratio = 0 +# vm.dirty_background_bytes = 1610612736 # 1.5GB +# vm.dirty_bytes = 4294967296 # 4GB +# +- name: sysctl | Adjust memory settings on hosts with 64+ Gb RAM + ansible.builtin.sysctl: + name: "{{ item.option }}" + value: "{{ item.value }}" + state: present + reload: true + loop_control: + label: "{{ item.option }} = {{ item.value }}" + loop: + - { option: 'vm.dirty_background_ratio', value: '0' } + - { option: 'vm.dirty_ratio', value: '0' } + - { option: 'vm.dirty_background_bytes', value: '1610612736' } + - { option: 'vm.dirty_bytes', value: '4294967296' } + - { option: 'vm.min_free_kbytes', value: '{{ vm_min_free_kbytes }}' } + when: ansible_memtotal_mb >= 65536 + + # For host systems with 64GB of memory or less, remove + # vm.dirty_background_bytes and vm.dirty_bytes and set the two ratio parameters + # to these values: + # + # vm.dirty_background_ratio = 3 + # vm.dirty_ratio = 10 + # +- name: sysctl | Adjust memory settings on hosts with <64 Gb RAM + ansible.builtin.sysctl: + name: "{{ item.option }}" + value: "{{ item.value }}" + state: present + reload: true + loop_control: + label: "{{ item.option }} = {{ item.value }}" + loop: + - { option: 'vm.dirty_background_ratio', value: '3' } + - { option: 'vm.dirty_ratio', value: '10' } + - { option: 'vm.min_free_kbytes', value: '{{ vm_min_free_kbytes }}' } + when: ansible_memtotal_mb < 65536 + diff --git a/roles/common/tasks/timezone.yml b/roles/common/tasks/timezone.yml new file mode 100644 index 0000000..0df0b20 --- /dev/null +++ b/roles/common/tasks/timezone.yml @@ -0,0 +1,6 @@ +--- + +- name: Set timezone to {{ timezone }} + community.general.timezone: + name: "{{ timezone }}" + diff --git a/roles/common/tasks/users.yml b/roles/common/tasks/users.yml new file mode 100644 index 0000000..82186e0 --- /dev/null +++ b/roles/common/tasks/users.yml @@ -0,0 +1,25 @@ +--- + +- name: users | Create Greenplum admin group + ansible.builtin.group: + name: "{{ greenplum_group }}" + gid: "{{ greenplum_user_id }}" + state: present + system: true # Prevent IPC connections removing when user logs out. + +- name: users | Create Greenplum admin user + ansible.builtin.user: + name: "{{ greenplum_user }}" + uid: "{{ greenplum_user_id }}" + group: "{{ greenplum_group }}" + comment: Greenplum admin user + system: true # Prevent IPC connections removing when user logs out. + shell: /bin/bash + +- name: users | Configure sudo for Greenplum admin user + ansible.builtin.copy: + dest: "/etc/sudoers.d/{{ greenplum_user }}" + content: "{{ greenplum_user }} ALL=(ALL) NOPASSWD: ALL" + mode: 0644 + when: greenplum_sudo + diff --git a/roles/greenplum-master/defaults/main.yml b/roles/greenplum-master/defaults/main.yml new file mode 100644 index 0000000..8b9e717 --- /dev/null +++ b/roles/greenplum-master/defaults/main.yml @@ -0,0 +1,16 @@ +--- + +greenplum_src_directory: /opt/src + +greenplum_data_directory: /opt/data +greenplum_config_directory: /opt/gpconfig + +greenplum_postgis_databases: + - template1 # enable PostGIS for all new databases by default + +# All supported extensions are listed here: https://gpdb.docs.pivotal.io/6-4/ref_guide/modules/intro.html +greenplum_extensions: + - name: hstore + databases: + - template1 # enable hstore extencion for all new databases by default + diff --git a/roles/greenplum-master/handlers/main.yml b/roles/greenplum-master/handlers/main.yml new file mode 100644 index 0000000..2e324bd --- /dev/null +++ b/roles/greenplum-master/handlers/main.yml @@ -0,0 +1,39 @@ +--- + +- name: enable greenplum service + ansible.builtin.systemd: + name: greenplum + state: started + enabled: true + daemon_reload: true + +- name: start greenplum service + ansible.builtin.systemd: + name: greenplum + state: started + enabled: true + daemon_reload: true + +- name: restart greenplum service + ansible.builtin.systemd: + name: greenplum + state: restarted + enabled: true + daemon_reload: true + +- name: stop greenplum service + ansible.builtin.systemd: + name: greenplum + state: stopped + enabled: true + daemon_reload: true + +- name: update greenplum configuration + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh && + gpstop -u -a + tags: skip_ansible_lint + diff --git a/roles/greenplum-master/tasks/extensions.yml b/roles/greenplum-master/tasks/extensions.yml new file mode 100644 index 0000000..f6dfceb --- /dev/null +++ b/roles/greenplum-master/tasks/extensions.yml @@ -0,0 +1,93 @@ +--- + +- name: greenplum master | Upload Greenplum extensions + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ greenplum_src_directory }}" + mode: 0644 + with_fileglob: + - "files/pkg/*" + +- name: greenplum master | Install Greenplum extensions + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh; + + installed_packages=$(gppkg --query --all \ + | tail -n +2 \ + | awk '{printf NR==1?$0:"\\|"$0}'); + + if [ -z "$installed_packages" ]; then + mapfile -t packages < <(\ls -1 {{ greenplum_src_directory }}/*.gppkg) + else + mapfile -t packages < <(\ls -1 {{ greenplum_src_directory }}/*.gppkg \ + | grep -v "$installed_packages"); + fi + + echo "${packages[@]}" + + for pkg in "${packages[@]}"; do + gppkg -a -i "$pkg" + done + args: + executable: /bin/bash + register: gppkg_log + changed_when: "'Completed local installation' in gppkg_log.stdout" + failed_when: false + tags: skip_ansible_lint + +- name: greenplum master | Show gppkg log + ansible.builtin.debug: var=gppkg_log verbosity=2 + +- name: greenplum master | Get all Greenplum databases + become: true + become_user: "{{ greenplum_user }}" + community.general.postgresql_info: + db: template1 + login_host: "127.0.0.1" + login_user: "{{ greenplum_user }}" + filter: + - "databases" + register: greenplum_databases + +- name: greenplum master | Enable PostGIS for databases + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh; + + psql {{ item.key }} -c '\dv' | grep -q geography; + + if [ "$?" -ne 0 ]; then + /bin/bash $GPHOME/share/postgresql/contrib/postgis*/postgis_manager.sh "{{ item.key }}" install; + fi + args: + executable: /bin/bash + register: postgis_install_log + changed_when: + - 'postgis_install_log.stdout_lines | length > 0' + - 'postgis_install_log.stdout_lines | last == "ANALYZE"' + tags: skip_ansible_lint + when: item.key in greenplum_postgis_databases + loop_control: + label: "{{ item.key }}" + loop: "{{ lookup('dict', greenplum_databases.databases) }}" + +- name: greenplum master | Show postgis installation log + ansible.builtin.debug: var=postgis_install_log verbosity=2 + +- name: greenplum master | Enable Greenplum extensions + become: true + become_user: "{{ greenplum_user }}" + community.general.postgresql_ext: + login_host: "127.0.0.1" + login_user: "{{ greenplum_user }}" + name: "{{ item.0.name }}" + db: "{{ item.1 }}" + loop_control: + label: "{{ item.1 }}/{{ item.0.name }}" + loop: "{{ greenplum_extensions | subelements('databases') }}" + diff --git a/roles/greenplum-master/tasks/init.yml b/roles/greenplum-master/tasks/init.yml new file mode 100644 index 0000000..1359929 --- /dev/null +++ b/roles/greenplum-master/tasks/init.yml @@ -0,0 +1,106 @@ +--- + +- name: greenplum master | Make directory to store data + ansible.builtin.file: + path: "{{ greenplum_data_directory }}/master" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + state: directory + recurse: true + +- name: greenplum master | Make directory to save configuration files + ansible.builtin.file: + path: "{{ greenplum_config_directory }}" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + state: directory + recurse: true + +- name: greenplum master | Make Greenplum configuration file + ansible.builtin.template: + src: gpinitsystem_config.j2 + dest: "{{ greenplum_config_directory }}/gpinitsystem_config" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + mode: 0644 + register: greenplum_configuration + +- name: greenplum master | Make a hosts file + ansible.builtin.template: + src: hostfile_gpinitsystem.j2 + dest: "{{ greenplum_config_directory }}/hostfile_gpinitsystem" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + mode: 0644 + +- name: greenplum master | Exchange ssh keys between all Greenplum nodes + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh && + gpssh-exkeys -f "{{ greenplum_config_directory }}/hostfile_gpinitsystem" + changed_when: false + failed_when: false + tags: skip_ansible_lint + +- name: greenplum master | Check current Greenplum timezone + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh && + gpconfig -s TimeZone | grep -E 'Master|Segment' | cut -d : -f 2 | sort -u | grep -v "{{ timezone }}" + register: greenplum_timezone + failed_when: false + changed_when: greenplum_timezone.stdout_lines | length > 0 + tags: skip_ansible_lint + +- name: greenplum master | Set Greenplum timezone to {{ timezone }} + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh && + gpconfig -c TimeZone -v "{{ timezone }}" + when: greenplum_timezone.stdout_lines | length > 0 + notify: restart greenplum service + tags: skip_ansible_lint + +- name: greenplum master | Check Greenplum cluster status + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1; + source /usr/local/greenplum-db/greenplum_path.sh && + gpstate -s + ignore_errors: true + register: gpstate + changed_when: false + failed_when: false + tags: skip_ansible_lint + +- name: greenplum master | Initialize Greenplum database cluster + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + source /usr/local/greenplum-db/greenplum_path.sh && + gpinitsystem -a + -c {{ greenplum_config_directory }}/gpinitsystem_config + -h {{ greenplum_config_directory }}/hostfile_gpinitsystem + register: gpinitsystem_log + tags: skip_ansible_lint + when: gpstate.rc != 0 + failed_when: + - '"Greenplum Database instance successfully created" not in gpinitsystem_log.stdout' + +- name: greenplum master | Add Greenplum master directory to user profile + ansible.builtin.lineinfile: + path: "{{ greenplum_user_profile_file }}" + line: "export MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1" + +- name: greenplum master | Adjust LD_PRELOAD for ps command + ansible.builtin.lineinfile: + path: "{{ greenplum_user_profile_file }}" + line: "export LD_PRELOAD=/lib64/libz.so.1 ps" + diff --git a/roles/greenplum-master/tasks/main.yml b/roles/greenplum-master/tasks/main.yml new file mode 100644 index 0000000..e8acf8b --- /dev/null +++ b/roles/greenplum-master/tasks/main.yml @@ -0,0 +1,46 @@ +--- + +# Initialize Greenplum cluster +- include: init.yml + +- name: greenplum master | Create systemd service + ansible.builtin.template: + src: greenplum.service.j2 + dest: /etc/systemd/system/greenplum.service + owner: root + group: root + mode: 0644 + register: greenplum_service + +- name: greenplum master | Stop greenplum started via cli and start it via systemd service + when: greenplum_service.changed or gpstate.rc != 0 + block: + - name: greenplum master | Stop Greenplum + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + source {{ greenplum_user_profile_file }} && + gpstop -a + tags: skip_ansible_lint + + - name: greenplum master | Start Greenplum service + ansible.builtin.systemd: + name: greenplum + state: started + enabled: true + daemon_reload: true + +# Greenplum database extensions (e.g. PostGIS) +- include: 'extensions.yml' + +# Users, permissions, pg_hba.conf +- include: 'roles.yml' + +- name: greenplum master | Reload Greenplum configuration + ansible.builtin.debug: + msg: "Greenplum configuration has been changed. Require restart" + when: + - gpstate.rc != 0 + - greenplum_configuration.changed + notify: update greenplum configuration + diff --git a/roles/greenplum-master/tasks/roles.yml b/roles/greenplum-master/tasks/roles.yml new file mode 100644 index 0000000..bdb0d59 --- /dev/null +++ b/roles/greenplum-master/tasks/roles.yml @@ -0,0 +1,29 @@ +--- + +- name: greenplum master | Create Greenplum users + community.general.postgresql_user: + db: template1 + login_host: "127.0.0.1" + login_user: "{{ greenplum_user }}" + name: "{{ item.name }}" + password: "{{ item.password }}" + groups: "{{ item.groups | default(omit) }}" + role_attr_flags: "{{ 'SUPERUSER' if item.superuser else '' }}" + state: present + loop: "{{ greenplum_users }}" + loop_control: + label: "{{ item.name }}" + notify: update greenplum configuration + +- name: greenplum master | Adjust pg_hba.conf + community.general.postgresql_pg_hba: + dest: "{{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1/pg_hba.conf" + contype: "{{ item.contype }}" + source: "{{ item.source }}" + databases: "{{ item.databases }}" + users: "{{ item.users }}" + method: "{{ item.method }}" + state: present + loop: "{{ greenplum_trusted_hosts }}" + notify: update greenplum configuration + diff --git a/roles/greenplum-master/templates/gpinitsystem_config.j2 b/roles/greenplum-master/templates/gpinitsystem_config.j2 new file mode 100644 index 0000000..28fc1ef --- /dev/null +++ b/roles/greenplum-master/templates/gpinitsystem_config.j2 @@ -0,0 +1,71 @@ +# FILE NAME: gpinitsystem_config +# {{ ansible_managed }} + +# Configuration file needed by the gpinitsystem + +################################################ +#### REQUIRED PARAMETERS +################################################ + +#### Name of this Greenplum system enclosed in quotes. +ARRAY_NAME="{{ deploy_cluster | upper }} Greenplum Data Platform" + +#### Naming convention for utility-generated data directories. +SEG_PREFIX={{ greenplum_seg_prefix }} + +#### Base number by which primary segment port numbers +#### are calculated. +PORT_BASE={{ greenplum_port_base }} + +#### File system location(s) where primary segment data directories +#### will be created. The number of locations in the list dictate +#### the number of primary segments that will get created per +#### physical host (if multiple addresses for a host are listed in +#### the hostfile, the number of segments will be spread evenly across +#### the specified interface addresses). +declare -a DATA_DIRECTORY=({% for _host in groups['greenplum_segments'] %}{{ greenplum_data_directory }}/primary {% endfor %}) + +#### OS-configured hostname or IP address of the master host. +MASTER_HOSTNAME={{ hostvars[inventory_hostname]['greenplum_hostname'] }} + +#### File system location where the master data directory +#### will be created. +MASTER_DIRECTORY={{ greenplum_master_directory }} + +#### Port number for the master instance. +MASTER_PORT={{ greenplum_master_port }} + +#### Shell utility used to connect to remote hosts. +TRUSTED_SHELL=ssh + +#### Maximum log file segments between automatic WAL checkpoints. +CHECK_POINT_SEGMENTS={{ greenplum_check_point_segments }} + +#### Default server-side character set encoding. +ENCODING=UNICODE + +################################################ +#### OPTIONAL MIRROR PARAMETERS +################################################ + +#### Base number by which mirror segment port numbers +#### are calculated. +#MIRROR_PORT_BASE=7000 + +#### File system location(s) where mirror segment data directories +#### will be created. The number of mirror locations must equal the +#### number of primary locations as specified in the +#### DATA_DIRECTORY parameter. +#declare -a MIRROR_DATA_DIRECTORY=(/data1/mirror /data1/mirror /data1/mirror /data2/mirror /data2/mirror /data2/mirror) + +################################################ +#### OTHER OPTIONAL PARAMETERS +################################################ + +#### Create a database of this name after initialization. +#DATABASE_NAME=name_of_database + +#### Specify the location of the host address file here instead of +#### with the -h option of gpinitsystem. +#MACHINE_LIST_FILE=/home/gpadmin/gpconfigs/hostfile_gpinitsystem + diff --git a/roles/greenplum-master/templates/greenplum.service.j2 b/roles/greenplum-master/templates/greenplum.service.j2 new file mode 100644 index 0000000..7e3562c --- /dev/null +++ b/roles/greenplum-master/templates/greenplum.service.j2 @@ -0,0 +1,29 @@ +# {{ ansible_managed }} + +[Unit] +Description=Greenplum database server +After=network.target + +[Service] +Type=forking + +User={{ greenplum_user }} +Group={{ greenplum_group }} + +WorkingDirectory=/usr/local/greenplum-db/ + +# Disable OOM killer +OOMScoreAdjust=-1000 + +Environment=SHELL=/bin/bash +Environment="MASTER_DATA_DIRECTORY={{ greenplum_master_directory }}/{{ greenplum_seg_prefix }}-1" + +ExecStart=/bin/bash -c "source {{ greenplum_user_profile_file }} && /usr/local/greenplum-db/bin/gpstart -a" +ExecStop=/bin/bash -c "source {{ greenplum_user_profile_file }} && /usr/local/greenplum-db/bin/gpstop -a" +ExecReload=/bin/bash -c "source {{ greenplum_user_profile_file }} && /usr/local/greenplum-db/bin/gpstop -a -r" + +TimeoutSec=300 + +[Install] +WantedBy=multi-user.target + diff --git a/roles/greenplum-master/templates/hostfile_gpinitsystem.j2 b/roles/greenplum-master/templates/hostfile_gpinitsystem.j2 new file mode 100644 index 0000000..b737add --- /dev/null +++ b/roles/greenplum-master/templates/hostfile_gpinitsystem.j2 @@ -0,0 +1,3 @@ +{% for host in groups['greenplum_segments'] %} +{{ hostvars[host]['greenplum_hostname'] }} +{% endfor %} diff --git a/roles/greenplum-segment/defaults/main.yml b/roles/greenplum-segment/defaults/main.yml new file mode 100644 index 0000000..fe96416 --- /dev/null +++ b/roles/greenplum-segment/defaults/main.yml @@ -0,0 +1,4 @@ +--- + +greenplum_data_directory: /opt/data + diff --git a/roles/greenplum-segment/tasks/main.yml b/roles/greenplum-segment/tasks/main.yml new file mode 100644 index 0000000..9d4f542 --- /dev/null +++ b/roles/greenplum-segment/tasks/main.yml @@ -0,0 +1,14 @@ +--- + +- name: greenplum segment | Make directory to store data + ansible.builtin.file: + path: "{{ greenplum_data_directory }}/{{ item }}" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + mode: 0644 + state: directory + recurse: true + with_items: + - primary + - mirror + diff --git a/roles/greenplum/defaults/main.yml b/roles/greenplum/defaults/main.yml new file mode 100644 index 0000000..9038a0f --- /dev/null +++ b/roles/greenplum/defaults/main.yml @@ -0,0 +1,15 @@ +--- + +greenplum_src_directory: /opt/src + +greenplum_version: 6.9.1 + +greenplum_db_rpm: "greenplum-db-{{ greenplum_version }}-rhel7-x86_64.rpm" + +greenplum_contrib_repository: https://github.com/greenplum-db/gpdb +greenplum_contrib_version: 6X_STABLE + +greenplum_contrib_exclude_list: + - btree_gin + - pgrowlocks + diff --git a/roles/greenplum/tasks/extensions-contrib.yml b/roles/greenplum/tasks/extensions-contrib.yml new file mode 100644 index 0000000..6b00f01 --- /dev/null +++ b/roles/greenplum/tasks/extensions-contrib.yml @@ -0,0 +1,111 @@ +--- + +- name: contrib extensions | Install centos-release-scl + ansible.builtin.package: + name: centos-release-scl + state: present + +- name: contrib extensions | Install build tools + ansible.builtin.package: + name: + - apr-devel + - bison + - bzip2-devel + - curl + - devtoolset-8 + - flex + - git + - libcurl-devel + - libevent-devel + - libzstd-devel + - zlib-devel + state: present + +- name: contrib extensions | Clone repository + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.git: + repo: "{{ greenplum_contrib_repository }}" + version: "{{ greenplum_contrib_version }}" + dest: "{{ greenplum_src_directory }}/contrib" + force: true + +- name: contrib extensions | Disable excluded extensions + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.lineinfile: + dest: "{{ greenplum_src_directory }}/contrib/contrib/Makefile" + regexp: '\s+{{ item }}.*$' + state: absent + loop: "{{ greenplum_contrib_exclude_list }}" + +- name: contrib extensions | Configure sources + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + source {{ greenplum_user_profile_file }} + && scl enable devtoolset-8 -- bash -c "./configure --prefix=$GPHOME --disable-gpcloud --without-readline" + args: + chdir: "{{ greenplum_src_directory }}/contrib" + tags: skip_ansible_lint + +- name: contrib extensions | Build backend + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + source {{ greenplum_user_profile_file }} + && cd src/backend + && scl enable devtoolset-8 -- make + args: + chdir: "{{ greenplum_src_directory }}/contrib" + tags: skip_ansible_lint + +- name: contrib extensions | Build utils + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + source {{ greenplum_user_profile_file }} + && cd src/backend/utils + && scl enable devtoolset-8 -- make + args: + chdir: "{{ greenplum_src_directory }}/contrib" + tags: skip_ansible_lint + +- name: contrib extensions | Build extensions + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: > + source {{ greenplum_user_profile_file }} + && cd contrib + && scl enable devtoolset-8 -- make + args: + chdir: "{{ greenplum_src_directory }}/contrib" + tags: skip_ansible_lint + +- name: contrib extensions | Install extensions + ansible.builtin.shell: > + source {{ greenplum_user_profile_file }} + && cd contrib/ + && make install + args: + chdir: "{{ greenplum_src_directory }}/contrib" + tags: skip_ansible_lint + +- name: contrib extensions | Get list of available extensions + become: true + become_user: "{{ greenplum_user }}" + ansible.builtin.shell: | + source {{ greenplum_user_profile_file }} + psql postgres -t -c 'SELECT * FROM pg_available_extensions;' \ + | cut -d '|' -f 1 \ + | expand \ + | sed 's/ \+$//' \ + | tr '\n' ',' \ + | sed 's/,\+$//' + register: contrib_extensions + tags: skip_ansible_lint + +- name: contrib extensions | Show available extensions + ansible.builtin.debug: + msg: "The following extensions are available: {{ contrib_extensions.stdout }}" + diff --git a/roles/greenplum/tasks/main.yml b/roles/greenplum/tasks/main.yml new file mode 100644 index 0000000..414f100 --- /dev/null +++ b/roles/greenplum/tasks/main.yml @@ -0,0 +1,67 @@ +--- + +- name: greenplum | Make directory to store package files + ansible.builtin.file: + path: "{{ greenplum_src_directory }}" + state: directory + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + recurse: true + +- name: greenplum | Upload Greenplum rpm package to the host + ansible.builtin.copy: + src: "{{ 'files/rpm/' ~ greenplum_db_rpm }}" + dest: "{{ greenplum_src_directory }}" + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + mode: 0644 + +- name: greenplum | Install Greenplum server + ansible.builtin.yum: + name: "{{ greenplum_src_directory }}/{{ greenplum_db_rpm }}" + state: present + +- name: greenplum | Find install directory + ansible.builtin.find: + paths: /usr/local + patterns: 'greenplum*' + file_type: directory + register: installed_dir + +- name: greenplum | Change install directory ownership + ansible.builtin.file: + path: '{{ item.path }}' + owner: "{{ greenplum_user }}" + group: "{{ greenplum_group }}" + recurse: true + with_items: "{{ installed_dir.files }}" + +- name: greenplum | Update pam_limits + community.general.pam_limits: + domain: "{{ greenplum_user }}" + limit_type: '-' + limit_item: "{{ item.key }}" + value: "{{ item.value }}" + with_dict: + nofile: 524288 + nproc: 131072 + +- name: greenplum | Find installed Greenplum version + ansible.builtin.shell: . /usr/local/greenplum-db/greenplum_path.sh && /usr/local/greenplum-db/bin/postgres --gp-version + changed_when: false + register: postgres_gp_version + tags: skip_ansible_lint + +- name: greenplum | Fail if the correct Greenplum version is not installed + ansible.builtin.fail: + msg: "Expected Greenplum version {{ greenplum_version }}, but found '{{ postgres_gp_version.stdout }}'" + when: "greenplum_version is not defined or greenplum_version not in postgres_gp_version.stdout" + +- name: greenplum | Add Greenplum paths to {{ greenplum_user }} profile + ansible.builtin.lineinfile: + path: "{{ greenplum_user_profile_file }}" + line: "source /usr/local/greenplum-db/greenplum_path.sh" + +# PostgreSQL database extensions +- include: 'extensions-contrib.yml' + diff --git a/roles/ntpd/defaults/main.yml b/roles/ntpd/defaults/main.yml new file mode 100644 index 0000000..7743013 --- /dev/null +++ b/roles/ntpd/defaults/main.yml @@ -0,0 +1,8 @@ +--- + +ntp_pool_servers: + - 0.uk.pool.ntp.org + - 1.uk.pool.ntp.org + - 2.uk.pool.ntp.org + - 3.uk.pool.ntp.org + diff --git a/roles/ntpd/handlers/main.yml b/roles/ntpd/handlers/main.yml new file mode 100644 index 0000000..10ec0c2 --- /dev/null +++ b/roles/ntpd/handlers/main.yml @@ -0,0 +1,16 @@ +--- + +- name: start ntpd service + systemd: + name: ntpd + state: started + enabled: true + daemon_reload: yes + +- name: restart ntpd service + systemd: + name: ntpd + state: restarted + enabled: true + daemon_reload: yes + diff --git a/roles/ntpd/tasks/main.yml b/roles/ntpd/tasks/main.yml new file mode 100644 index 0000000..c8a538c --- /dev/null +++ b/roles/ntpd/tasks/main.yml @@ -0,0 +1,17 @@ +--- + +- name: ntp | Install ntp package + package: + name: ntp + state: present + notify: start ntpd service + +- name: ntp | Create ntp configuration file + template: + src: ntp.conf.j2 + dest: "/etc/ntp.conf" + owner: root + group: root + mode: 0644 + notify: restart ntpd service + diff --git a/roles/ntpd/templates/ntp.conf.j2 b/roles/ntpd/templates/ntp.conf.j2 new file mode 100644 index 0000000..520de59 --- /dev/null +++ b/roles/ntpd/templates/ntp.conf.j2 @@ -0,0 +1,60 @@ +# For more information about this file, see the man pages +# ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5). + +driftfile /var/lib/ntp/drift + +# Permit time synchronization with our time source, but do not +# permit the source to query or modify the service on this system. +restrict default nomodify notrap nopeer noquery + +# Permit all access over the loopback interface. This could +# be tightened as well, but to do so would effect some of +# the administrative functions. +restrict 127.0.0.1 +restrict ::1 + +# Hosts on local network are less restricted. +#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap + +# Use public servers from the pool.ntp.org project. +# Please consider joining the pool (http://www.pool.ntp.org/join.html). +{% for pool in ntp_pool_servers %} +server {{ pool }} iburst +{% endfor %} + +#broadcast 192.168.1.255 autokey # broadcast server +#broadcastclient # broadcast client +#broadcast 224.0.1.1 autokey # multicast server +#multicastclient 224.0.1.1 # multicast client +#manycastserver 239.255.254.254 # manycast server +#manycastclient 239.255.254.254 autokey # manycast client + +# Enable public key cryptography. +#crypto + +includefile /etc/ntp/crypto/pw + +# Key file containing the keys and key identifiers used when operating +# with symmetric key cryptography. +keys /etc/ntp/keys + +# Specify the key identifiers which are trusted. +#trustedkey 4 8 42 + +# Specify the key identifier to use with the ntpdc utility. +#requestkey 8 + +# Specify the key identifier to use with the ntpq utility. +#controlkey 8 + +# Enable writing of statistics records. +#statistics clockstats cryptostats loopstats peerstats + +# Disable the monitoring facility to prevent amplification attacks using ntpdc +# monlist command when default restrict does not include the noquery flag. See +# CVE-2013-5211 for more details. +# Note: Monitoring will not be disabled with the limited restriction flag. +disable monitor + +logfile /var/log/ntp.log + diff --git a/roles/prometheus-exporter/defaults/main.yml b/roles/prometheus-exporter/defaults/main.yml new file mode 100644 index 0000000..5d87a72 --- /dev/null +++ b/roles/prometheus-exporter/defaults/main.yml @@ -0,0 +1,19 @@ +--- + +postgres_exporter_archive_url: https://github.com/wrouesnel/postgres_exporter/releases/download/v0.8.0/postgres_exporter_v0.8.0_linux-amd64.tar.gz + +# enable | disable +postgres_exporter_sslmode: disable + +# postgres_exporter_enabled: true +# postgres_exporter_user: user +# postgres_exporter_password: password + +postgres_exporter_host: "127.0.0.1:5432" +postgres_exporter_database: "postgres" +postgres_exporter_listen_address: "0.0.0.0:9020" +postgres_exporter_telemetry_path: "/metrics" + +# true | false +postgres_exporter_discovery: true + diff --git a/roles/prometheus-exporter/handlers/main.yml b/roles/prometheus-exporter/handlers/main.yml new file mode 100644 index 0000000..920b442 --- /dev/null +++ b/roles/prometheus-exporter/handlers/main.yml @@ -0,0 +1,16 @@ +--- + +- name: start postgres_exporter service + ansible.builtin.systemd: + name: postgres_exporter + state: started + enabled: true + daemon_reload: true + +- name: restart postgres_exporter service + ansible.builtin.systemd: + name: postgres_exporter + state: restarted + enabled: true + daemon_reload: true + diff --git a/roles/prometheus-exporter/tasks/main.yml b/roles/prometheus-exporter/tasks/main.yml new file mode 100644 index 0000000..53ec06a --- /dev/null +++ b/roles/prometheus-exporter/tasks/main.yml @@ -0,0 +1,27 @@ +--- + +- name: prometheus exporter | Download postgres_exporter release + ansible.builtin.unarchive: + src: "{{ postgres_exporter_archive_url }}" + dest: /usr/local/bin/ + remote_src: true + extra_opts: + - --strip-components=1 + notify: restart postgres_exporter service + +- name: prometheus exporter | Create systemd service + ansible.builtin.template: + src: postgres_exporter.service.j2 + dest: /etc/systemd/system/postgres_exporter.service + owner: root + group: root + mode: 0755 + notify: restart postgres_exporter service + +- name: prometheus exporter | Start exporter service + ansible.builtin.systemd: + name: postgres_exporter + state: started + enabled: true + daemon_reload: true + diff --git a/roles/prometheus-exporter/templates/postgres_exporter.service.j2 b/roles/prometheus-exporter/templates/postgres_exporter.service.j2 new file mode 100644 index 0000000..837f521 --- /dev/null +++ b/roles/prometheus-exporter/templates/postgres_exporter.service.j2 @@ -0,0 +1,27 @@ +# {{ ansible_managed }} + +[Unit] +Description=Postgres metrics exporter +After=network.target + +[Service] +Type=simple + +User={{ greenplum_user }} +Group={{ greenplum_group }} + +Environment="DATA_SOURCE_URI={{ postgres_exporter_host }}/{{ postgres_exporter_database }}?sslmode={{ postgres_exporter_sslmode }}" +Environment="DATA_SOURCE_USER={{ postgres_exporter_user }}" +Environment="DATA_SOURCE_PASS={{ postgres_exporter_password }}" +Environment="PG_EXPORTER_WEB_LISTEN_ADDRESS={{ postgres_exporter_listen_address }}" +Environment="PG_EXPORTER_WEB_TELEMETRY_PATH={{ postgres_exporter_telemetry_path }}" +Environment="PG_EXPORTER_AUTO_DISCOVER_DATABASES={{ postgres_exporter_discovery }}" + +ExecStart=/usr/local/bin/postgres_exporter + +Restart=on-failure +RestartSec=10 + +[Install] +WantedBy=multi-user.target + diff --git a/site.yml b/site.yml new file mode 100644 index 0000000..b54eaa8 --- /dev/null +++ b/site.yml @@ -0,0 +1,46 @@ +--- + +- hosts: all + pre_tasks: + - name: Check if python is available + raw: command -v python + changed_when: false + ignore_errors: true + register: python_exists + tags: skip_ansible_lint + + - name: Install python using apt + raw: apt update && apt install -y python + tags: skip_ansible_lint + when: + - python_exists.rc != 0 + - ansible_os_family == "Debian" + + - name: Install python using yum + raw: yum install -y python + tags: skip_ansible_lint + when: + - python_exists.rc != 0 + - ansible_os_family == "RedHat" + +- hosts: greenplum_cluster + tasks: + - name: Disable SELinux + selinux: + state: disabled + + roles: + - common + - ntpd + - greenplum + +- hosts: greenplum_segments + roles: + - greenplum-segment + +- hosts: greenplum_master + roles: + - role: greenplum-master + - role: prometheus-exporter + when: postgres_exporter_enabled +