feat: 纳管共享 etcd 与 k3s 外 PostgreSQL 高可用及备份
yaml / yaml (pull_request) Successful in 41s
ansible / collection-test (pull_request) Successful in 2m41s
terraform / validate (pull_request) Successful in 2m41s
ansible / lint (pull_request) Successful in 4m36s

This commit is contained in:
2026-09-25 19:34:48 +00:00
parent acd4b55722
commit 3a2fe5fa0c
92 changed files with 4211 additions and 0 deletions
@@ -0,0 +1,69 @@
---
- name: 本地生成私钥
community.crypto.openssl_privatekey:
path: "{{ pg_config_dir }}/{{ pg_cert_name }}.key"
type: ECC
curve: secp256r1
owner: root
group: "{{ pg_profile.user }}"
mode: '0640'
- name: 本地生成 CSR
community.crypto.openssl_csr:
path: "{{ pg_config_dir }}/{{ pg_cert_name }}.csr"
privatekey_path: "{{ pg_config_dir }}/{{ pg_cert_name }}.key"
common_name: "{{ pg_cert_cn | default(omit, true) }}"
use_common_name_for_san: false
subject_alt_name: >-
{{ ['DNS:' ~ pg_profile.dns, 'IP:' ~ pg_address] if pg_cert_name == 'server'
else ['DNS:etcd-patroni-pg-prod'] }}
extended_key_usage: "{{ pg_cert_eku }}"
key_usage: [digitalSignature]
mode: '0644'
register: pg_csr
- name: 检查证书文件
ansible.builtin.stat:
path: "{{ pg_config_dir }}/{{ pg_cert_name }}.crt"
register: pg_cert_file
- name: 检查续签窗口
community.crypto.x509_certificate_info:
path: "{{ pg_config_dir }}/{{ pg_cert_name }}.crt"
valid_at: {renewal: '+14d'}
register: pg_cert_info
when: pg_cert_file.stat.exists
- name: 需要时请求中央 CA 签发
when: not pg_cert_file.stat.exists or pg_csr is changed or not (pg_cert_info.valid_at.renewal | default(false))
block:
- name: 读取公开 CSR
ansible.builtin.slurp:
src: "{{ pg_config_dir }}/{{ pg_cert_name }}.csr"
register: pg_csr_content
- name: 请求签发(凭据仅在控制端)
ansible.builtin.uri:
url: "{{ pg_bao_url }}/v1/pki/sign/{{ pg_cert_role }}"
method: POST
headers:
X-Vault-Token: "{{ pg_bao_token }}"
body_format: json
body:
csr: "{{ pg_csr_content.content | b64decode }}"
ttl: 1440h
status_code: 200
delegate_to: localhost
become: false
register: pg_signed
no_log: true
- name: 保存证书和信任链
ansible.builtin.copy:
content: "{{ item.content }}"
dest: "{{ pg_config_dir }}/{{ item.name }}"
owner: root
group: "{{ pg_profile.user }}"
mode: '0644'
loop:
- name: "{{ pg_cert_name }}.crt"
content: "{{ pg_signed.json.data.certificate }}\n{{ pg_signed.json.data.ca_chain | join('\n') }}\n"
- name: ca.crt
content: "{{ pg_signed.json.data.ca_chain | join('\n') }}\n"
- name: 记录本轮已签发证书以供显式续签入口重载
ansible.builtin.set_fact:
pg_certificates_changed: true
@@ -0,0 +1,80 @@
---
- name: 派生实例专用路径
ansible.builtin.set_fact:
pg_profile: "{{ pg_profiles[pg_instance] }}"
pg_config_dir: "{{ pg_config_root }}/{{ pg_instance }}"
pg_parent_dir: "{{ pg_data_root }}/{{ pg_instance }}"
pg_data_dir: "{{ pg_data_root }}/{{ pg_instance }}/data"
pg_socket_dir: "/run/homelab-postgresql-{{ pg_instance }}"
pg_member: "{{ inventory_hostname }}"
pg_credentials: "{{ hostvars['localhost'].pg_loaded_credentials[pg_instance] }}"
pg_etcd_credentials: "{{ hostvars['localhost'].pg_loaded_etcd }}"
no_log: true
- name: 创建实例操作系统组
ansible.builtin.group:
name: "{{ pg_profile.user }}"
system: true
- name: 创建实例操作系统账号
ansible.builtin.user:
name: "{{ pg_profile.user }}"
group: "{{ pg_profile.user }}"
home: "{{ pg_parent_dir }}"
create_home: false
shell: /bin/bash
system: true
- name: 创建隔离目录
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ pg_profile.user }}"
group: "{{ pg_profile.user }}"
mode: '0700'
loop:
- "{{ pg_parent_dir }}"
- "{{ pg_data_dir }}"
- "{{ pg_socket_dir }}"
- "{{ pg_parent_dir }}/backup-lock"
- "{{ pg_parent_dir }}/backup-spool"
- name: 保持共享配置父目录可遍历,实例目录各自受限
ansible.builtin.file:
path: "{{ pg_config_root }}"
state: directory
owner: root
group: root
mode: '0755'
- name: 创建 root 管理的配置目录
ansible.builtin.file:
path: "{{ pg_config_dir }}"
state: directory
owner: root
group: "{{ pg_profile.user }}"
mode: '0750'
- name: 签发实例服务器证书
ansible.builtin.include_tasks: certificate.yml
vars:
pg_cert_name: server
pg_cert_cn: "{{ pg_profile.dns }}"
pg_cert_role: "homelab-pg-{{ pg_instance }}"
pg_cert_eku: [serverAuth]
- name: 签发 Patroni 独立无 CN 客户端证书
ansible.builtin.include_tasks: certificate.yml
vars:
pg_cert_name: etcd
pg_cert_cn: ''
pg_cert_role: homelab-etcd-client
pg_cert_eku: [clientAuth]
when: pg_instance == 'prod'
- name: 写入实例配置
ansible.builtin.template:
src: "{{ item }}.j2"
dest: "{{ pg_config_dir }}/{{ item }}"
owner: root
group: "{{ pg_profile.user }}"
mode: '0640'
loop: "{{ ['patroni.yml', 'pgbackrest.conf'] if pg_instance == 'prod' else ['postgresql.conf', 'pg_hba.conf'] }}"
no_log: true
- name: 安装实例专用服务(不自动启动或重启)
ansible.builtin.template:
src: instance.service.j2
dest: "/etc/systemd/system/homelab-postgresql-{{ pg_instance }}.service"
mode: '0644'