Skip to content

Commit 07e7c6f

Browse files
committed
Create Cluster from Backup
This change allows a new PostgreSQL cluster to be bootstrapped using an existing data source, specifically an existing pgBackRest repository. The repository that is used to bootstrap the cluster can either be a repository from a former PostgreSQL cluster that no longer exists (assuming backups and the pgBackRest repository secret were retained by specifying the '--keep-backups' when deleting it), or from a cluster that is currently running. When bootstrapping from a previous cluster that no longer exists, the Operator will temporarily deploy a pgBackRest repository host for that repository for purposes of bootstrapping the new cluster. The new cluster being created will then connect to that repository using SSH to perform the restore needed to initially populate its PGDATA directory. On the other hand, when bootstrapping from a cluster that is currently running, the new cluster being created will simply connect (also via SSH) to the pgBackRest repository host that is currently running for that cluster. The actual bootstrapping of the new cluster, i.e. the pgBackRest restore that is executed to populate the PGDATA directory for the new cluster, is done via a Kubernetes Job. This Job will mount the secrets needed to access the appropriate pgBackRest repository host for the cluster being restored from and execute the 'pgbackrest restore' command. Once the Job has completed successfully (i.e. the 'pgbackrest restore' command was successful and any recovery completed), any resources created (e.g. a repository host) created for the bootstrap are removed, and cluster initialization (stanza-creation, initial backup, etc.) proceeds as usual. The only difference is that the cluster will start with the PGDATA content populated when the bootstrap Job was run, instead of initializing from scratch using 'initdb'. Two new flags have been added to the 'pgo create cluster' command to specify an existing cluster to bootstrap from: - restore-from: the name of the cluster (past or present) to restore from when bootstrapping the cluster. - restore-opts: the CLI options that should be passed to pgBackRest when the 'pgbackrest restore' command is run (e.g. the '--type' and 'target' flags if performing a PITR) Only a single cluster can bootstrap from another cluster (running or not) at any given time. Additionally, the Operator will not allow a client to bootstrap from an existing cluster if it is not in the proper status (e.g. if it is in a 'shutdown' or 'restoring' status).
1 parent 6c012cc commit 07e7c6f

File tree

27 files changed

+1400
-140
lines changed

27 files changed

