Merge branch 'master' into delete-volume-on-scale-down
This commit is contained in:
		
						commit
						a562a6ed59
					
				|  | @ -68,6 +68,8 @@ spec: | |||
|               type: boolean | ||||
|             etcd_host: | ||||
|               type: string | ||||
|             kubernetes_use_configmaps: | ||||
|               type: boolean | ||||
|             max_instances: | ||||
|               type: integer | ||||
|               minimum: -1  # -1 = disabled | ||||
|  |  | |||
|  | @ -218,6 +218,10 @@ spec: | |||
|                   type: integer | ||||
|                 retry_timeout: | ||||
|                   type: integer | ||||
|                 synchronous_mode: | ||||
|                   type: boolean | ||||
|                 synchronous_mode_strict: | ||||
|                   type: boolean | ||||
|                 maximum_lag_on_failover: | ||||
|                   type: integer | ||||
|             podAnnotations: | ||||
|  |  | |||
|  | @ -25,6 +25,8 @@ configGeneral: | |||
|   enable_unused_pvc_deletion: false | ||||
|   # etcd connection string for Patroni. Empty uses K8s-native DCS. | ||||
|   etcd_host: "" | ||||
|   # Select if setup uses endpoints (default), or configmaps to manage leader (DCS=k8s) | ||||
|   # kubernetes_use_configmaps: false | ||||
|   # Spilo docker image | ||||
|   docker_image: registry.opensource.zalan.do/acid/spilo-12:1.6-p2 | ||||
|   # max number of instances in Postgres cluster. -1 = no limit | ||||
|  |  | |||
|  | @ -25,6 +25,8 @@ configGeneral: | |||
|   enable_unused_pvc_deletion: "false" | ||||
|   # etcd connection string for Patroni. Empty uses K8s-native DCS. | ||||
|   etcd_host: "" | ||||
|   # Select if setup uses endpoints (default), or configmaps to manage leader (DCS=k8s) | ||||
|   # kubernetes_use_configmaps: "false" | ||||
|   # Spilo docker image | ||||
|   docker_image: registry.opensource.zalan.do/acid/spilo-12:1.6-p2 | ||||
|   # max number of instances in Postgres cluster. -1 = no limit | ||||
|  |  | |||
|  | @ -217,6 +217,12 @@ explanation of `ttl` and `loop_wait` parameters. | |||
|   automatically created by Patroni for cluster members and permanent replication | ||||
|   slots. Optional. | ||||
| 
 | ||||
| * **synchronous_mode** | ||||
|   Patroni `synchronous_mode` parameter value. The default is set to `false`. Optional. | ||||
|    | ||||
| * **synchronous_mode_strict** | ||||
|   Patroni `synchronous_mode_strict` parameter value. Can be used in addition to `synchronous_mode`. The default is set to `false`. Optional. | ||||
|    | ||||
| ## Postgres container resources | ||||
| 
 | ||||
| Those parameters define [CPU and memory requests and limits](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/) | ||||
|  | @ -376,10 +382,11 @@ present. | |||
|   How many instances of connection pooler to create. | ||||
| 
 | ||||
| * **schema** | ||||
|   Schema to create for credentials lookup function. | ||||
|   Database schema to create for credentials lookup function. | ||||
| 
 | ||||
| * **user** | ||||
|   User to create for connection pooler to be able to connect to a database. | ||||
|   You can also choose a role from the `users` section or a system user role. | ||||
| 
 | ||||
| * **dockerImage** | ||||
|   Which docker image to use for connection pooler deployment. | ||||
|  |  | |||
|  | @ -80,6 +80,12 @@ Those are top-level keys, containing both leaf keys and groups. | |||
|   Patroni native Kubernetes support is used. The default is empty (use | ||||
|   Kubernetes-native DCS). | ||||
| 
 | ||||
| * **kubernetes_use_configmaps** | ||||
|   Select if setup uses endpoints (default), or configmaps to manage leader when | ||||
|   DCS is kubernetes (not etcd or similar). In OpenShift it is not possible to | ||||
|   use endpoints option, and configmaps is required. By default, | ||||
|   `kubernetes_use_configmaps: false`, meaning endpoints will be used. | ||||
| 
 | ||||
| * **docker_image** | ||||
|   Spilo Docker image for Postgres instances. For production, don't rely on the | ||||
|   default image, as it might be not the most up-to-date one. Instead, build | ||||
|  | @ -613,11 +619,14 @@ operator being able to provide some reasonable defaults. | |||
|   the required minimum. | ||||
| 
 | ||||
