315 lines
7.3 KiB
Bash
315 lines
7.3 KiB
Bash
kubectl apply --server-side -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.28/releases/cnpg-1.28.0.yaml--force-conflicts
|
|
curl -sSfL https://github.com/cloudnative-pg/cloudnative-pg/raw/main/hack/install-cnpg-plugin.sh | sudo sh -s -- -b /usr/local/bin
|
|
|
|
|
|
kubectl create namespace database
|
|
|
|
|
|
database.yaml:
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: pg-app-user
|
|
namespace: demo-apps
|
|
type: kubernetes.io/basic-auth
|
|
stringData:
|
|
username: admin
|
|
password: admin
|
|
---
|
|
apiVersion: postgresql.cnpg.io/v1
|
|
kind: Cluster
|
|
metadata:
|
|
name: pg-test
|
|
namespace: demo-apps
|
|
spec:
|
|
instances: 3
|
|
|
|
storage:
|
|
size: 1Gi
|
|
storageClass: csi-rbdfs-sc
|
|
|
|
walStorage:
|
|
storageClass: csi-rbdfs-sc
|
|
size: 1Gi
|
|
|
|
bootstrap:
|
|
initdb:
|
|
database: testdb
|
|
owner: admin
|
|
secret:
|
|
name: pg-app-user
|
|
|
|
postgresql:
|
|
parameters:
|
|
max_connections: "300"
|
|
shared_buffers: "1GB"
|
|
|
|
resources:
|
|
requests:
|
|
cpu: "500m"
|
|
memory: "1Gi"
|
|
limits:
|
|
cpu: "2"
|
|
memory: "2Gi"
|
|
|
|
|
|
#test
|
|
kubectl run psql-client -n database --rm -it --image=postgres:16 --env="PGPASSWORD=admin" -- psql -h pg-test-rw.demo-apps.svc -U admin -d appdb
|
|
|
|
kubectl patch pvc pg-test-1-wal -n demo_apps -p '{"spec":{"resources":{"requests":{"storage":"32Gi"}}}}'
|
|
|
|
backup:
|
|
barmanObjectStore:
|
|
destinationPath: s3://pg-backups/prod
|
|
endpointURL: http://minio.minio.svc:9000
|
|
s3Credentials:
|
|
accessKeyId:
|
|
name: s3-creds
|
|
key: ACCESS_KEY
|
|
secretAccessKey:
|
|
name: s3-creds
|
|
key: SECRET_KEY
|
|
|
|
|
|
|
|
|
|
--- pgadmin -------------------
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: pgadmin-deployment
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: pgadmin
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: pgadmin
|
|
spec:
|
|
containers:
|
|
- name: pgadmin
|
|
image: dpage/pgadmin4
|
|
ports:
|
|
- containerPort: 80
|
|
env:
|
|
- name: PGADMIN_DEFAULT_EMAIL
|
|
value: pgadmin@italiadatacenter.com
|
|
- name: PGADMIN_DEFAULT_PASSWORD
|
|
value: KAYQE1QA7uwUZ8uI
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: pgadmin-service
|
|
spec:
|
|
selector:
|
|
app: pgadmin
|
|
ports:
|
|
- protocol: TCP
|
|
port: 80
|
|
targetPort: 80
|
|
---
|
|
apiVersion: gateway.networking.k8s.io/v1
|
|
kind: HTTPRoute
|
|
metadata:
|
|
name: demo-route
|
|
namespace: demo-apps
|
|
spec:
|
|
hostnames:
|
|
- poc3.italiadatacenter.com
|
|
parentRefs:
|
|
- name: main-gateway
|
|
namespace: nginx-gateway
|
|
rules:
|
|
- matches:
|
|
- path:
|
|
type: PathPrefix
|
|
value: /
|
|
backendRefs:
|
|
- name: pgadmin-service
|
|
port: 80
|
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
cat <<EOF | kubectl -n database apply -f -
|
|
# This StorageClass is optimized for use with CloudNativePG.
|
|
# It disables storage-level replication and ensures data is local to the pod.
|
|
apiVersion: storage.k8s.io/v1
|
|
kind: StorageClass
|
|
metadata:
|
|
name: longhorn-cnpg-strict-local
|
|
provisioner: driver.longhorn.io
|
|
# allowVolumeExpansion is crucial for scaling database storage without downtime.
|
|
allowVolumeExpansion: true
|
|
# reclaimPolicy: Delete ensures that when a PVC is deleted, the underlying
|
|
# Longhorn volume is also removed, preventing orphaned storage.
|
|
reclaimPolicy: Delete
|
|
parameters:
|
|
# This is the most important setting. We rely on CloudNativePG for replication,
|
|
# so we only need one copy at the storage layer to avoid write amplification.
|
|
numberOfReplicas: "1"
|
|
# dataLocality: strict-local guarantees that the volume data will be stored
|
|
# on the same node as the pod that uses it. This is essential for performance
|
|
# and for aligning with a true shared-nothing architecture.
|
|
dataLocality: "strict-local"
|
|
# A longer timeout for stale replicas is suitable for database workloads.
|
|
staleReplicaTimeout: "2880" # 48 hours in minutes
|
|
# Default filesystem.
|
|
fsType: "ext4"
|
|
EOF
|
|
|
|
|
|
|
|
|
|
|
|
kubectl cnpg psql pg-devops -n devops
|
|
|
|
CREATE DATABASE giteadb;
|
|
CREATE USER gitea WITH PASSWORD 'KAYQE1QA7uwUZ8uI';
|
|
GRANT ALL PRIVILEGES ON DATABASE giteadb TO gitea;
|
|
ALTER DATABASE giteadb OWNER TO gitea;
|
|
|
|
|
|
cluster production ready:
|
|
|
|
apiVersion: postgresql.cnpg.io/v1
|
|
kind: Cluster
|
|
metadata:
|
|
name: mycluster
|
|
namespace: database
|
|
spec:
|
|
instances: 3 # → 3 nodi per HA reale
|
|
|
|
primaryUpdateStrategy: unsupervised
|
|
failover: # → Failover automatico
|
|
promoteTimeout: 5m
|
|
targetPromotionRule: "prefer-high-promotion-score"
|
|
|
|
# ---------------------------
|
|
# STORAGE (PRODUCTION)
|
|
# ---------------------------
|
|
storage:
|
|
size: 200Gi
|
|
storageClass: fast-rbd # Ceph, SSD, GP3 ecc.
|
|
resizeInUse: true
|
|
|
|
walStorage: # Consigliato in produzione
|
|
size: 50Gi
|
|
storageClass: fast-rbd
|
|
|
|
# ---------------------------
|
|
# WAL ARCHIVING (S3/MINIO)
|
|
# ---------------------------
|
|
walArchive:
|
|
enabled: true
|
|
destinationPath: "s3://mybucket/wal/"
|
|
s3Credentials:
|
|
accessKeyId:
|
|
name: cnpg-s3-creds
|
|
key: ACCESS_KEY_ID
|
|
secretAccessKey:
|
|
name: cnpg-s3-creds
|
|
key: SECRET_ACCESS_KEY
|
|
endpointURL: "https://s3.myregion.amazonaws.com"
|
|
region: "myregion"
|
|
encryption: AES256
|
|
|
|
# ---------------------------
|
|
# BACKUP AUTOMATICI
|
|
# ---------------------------
|
|
backup:
|
|
barmanObjectStore:
|
|
destinationPath: "s3://mybucket/basebackup/"
|
|
endpointURL: "https://s3.myregion.amazonaws.com"
|
|
s3Credentials:
|
|
accessKeyId:
|
|
name: cnpg-s3-creds
|
|
key: ACCESS_KEY_ID
|
|
secretAccessKey:
|
|
name: cnpg-s3-creds
|
|
key: SECRET_ACCESS_KEY
|
|
wal:
|
|
compression: bzip2
|
|
encryption: AES256
|
|
retentionPolicy: "30d" # → 30 giorni di retention
|
|
monitoring:
|
|
enablePodMonitor: true
|
|
|
|
# ---------------------------
|
|
# TLS INTERNO (RACCOMANDATO)
|
|
# ---------------------------
|
|
certificates:
|
|
serverTLSSecret: cnpg-server-tls
|
|
clientTLSSecret: cnpg-client-tls
|
|
|
|
# ---------------------------
|
|
# RESOURCE MANAGEMENT
|
|
# ---------------------------
|
|
resources:
|
|
requests:
|
|
cpu: "1"
|
|
memory: "2Gi"
|
|
limits:
|
|
cpu: "4"
|
|
memory: "8Gi"
|
|
|
|
# ---------------------------
|
|
# ANTI-AFFINITY & PDB
|
|
# ---------------------------
|
|
affinity:
|
|
enablePodAntiAffinity: true
|
|
topologyKey: "kubernetes.io/hostname"
|
|
|
|
podDisruptionBudget:
|
|
minAvailable: 2
|
|
|
|
# ---------------------------
|
|
# STARTUP & HEALTH
|
|
# ---------------------------
|
|
postgresql:
|
|
shared_preload_libraries:
|
|
- "pg_stat_statements"
|
|
- "auto_explain"
|
|
parameters:
|
|
max_connections: "300"
|
|
shared_buffers: "2GB"
|
|
effective_cache_size: "6GB"
|
|
maintenance_work_mem: "512MB"
|
|
wal_compression: "on"
|
|
wal_level: "replica"
|
|
max_wal_size: "4GB"
|
|
checkpoint_timeout: "15min"
|
|
synchronous_commit: "remote_apply"
|
|
|
|
# ---------------------------
|
|
# SYNCHRONOUS REPLICATION
|
|
# ---------------------------
|
|
replication:
|
|
synchronous:
|
|
mode: " quorum "
|
|
number: 1 # One sync replica; others async
|
|
|
|
# ---------------------------
|
|
# SERVICE & NETWORKING
|
|
# ---------------------------
|
|
service:
|
|
type: ClusterIP
|
|
primary:
|
|
type: ClusterIP
|
|
replicas:
|
|
type: ClusterIP
|
|
|
|
# ---------------------------
|
|
# ENCRYPTION AT REST (OPZIONALE)
|
|
# ---------------------------
|
|
encryption:
|
|
enabled: true
|
|
mode: aes256-gcm |