+1400
-140
lines changed
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
{
2+
"apiVersion": "batch/v1",
3+
"kind": "Job",
4+
"metadata": {
5+
"name": "{{.Name}}-bootstrap",
6+
"labels": {
7+
"vendor": "crunchydata",
8+
"pgo-pg-database": "true",
9+
"pgo-backrest-job": "true",
10+
"pgha-bootstrap": "{{.Name}}",
11+
{{.DeploymentLabels}}
12+
}
13+
},
14+
"spec": {
15+
"template": {
16+
"metadata": {
17+
"labels": {
18+
"name": "{{.Name}}",
19+
"vendor": "crunchydata",
20+
"pgo-pg-database": "true",
21+
{{.PodLabels}}
22+
}
23+
},
24+
"spec": {
25+
"securityContext": {{.SecurityContext}},
26+
"serviceAccountName": "pgo-pg",
27+
"containers": [{
28+
"name": "database",
29+
"image": "{{.CCPImagePrefix}}/{{.CCPImage}}:{{.CCPImageTag}}",
30+
{{.ContainerResources}}
31+
"env": [{
32+
"name": "PGHA_PG_PORT",
33+
"value": "{{.Port}}"
34+
}, {
35+
"name": "PGHA_USER",
36+
"value": "postgres"
37+
},
38+
{
39+
"name": "PGHA_INIT",
40+
"value": "true"
41+
},
42+
{
43+
"name": "PGHA_BOOTSTRAP_METHOD",
44+
"value": "pgbackrest_init"
45+
},
46+
{{if .Tablespaces}}
47+
{
48+
"name": "PGHA_TABLESPACES",
49+
"value": "{{ .Tablespaces }}"
50+
},
51+
{{ end }}
52+
{
53+
"name": "PATRONI_POSTGRESQL_DATA_DIR",
54+
"value": "/pgdata/{{.Name}}"
55+
},
56+
{{.PgbackrestS3EnvVars}}
57+
{{.PgbackrestEnvVars}}
58+
{
59+
"name": "PGHA_DATABASE",
60+
"value": "{{.Database}}"
61+
}, {
62+
"name": "PGHA_CRUNCHYADM",
63+
"value": "true"
64+
}, {
65+
"name": "PGHA_REPLICA_REINIT_ON_START_FAIL",
66+
"value": "{{.ReplicaReinitOnStartFail}}"
67+
}, {
68+
"name": "PGHA_SYNC_REPLICATION",
69+
"value": "{{.SyncReplication}}"
70+
}, {
71+
"name": "PGHA_TLS_ENABLED",
72+
"value": "{{.TLSEnabled}}"
73+
}, {
74+
"name": "PGHA_TLS_ONLY",
75+
"value": "{{.TLSOnly}}"
76+
}, {
77+
"name": "PGHA_STANDBY",
78+
"value": "{{.Standby}}"
79+
}, {
80+
"name": "PATRONI_KUBERNETES_NAMESPACE",
81+
"valueFrom": {
82+
"fieldRef": {
83+
"fieldPath": "metadata.namespace"
84+
}
85+
}
86+
}, {
87+
"name": "PATRONI_KUBERNETES_SCOPE_LABEL",
88+
"value": "{{.ScopeLabel}}"
89+
}, {
90+
"name": "PATRONI_SCOPE",
91+
"valueFrom": {
92+
"fieldRef": {
93+
"fieldPath": "metadata.labels['{{.ScopeLabel}}']"
94+
}
95+
}
96+
}, {
97+
"name": "PATRONI_KUBERNETES_LABELS",
98+
"value": "{vendor: \"crunchydata\"}"
99+
}, {
100+
"name": "PATRONI_LOG_LEVEL",
101+
"value": "INFO"
102+
}, {
103+
"name": "PGHOST",
104+
"value": "/tmp"
105+
}, {
106+
"name": "RESTORE_OPTS",
107+
"value": "{{.RestoreOpts}}"
108+
}],
109+
"volumeMounts": [{
110+
"mountPath": "/pgdata",
111+
"name": "pgdata"
112+
}, {
113+
"mountPath": "/pgconf/pguser",
114+
"name": "user-volume"
115+
}, {
116+
"mountPath": "/pgconf/pgreplicator",
117+
"name": "primary-volume"
118+
}, {
119+
"mountPath": "/pgconf/pgsuper",
120+
"name": "root-volume"
121+
},
122+
{{if .TLSEnabled}}
123+
{
124+
"mountPath": "/pgconf/tls",
125+
"name": "tls-server"
126+
},
127+
{{ end }}
128+
{
129+
"mountPath": "/sshd",
130+
"name": "sshd",
131+
"readOnly": true
132+
}, {
133+
"mountPath": "/pgconf",
134+
"name": "pgconf-volume"
135+
}, {
136+
"mountPath": "/dev/shm",
137+
"name": "dshm"
138+
}, {
139+
"mountPath": "/crunchyadm",
140+
"name": "crunchyadm"
141+
}
142+
{{.TablespaceVolumeMounts}}
143+
],
144+
"imagePullPolicy": "IfNotPresent"
145+
}],
146+
"volumes": [{
147+
"name": "pgdata",
148+
{{.PVCName}}
149+
}, {
150+
"name": "user-volume",
151+
"secret": {
152+
"secretName": "{{.UserSecretName}}"
153+
}
154+
}, {
155+
"name": "primary-volume",
156+
"secret": {
157+
"secretName": "{{.PrimarySecretName}}"
158+
}
159+
}, {
160+
"name": "root-volume",
161+
"secret": {
162+
"secretName": "{{.RootSecretName}}"
163+
}
164+
}, {
165+
"name": "sshd",
166+
"secret": {
167+
"secretName": "{{.RestoreFrom}}-backrest-repo-config",
168+
"defaultMode": 511
169+
}
170+
},
171+
{{if .TLSEnabled}}
172+
{
173+
"name": "tls-server",
174+
"projected": {
175+
"defaultMode": 288,
176+
"sources": [
177+
{
178+
"secret": {
179+
"name": "{{.TLSSecret}}"
180+
}
181+
},
182+
{
183+
"secret": {
184+
"name": "{{.CASecret}}"
185+
}
186+
}
187+
]
188+
}
189+
},
190+
{{ end }}
191+
{
192+
"name": "crunchyadm",
193+
"emptyDir": {}
194+
},
195+
{
196+
"name": "dshm",
197+
"emptyDir": {
198+
"medium": "Memory"
199+
}
200+
},
201+
{
202+
"name": "pgconf-volume",
203+
"projected": {
204+
"sources": [
205+
{{if .ConfVolume}}
206+
{
207+
"configMap": {
208+
"name": {{.ConfVolume}}
209+
}
210+
},
211+
{{end}}
212+
{
213+
"configMap": {
214+
"name": "{{.ClusterName}}-pgha-config",
215+
"optional": true
216+
}
217+
}
218+
]
219+
}
220+
}
221+
{{.TablespaceVolumes}}],
222+
"affinity": {
223+
{{.NodeSelector}}
224+
{{if and .NodeSelector .PodAntiAffinity}},{{end}}
225+
{{.PodAntiAffinity}}
226+
},
227+
"restartPolicy": "Never"
228+
}
229+
}
230+
}
231+
}

conf/postgres-operator/pgo-backrest-repo-template.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
"metadata": {
55
"name": "{{.Name}}",
66
"labels": {
7+
{{if .BootstrapCluster}}
8+
"pgha-bootstrap": "{{.BootstrapCluster}}",
9+
{{ end }}
710
"name": "{{.Name}}",
811
"pg-cluster": "{{.ClusterName}}",
912
"service-name": "{{.Name}}",
@@ -26,6 +29,9 @@
2629
"template": {
2730
"metadata": {
2831
"labels": {
32+
{{if .BootstrapCluster}}
33+
"pgha-bootstrap": "{{.BootstrapCluster}}",
34+
{{ end }}
2935
"name": "{{.Name}}",
3036
"pg-cluster": "{{.ClusterName}}",
3137
"service-name": "{{.Name}}",
@@ -93,7 +99,7 @@
9399
"volumes": [{
94100
"name": "sshd",
95101
"secret": {
96-
"secretName": "{{.ClusterName}}-backrest-repo-config",
102+
"secretName": "{{.SshdSecretsName}}",
97103
"defaultMode": 511
98104
}
99105
}, {

0 commit comments

Comments
 (0)