mirror of
https://github.com/batonogov/learn-devops.git
synced 2025-11-29 00:33:02 +00:00
patroni-postgresql-cluster (#13)
* Описана инфрастуктура кластера * Добавлена роль etcd * Добавлена роль haproxy * Добавлена роль keepalived * Добавлена роль ntp_install * Добавлена роль patroni * Добавлена групповые переменные --------- Co-authored-by: Fedor Batonogov <f.batonogov@yandex.ru>
This commit is contained in:
committed by
GitHub
parent
5b7920bdca
commit
f8fe304cd9
@@ -1,5 +1,6 @@
|
||||
skip_list:
|
||||
- risky-file-permissions
|
||||
- var-naming[no-role-prefix]
|
||||
|
||||
exclude_paths:
|
||||
- ansible/roles/haproxy_static_pods/files/haproxy.yaml
|
||||
|
||||
2
ansible/group_vars/all.yml
Normal file
2
ansible/group_vars/all.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
patroni_user: patroni
|
||||
patroni_uid: 1666
|
||||
@@ -27,3 +27,23 @@ test_hosts:
|
||||
vars:
|
||||
ansible_user: infra
|
||||
ansible_port: 22
|
||||
|
||||
patroni_postgresql_cluster:
|
||||
children:
|
||||
patroni_postgresql_hosts:
|
||||
hosts:
|
||||
patroni-postgresql-01:
|
||||
ansible_host: 10.0.75.111
|
||||
patroni-postgresql-02:
|
||||
ansible_host: 10.0.75.112
|
||||
patroni-postgresql-03:
|
||||
ansible_host: 10.0.75.113
|
||||
haproxy_hosts:
|
||||
hosts:
|
||||
haproxy-01:
|
||||
ansible_host: 10.0.75.114
|
||||
haproxy-02:
|
||||
ansible_host: 10.0.75.115
|
||||
vars:
|
||||
ansible_user: infra
|
||||
ansible_port: 22
|
||||
|
||||
53
ansible/patroni-postgresql.yml
Normal file
53
ansible/patroni-postgresql.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
- name: Подготовка узлов
|
||||
become: true
|
||||
hosts:
|
||||
- patroni_postgresql_hosts
|
||||
roles:
|
||||
- ntp_install
|
||||
- docker_install
|
||||
tasks:
|
||||
- name: Создаю пользователя
|
||||
ansible.builtin.user:
|
||||
name: "{{ patroni_user }}"
|
||||
uid: "{{ patroni_uid }}"
|
||||
shell: /usr/sbin/nologin
|
||||
groups:
|
||||
- docker
|
||||
|
||||
- name: Подготовка кластера
|
||||
become: true
|
||||
hosts:
|
||||
- patroni_postgresql_hosts
|
||||
roles:
|
||||
- etcd
|
||||
- patroni
|
||||
|
||||
- name: Подготовка кластера
|
||||
become: true
|
||||
hosts:
|
||||
- haproxy_hosts
|
||||
roles:
|
||||
- ntp_install
|
||||
- docker_install
|
||||
- haproxy
|
||||
|
||||
- name: Настройка master keepalived
|
||||
become: true
|
||||
hosts:
|
||||
- haproxy-01
|
||||
roles:
|
||||
- role: keepalived
|
||||
unit_file: "keepalived.master.conf.j2"
|
||||
virtual_ip: "10.0.75.110/24"
|
||||
virtual_router_id: 250
|
||||
|
||||
- name: Настройка backup keepalived
|
||||
become: true
|
||||
hosts:
|
||||
- haproxy-02
|
||||
roles:
|
||||
- role: keepalived
|
||||
unit_file: "keepalived.backup.conf.j2"
|
||||
virtual_ip: "10.0.75.110/24"
|
||||
virtual_router_id: 250
|
||||
7
ansible/roles/etcd/handlers/main.yml
Normal file
7
ansible/roles/etcd/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Перезапускаю etcd.service
|
||||
ansible.builtin.systemd:
|
||||
name: etcd.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
3
ansible/roles/etcd/tasks/main.yml
Normal file
3
ansible/roles/etcd/tasks/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
- name: Наливаю юнит файл
|
||||
ansible.builtin.import_tasks: service.yml
|
||||
21
ansible/roles/etcd/tasks/service.yml
Normal file
21
ansible/roles/etcd/tasks/service.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Задаю права для директории
|
||||
ansible.builtin.file:
|
||||
path: /var/lib/etcd
|
||||
state: directory
|
||||
recurse: true
|
||||
owner: "{{ patroni_uid }}"
|
||||
group: "{{ patroni_uid }}"
|
||||
|
||||
- name: Наливаю юнит файл etcd
|
||||
ansible.builtin.template:
|
||||
src: etcd.service.j2
|
||||
dest: /etc/systemd/system/etcd.service
|
||||
notify:
|
||||
- Перезапускаю etcd.service
|
||||
|
||||
- name: Настраиваю etcd.service
|
||||
ansible.builtin.systemd:
|
||||
name: etcd.service
|
||||
state: started
|
||||
enabled: true
|
||||
34
ansible/roles/etcd/templates/etcd.service.j2
Normal file
34
ansible/roles/etcd/templates/etcd.service.j2
Normal file
@@ -0,0 +1,34 @@
|
||||
[Unit]
|
||||
Description=etcd
|
||||
Requires=docker.service
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
User={{ patroni_user }}
|
||||
Restart=always
|
||||
Environment="TOKEN={{ lookup('password', 'secrets/patroni-postgresql/etcd_cluster_token length=64') }}"
|
||||
Environment="CLUSTER=patroni-postgresql-01=http://10.0.75.111:2380,patroni-postgresql-02=http://10.0.75.112:2380,patroni-postgresql-03=http://10.0.75.113:2380"
|
||||
ExecStartPre=-/usr/bin/docker rm -f etcd
|
||||
ExecStart=/usr/bin/docker run \
|
||||
--rm \
|
||||
--user {{ patroni_uid }}:{{ patroni_uid }} \
|
||||
--publish 2379:2379 \
|
||||
--publish 2380:2380 \
|
||||
--name etcd \
|
||||
--volume=/var/lib/etcd:/etcd-data \
|
||||
quay.io/coreos/etcd:{{ etcd_version }} \
|
||||
/usr/local/bin/etcd \
|
||||
--data-dir=/etcd-data \
|
||||
--name {{ inventory_hostname }} \
|
||||
--initial-advertise-peer-urls http://{{ ansible_host }}:2380 \
|
||||
--listen-peer-urls http://0.0.0.0:2380 \
|
||||
--advertise-client-urls http://{{ ansible_host }}:2379 \
|
||||
--listen-client-urls http://0.0.0.0:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state new \
|
||||
--initial-cluster-token ${TOKEN} \
|
||||
--enable-v2=true
|
||||
ExecStop=/usr/bin/docker stop -t 10 etcd
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
ansible/roles/etcd/vars/main.yml
Normal file
1
ansible/roles/etcd/vars/main.yml
Normal file
@@ -0,0 +1 @@
|
||||
etcd_version: v3.5.14
|
||||
8
ansible/roles/haproxy/handlers/main.yml
Normal file
8
ansible/roles/haproxy/handlers/main.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# handlers file for haproxy
|
||||
- name: Перезапускаю haproxy.service
|
||||
ansible.builtin.systemd:
|
||||
name: haproxy.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
13
ansible/roles/haproxy/tasks/config.yml
Normal file
13
ansible/roles/haproxy/tasks/config.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Создаю директорию /usr/local/etc/haproxy/
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/etc/haproxy/
|
||||
state: directory
|
||||
|
||||
- name: Наливаю haproxy.cfg
|
||||
ansible.builtin.template:
|
||||
src: haproxy.cfg.j2
|
||||
dest: "/usr/local/etc/haproxy/haproxy.cfg"
|
||||
mode: "755"
|
||||
notify:
|
||||
- Перезапускаю haproxy.service
|
||||
13
ansible/roles/haproxy/tasks/install.yml
Normal file
13
ansible/roles/haproxy/tasks/install.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Наливаю юнит файл haproxy
|
||||
ansible.builtin.template:
|
||||
src: haproxy.service.j2
|
||||
dest: /etc/systemd/system/haproxy.service
|
||||
notify:
|
||||
- Перезапускаю haproxy.service
|
||||
|
||||
- name: Настраиваю haproxy.service
|
||||
ansible.builtin.systemd:
|
||||
name: haproxy.service
|
||||
state: started
|
||||
enabled: true
|
||||
7
ansible/roles/haproxy/tasks/main.yml
Normal file
7
ansible/roles/haproxy/tasks/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
# tasks file for haproxy
|
||||
- name: Копирую конфигурацию haproxy
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
|
||||
- name: Устанавливаю haproxy
|
||||
ansible.builtin.import_tasks: install.yml
|
||||
36
ansible/roles/haproxy/templates/haproxy.cfg.j2
Normal file
36
ansible/roles/haproxy/templates/haproxy.cfg.j2
Normal file
@@ -0,0 +1,36 @@
|
||||
global
|
||||
maxconn 100
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode tcp
|
||||
retries 2
|
||||
timeout client 30m
|
||||
timeout connect 4s
|
||||
timeout server 30m
|
||||
timeout check 5s
|
||||
|
||||
listen stats
|
||||
mode http
|
||||
bind *:7000
|
||||
stats enable
|
||||
stats uri /
|
||||
|
||||
listen patroni-postgresql-primary
|
||||
bind *:5000
|
||||
option httpchk OPTIONS /master
|
||||
http-check expect status 200
|
||||
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
|
||||
server 10.0.75.111 10.0.75.111:5432 maxconn 100 check port 8008
|
||||
server 10.0.75.112 10.0.75.112:5432 maxconn 100 check port 8008
|
||||
server 10.0.75.113 10.0.75.113:5432 maxconn 100 check port 8008
|
||||
|
||||
listen patroni-postgresql-standbys
|
||||
balance roundrobin
|
||||
bind *:5001
|
||||
option httpchk OPTIONS /replica
|
||||
http-check expect status 200
|
||||
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
|
||||
server 10.0.75.111 10.0.75.111:5432 maxconn 100 check port 8008
|
||||
server 10.0.75.112 10.0.75.112:5432 maxconn 100 check port 8008
|
||||
server 10.0.75.113 10.0.75.113:5432 maxconn 100 check port 8008
|
||||
21
ansible/roles/haproxy/templates/haproxy.service.j2
Normal file
21
ansible/roles/haproxy/templates/haproxy.service.j2
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=haproxy
|
||||
Requires=docker.service
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
ExecStartPre=-/usr/bin/docker rm -f haproxy
|
||||
ExecStart=/usr/bin/docker run \
|
||||
--rm \
|
||||
--publish 5000:5000 \
|
||||
--publish 5001:5001 \
|
||||
--publish 7000:7000 \
|
||||
--volume /usr/local/etc/haproxy/:/usr/local/etc/haproxy/:ro \
|
||||
--sysctl net.ipv4.ip_unprivileged_port_start=0 \
|
||||
--name haproxy \
|
||||
haproxy:{{ haproxy_version }}
|
||||
ExecStop=/usr/bin/docker stop -t 10 haproxy
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
3
ansible/roles/haproxy/vars/main.yml
Normal file
3
ansible/roles/haproxy/vars/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
# vars file for haproxy
|
||||
haproxy_version: 3.0.2-alpine
|
||||
3
ansible/roles/keepalived/defaults/main.yml
Normal file
3
ansible/roles/keepalived/defaults/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
# defaults file for keepalived
|
||||
unit_file: keepalived.master.conf.j2
|
||||
7
ansible/roles/keepalived/handlers/main.yml
Normal file
7
ansible/roles/keepalived/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Перезапускаю keepalived.service
|
||||
ansible.builtin.systemd:
|
||||
name: keepalived.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
7
ansible/roles/keepalived/tasks/config.yml
Normal file
7
ansible/roles/keepalived/tasks/config.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
- name: Наливаю конфигурацию keepalived
|
||||
ansible.builtin.template:
|
||||
src: "{{ unit_file }}"
|
||||
dest: /etc/keepalived/keepalived.conf
|
||||
mode: "644"
|
||||
notify:
|
||||
- Перезапускаю keepalived.service
|
||||
7
ansible/roles/keepalived/tasks/install.yml
Normal file
7
ansible/roles/keepalived/tasks/install.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Устанавливаю keepalived
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- keepalived
|
||||
state: present
|
||||
update_cache: true
|
||||
10
ansible/roles/keepalived/tasks/main.yml
Normal file
10
ansible/roles/keepalived/tasks/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
# tasks file for keepalived
|
||||
- name: Устанавливаю keepalived
|
||||
ansible.builtin.import_tasks: install.yml
|
||||
|
||||
- name: Наливаю конфигурацию
|
||||
ansible.builtin.include_tasks: config.yml
|
||||
|
||||
- name: Запускаю сервис
|
||||
ansible.builtin.include_tasks: start.yml
|
||||
5
ansible/roles/keepalived/tasks/start.yml
Normal file
5
ansible/roles/keepalived/tasks/start.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: Настраиваю keepalived.service
|
||||
ansible.builtin.systemd:
|
||||
name: keepalived.service
|
||||
state: started
|
||||
enabled: true
|
||||
14
ansible/roles/keepalived/templates/keepalived.backup.conf.j2
Normal file
14
ansible/roles/keepalived/templates/keepalived.backup.conf.j2
Normal file
@@ -0,0 +1,14 @@
|
||||
vrrp_instance VI_1 {
|
||||
state BACKUP
|
||||
interface eth0
|
||||
virtual_router_id {{ virtual_router_id }}
|
||||
priority 100 # PAY ATTENTION ON PRIORITY!!
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass {{ lookup('password', 'secrets/keepalived/' + virtual_ip + ' length=64') }}
|
||||
}
|
||||
|
||||
virtual_ipaddress {
|
||||
{{ virtual_ip }} dev eth0
|
||||
}
|
||||
}
|
||||
14
ansible/roles/keepalived/templates/keepalived.master.conf.j2
Normal file
14
ansible/roles/keepalived/templates/keepalived.master.conf.j2
Normal file
@@ -0,0 +1,14 @@
|
||||
vrrp_instance VI_1 {
|
||||
state MASTER
|
||||
interface eth0
|
||||
virtual_router_id {{ virtual_router_id }}
|
||||
priority 101 # PAY ATTENTION ON PRIORITY!!
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass {{ lookup('password', 'secrets/keepalived/' + virtual_ip + ' length=64') }}
|
||||
}
|
||||
|
||||
virtual_ipaddress {
|
||||
{{ virtual_ip }} dev eth0
|
||||
}
|
||||
}
|
||||
36
ansible/roles/ntp_install/README.md
Normal file
36
ansible/roles/ntp_install/README.md
Normal file
@@ -0,0 +1,36 @@
|
||||
Настройка NTP
|
||||
=========
|
||||
|
||||
Данная роль настраивает часовой пояс и NTP на узлах.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Тестирование приводилось на **Ubuntu 20.04 (Focal Fossa)** и **Ubuntu 22.04 (Jammy Jellyfish)**.
|
||||
|
||||
Role Variables
|
||||
--------------
|
||||
|
||||
Переменные не используются.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Для настройки часового пояса используется роль [community.general.timezone](https://docs.ansible.com/ansible/latest/collections/community/general/timezone_module.html), в качестве параметра принимается строка с нужным часовым поясом, например **Europe/Moscow**.
|
||||
|
||||
Example Playbook
|
||||
----------------
|
||||
|
||||
- hosts: servers
|
||||
roles:
|
||||
- ntp-install
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
|
||||
Author Information
|
||||
------------------
|
||||
|
||||
Федор Батоногов f.batonogov@yandex.ru
|
||||
22
ansible/roles/ntp_install/tasks/debian.yml
Normal file
22
ansible/roles/ntp_install/tasks/debian.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# tasks file for ntp-install
|
||||
- name: Настраиваю Московское время
|
||||
community.general.timezone:
|
||||
name: Europe/Moscow
|
||||
|
||||
- name: Устанавливаю ntp
|
||||
ansible.builtin.apt:
|
||||
pkg:
|
||||
- ntp
|
||||
update_cache: true
|
||||
|
||||
- name: Настраиваю сервис ntp
|
||||
ansible.builtin.systemd:
|
||||
name: ntp
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Наливаю конфигурацию ntp из шаблона
|
||||
ansible.builtin.template:
|
||||
src: debian.conf.j2
|
||||
dest: '/etc/ntpsec/ntp.conf'
|
||||
9
ansible/roles/ntp_install/tasks/main.yml
Normal file
9
ansible/roles/ntp_install/tasks/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# tasks file for ntp-install
|
||||
- name: Устанавливаю ntp на Ubuntu
|
||||
ansible.builtin.import_tasks: ubuntu.yml
|
||||
when: ansible_distribution == 'Ubuntu'
|
||||
|
||||
- name: Устанавливаю ntp на Debian
|
||||
ansible.builtin.import_tasks: debian.yml
|
||||
when: ansible_distribution == 'Debian'
|
||||
22
ansible/roles/ntp_install/tasks/ubuntu.yml
Normal file
22
ansible/roles/ntp_install/tasks/ubuntu.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
# tasks file for ntp-install
|
||||
- name: Настраиваю Московское время
|
||||
community.general.timezone:
|
||||
name: Europe/Moscow
|
||||
|
||||
- name: Устанавливаю ntp
|
||||
ansible.builtin.apt:
|
||||
pkg:
|
||||
- ntp
|
||||
update_cache: true
|
||||
|
||||
- name: Настраиваю сервис ntp
|
||||
ansible.builtin.systemd:
|
||||
name: ntp
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Наливаю конфигурацию ntp из шаблона
|
||||
ansible.builtin.template:
|
||||
src: ubuntu.conf.j2
|
||||
dest: '/etc/ntp.conf'
|
||||
51
ansible/roles/ntp_install/templates/debian.conf.j2
Normal file
51
ansible/roles/ntp_install/templates/debian.conf.j2
Normal file
@@ -0,0 +1,51 @@
|
||||
# /etc/ntpsec/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
|
||||
|
||||
driftfile /var/lib/ntpsec/ntp.drift
|
||||
leapfile /usr/share/zoneinfo/leap-seconds.list
|
||||
|
||||
# To enable Network Time Security support as a server, obtain a certificate
|
||||
# (e.g. with Let's Encrypt), configure the paths below, and uncomment:
|
||||
# nts cert CERT_FILE
|
||||
# nts key KEY_FILE
|
||||
# nts enable
|
||||
|
||||
# You must create /var/log/ntpsec (owned by ntpsec:ntpsec) to enable logging.
|
||||
#statsdir /var/log/ntpsec/
|
||||
#statistics loopstats peerstats clockstats
|
||||
#filegen loopstats file loopstats type day enable
|
||||
#filegen peerstats file peerstats type day enable
|
||||
#filegen clockstats file clockstats type day enable
|
||||
|
||||
# This should be maxclock 7, but the pool entries count towards maxclock.
|
||||
tos maxclock 11
|
||||
|
||||
# Comment this out if you have a refclock and want it to be able to discipline
|
||||
# the clock by itself (e.g. if the system is not connected to the network).
|
||||
tos minclock 4 minsane 3
|
||||
|
||||
# Specify one or more NTP servers.
|
||||
|
||||
# Public NTP servers supporting Network Time Security:
|
||||
# server time.cloudflare.com nts
|
||||
|
||||
# pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will
|
||||
# pick a different set every time it starts up. Please consider joining the
|
||||
# pool: <https://www.pool.ntp.org/join.html>
|
||||
pool 0.debian.pool.ntp.org iburst
|
||||
pool 1.debian.pool.ntp.org iburst
|
||||
pool 2.debian.pool.ntp.org iburst
|
||||
pool 3.debian.pool.ntp.org iburst
|
||||
|
||||
# Access control configuration; see /usr/share/doc/ntpsec-doc/html/accopt.html
|
||||
# for details.
|
||||
#
|
||||
# Note that "restrict" applies to both servers and clients, so a configuration
|
||||
# that might be intended to block requests from certain clients could also end
|
||||
# up blocking replies from your own upstream servers.
|
||||
|
||||
# By default, exchange time with everybody, but don't allow configuration.
|
||||
restrict default kod nomodify nopeer noquery limited
|
||||
|
||||
# Local users may interrogate the ntp server more closely.
|
||||
restrict 127.0.0.1
|
||||
restrict ::1
|
||||
60
ansible/roles/ntp_install/templates/ubuntu.conf.j2
Normal file
60
ansible/roles/ntp_install/templates/ubuntu.conf.j2
Normal file
@@ -0,0 +1,60 @@
|
||||
# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
|
||||
|
||||
driftfile /var/lib/ntp/ntp.drift
|
||||
|
||||
# Leap seconds definition provided by tzdata
|
||||
leapfile /usr/share/zoneinfo/leap-seconds.list
|
||||
|
||||
# Enable this if you want statistics to be logged.
|
||||
#statsdir /var/log/ntpstats/
|
||||
|
||||
statistics loopstats peerstats clockstats
|
||||
filegen loopstats file loopstats type day enable
|
||||
filegen peerstats file peerstats type day enable
|
||||
filegen clockstats file clockstats type day enable
|
||||
|
||||
# Specify one or more NTP servers.
|
||||
|
||||
# Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board
|
||||
# on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for
|
||||
# more information.
|
||||
pool 0.ubuntu.pool.ntp.org iburst
|
||||
pool 1.ubuntu.pool.ntp.org iburst
|
||||
pool 2.ubuntu.pool.ntp.org iburst
|
||||
pool 3.ubuntu.pool.ntp.org iburst
|
||||
|
||||
# Use Ubuntu's ntp server as a fallback.
|
||||
pool ntp.ubuntu.com
|
||||
|
||||
# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
|
||||
# details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions>
|
||||
# might also be helpful.
|
||||
#
|
||||
# Note that "restrict" applies to both servers and clients, so a configuration
|
||||
# that might be intended to block requests from certain clients could also end
|
||||
# up blocking replies from your own upstream servers.
|
||||
|
||||
# By default, exchange time with everybody, but don't allow configuration.
|
||||
restrict -4 default kod notrap nomodify nopeer noquery limited
|
||||
restrict -6 default kod notrap nomodify nopeer noquery limited
|
||||
|
||||
# Local users may interrogate the ntp server more closely.
|
||||
restrict 127.0.0.1
|
||||
restrict ::1
|
||||
|
||||
# Needed for adding pool entries
|
||||
restrict source notrap nomodify noquery
|
||||
|
||||
# Clients from this (example!) subnet have unlimited access, but only if
|
||||
# cryptographically authenticated.
|
||||
#restrict 192.168.123.0 mask 255.255.255.0 notrust
|
||||
|
||||
|
||||
# If you want to provide time to your local subnet, change the next line.
|
||||
# (Again, the address is an example only.)
|
||||
#broadcast 192.168.123.255
|
||||
|
||||
# If you want to listen to time broadcasts on your local subnet, de-comment the
|
||||
# next lines. Please do this only if you trust everybody on the network!
|
||||
#disable auth
|
||||
#broadcastclient
|
||||
7
ansible/roles/patroni/handlers/main.yml
Normal file
7
ansible/roles/patroni/handlers/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
- name: Перезапускаю patroni.service
|
||||
ansible.builtin.systemd:
|
||||
name: patroni.service
|
||||
state: restarted
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
17
ansible/roles/patroni/tasks/config.yml
Normal file
17
ansible/roles/patroni/tasks/config.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
- name: Создаю директории и задаю права
|
||||
ansible.builtin.file:
|
||||
path: "{{ patroni_config_dir }}"
|
||||
state: directory
|
||||
mode: "755"
|
||||
owner: "999"
|
||||
group: "999"
|
||||
|
||||
- name: Наливаю конфиг patroni
|
||||
ansible.builtin.template:
|
||||
src: config.yml.j2
|
||||
dest: "{{ patroni_config_dir }}/config.yml"
|
||||
mode: "755"
|
||||
# backup: true
|
||||
notify:
|
||||
- Перезапускаю patroni.service
|
||||
6
ansible/roles/patroni/tasks/main.yml
Normal file
6
ansible/roles/patroni/tasks/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Наливаю юнит файл
|
||||
ansible.builtin.import_tasks: service.yml
|
||||
|
||||
- name: Наливаю конфигурацию
|
||||
ansible.builtin.import_tasks: config.yml
|
||||
26
ansible/roles/patroni/tasks/service.yml
Normal file
26
ansible/roles/patroni/tasks/service.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
- name: Наливаю юнит файл patroni
|
||||
ansible.builtin.template:
|
||||
src: patroni.service.j2
|
||||
dest: /etc/systemd/system/patroni.service
|
||||
notify:
|
||||
- Перезапускаю patroni.service
|
||||
|
||||
- name: Создаю директории и задаю права
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
owner: "999"
|
||||
group: "999"
|
||||
loop:
|
||||
- "{{ pg_data_dir }}"
|
||||
- "{{ pg_data_dir }}/data"
|
||||
notify:
|
||||
- Перезапускаю patroni.service
|
||||
|
||||
- name: Настраиваю patroni.service
|
||||
ansible.builtin.systemd:
|
||||
name: patroni.service
|
||||
state: started
|
||||
enabled: true
|
||||
82
ansible/roles/patroni/templates/config.yml.j2
Normal file
82
ansible/roles/patroni/templates/config.yml.j2
Normal file
@@ -0,0 +1,82 @@
|
||||
scope: patroni
|
||||
name: {{ inventory_hostname }}
|
||||
|
||||
restapi:
|
||||
listen: 0.0.0.0:8008
|
||||
connect_address: {{ inventory_hostname }}:8008
|
||||
|
||||
etcd:
|
||||
host: {{ inventory_hostname }}:2379
|
||||
|
||||
bootstrap:
|
||||
# this section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
|
||||
dcs:
|
||||
ttl: 30
|
||||
loop_wait: 10
|
||||
retry_timeout: 10
|
||||
maximum_lag_on_failover: 1048576
|
||||
# master_start_timeout: 300
|
||||
# synchronous_mode: false
|
||||
postgresql:
|
||||
use_pg_rewind: true
|
||||
use_slots: true
|
||||
parameters:
|
||||
wal_level: replica
|
||||
hot_standby: "on"
|
||||
logging_collector: 'on'
|
||||
max_wal_senders: 5
|
||||
max_replication_slots: 5
|
||||
wal_log_hints: "on"
|
||||
#archive_mode: "on"
|
||||
#archive_timeout: 600
|
||||
#archive_command: "cp -f %p /home/postgres/archived/%f"
|
||||
#recovery_conf:
|
||||
#restore_command: cp /home/postgres/archived/%f %p
|
||||
|
||||
# some desired options for 'initdb'
|
||||
initdb: # Note: It needs to be a list (some options need values, others are switches)
|
||||
- encoding: UTF8
|
||||
- data-checksums
|
||||
|
||||
pg_hba: # Add following lines to pg_hba.conf after running 'initdb'
|
||||
- host replication replicator 10.0.75.0/24 md5
|
||||
- host replication replicator 127.0.0.1/32 trust
|
||||
- host all all 10.0.75.0/24 md5
|
||||
- host all all 0.0.0.0/0 md5
|
||||
# - hostssl all all 0.0.0.0/0 md5
|
||||
|
||||
# Additional script to be launched after initial cluster creation (will be passed the connection URL as parameter)
|
||||
# post_init: /usr/local/bin/setup_cluster.sh
|
||||
# Some additional users users which needs to be created after initializing new cluster
|
||||
users:
|
||||
admin:
|
||||
password: admin
|
||||
options:
|
||||
- createrole
|
||||
- createdb
|
||||
|
||||
postgresql:
|
||||
listen: 0.0.0.0:5432
|
||||
connect_address: {{ inventory_hostname }}:5432
|
||||
data_dir: "/var/lib/postgresql/patroni/main"
|
||||
bin_dir: "/usr/lib/postgresql/16/bin"
|
||||
# config_dir:
|
||||
pgpass: /tmp/pgpass0
|
||||
authentication:
|
||||
replication:
|
||||
username: replicator
|
||||
password: {{ lookup('password', 'secrets/patroni-postgresql/replicator-password length=64') }}
|
||||
superuser:
|
||||
username: postgres
|
||||
password: {{ lookup('password', 'secrets/patroni-postgresql/postgres-password length=64') }}
|
||||
parameters:
|
||||
unix_socket_directories: '/var/run/postgresql'
|
||||
|
||||
watchdog:
|
||||
mode: off
|
||||
|
||||
tags:
|
||||
nofailover: false
|
||||
noloadbalance: false
|
||||
clonefrom: false
|
||||
nosync: false
|
||||
26
ansible/roles/patroni/templates/patroni.service.j2
Normal file
26
ansible/roles/patroni/templates/patroni.service.j2
Normal file
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=patroni
|
||||
Requires=etcd.service
|
||||
After=etcd.service
|
||||
|
||||
[Service]
|
||||
User={{ patroni_user }}
|
||||
Restart=always
|
||||
ExecStartPre=-/usr/bin/docker rm -f patroni
|
||||
ExecStart=/usr/bin/docker run \
|
||||
--rm \
|
||||
--name patroni \
|
||||
--hostname {{ inventory_hostname }} \
|
||||
--publish 5432:5432 \
|
||||
--publish 8008:8008 \
|
||||
--publish 8091:8091 \
|
||||
--add-host "patroni-postgresql-01:10.0.75.111" \
|
||||
--add-host "patroni-postgresql-02:10.0.75.112" \
|
||||
--add-host "patroni-postgresql-03:10.0.75.113" \
|
||||
--volume={{ patroni_config_dir }}/config.yml:{{ patroni_config_dir }}/config.yml:ro \
|
||||
--volume={{ pg_data_dir }}:{{ pg_data_dir }} \
|
||||
ghcr.io/batonogov/patroni-docker:{{ image_version }}
|
||||
ExecStop=/usr/bin/docker stop -t 10 patroni
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
4
ansible/roles/patroni/vars/main.yml
Normal file
4
ansible/roles/patroni/vars/main.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
image_version: v3.3.0-pg16.3
|
||||
pg_data_dir: /var/lib/postgresql
|
||||
patroni_config_dir: /etc/patroni
|
||||
25
opentofu/patroni-postgresql/.terraform.lock.hcl
generated
Normal file
25
opentofu/patroni-postgresql/.terraform.lock.hcl
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
# This file is maintained automatically by "tofu init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/bpg/proxmox" {
|
||||
version = "0.60.0"
|
||||
constraints = ">= 0.53.1"
|
||||
hashes = [
|
||||
"h1:ZC+6RI6NKsTB8Y0Lm0onj6N/+k8RZP//GwGqQZN/UVM=",
|
||||
"zh:0d244b94bdfba501ae285db1d563ad91c393cdb97807377ecdbbc96454e345f7",
|
||||
"zh:146617d6065d52f512e8e7f9d230e5f8e6e11a67e67c7d8906e212631e53c61e",
|
||||
"zh:6290bed20fa3e5c070ff867b7a6f2be750c22b9bc97b976a134ab342bdc617ae",
|
||||
"zh:70d69b7863d0bb5cede73bcb04b81e8ea2be124e19ba854795198302ba04762a",
|
||||
"zh:7655a8326618cfce8d9e24c1f3fad4a191f80bfc3b3be9a2b7e9169f0c11c05a",
|
||||
"zh:7700e2443eea1508de880484209f625015b7e8f2c74f615e2c18cc986ee1ffdf",
|
||||
"zh:96805c02119733f0639084ffd1a194795b153801f91cc22ed4f1cb5487efc035",
|
||||
"zh:9f8a331cecd7db82cba94e58016ec92d0835fd2f6efc7c5ec46217e4109f1914",
|
||||
"zh:ae7cdd011e156dd8dadf836c8f1badbc9798c5dbf308313ca29153855bf4f17f",
|
||||
"zh:b5937d52fdf294b92be3e39581e4c1ecceb89fe614756334c5384102b4551a87",
|
||||
"zh:b5e11bec8bad9b1ed044d550a8d0a95ca5e94ecd0660a876260909ed42e4dcdb",
|
||||
"zh:d3f390ae2788240ca3db0aac2d36a01128257649a3e90dd9e600fd8b0c9d9e33",
|
||||
"zh:d947c22f05af6d81025bf92c5d99fd7db27ee2e5642f4b3a9b1e251673c80656",
|
||||
"zh:dfeed9507c83d7d4b25539c010d04bd6de12396f15d180a15119b923b3b49fb5",
|
||||
"zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597",
|
||||
]
|
||||
}
|
||||
94
opentofu/patroni-postgresql/etcd.tf
Normal file
94
opentofu/patroni-postgresql/etcd.tf
Normal file
@@ -0,0 +1,94 @@
|
||||
variable "etcd_vms" {
|
||||
type = list(object({
|
||||
name = string
|
||||
address = string
|
||||
node_name = string
|
||||
}))
|
||||
default = [
|
||||
{
|
||||
name = "etcd-01"
|
||||
address = "10.0.75.114/24"
|
||||
node_name = "pve-01"
|
||||
},
|
||||
{
|
||||
name = "etcd-02"
|
||||
address = "10.0.75.115/24"
|
||||
node_name = "pve-02"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Создание виртуальных машин
|
||||
resource "proxmox_virtual_environment_vm" "etcd" {
|
||||
for_each = { for vm in var.etcd_vms : vm.name => vm }
|
||||
|
||||
name = each.value.name
|
||||
migrate = true
|
||||
description = "Managed by OpenTofu"
|
||||
tags = ["etcd"]
|
||||
on_boot = true
|
||||
node_name = each.value.node_name
|
||||
|
||||
clone {
|
||||
vm_id = "2404"
|
||||
node_name = "pve-01"
|
||||
retries = 3
|
||||
}
|
||||
|
||||
agent {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
operating_system {
|
||||
type = "l26"
|
||||
}
|
||||
|
||||
cpu {
|
||||
cores = 2
|
||||
type = "host"
|
||||
numa = true
|
||||
}
|
||||
|
||||
memory {
|
||||
dedicated = 2048
|
||||
}
|
||||
|
||||
vga {
|
||||
memory = 4
|
||||
type = "serial0"
|
||||
}
|
||||
|
||||
disk {
|
||||
size = "20"
|
||||
interface = "virtio0"
|
||||
datastore_id = "proxmox-data-01"
|
||||
file_format = "raw"
|
||||
}
|
||||
|
||||
network_device {
|
||||
bridge = "vmbr0"
|
||||
model = "virtio"
|
||||
}
|
||||
|
||||
initialization {
|
||||
datastore_id = "proxmox-data-01"
|
||||
ip_config {
|
||||
ipv4 {
|
||||
address = each.value.address
|
||||
gateway = "10.0.75.1"
|
||||
}
|
||||
}
|
||||
dns {
|
||||
servers = [
|
||||
"10.0.75.65",
|
||||
"10.0.75.66"
|
||||
]
|
||||
}
|
||||
user_account {
|
||||
username = "infra"
|
||||
keys = [
|
||||
var.ssh_public_key
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
99
opentofu/patroni-postgresql/patroni-postgresql.tf
Normal file
99
opentofu/patroni-postgresql/patroni-postgresql.tf
Normal file
@@ -0,0 +1,99 @@
|
||||
variable "patroni_vms" {
|
||||
type = list(object({
|
||||
name = string
|
||||
address = string
|
||||
node_name = string
|
||||
}))
|
||||
default = [
|
||||
{
|
||||
name = "patroni-postgresql-01"
|
||||
address = "10.0.75.111/24"
|
||||
node_name = "pve-01"
|
||||
},
|
||||
{
|
||||
name = "patroni-postgresql-02"
|
||||
address = "10.0.75.112/24"
|
||||
node_name = "pve-02"
|
||||
},
|
||||
{
|
||||
name = "patroni-postgresql-03" # Исправлено имя
|
||||
address = "10.0.75.113/24"
|
||||
node_name = "pve-02"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Создание виртуальных машин
|
||||
resource "proxmox_virtual_environment_vm" "patroni" {
|
||||
for_each = { for vm in var.patroni_vms : vm.name => vm }
|
||||
|
||||
name = each.value.name
|
||||
migrate = true
|
||||
description = "Managed by OpenTofu"
|
||||
tags = ["patroni", "postgresql"]
|
||||
on_boot = true
|
||||
node_name = each.value.node_name
|
||||
|
||||
clone {
|
||||
vm_id = "2404"
|
||||
node_name = "pve-01"
|
||||
retries = 3
|
||||
}
|
||||
|
||||
agent {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
operating_system {
|
||||
type = "l26"
|
||||
}
|
||||
|
||||
cpu {
|
||||
cores = 2
|
||||
type = "host"
|
||||
numa = true
|
||||
}
|
||||
|
||||
memory {
|
||||
dedicated = 2048
|
||||
}
|
||||
|
||||
vga {
|
||||
memory = 4
|
||||
type = "serial0"
|
||||
}
|
||||
|
||||
disk {
|
||||
size = "20"
|
||||
interface = "virtio0"
|
||||
datastore_id = "proxmox-data-01"
|
||||
file_format = "raw"
|
||||
}
|
||||
|
||||
network_device {
|
||||
bridge = "vmbr0"
|
||||
model = "virtio"
|
||||
}
|
||||
|
||||
initialization {
|
||||
datastore_id = "proxmox-data-01"
|
||||
ip_config {
|
||||
ipv4 {
|
||||
address = each.value.address
|
||||
gateway = "10.0.75.1"
|
||||
}
|
||||
}
|
||||
dns {
|
||||
servers = [
|
||||
"10.0.75.65",
|
||||
"10.0.75.66"
|
||||
]
|
||||
}
|
||||
user_account {
|
||||
username = "infra"
|
||||
keys = [
|
||||
var.ssh_public_key
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
17
opentofu/patroni-postgresql/provider.tf
Normal file
17
opentofu/patroni-postgresql/provider.tf
Normal file
@@ -0,0 +1,17 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
proxmox = {
|
||||
source = "bpg/proxmox"
|
||||
version = ">= 0.60.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "proxmox" {
|
||||
endpoint = var.virtual_environment_endpoint
|
||||
api_token = var.virtual_environment_api_token
|
||||
insecure = true
|
||||
ssh {
|
||||
agent = false
|
||||
}
|
||||
}
|
||||
3
opentofu/patroni-postgresql/terraform.tfvars.example
Normal file
3
opentofu/patroni-postgresql/terraform.tfvars.example
Normal file
@@ -0,0 +1,3 @@
|
||||
virtual_environment_api_token = "root@pam!for-terraform-provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
virtual_environment_endpoint = "https://x.x.x.x:8006/"
|
||||
ssh_public_key = "ssh-rsa ..."
|
||||
14
opentofu/patroni-postgresql/variables.tf
Normal file
14
opentofu/patroni-postgresql/variables.tf
Normal file
@@ -0,0 +1,14 @@
|
||||
variable "virtual_environment_endpoint" {
|
||||
type = string
|
||||
description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)"
|
||||
}
|
||||
|
||||
variable "virtual_environment_api_token" {
|
||||
type = string
|
||||
description = "The api roken the Proxmox Virtual Environment API (example: root@pam!for-terraform-provider=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)"
|
||||
}
|
||||
|
||||
variable "ssh_public_key" {
|
||||
type = string
|
||||
description = "SSH Puclic key for VMs (example: ssh-rsa ...)"
|
||||
}
|
||||
Reference in New Issue
Block a user