| * **connection_pooler_schema** | ||||
|   Schema to create for credentials lookup function. Default is `pooler`. | ||||
|   Database schema to create for credentials lookup function to be used by the | ||||
|   connection pooler. Is is created in every database of the Postgres cluster. | ||||
|   You can also choose an existing schema. Default schema is `pooler`. | ||||
| 
 | ||||
| * **connection_pooler_user** | ||||
|   User to create for connection pooler to be able to connect to a database. | ||||
|   Default is `pooler`. | ||||
|   You can also choose an existing role, but make sure it has the `LOGIN` | ||||
|   privilege. Default role is `pooler`. | ||||
| 
 | ||||
| * **connection_pooler_image** | ||||
|   Docker image to use for connection pooler deployment. | ||||
|  |  | |||
							
								
								
									
										11
									
								
								docs/user.md
								
								
								
								
							
							
						
						
									
										11
									
								
								docs/user.md
								
								
								
								
							|  | @ -527,7 +527,7 @@ spec: | |||
| This will tell the operator to create a connection pooler with default | ||||
| configuration, through which one can access the master via a separate service | ||||
| `{cluster-name}-pooler`. In most of the cases the | ||||
| [default configuration](reference/operator_parameters.md#connection-pool-configuration) | ||||
| [default configuration](reference/operator_parameters.md#connection-pooler-configuration) | ||||
| should be good enough. To configure a new connection pooler individually for | ||||
| each Postgres cluster, specify: | ||||
| 
 | ||||
|  | @ -540,7 +540,8 @@ spec: | |||
|     # in which mode to run, session or transaction | ||||
|     mode: "transaction" | ||||
| 
 | ||||
|     # schema, which operator will create to install credentials lookup function | ||||
|     # schema, which operator will create in each database | ||||
|     # to install credentials lookup function for connection pooler | ||||
|     schema: "pooler" | ||||
| 
 | ||||
|     # user, which operator will create for connection pooler | ||||
|  | @ -560,11 +561,11 @@ The `enableConnectionPooler` flag is not required when the `connectionPooler` | |||
| section is present in the manifest. But, it can be used to disable/remove the | ||||
| pooler while keeping its configuration. | ||||
| 
 | ||||
| By default, `pgbouncer` is used as connection pooler. To find out about pooler | ||||
| modes read the `pgbouncer` [docs](https://www.pgbouncer.org/config.html#pooler_mode) | ||||
| By default, [`PgBouncer`](https://www.pgbouncer.org/) is used as connection pooler. | ||||
| To find out about pool modes read the `PgBouncer` [docs](https://www.pgbouncer.org/config.html#pooler_mode) | ||||
| (but it should be the general approach between different implementation). | ||||
| 
 | ||||
| Note, that using `pgbouncer` a meaningful resource CPU limit should be 1 core | ||||
| Note, that using `PgBouncer` a meaningful resource CPU limit should be 1 core | ||||
| or less (there is a way to utilize more than one, but in K8s it's easier just to | ||||
| spin up more instances). | ||||
| 
 | ||||
|  |  | |||
|  | @ -67,6 +67,8 @@ spec: | |||
|     ttl: 30 | ||||
|     loop_wait: &loop_wait 10 | ||||
|     retry_timeout: 10 | ||||
|     synchronous_mode: false | ||||
|     synchronous_mode_strict: false | ||||
|     maximum_lag_on_failover: 33554432 | ||||
| 
 | ||||
| # restore a Postgres DB with point-in-time-recovery | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ data: | |||
|   # connection_pooler_default_cpu_request: "500m" | ||||
|   # connection_pooler_default_memory_limit: 100Mi | ||||
|   # connection_pooler_default_memory_request: 100Mi | ||||
|   connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-5" | ||||
|   connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-6" | ||||
|   # connection_pooler_max_db_connections: 60 | ||||
|   # connection_pooler_mode: "transaction" | ||||
|   # connection_pooler_number_of_instances: 2 | ||||
|  | @ -43,6 +43,7 @@ data: | |||
|   # enable_team_superuser: "false" | ||||
|   enable_teams_api: "false" | ||||
|   # etcd_host: "" | ||||
|   # kubernetes_use_configmaps: "false" | ||||
|   # infrastructure_roles_secret_name: postgresql-infrastructure-roles | ||||
|   # inherited_labels: application,environment | ||||
|   # kube_iam_role: "" | ||||
|  |  | |||
|  | @ -44,6 +44,8 @@ spec: | |||
|               type: boolean | ||||
|             etcd_host: | ||||
|               type: string | ||||
|             kubernetes_use_configmaps: | ||||
|               type: boolean | ||||
|             max_instances: | ||||
|               type: integer | ||||
|               minimum: -1  # -1 = disabled | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ metadata: | |||
| configuration: | ||||
|   # enable_crd_validation: true | ||||
|   etcd_host: "" | ||||
|   # kubernetes_use_configmaps: false | ||||
|   docker_image: registry.opensource.zalan.do/acid/spilo-12:1.6-p2 | ||||
|   # enable_shm_volume: true | ||||
|   # enable_unused_pvc_deletion: false | ||||
|  | @ -127,7 +128,7 @@ configuration: | |||
|     connection_pooler_default_cpu_request: "500m" | ||||
|     connection_pooler_default_memory_limit: 100Mi | ||||
|     connection_pooler_default_memory_request: 100Mi | ||||
|     connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-5" | ||||
|     connection_pooler_image: "registry.opensource.zalan.do/acid/pgbouncer:master-6" | ||||
|     # connection_pooler_max_db_connections: 60 | ||||
|     connection_pooler_mode: "transaction" | ||||
|     connection_pooler_number_of_instances: 2 | ||||
|  |  | |||
|  | @ -184,6 +184,10 @@ spec: | |||
|                   type: integer | ||||
|                 maximum_lag_on_failover: | ||||
|                   type: integer | ||||
|                 synchronous_mode: | ||||
|                   type: boolean | ||||
|                 synchronous_mode_strict: | ||||
|                   type: boolean | ||||
|             podAnnotations: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|  |  | |||
|  | @ -358,6 +358,12 @@ var PostgresCRDResourceValidation = apiextv1beta1.CustomResourceValidation{ | |||
| 							"maximum_lag_on_failover": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"synchronous_mode": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"synchronous_mode_strict": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"podAnnotations": { | ||||
|  | @ -727,6 +733,9 @@ var OperatorConfigCRDResourceValidation = apiextv1beta1.CustomResourceValidation | |||
| 					"etcd_host": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"kubernetes_use_configmaps": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"max_instances": { | ||||
| 						Type:        "integer", | ||||
| 						Description: "-1 = disabled", | ||||
|  |  | |||
|  | @ -183,6 +183,7 @@ type OperatorLogicalBackupConfiguration struct { | |||
| type OperatorConfigurationData struct { | ||||
| 	EnableCRDValidation        *bool                              `json:"enable_crd_validation,omitempty"` | ||||
| 	EtcdHost                   string                             `json:"etcd_host,omitempty"` | ||||
| 	KubernetesUseConfigMaps    bool                               `json:"kubernetes_use_configmaps,omitempty"` | ||||
| 	DockerImage                string                             `json:"docker_image,omitempty"` | ||||
| 	Workers                    uint32                             `json:"workers,omitempty"` | ||||
| 	MinInstances               int32                              `json:"min_instances,omitempty"` | ||||
|  |  | |||
|  | @ -118,13 +118,15 @@ type Resources struct { | |||
| 
 | ||||
| // Patroni contains Patroni-specific configuration
 | ||||
| type Patroni struct { | ||||
| 	InitDB               map[string]string            `json:"initdb"` | ||||
| 	PgHba                []string                     `json:"pg_hba"` | ||||
| 	TTL                  uint32                       `json:"ttl"` | ||||
| 	LoopWait             uint32                       `json:"loop_wait"` | ||||
| 	RetryTimeout         uint32                       `json:"retry_timeout"` | ||||
| 	MaximumLagOnFailover float32                      `json:"maximum_lag_on_failover"` // float32 because https://github.com/kubernetes/kubernetes/issues/30213
 | ||||
| 	Slots                map[string]map[string]string `json:"slots"` | ||||
| 	InitDB                map[string]string            `json:"initdb"` | ||||
| 	PgHba                 []string                     `json:"pg_hba"` | ||||
| 	TTL                   uint32                       `json:"ttl"` | ||||
| 	LoopWait              uint32                       `json:"loop_wait"` | ||||
| 	RetryTimeout          uint32                       `json:"retry_timeout"` | ||||
| 	MaximumLagOnFailover  float32                      `json:"maximum_lag_on_failover"` // float32 because https://github.com/kubernetes/kubernetes/issues/30213
 | ||||
| 	Slots                 map[string]map[string]string `json:"slots"` | ||||
| 	SynchronousMode       bool                         `json:"synchronous_mode"` | ||||
| 	SynchronousModeStrict bool                         `json:"synchronous_mode_strict"` | ||||
| } | ||||
| 
 | ||||
| //StandbyCluster
 | ||||
|  |  | |||
|  | @ -49,6 +49,8 @@ type patroniDCS struct { | |||
| 	LoopWait                 uint32                       `json:"loop_wait,omitempty"` | ||||
| 	RetryTimeout             uint32                       `json:"retry_timeout,omitempty"` | ||||
| 	MaximumLagOnFailover     float32                      `json:"maximum_lag_on_failover,omitempty"` | ||||
| 	SynchronousMode          bool                         `json:"synchronous_mode,omitempty"` | ||||
| 	SynchronousModeStrict    bool                         `json:"synchronous_mode_strict,omitempty"` | ||||
| 	PGBootstrapConfiguration map[string]interface{}       `json:"postgresql,omitempty"` | ||||
| 	Slots                    map[string]map[string]string `json:"slots,omitempty"` | ||||
| } | ||||
|  | @ -283,6 +285,12 @@ PatroniInitDBParams: | |||
| 	if patroni.Slots != nil { | ||||
| 		config.Bootstrap.DCS.Slots = patroni.Slots | ||||
| 	} | ||||
| 	if patroni.SynchronousMode { | ||||
| 		config.Bootstrap.DCS.SynchronousMode = patroni.SynchronousMode | ||||
| 	} | ||||
| 	if patroni.SynchronousModeStrict != false { | ||||
| 		config.Bootstrap.DCS.SynchronousModeStrict = patroni.SynchronousModeStrict | ||||
| 	} | ||||
| 
 | ||||
| 	config.PgLocalConfiguration = make(map[string]interface{}) | ||||
| 	config.PgLocalConfiguration[patroniPGBinariesParameterName] = fmt.Sprintf(pgBinariesLocationTemplate, pg.PgVersion) | ||||
|  | @ -672,6 +680,10 @@ func (c *Cluster) generateSpiloPodEnvVars(uid types.UID, spiloConfiguration stri | |||
| 		envVars = append(envVars, v1.EnvVar{Name: "ETCD_HOST", Value: c.OpConfig.EtcdHost}) | ||||
| 	} | ||||
| 
 | ||||
| 	if c.patroniKubernetesUseConfigMaps() { | ||||
| 		envVars = append(envVars, v1.EnvVar{Name: "KUBERNETES_USE_CONFIGMAPS", Value: "true"}) | ||||
| 	} | ||||
| 
 | ||||
| 	if cloneDescription.ClusterName != "" { | ||||
| 		envVars = append(envVars, c.generateCloneEnvironment(cloneDescription)...) | ||||
| 	} | ||||
|  | @ -1406,7 +1418,7 @@ func (c *Cluster) generateService(role PostgresRole, spec *acidv1.PostgresSpec) | |||
| 		Type:  v1.ServiceTypeClusterIP, | ||||
| 	} | ||||
| 
 | ||||
| 	if role == Replica { | ||||
| 	if role == Replica || c.patroniKubernetesUseConfigMaps() { | ||||
| 		serviceSpec.Selector = c.roleLabelsSet(false, role) | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,16 +65,18 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) { | |||
| 					"locale":         "en_US.UTF-8", | ||||
| 					"data-checksums": "true", | ||||
| 				}, | ||||
| 				PgHba:                []string{"hostssl all all 0.0.0.0/0 md5", "host    all all 0.0.0.0/0 md5"}, | ||||
| 				TTL:                  30, | ||||
| 				LoopWait:             10, | ||||
| 				RetryTimeout:         10, | ||||
| 				MaximumLagOnFailover: 33554432, | ||||
| 				Slots:                map[string]map[string]string{"permanent_logical_1": {"type": "logical", "database": "foo", "plugin": "pgoutput"}}, | ||||
| 				PgHba:                 []string{"hostssl all all 0.0.0.0/0 md5", "host    all all 0.0.0.0/0 md5"}, | ||||
| 				TTL:                   30, | ||||
| 				LoopWait:              10, | ||||
| 				RetryTimeout:          10, | ||||
| 				MaximumLagOnFailover:  33554432, | ||||
| 				SynchronousMode:       true, | ||||
| 				SynchronousModeStrict: true, | ||||
| 				Slots:                 map[string]map[string]string{"permanent_logical_1": {"type": "logical", "database": "foo", "plugin": "pgoutput"}}, | ||||
| 			}, | ||||
| 			role:     "zalandos", | ||||
| 			opConfig: config.Config{}, | ||||
| 			result:   `{"postgresql":{"bin_dir":"/usr/lib/postgresql/11/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host    all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}}}}`, | ||||
| 			result:   `{"postgresql":{"bin_dir":"/usr/lib/postgresql/11/bin","pg_hba":["hostssl all all 0.0.0.0/0 md5","host    all all 0.0.0.0/0 md5"]},"bootstrap":{"initdb":[{"auth-host":"md5"},{"auth-local":"trust"},"data-checksums",{"encoding":"UTF8"},{"locale":"en_US.UTF-8"}],"users":{"zalandos":{"password":"","options":["CREATEDB","NOLOGIN"]}},"dcs":{"ttl":30,"loop_wait":10,"retry_timeout":10,"maximum_lag_on_failover":33554432,"synchronous_mode":true,"synchronous_mode_strict":true,"slots":{"permanent_logical_1":{"database":"foo","plugin":"pgoutput","type":"logical"}}}}}`, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tt := range tests { | ||||
|  |  | |||
|  | @ -510,6 +510,15 @@ func (c *Cluster) patroniUsesKubernetes() bool { | |||
| 	return c.OpConfig.EtcdHost == "" | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) patroniKubernetesUseConfigMaps() bool { | ||||
| 	if !c.patroniUsesKubernetes() { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	// otherwise, follow the operator configuration
 | ||||
| 	return c.OpConfig.KubernetesUseConfigMaps | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) needConnectionPoolerWorker(spec *acidv1.PostgresSpec) bool { | ||||
| 	if spec.EnableConnectionPooler == nil { | ||||
| 		return spec.ConnectionPooler != nil | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur | |||
| 	// general config
 | ||||
| 	result.EnableCRDValidation = fromCRD.EnableCRDValidation | ||||
| 	result.EtcdHost = fromCRD.EtcdHost | ||||
| 	result.KubernetesUseConfigMaps = fromCRD.KubernetesUseConfigMaps | ||||
| 	result.DockerImage = fromCRD.DockerImage | ||||
| 	result.Workers = fromCRD.Workers | ||||
| 	result.MinInstances = fromCRD.MinInstances | ||||
|  |  | |||
|  | @ -107,11 +107,12 @@ type Config struct { | |||
| 	LogicalBackup | ||||
| 	ConnectionPooler | ||||
| 
 | ||||
| 	WatchedNamespace      string            `name:"watched_namespace"`    // special values: "*" means 'watch all namespaces', the empty string "" means 'watch a namespace where operator is deployed to'
 | ||||
| 	EtcdHost              string            `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
 | ||||
| 	DockerImage           string            `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-12:1.6-p2"` | ||||
| 	Sidecars              map[string]string `name:"sidecar_docker_images"` | ||||
| 	PodServiceAccountName string            `name:"pod_service_account_name" default:"postgres-pod"` | ||||
| 	WatchedNamespace        string            `name:"watched_namespace"` // special values: "*" means 'watch all namespaces', the empty string "" means 'watch a namespace where operator is deployed to'
 | ||||
| 	KubernetesUseConfigMaps bool              `name:"kubernetes_use_configmaps" default:"false"` | ||||
| 	EtcdHost                string            `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
 | ||||
| 	DockerImage             string            `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-12:1.6-p2"` | ||||
| 	Sidecars                map[string]string `name:"sidecar_docker_images"` | ||||
| 	PodServiceAccountName   string            `name:"pod_service_account_name" default:"postgres-pod"` | ||||
| 	// value of this string must be valid JSON or YAML; see initPodServiceAccount
 | ||||
| 	PodServiceAccountDefinition            string            `name:"pod_service_account_definition" default:""` | ||||
| 	PodServiceAccountRoleBindingDefinition string            `name:"pod_service_account_role_binding_definition" default:""` | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue