230 lines
9.2 KiB
YAML
230 lines
9.2 KiB
YAML
---
|
|
# Install CloudNativePG via OLM and provision the PostgreSQL Cluster + Database CRs
|
|
# and credential Secrets that back Automation Orchestrator (backend + Temporal +
|
|
# Temporal Visibility databases, one shared owner role).
|
|
#
|
|
# WARNING: this is a single-instance (no HA), operator-provisioned PostgreSQL
|
|
# cluster intended for demo/dev use. For production, point automation_orchestrator_operator
|
|
# at a customer-managed PostgreSQL instance instead of running this role.
|
|
#
|
|
# Modeled on https://github.com/ansible/aapctl (internal/install/cloudnativepg).
|
|
# CloudNativePG's OLM subscription uses Manual install-plan approval, so this role
|
|
# approves the InstallPlan itself rather than relying on Automatic.
|
|
#
|
|
# All tasks are idempotent (kubernetes.core.k8s state: present).
|
|
|
|
- name: Resolve postgres credentials from Vault
|
|
ansible.builtin.include_tasks: vault_secrets.yml
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 1: Install CloudNativePG operator via OLM
|
|
# ------------------------------------------------------------------
|
|
- name: Create CloudNativePG operator namespace
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
|
|
- name: Create CloudNativePG OperatorGroup
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
metadata:
|
|
name: "{{ cloudnativepg_operator_name }}"
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
spec: {}
|
|
|
|
- name: Subscribe to CloudNativePG operator
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: operators.coreos.com/v1alpha1
|
|
kind: Subscription
|
|
metadata:
|
|
name: "{{ cloudnativepg_operator_name }}"
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
spec:
|
|
channel: "{{ cloudnativepg_operator_channel }}"
|
|
installPlanApproval: Manual
|
|
name: "{{ cloudnativepg_operator_name }}"
|
|
source: "{{ cloudnativepg_operator_catalog_source }}"
|
|
sourceNamespace: openshift-marketplace
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 2: Approve the Manual InstallPlan and wait for the CSV to succeed
|
|
# ------------------------------------------------------------------
|
|
- name: Wait for OLM to create an InstallPlan for the Subscription
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: Subscription
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
name: "{{ cloudnativepg_operator_name }}"
|
|
register: __cloudnativepg_operator_sub
|
|
until: >-
|
|
__cloudnativepg_operator_sub.resources | length > 0 and
|
|
(__cloudnativepg_operator_sub.resources[0].status.installPlanRef.name | default('')) | length > 0
|
|
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
- name: Read the InstallPlan
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: InstallPlan
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
name: "{{ __cloudnativepg_operator_sub.resources[0].status.installPlanRef.name }}"
|
|
register: __cloudnativepg_operator_installplan
|
|
|
|
- name: Approve the InstallPlan
|
|
kubernetes.core.k8s_json_patch:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: InstallPlan
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
name: "{{ __cloudnativepg_operator_sub.resources[0].status.installPlanRef.name }}"
|
|
patch:
|
|
- op: add
|
|
path: /spec/approved
|
|
value: true
|
|
|
|
- name: Wait for CloudNativePG CSV to succeed
|
|
kubernetes.core.k8s_info:
|
|
api_version: operators.coreos.com/v1alpha1
|
|
kind: ClusterServiceVersion
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
name: "{{ __cloudnativepg_operator_installplan.resources[0].spec.clusterServiceVersionNames[0] }}"
|
|
register: __cloudnativepg_operator_csv
|
|
until: >-
|
|
__cloudnativepg_operator_csv.resources | length > 0 and
|
|
__cloudnativepg_operator_csv.resources[0].status.phase | default('') == 'Succeeded'
|
|
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
- name: Wait for CloudNativePG controller manager webhook to be reachable
|
|
kubernetes.core.k8s_info:
|
|
api_version: v1
|
|
kind: Endpoints
|
|
namespace: "{{ cloudnativepg_operator_operator_namespace }}"
|
|
name: cnpg-controller-manager-service
|
|
register: __cloudnativepg_operator_endpoints
|
|
until: >-
|
|
__cloudnativepg_operator_endpoints.resources | length > 0 and
|
|
(__cloudnativepg_operator_endpoints.resources[0].subsets | default([])
|
|
| map(attribute='addresses', default=[]) | flatten | length) > 0
|
|
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 3: Credential secrets (type kubernetes.io/basic-auth)
|
|
# ------------------------------------------------------------------
|
|
- name: Create cluster namespace
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: "{{ cloudnativepg_operator_cluster_namespace }}"
|
|
|
|
- name: Create postgres credential secrets
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: "{{ item.name }}"
|
|
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
|
type: kubernetes.io/basic-auth
|
|
stringData:
|
|
username: "{{ cloudnativepg_operator_owner_user }}"
|
|
password: "{{ __cloudnativepg_operator_password }}"
|
|
host: "{{ cloudnativepg_operator_cluster_name }}-rw.{{ cloudnativepg_operator_cluster_namespace }}.svc"
|
|
port: "5432"
|
|
database: "{{ item.database }}"
|
|
loop: "{{ cloudnativepg_operator_secrets }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
no_log: "{{ cloudnativepg_operator_no_log }}"
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 4: PostgreSQL Cluster
|
|
# ------------------------------------------------------------------
|
|
- name: Create PostgreSQL Cluster
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: postgresql.cnpg.io/v1
|
|
kind: Cluster
|
|
metadata:
|
|
name: "{{ cloudnativepg_operator_cluster_name }}"
|
|
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
|
spec: >-
|
|
{{
|
|
{
|
|
'instances': cloudnativepg_operator_instances,
|
|
'imageName': cloudnativepg_operator_image_name,
|
|
'bootstrap': {
|
|
'initdb': {
|
|
'owner': cloudnativepg_operator_owner_user,
|
|
'secret': {'name': cloudnativepg_operator_secrets[0].name},
|
|
},
|
|
},
|
|
'storage': {'size': cloudnativepg_operator_storage_size},
|
|
}
|
|
| combine({'storage': {'storageClass': cloudnativepg_operator_storage_class}} if cloudnativepg_operator_storage_class else {}, recursive=True)
|
|
| combine({'postgresql': {'parameters': {'max_connections': cloudnativepg_operator_max_connections | string}}} if cloudnativepg_operator_max_connections else {}, recursive=True)
|
|
}}
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 5: Logical databases
|
|
# ------------------------------------------------------------------
|
|
- name: Create Database CRs
|
|
kubernetes.core.k8s:
|
|
state: present
|
|
definition:
|
|
apiVersion: postgresql.cnpg.io/v1
|
|
kind: Database
|
|
metadata:
|
|
name: "{{ item.name }}"
|
|
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
|
spec:
|
|
name: "{{ item.dbname }}"
|
|
owner: "{{ cloudnativepg_operator_owner_user }}"
|
|
cluster:
|
|
name: "{{ cloudnativepg_operator_cluster_name }}"
|
|
loop: "{{ cloudnativepg_operator_databases }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
|
|
- name: Wait for Database CRs to be applied
|
|
kubernetes.core.k8s_info:
|
|
api_version: postgresql.cnpg.io/v1
|
|
kind: Database
|
|
namespace: "{{ cloudnativepg_operator_cluster_namespace }}"
|
|
register: __cloudnativepg_operator_databases_status
|
|
until: >-
|
|
__cloudnativepg_operator_databases_status.resources | length >= (cloudnativepg_operator_databases | length) and
|
|
(__cloudnativepg_operator_databases_status.resources
|
|
| rejectattr('status.applied', 'undefined')
|
|
| selectattr('status.applied')
|
|
| list | length) == (__cloudnativepg_operator_databases_status.resources | length)
|
|
retries: "{{ __cloudnativepg_operator_wait_retries }}"
|
|
delay: 10
|
|
|
|
# ------------------------------------------------------------------
|
|
# Step 6: Summary
|
|
# ------------------------------------------------------------------
|
|
- name: Display CloudNativePG deployment summary
|
|
ansible.builtin.debug:
|
|
msg:
|
|
- "CloudNativePG PostgreSQL cluster ready!"
|
|
- " Operator namespace : {{ cloudnativepg_operator_operator_namespace }}"
|
|
- " Cluster : {{ cloudnativepg_operator_cluster_name }} ({{ cloudnativepg_operator_cluster_namespace }})"
|
|
- " Owner role : {{ cloudnativepg_operator_owner_user }}"
|
|
- " Databases : {{ cloudnativepg_operator_databases | map(attribute='dbname') | join(', ') }}"
|
|
- " Credential secrets : {{ cloudnativepg_operator_secrets | map(attribute='name') | join(', ') }}"
|