feat: CDKTF | migrate postgres to CDKTF

This commit is contained in:
2025-07-14 21:09:38 +05:00
parent cde19a0d73
commit 5bfb72ef81
5 changed files with 322 additions and 166 deletions

View File

@@ -9,8 +9,6 @@ repositories:
url: https://kubernetes.github.io/ingress-nginx url: https://kubernetes.github.io/ingress-nginx
- name: bitnami - name: bitnami
url: https://charts.bitnami.com/bitnami url: https://charts.bitnami.com/bitnami
- name: cnpg
url: https://cloudnative-pg.github.io/charts
- name: jetstack - name: jetstack
url: https://charts.jetstack.io url: https://charts.jetstack.io
- name: prometheus-community - name: prometheus-community
@@ -57,12 +55,6 @@ releases:
values: values:
- ./values/externaldns.values.yaml - ./values/externaldns.values.yaml
# Postgres operator
- name: postgres-system
namespace: postgres-system
chart: cnpg/cloudnative-pg
version: 0.23.0
# Memcached # Memcached
- name: memcached - name: memcached
namespace: memcached-system namespace: memcached-system

14
main.ts
View File

@@ -7,6 +7,7 @@ import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
import { GiteaServer } from "./gitea/server"; import { GiteaServer } from "./gitea/server";
import { OnePassword } from "./1password/1password"; import { OnePassword } from "./1password/1password";
import { PostgresCluster } from "./postgres/postgres";
dotenv.config(); dotenv.config();
@@ -31,6 +32,19 @@ class Homelab extends TerraformStack {
}, },
}); });
new PostgresCluster(this, "postgres-cluster", {
name: "postgres-cluster",
namespace: "postgres-system",
providers: {
kubernetes,
helm,
},
storageClass: "longhorn-crypto",
users: ["shahab"],
primaryUser: "shahab",
initSecretName: "postgres-password",
});
new GiteaServer(this, "gitea-server", { new GiteaServer(this, "gitea-server", {
name: "gitea", name: "gitea",
namespace: "gitea-system", namespace: "gitea-system",

View File

@@ -1,125 +0,0 @@
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: postgres-system
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: server-ca
namespace: postgres-system
spec:
isCA: true
commonName: postgres-server-ca
secretName: postgres-server-ca
privateKey:
algorithm: ECDSA
size: 384
issuerRef:
name: selfsigned-issuer
kind: Issuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: postgres-server-ca-issuer
namespace: postgres-system
spec:
ca:
secretName: postgres-server-ca
---
apiVersion: v1
kind: Secret
metadata:
name: postgres-server-cert
namespace: postgres-system
labels:
cnpg.io/reload: ""
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: postgres-server-cert
namespace: postgres-system
spec:
secretName: postgres-server-cert
usages:
- server auth
dnsNames:
- postgres-cluster-rw.postgres-system.svc.cluster.local
- postgres-cluster-ro.postgres-system.svc.cluster.local
- postgres-cluster-r.postgres-system.svc.cluster.local
- postgres.dogar.dev
issuerRef:
name: postgres-server-ca-issuer
kind: Issuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: client-ca
namespace: postgres-system
spec:
isCA: true
commonName: postgres-client-ca
secretName: postgres-client-ca
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-issuer
kind: Issuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: postgres-client-ca-issuer
namespace: postgres-system
spec:
ca:
secretName: postgres-client-ca
---
apiVersion: v1
kind: Secret
metadata:
name: postgres-client-cert
namespace: postgres-system
labels:
cnpg.io/reload: ""
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: postgres-client-cert
namespace: postgres-system
spec:
secretName: postgres-client-cert
usages:
- client auth
commonName: streaming_replica
issuerRef:
name: postgres-client-ca-issuer
kind: Issuer
group: cert-manager.io
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: shahab-client-cert
namespace: postgres-system
spec:
secretName: shahab-client-cert
usages:
- client auth
commonName: shahab
issuerRef:
name: postgres-client-ca-issuer
kind: Issuer
group: cert-manager.io

View File

@@ -1,33 +0,0 @@
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: postgres-cluster
namespace: postgres-system
spec:
instances: 3
maxSyncReplicas: 0
primaryUpdateStrategy: unsupervised
certificates:
serverCASecret: postgres-server-cert
serverTLSSecret: postgres-server-cert
clientCASecret: postgres-client-cert
replicationTLSSecret: postgres-client-cert
postgresql:
pg_hba:
- hostssl all shahab all cert
- hostssl sameuser all all cert
enableSuperuserAccess: false
bootstrap:
initdb:
database: postgres
secret:
name: postgres-password
postInitSQL:
- 'CREATE USER shahab SUPERUSER;'
storage:
size: 10Gi
storageClass: longhorn-crypto
walStorage:
size: 10Gi
storageClass: longhorn-crypto

308
postgres/postgres.ts Normal file
View File

@@ -0,0 +1,308 @@
import { HelmProvider } from "@cdktf/provider-helm/lib/provider";
import { Release } from "@cdktf/provider-helm/lib/release";
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
import { Construct } from "constructs";
type PostgresClusterOptions = {
providers: {
kubernetes: KubernetesProvider;
helm: HelmProvider;
};
name: string;
namespace: string;
storageClass: string;
users: string[];
primaryUser: string;
initSecretName: string;
};
export class PostgresCluster extends Construct {
constructor(scope: Construct, id: string, options: PostgresClusterOptions) {
super(scope, id);
const { kubernetes, helm } = options.providers;
new Release(this, "cnpg-operator", {
provider: helm,
repository: "https://cloudnative-pg.github.io/charts",
chart: "cloudnative-pg",
name: "postgres-system",
namespace: options.namespace,
});
const certManagerApiVersion = "cert-manager.io/v1";
const certNames = {
server: "postgres-server-cert",
client: "postgres-client-cert",
};
const caNames = {
server: "postgres-server-ca",
client: "postgres-client-ca",
};
// Self-signed issuer for creating CA certificates
new Manifest(this, "selfsigned-issuer", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Issuer",
metadata: {
name: "selfsigned-issuer",
namespace: options.namespace,
},
spec: {
selfSigned: {},
},
},
});
// Server CA certificate
new Manifest(this, "server-ca-cert", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Certificate",
metadata: {
name: "server-ca",
namespace: options.namespace,
},
spec: {
isCA: true,
commonName: caNames.server,
secretName: caNames.server,
privateKey: {
algorithm: "ECDSA",
size: 384,
},
issuerRef: {
name: "selfsigned-issuer",
kind: "Issuer",
group: "cert-manager.io",
},
},
},
});
// Issuer using the server CA
new Manifest(this, "server-ca-issuer", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Issuer",
metadata: {
name: `${caNames.server}-issuer`,
namespace: options.namespace,
},
spec: {
ca: {
secretName: caNames.server,
},
},
},
});
// Secret for server certificate
new Manifest(this, "server-ca-cert-secret", {
provider: kubernetes,
manifest: {
apiVersion: "v1",
kind: "Secret",
metadata: {
name: certNames.server,
namespace: options.namespace,
labels: {
"cnpg.io/reload": "",
},
},
},
});
// Server certificate
new Manifest(this, "server-cert", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Certificate",
metadata: {
name: certNames.server,
namespace: options.namespace,
},
spec: {
secretName: certNames.server,
usages: ["server auth"],
dnsNames: [
"postgres-cluster-rw.postgres-system.svc.cluster.local",
"postgres-cluster-ro.postgres-system.svc.cluster.local",
"postgres-cluster-r.postgres-system.svc.cluster.local",
"postgres.dogar.dev",
],
issuerRef: {
name: `${caNames.server}-issuer`,
kind: "Issuer",
group: "cert-manager.io",
},
},
},
});
// Client CA certificate
new Manifest(this, "client-ca", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Certificate",
metadata: {
name: "client-ca",
namespace: options.namespace,
},
spec: {
isCA: true,
commonName: caNames.client,
secretName: caNames.client,
privateKey: {
algorithm: "ECDSA",
size: 256,
},
issuerRef: {
name: "selfsigned-issuer",
kind: "Issuer",
group: "cert-manager.io",
},
},
},
});
// Issuer using the client CA
new Manifest(this, "client-ca-issuer", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Issuer",
metadata: {
name: `${caNames.client}-issuer`,
namespace: options.namespace,
},
spec: {
ca: {
secretName: caNames.client,
},
},
},
});
// Secret for client certificate
new Manifest(this, `${certNames.client}-secret`, {
provider: kubernetes,
manifest: {
apiVersion: "v1",
kind: "Secret",
metadata: {
name: certNames.client,
namespace: options.namespace,
labels: {
"cnpg.io/reload": "",
},
},
},
});
// Client certificate for streaming replica
new Manifest(this, "streaming-replica-cert", {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Certificate",
metadata: {
name: certNames.client,
namespace: options.namespace,
},
spec: {
secretName: certNames.client,
usages: ["client auth"],
commonName: "streaming_replica",
issuerRef: {
name: "postgres-client-ca-issuer",
kind: "Issuer",
group: "cert-manager.io",
},
},
},
});
// Client certificates for users
options.users.forEach(
(user) =>
new Manifest(this, `${user}-client-cert`, {
provider: kubernetes,
manifest: {
apiVersion: certManagerApiVersion,
kind: "Certificate",
metadata: {
name: `${user}-client-cert`,
namespace: options.namespace,
},
spec: {
secretName: `${user}-client-cert`,
usages: ["client auth"],
commonName: user,
issuerRef: {
name: "postgres-client-ca-issuer",
kind: "Issuer",
group: "cert-manager.io",
},
},
},
}),
);
new Manifest(this, "postgres-cluster", {
provider: kubernetes,
manifest: {
apiVersion: "postgresql.cnpg.io/v1",
kind: "Cluster",
metadata: {
name: options.name,
namespace: options.namespace,
},
spec: {
instances: 3,
maxSyncReplicas: 0,
primaryUpdateStrategy: "unsupervised",
certificates: {
serverCASecret: certNames.server,
serverTLSSecret: certNames.server,
clientCASecret: certNames.client,
replicationTLSSecret: certNames.client,
},
postgresql: {
pg_hba: [
`hostssl all ${options.primaryUser} all cert`,
"hostssl sameuser all all cert",
],
},
enableSuperuserAccess: false,
bootstrap: {
initdb: {
database: "postgres",
secret: {
name: options.initSecretName,
},
postInitSQL: [`CREATE USER ${options.primaryUser} SUPERUSER;`],
},
},
storage: {
size: "10Gi",
storageClass: options.storageClass,
},
walStorage: {
size: "10Gi",
storageClass: options.storageClass,
},
},
},
});
}
}