diff --git a/manifests/cloudnativepg-operator/components/metrics/PodMonitor-cnpg-controller-manager.yaml b/manifests/cloudnativepg-operator/components/metrics/PodMonitor-cnpg-controller-manager.yaml new file mode 100644 index 0000000..3926a6a --- /dev/null +++ b/manifests/cloudnativepg-operator/components/metrics/PodMonitor-cnpg-controller-manager.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: cnpg-controller-manager +spec: + selector: + matchLabels: + app.kubernetes.io/name: cloudnative-pg + podMetricsEndpoints: + - port: metrics diff --git a/manifests/cloudnativepg-operator/components/metrics/kustomization.yaml b/manifests/cloudnativepg-operator/components/metrics/kustomization.yaml new file mode 100644 index 0000000..6657fd9 --- /dev/null +++ b/manifests/cloudnativepg-operator/components/metrics/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + + +resources: + - PodMonitor-cnpg-controller-manager.yaml diff --git a/manifests/postgres/README.md b/manifests/postgres/README.md new file mode 100644 index 0000000..cc6373c --- /dev/null +++ b/manifests/postgres/README.md @@ -0,0 +1,15 @@ +# PostgreSQL Cluster including HA Multi-cluster replication + +Following Components are available: + +- `enable-super_user_access` Enable super user account and access to cluster + +- `ha` Deploy replicated multi-cluster in master-slave configuration + +- `metrics` Enable prometheus metrics endpoint + +Following Overlays are available: + +- `Production` - Base deployment manifests + +- `HA` - HA Multi-Cluster deployment with replication between clusters diff --git a/manifests/postgres/base/Cluster.yaml b/manifests/postgres/base/Cluster.yaml new file mode 100644 index 0000000..ec23942 --- /dev/null +++ b/manifests/postgres/base/Cluster.yaml @@ -0,0 +1,95 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + labels: + app.kubernetes.io/component: base + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: postgres + name: main +spec: + + affinity: + additionalPodAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - postgres + topologyKey: kubernetes.io/hostname + + enablePodAntiAffinity: true + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: Exists + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/prime + operator: Exists + topologyKey: kubernetes.io/hostname + + # bootstrap: {} + + description: "Cluster PostgreSQL Instance" + + enableSuperuserAccess: false + + # externalClusters: [] + + imageName: ghcr.io/cloudnative-pg/postgresql:-updated_by_patch- + + inheritedMetadata: + labels: + app.kubernetes.io/component: base + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: postgres + + instances: 3 + + # monitoring: {} + + nodeMaintenanceWindow: + inProgress: false + reusePVC: false + + primaryUpdateStrategy: unsupervised + + postgresql: + parameters: + max_parallel_workers: '34' + max_replication_slots: '32' + max_worker_processes: '34' + + # replica: {} + + resources: + requests: + cpu: "100m" + memory: "100Mi" + limits: + cpu: "2" + memory: "1Gi" + + startDelay: 300 + + stopDelay: 300 + + storage: + resizeInUseVolumes: false + size: 10Gi diff --git a/manifests/postgres/base/kustomization.yaml b/manifests/postgres/base/kustomization.yaml new file mode 100644 index 0000000..95cb127 --- /dev/null +++ b/manifests/postgres/base/kustomization.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: postgres + +resources: + - Cluster.yaml diff --git a/manifests/postgres/components/dashboard/GrafanaDashboard-cloudnativepg.yaml b/manifests/postgres/components/dashboard/GrafanaDashboard-cloudnativepg.yaml new file mode 100644 index 0000000..504f001 --- /dev/null +++ b/manifests/postgres/components/dashboard/GrafanaDashboard-cloudnativepg.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + labels: + app.kubernetes.io/component: database + name: cloudnativepg +spec: + allowCrossNamespaceImport: true + folder: "General" + resyncPeriod: 24h + instanceSelector: + matchLabels: + dashboards: grafana + grafanaCom: + id: 20417 + revision: 4 # as @ 2025-08-02 diff --git a/manifests/postgres/components/dashboard/kustomization.yaml b/manifests/postgres/components/dashboard/kustomization.yaml new file mode 100644 index 0000000..64457a7 --- /dev/null +++ b/manifests/postgres/components/dashboard/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + + +resources: + - GrafanaDashboard-cloudnativepg.yaml diff --git a/manifests/postgres/components/enable-super_user_access/kustomization.yaml b/manifests/postgres/components/enable-super_user_access/kustomization.yaml new file mode 100644 index 0000000..38c0bf3 --- /dev/null +++ b/manifests/postgres/components/enable-super_user_access/kustomization.yaml @@ -0,0 +1,24 @@ +--- + +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + + +patches: + # yamllint disable rule:indentation + - patch: |- + + - op: replace + path: /spec/enableSuperuserAccess + value: true + + - op: add + path: /spec/superuserSecret + value: + name: cluster-superuser + + # yamllint enable rule:indentation + target: + group: postgresql.cnpg.io + version: v1 + kind: Cluster diff --git a/manifests/postgres/components/ha/Cluster-main-02.yaml b/manifests/postgres/components/ha/Cluster-main-02.yaml new file mode 100644 index 0000000..64e1f31 --- /dev/null +++ b/manifests/postgres/components/ha/Cluster-main-02.yaml @@ -0,0 +1,99 @@ +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + labels: + app.kubernetes.io/component: ha + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: production-ha + name: main-02 +spec: + + affinity: + additionalPodAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - postgres + topologyKey: kubernetes.io/hostname + + enablePodAntiAffinity: true + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + - weight: 50 + preference: + matchExpressions: + - key: node-role.kubernetes.io/master + operator: Exists + - weight: 100 + preference: + matchExpressions: + - key: node-role.kubernetes.io/prime + operator: Exists + topologyKey: kubernetes.io/hostname + + bootstrap: + pg_basebackup: + source: main-01 + + description: "Cluster PostgreSQL Instance" + + enableSuperuserAccess: false + + externalClusters: [] + + imageName: ghcr.io/cloudnative-pg/postgresql:-updated_by_patch- + + inheritedMetadata: + labels: + app.kubernetes.io/component: ha + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: production-ha + + instances: 3 + + monitoring: {} + + nodeMaintenanceWindow: + inProgress: false + reusePVC: false + + primaryUpdateStrategy: unsupervised + + postgresql: + parameters: + max_parallel_workers: '34' + max_replication_slots: '32' + max_worker_processes: '34' + + replica: + primary: main-01 + source: main-01 + + resources: + requests: + cpu: "100m" + memory: "100Mi" + limits: + cpu: "2" + memory: "1Gi" + + startDelay: 300 + + stopDelay: 300 + + storage: + resizeInUseVolumes: false + size: 10Gi diff --git a/manifests/postgres/components/ha/Service-main-r.yaml b/manifests/postgres/components/ha/Service-main-r.yaml new file mode 100644 index 0000000..ee88e99 --- /dev/null +++ b/manifests/postgres/components/ha/Service-main-r.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: ha + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: production-ha + name: main-r +spec: + ports: + - name: postgres + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + cnpg.io/cluster: -updated_by_replacement- + cnpg.io/podRole: instance + sessionAffinity: None + type: ClusterIP diff --git a/manifests/postgres/components/ha/Service-main-ro.yaml b/manifests/postgres/components/ha/Service-main-ro.yaml new file mode 100644 index 0000000..73dab48 --- /dev/null +++ b/manifests/postgres/components/ha/Service-main-ro.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: ha + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: production-ha + name: main-ro +spec: + ports: + - name: postgres + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + cnpg.io/cluster: -updated_by_replacement- + cnpg.io/instanceRole: replica + sessionAffinity: None + type: ClusterIP diff --git a/manifests/postgres/components/ha/Service-main-rw.yaml b/manifests/postgres/components/ha/Service-main-rw.yaml new file mode 100644 index 0000000..0d51ee8 --- /dev/null +++ b/manifests/postgres/components/ha/Service-main-rw.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: ha + app.kubernetes.io/instance: production + app.kubernetes.io/name: postgres + app.kubernetes.io/part-of: production-ha + name: main-rw +spec: + ports: + - name: postgres + port: 5432 + protocol: TCP + targetPort: 5432 + selector: + cnpg.io/cluster: -updated_by_replacement- + cnpg.io/instanceRole: primary + sessionAffinity: None + type: ClusterIP diff --git a/manifests/postgres/components/ha/kustomization.yaml b/manifests/postgres/components/ha/kustomization.yaml new file mode 100644 index 0000000..f897f70 --- /dev/null +++ b/manifests/postgres/components/ha/kustomization.yaml @@ -0,0 +1,154 @@ +--- + +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + + +resources: + # - ../../base + - Cluster-main-02.yaml + - Service-main-r.yaml + - Service-main-ro.yaml + - Service-main-rw.yaml + + +patches: + + # yamllint disable rule:indentation + - patch: |- + + - op: add + path: /metadata/name + value: main-01 + + - op: replace + path: /spec/replica + value: + primary: main-01 + source: main-02 + + # yamllint enable rule:indentation + target: + group: postgresql.cnpg.io + version: v1 + kind: Cluster + name: main + + # yamllint disable rule:indentation + - patch: |- + + - op: add + path: /spec/affinity/additionalPodAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/0 + value: + weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/part-of + operator: In + values: + - production-ha + topologyKey: kubernetes.io/hostname + + + - op: replace + path: /spec/externalClusters + value: + + - name: main-01 + connectionParameters: + host: main-01-rw.updated_by_replacement.svc + user: streaming_replica + dbname: postgres + sslmode: verify-full + sslKey: + name: main-01-replication + key: tls.key + sslCert: + name: main-01-replication + key: tls.crt + sslRootCert: + name: main-01-ca + key: ca.crt + + - name: main-02 + connectionParameters: + host: main-02-rw.updated_by_replacement.svc + user: streaming_replica + dbname: postgres + sslmode: verify-full + sslKey: + name: main-02-replication + key: tls.key + sslCert: + name: main-02-replication + key: tls.crt + sslRootCert: + name: main-02-ca + key: ca.crt + + # yamllint enable rule:indentation + target: + group: postgresql.cnpg.io + version: v1 + kind: Cluster + + + +replacements: + # + # Add to Top-most Kustomization.yaml + # + # Updates extenal cluster DNS name octet that contains the namespace + # - source: + # kind: Cluster + # name: main-01 + # fieldPath: metadata.namespace + # targets: + # - select: + # kind: Cluster + # fieldPaths: + # - spec.externalClusters.[name=main-01].connectionParameters.host + # - spec.externalClusters.[name=main-02].connectionParameters.host + # options: + # delimiter: "." + # index: 1 + + + # + # Add to Top-most Kustomization.yaml, if primary has be changed + # + # Updates each of the services to point the cluster that is denoted as primary + # within cluster main-02 + - source: + kind: Cluster + name: main-02 + fieldPath: spec.replica.primary + targets: + - select: + kind: Service + name: main-r + fieldPaths: + - spec.selector.[cnpg.io/cluster] + - select: + kind: Service + name: main-ro + fieldPaths: + - spec.selector.[cnpg.io/cluster] + - select: + kind: Service + name: main-rw + fieldPaths: + - spec.selector.[cnpg.io/cluster] + + # Dont change + - source: + kind: Cluster + name: main-02 + fieldPath: metadata.labels.[app.kubernetes.io/part-of] + targets: + - select: + kind: Cluster + fieldPaths: + - metadata.labels.[app.kubernetes.io/part-of] + - spec.inheritedMetadata.labels.[app.kubernetes.io/part-of] diff --git a/manifests/postgres/components/metrics/kustomization.yaml b/manifests/postgres/components/metrics/kustomization.yaml new file mode 100644 index 0000000..aaba1f9 --- /dev/null +++ b/manifests/postgres/components/metrics/kustomization.yaml @@ -0,0 +1,29 @@ +--- + +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + + +patches: + # yamllint disable rule:indentation + - patch: |- + + - op: add + path: /spec/monitoring + value: + enablePodMonitor: true + + - op: add + path: /spec/monitoring/podMonitorRelabelings + value: + - sourceLabels: ["__meta_kubernetes_pod_label_cnpg_io_cluster"] + targetLabel: cluster + action: replace + - sourceLabels: ["__meta_kubernetes_pod_name"] + targetLabel: instance + action: replace + # yamllint enable rule:indentation + target: + group: postgresql.cnpg.io + version: v1 + kind: Cluster diff --git a/manifests/postgres/overlays/ha/kustomization.yaml b/manifests/postgres/overlays/ha/kustomization.yaml new file mode 100644 index 0000000..bfbcc17 --- /dev/null +++ b/manifests/postgres/overlays/ha/kustomization.yaml @@ -0,0 +1,57 @@ +--- + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: postgres-15 + + +resources: + - ../../base + + +components: + - ../../components/ha + - ../../components/metrics + - ../../components/dashboard + + +patches: + + # yamllint disable rule:indentation + - patch: |- + + - op: replace + path: /spec/instances + value: 2 + # yamllint enable rule:indentation + target: + kind: Cluster + + # yamllint disable rule:indentation + - patch: |- + + - op: replace + path: /spec/imageName + value: ghcr.io/cloudnative-pg/postgresql:15.12-11 + # yamllint enable rule:indentation + target: + kind: Cluster + + +replacements: + + # Updates extenal cluster DNS name octet that contains the namespace + - source: + kind: Cluster + name: main-01 + fieldPath: metadata.namespace + targets: + - select: + kind: Cluster + fieldPaths: + - spec.externalClusters.[name=main-01].connectionParameters.host + - spec.externalClusters.[name=main-02].connectionParameters.host + options: + delimiter: "." + index: 1 diff --git a/manifests/postgres/overlays/production/kustomization.yaml b/manifests/postgres/overlays/production/kustomization.yaml new file mode 100644 index 0000000..f448f5c --- /dev/null +++ b/manifests/postgres/overlays/production/kustomization.yaml @@ -0,0 +1,27 @@ +--- + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + + +resources: + - ../../base + + +components: + - ../../components/metrics + + +patches: + # + # Add to Top-most Kustomization.yaml + # + # yamllint disable rule:indentation + - patch: |- + + - op: replace + path: /spec/imageName + value: ghcr.io/cloudnative-pg/postgresql:15.12-11 + # yamllint enable rule:indentation + target: + kind: Cluster