Skip to content

Commit e9a620f

Browse files
committed
add support for migrating postgres pvcs to hyperdisk
[static] Signed-off-by: Nicu Reut <nicu.reut@digitalasset.com>
1 parent ad0cd97 commit e9a620f

File tree

5 files changed

+145
-40
lines changed

5 files changed

+145
-40
lines changed

cluster/expected/multi-validator/expected.json

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4877,12 +4877,7 @@
48774877
}
48784878
}
48794879
},
4880-
"db": {
4881-
"maxConnections": 1000,
4882-
"volumeSize": "100Gi"
4883-
},
4884-
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
4885-
"nonHyperdiskAppsAffinityAndTolerations": {
4880+
"appsAffinityAndTolerations": {
48864881
"affinity": {
48874882
"nodeAffinity": {
48884883
"requiredDuringSchedulingIgnoredDuringExecution": {
@@ -4914,6 +4909,11 @@
49144909
}
49154910
]
49164911
},
4912+
"db": {
4913+
"maxConnections": 1000,
4914+
"volumeSize": "100Gi"
4915+
},
4916+
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
49174917
"persistence": {
49184918
"secretName": "postgres-0-secret"
49194919
},
@@ -4973,12 +4973,7 @@
49734973
}
49744974
}
49754975
},
4976-
"db": {
4977-
"maxConnections": 1000,
4978-
"volumeSize": "100Gi"
4979-
},
4980-
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
4981-
"nonHyperdiskAppsAffinityAndTolerations": {
4976+
"appsAffinityAndTolerations": {
49824977
"affinity": {
49834978
"nodeAffinity": {
49844979
"requiredDuringSchedulingIgnoredDuringExecution": {
@@ -5010,6 +5005,11 @@
50105005
}
50115006
]
50125007
},
5008+
"db": {
5009+
"maxConnections": 1000,
5010+
"volumeSize": "100Gi"
5011+
},
5012+
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
50135013
"persistence": {
50145014
"secretName": "postgres-1-secret"
50155015
},
@@ -5069,12 +5069,7 @@
50695069
}
50705070
}
50715071
},
5072-
"db": {
5073-
"maxConnections": 1000,
5074-
"volumeSize": "100Gi"
5075-
},
5076-
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
5077-
"nonHyperdiskAppsAffinityAndTolerations": {
5072+
"appsAffinityAndTolerations": {
50785073
"affinity": {
50795074
"nodeAffinity": {
50805075
"requiredDuringSchedulingIgnoredDuringExecution": {
@@ -5106,6 +5101,11 @@
51065101
}
51075102
]
51085103
},
5104+
"db": {
5105+
"maxConnections": 1000,
5106+
"volumeSize": "100Gi"
5107+
},
5108+
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
51095109
"persistence": {
51105110
"secretName": "postgres-2-secret"
51115111
},
@@ -5165,12 +5165,7 @@
51655165
}
51665166
}
51675167
},
5168-
"db": {
5169-
"maxConnections": 1000,
5170-
"volumeSize": "100Gi"
5171-
},
5172-
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
5173-
"nonHyperdiskAppsAffinityAndTolerations": {
5168+
"appsAffinityAndTolerations": {
51745169
"affinity": {
51755170
"nodeAffinity": {
51765171
"requiredDuringSchedulingIgnoredDuringExecution": {
@@ -5202,6 +5197,11 @@
52025197
}
52035198
]
52045199
},
5200+
"db": {
5201+
"maxConnections": 1000,
5202+
"volumeSize": "100Gi"
5203+
},
5204+
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
52055205
"persistence": {
52065206
"secretName": "postgres-3-secret"
52075207
},
@@ -5261,12 +5261,7 @@
52615261
}
52625262
}
52635263
},
5264-
"db": {
5265-
"maxConnections": 1000,
5266-
"volumeSize": "100Gi"
5267-
},
5268-
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
5269-
"nonHyperdiskAppsAffinityAndTolerations": {
5264+
"appsAffinityAndTolerations": {
52705265
"affinity": {
52715266
"nodeAffinity": {
52725267
"requiredDuringSchedulingIgnoredDuringExecution": {
@@ -5298,6 +5293,11 @@
52985293
}
52995294
]
53005295
},
5296+
"db": {
5297+
"maxConnections": 1000,
5298+
"volumeSize": "100Gi"
5299+
},
5300+
"imageRepo": "us-central1-docker.pkg.dev/da-cn-shared/ghcr/digital-asset/decentralized-canton-sync-dev/docker",
53015301
"persistence": {
53025302
"secretName": "postgres-4-secret"
53035303
},

cluster/helm/splice-postgres/templates/postgres.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ spec:
105105
storage: {{ $.Values.db.volumeSize }}
106106
storageClassName: {{ $.Values.db.volumeStorageClass }}
107107
volumeMode: Filesystem
108+
{{- with .Values.db.dataSource }}
109+
dataSource:
110+
{{- toYaml . | nindent 8 }}
111+
{{- end }}
108112
---
109113
apiVersion: v1
110114
kind: Service

cluster/pulumi/common/src/config/configSchema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const PulumiProjectConfigSchema = z.object({
1414
interAppsDependencies: z.boolean(),
1515
cloudSql: CloudSqlConfigSchema,
1616
allowDowngrade: z.boolean(),
17+
replacePostgresStatefulSetOnChanges: z.boolean().default(false),
1718
});
1819
export type PulumiProjectConfig = z.infer<typeof PulumiProjectConfigSchema>;
1920
export const ConfigSchema = z.object({

cluster/pulumi/common/src/postgres.ts

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ import * as gcp from '@pulumi/gcp';
44
import * as pulumi from '@pulumi/pulumi';
55
import * as random from '@pulumi/random';
66
import * as _ from 'lodash';
7+
import { CustomResource } from '@pulumi/kubernetes/apiextensions';
78
import { Resource } from '@pulumi/pulumi';
89

910
import { CnChartVersion } from './artifacts';
1011
import { clusterSmallDisk, CloudSqlConfig, config } from './config';
1112
import { spliceConfig } from './config/config';
13+
import { hyperdiskSupportConfig } from './config/hyperdiskSupportConfig';
1214
import {
15+
appsAffinityAndTolerations,
1316
infraAffinityAndTolerations,
1417
installSpliceHelmChart,
15-
nonHyperdiskAppsAffinityAndTolerations,
1618
} from './helm';
1719
import { installPostgresPasswordSecret } from './secrets';
20+
import { standardStorageClassName } from './storage/storageClass';
1821
import { ChartValues, CLUSTER_BASENAME, ExactNamespace, GCP_ZONE } from './utils';
1922

2023
const project = gcp.organizations.getProjectOutput({});
@@ -224,6 +227,35 @@ export class SplicePostgres extends pulumi.ComponentResource implements Postgres
224227

225228
// an initial database named cantonnet is created automatically (configured in the Helm chart).
226229
const smallDiskSize = clusterSmallDisk ? '240Gi' : undefined;
230+
const supportsHyperdisk =
231+
hyperdiskSupportConfig.hyperdiskSupport.enabled && !useInfraAffinityAndTolerations;
232+
let hyperdiskMigrationValues = {};
233+
if (supportsHyperdisk && hyperdiskSupportConfig.hyperdiskSupport.migrating) {
234+
const pvcSnapshot = new CustomResource(
235+
`pg-data-${xns.logicalName}-${instanceName}-snapshot`,
236+
{
237+
apiVersion: 'snapshot.storage.k8s.io/v1',
238+
kind: 'VolumeSnapshot',
239+
metadata: {
240+
name: `pg-data-${instanceName}-snapshot`,
241+
namespace: xns.logicalName,
242+
},
243+
spec: {
244+
volumeSnapshotClassName: 'dev-vsc',
245+
source: {
246+
persistentVolumeClaimName: `pg-data-${instanceName}-0`,
247+
},
248+
},
249+
}
250+
);
251+
hyperdiskMigrationValues = {
252+
dataSource: {
253+
kind: 'VolumeSnapshot',
254+
name: pvcSnapshot.metadata.name,
255+
apiGroup: 'snapshot.storage.k8s.io',
256+
},
257+
};
258+
}
227259
const pg = installSpliceHelmChart(
228260
xns,
229261
instanceName,
@@ -233,6 +265,13 @@ export class SplicePostgres extends pulumi.ComponentResource implements Postgres
233265
volumeSize: overrideDbSizeFromValues
234266
? values?.db?.volumeSize || smallDiskSize
235267
: smallDiskSize,
268+
...(supportsHyperdisk
269+
? {
270+
volumeStorageClass: standardStorageClassName,
271+
pvcTemplateName: 'pg-data-hd',
272+
...hyperdiskMigrationValues,
273+
}
274+
: {}),
236275
},
237276
persistence: {
238277
secretName: this.secretName,
@@ -242,11 +281,19 @@ export class SplicePostgres extends pulumi.ComponentResource implements Postgres
242281
{
243282
aliases: [{ name: logicalNameAlias, type: 'kubernetes:helm.sh/v3:Release' }],
244283
dependsOn: [passwordSecret],
284+
...((supportsHyperdisk &&
285+
// during the migration we first delete the stateful set, which keeps the old pvcs, and the recreate with the new pvcs
286+
// the stateful sets are immutable so they need to be recreated to force the change of the pvcs
287+
hyperdiskSupportConfig.hyperdiskSupport.migrating) ||
288+
spliceConfig.pulumiProjectConfig.replacePostgresStatefulSetOnChanges
289+
? {
290+
replaceOnChanges: ['*'],
291+
deleteBeforeReplace: true,
292+
}
293+
: {}),
245294
},
246295
true,
247-
useInfraAffinityAndTolerations
248-
? infraAffinityAndTolerations
249-
: nonHyperdiskAppsAffinityAndTolerations
296+
useInfraAffinityAndTolerations ? infraAffinityAndTolerations : appsAffinityAndTolerations
250297
);
251298
this.pg = pg;
252299

cluster/pulumi/multi-validator/src/postgres.ts

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ import * as pulumi from '@pulumi/pulumi';
44
import * as random from '@pulumi/random';
55
import {
66
activeVersion,
7+
appsAffinityAndTolerations,
78
CnInput,
89
ExactNamespace,
9-
installSpliceRunbookHelmChart,
10-
installPostgresPasswordSecret,
1110
InstalledHelmChart,
12-
nonHyperdiskAppsAffinityAndTolerations,
11+
installPostgresPasswordSecret,
12+
installSpliceRunbookHelmChart,
13+
spliceConfig,
14+
standardStorageClassName,
1315
} from '@lfdecentralizedtrust/splice-pulumi-common';
16+
import { CustomResource } from '@pulumi/kubernetes/apiextensions';
1417

18+
import { hyperdiskSupportConfig } from '../../common/src/config/hyperdiskSupportConfig';
1519
import { multiValidatorConfig } from './config';
1620

1721
export function installPostgres(
@@ -32,17 +36,66 @@ export function installPostgres(
3236
}
3337
const config = multiValidatorConfig!;
3438

39+
let hyperdiskMigrationValues = {};
40+
if (
41+
hyperdiskSupportConfig.hyperdiskSupport.enabled &&
42+
hyperdiskSupportConfig.hyperdiskSupport.migrating
43+
) {
44+
const pvcSnapshot = new CustomResource(`pg-data-${xns.logicalName}-${name}-snapshot`, {
45+
apiVersion: 'snapshot.storage.k8s.io/v1',
46+
kind: 'VolumeSnapshot',
47+
metadata: {
48+
name: `pg-data-${name}-snapshot`,
49+
namespace: xns.logicalName,
50+
},
51+
spec: {
52+
volumeSnapshotClassName: 'dev-vsc',
53+
source: {
54+
persistentVolumeClaimName: `pg-data-${name}-0`,
55+
},
56+
},
57+
});
58+
hyperdiskMigrationValues = {
59+
dataSource: {
60+
kind: 'VolumeSnapshot',
61+
name: pvcSnapshot.metadata.name,
62+
apiGroup: 'snapshot.storage.k8s.io',
63+
},
64+
};
65+
}
3566
return installSpliceRunbookHelmChart(
3667
xns,
3768
name,
3869
'splice-postgres',
3970
{
4071
persistence: { secretName },
41-
db: { volumeSize: config.postgresPvcSize, maxConnections: 1000 },
72+
db: {
73+
volumeSize: config.postgresPvcSize,
74+
maxConnections: 1000,
75+
...(hyperdiskSupportConfig.hyperdiskSupport.enabled
76+
? {
77+
volumeStorageClass: standardStorageClassName,
78+
pvcTemplateName: 'pg-data-hd',
79+
...hyperdiskMigrationValues,
80+
}
81+
: {}),
82+
},
4283
resources: config.resources?.postgres,
43-
nonHyperdiskAppsAffinityAndTolerations,
84+
appsAffinityAndTolerations,
4485
},
4586
activeVersion,
46-
{ dependsOn: [passwordSecret, ...dependsOn] }
87+
{
88+
dependsOn: [passwordSecret, ...dependsOn],
89+
...((hyperdiskSupportConfig.hyperdiskSupport.enabled &&
90+
// during the migration we first delete the stateful set, which keeps the old pvcs, and the recreate with the new pvcs
91+
// the stateful sets are immutable so they need to be recreated to force the change of the pvcs
92+
hyperdiskSupportConfig.hyperdiskSupport.migrating) ||
93+
spliceConfig.pulumiProjectConfig.replacePostgresStatefulSetOnChanges
94+
? {
95+
replaceOnChanges: ['*'],
96+
deleteBeforeReplace: true,
97+
}
98+
: {}),
99+
}
47100
);
48101
}

0 commit comments

Comments
 (0)