-
Notifications
You must be signed in to change notification settings - Fork 1k
Added option to create streaming standby cluster. #804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cc0e8d8
e4aa8cd
92d6358
a86e748
fbf43b2
127cbcf
1cc7166
7c9cdf3
eff8f8d
b6ce92e
fdffd5f
2d6598f
a5bcc5b
91194fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,8 @@ spec: | |
version: "14" | ||
# Make this a standby cluster and provide the s3 bucket path of source cluster for continuous streaming. | ||
standby: | ||
s3_wal_path: "s3://path/to/bucket/containing/wal/of/source/cluster/" | ||
s3_wal_path: "s3://path/to/bucket/containing/wal/of/source/cluster/" # Make this a standby cluster and provide the s3 bucket path of source cluster for continuous streaming. | ||
standby_method: "s3_wal" # s3_wal or streaming_host; | ||
# standby_host: "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would be nice to provide a reasonable example here? Same for the user docs. |
||
# standby_port: "" | ||
# standby_secret_name: "" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -745,17 +745,6 @@ func (c *Cluster) generateSpiloPodEnvVars(uid types.UID, spiloConfiguration stri | |
Name: "PGUSER_STANDBY", | ||
Value: c.OpConfig.ReplicationUsername, | ||
}, | ||
{ | ||
Name: "PGPASSWORD_STANDBY", | ||
ValueFrom: &v1.EnvVarSource{ | ||
SecretKeyRef: &v1.SecretKeySelector{ | ||
LocalObjectReference: v1.LocalObjectReference{ | ||
Name: c.credentialSecretName(c.OpConfig.ReplicationUsername), | ||
}, | ||
Key: "password", | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "PAM_OAUTH2", | ||
Value: c.OpConfig.PamConfiguration, | ||
|
@@ -765,6 +754,24 @@ func (c *Cluster) generateSpiloPodEnvVars(uid types.UID, spiloConfiguration stri | |
Value: c.OpConfig.PamRoleName, | ||
}, | ||
} | ||
|
||
var standbySecretName string | ||
if standbyDescription != nil && standbyDescription.StandbyMethod == "streaming_host" { | ||
standbySecretName = standbyDescription.StandbySecretName | ||
} else { | ||
standbySecretName = c.credentialSecretName(c.OpConfig.ReplicationUsername) | ||
} | ||
|
||
envVars = append(envVars, v1.EnvVar{Name: "PGPASSWORD_STANDBY", | ||
ValueFrom: &v1.EnvVarSource{ | ||
SecretKeyRef: &v1.SecretKeySelector{ | ||
LocalObjectReference: v1.LocalObjectReference{ | ||
Name: standbySecretName, | ||
}, | ||
Key: "password", | ||
}, | ||
}}) | ||
|
||
if c.OpConfig.EnablePgVersionEnvVar { | ||
envVars = append(envVars, v1.EnvVar{Name: "PGVERSION", Value: c.GetDesiredMajorVersion()}) | ||
} | ||
|
@@ -1080,6 +1087,18 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef | |
if err != nil { | ||
return nil, err | ||
} | ||
if spec.StandbyCluster != nil && spec.StandbyCluster.StandbyMethod == "" { | ||
// In order to be backward compatible, we fallback to s3_wal when standby_method is not specified | ||
if spec.StandbyCluster.S3WalPath != "" { | ||
c.logger.Warningf("Fallback to a s3_wal as standby_method is not specified.") | ||
spec.StandbyCluster.StandbyMethod = "s3_wal" | ||
} else if spec.StandbyCluster.GSWalPath != "" { | ||
c.logger.Warningf("Fallback to a gs_wal as standby_method is not specified.") | ||
spec.StandbyCluster.StandbyMethod = "gs_wal" | ||
} else { | ||
return nil, fmt.Errorf("standby_method is and s3_wal_path are empty, what standby method to use!?") | ||
} | ||
} | ||
|
||
// fetch env vars from custom ConfigMap | ||
secretEnvVarsList, err := c.getPodEnvironmentSecretVariables() | ||
|
@@ -1093,11 +1112,6 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef | |
sort.Slice(customPodEnvVarsList, | ||
func(i, j int) bool { return customPodEnvVarsList[i].Name < customPodEnvVarsList[j].Name }) | ||
|
||
if spec.StandbyCluster != nil && spec.StandbyCluster.S3WalPath == "" && | ||
spec.StandbyCluster.GSWalPath == "" { | ||
return nil, fmt.Errorf("one of s3_wal_path or gs_wal_path must be set for standby cluster") | ||
} | ||
|
||
// backward compatible check for InitContainers | ||
if spec.InitContainersOld != nil { | ||
msg := "Manifest parameter init_containers is deprecated." | ||
|
@@ -1905,40 +1919,49 @@ func (c *Cluster) generateCloneEnvironment(description *acidv1.CloneDescription) | |
func (c *Cluster) generateStandbyEnvironment(description *acidv1.StandbyDescription) []v1.EnvVar { | ||
result := make([]v1.EnvVar, 0) | ||
|
||
if description.S3WalPath == "" && description.GSWalPath == "" { | ||
if description.StandbyMethod == "" { | ||
return nil | ||
} | ||
|
||
if description.S3WalPath != "" { | ||
// standby with S3, find out the bucket to setup standby | ||
msg := "Standby from S3 bucket using custom parsed S3WalPath from the manifest %s " | ||
c.logger.Infof(msg, description.S3WalPath) | ||
|
||
result = append(result, v1.EnvVar{ | ||
Name: "STANDBY_WALE_S3_PREFIX", | ||
Value: description.S3WalPath, | ||
}) | ||
} else if description.GSWalPath != "" { | ||
msg := "Standby from GS bucket using custom parsed GSWalPath from the manifest %s " | ||
c.logger.Infof(msg, description.GSWalPath) | ||
|
||
envs := []v1.EnvVar{ | ||
{ | ||
Name: "STANDBY_WALE_GS_PREFIX", | ||
Value: description.GSWalPath, | ||
}, | ||
{ | ||
Name: "STANDBY_GOOGLE_APPLICATION_CREDENTIALS", | ||
Value: c.OpConfig.GCPCredentials, | ||
}, | ||
} | ||
result = append(result, envs...) | ||
if description.StandbyMethod == "s3_wal" || description.StandbyMethod == "gs_wal" { | ||
if description.S3WalPath != "" { | ||
// standby with S3, find out the bucket to setup standby | ||
msg := "Standby from S3 bucket using custom parsed S3WalPath from the manifest %s " | ||
c.logger.Infof(msg, description.S3WalPath) | ||
|
||
result = append(result, v1.EnvVar{ | ||
Name: "STANDBY_WALE_S3_PREFIX", | ||
Value: description.S3WalPath, | ||
}) | ||
} else if description.GSWalPath != "" { | ||
msg := "Standby from GS bucket using custom parsed GSWalPath from the manifest %s " | ||
c.logger.Infof(msg, description.GSWalPath) | ||
|
||
envs := []v1.EnvVar{ | ||
{ | ||
Name: "STANDBY_WALE_GS_PREFIX", | ||
Value: description.GSWalPath, | ||
}, | ||
{ | ||
Name: "STANDBY_GOOGLE_APPLICATION_CREDENTIALS", | ||
Value: c.OpConfig.GCPCredentials, | ||
}, | ||
} | ||
result = append(result, envs...) | ||
} | ||
result = append(result, v1.EnvVar{Name: "STANDBY_METHOD", Value: "STANDBY_WITH_WALE"}) | ||
result = append(result, v1.EnvVar{Name: "STANDBY_WAL_BUCKET_SCOPE_PREFIX", Value: ""}) | ||
Comment on lines
+1926
to
+1953
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, my conflict resolving messed up indentation in this part |
||
} else if description.StandbyMethod == "streaming_host" { | ||
// standby with streaming replication from standby host | ||
msg := "Standby using streaming replication from standby host: %s " | ||
c.logger.Infof(msg, description.StandbyHost) | ||
|
||
result = append(result, v1.EnvVar{Name: "STANDBY_HOST", Value: description.StandbyHost}) | ||
result = append(result, v1.EnvVar{Name: "STANDBY_PORT", Value: description.StandbyPort}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think STANDBY_PORT can be omitted when it's not set. Patroni will default to 5432. |
||
result = append(result, v1.EnvVar{Name: "STANDBY_CLUSTER", Value: "True"}) | ||
|
||
} | ||
|
||
result = append(result, v1.EnvVar{Name: "STANDBY_METHOD", Value: "STANDBY_WITH_WALE"}) | ||
result = append(result, v1.EnvVar{Name: "STANDBY_WAL_BUCKET_SCOPE_PREFIX", Value: ""}) | ||
|
||
return result | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not required so define it, since you default to the old behavior in the code.