diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml index e01a5f997..b29356bff 100644 --- a/charts/postgres-operator/crds/operatorconfigurations.yaml +++ b/charts/postgres-operator/crds/operatorconfigurations.yaml @@ -2,8 +2,6 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: operatorconfigurations.acid.zalan.do - labels: - app.kubernetes.io/name: postgres-operator spec: group: acid.zalan.do names: @@ -311,6 +309,11 @@ spec: pod_terminate_grace_period: type: string default: "5m" + pod_fs_group_change_policy: + type: string + enum: + - OnRootMismatch + - Always secret_name_template: type: string default: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 50414e00a..0a11821bf 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -193,6 +193,7 @@ configKubernetes: secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" # sharing unix socket of PostgreSQL (`pg_socket`) with the sidecars share_pgsocket_with_sidecars: false + # set user and group for the spilo container (required to run Spilo as non-root process) # spilo_runasuser: 101 # spilo_runasgroup: 103 @@ -200,6 +201,11 @@ configKubernetes: # group ID with write-access to volumes (required to run Spilo as non-root process) # spilo_fsgroup: 103 + # Configure volume permission and the ownership change policy for Pods + # Valid options are undefined, OnRootMismatch, Always + # See https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#configure-volume-permission-and-ownership-change-policy-for-pods + # pod_fs_group_change_policy: OnRootMismatch + # whether the Spilo container should run in privileged mode spilo_privileged: false # whether the Spilo container should run with additional permissions other than parent. diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index 198870d77..34a7c3c52 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -431,7 +431,7 @@ configuration they are grouped under the `kubernetes` key. environment if they not if conflict with the environment variables generated by the operator. The WAL location (bucket path) can be overridden, though. The default is empty. - + * **pod_environment_secret** similar to pod_environment_configmap but referencing a secret with custom environment variables. Because the secret is not allowed to exist in a @@ -459,6 +459,15 @@ configuration they are grouped under the `kubernetes` key. non-root process, but requires a custom Spilo image. Note the FSGroup of a Pod cannot be changed without recreating a new Pod. +* **pod_fs_group_change_policy** + Configure the `fsGroupChangePolicy` in the Pod `securityContext` to + avoid invalid volume permissions after `kubelet` restarts. See *[Configure volume permission and ownership change policy for Pods](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#configure-volume-permission-and-ownership-change-policy-for-pods)* + for details. If specified, valid options are `OnRootMismatch` + (change permissions and ownership if the permission and the + ownership of root directory does not match with expected permissions + of the volume) and `Always` (always change permission and ownership + of the volume when volume is mounted). + * **spilo_privileged** whether the Spilo container should run in privileged mode. Privileged mode is used for AWS volume resizing and not required if you don't need that @@ -558,7 +567,7 @@ effect, and the parameters are grouped under the `timeouts` key in the CRD-based configuration. * **PatroniAPICheckInterval** - the interval between consecutive attempts waiting for the return of + the interval between consecutive attempts waiting for the return of Patroni Api. The default is `1s`. * **PatroniAPICheckTimeout** @@ -797,7 +806,7 @@ grouped under the `logical_backup` key. is specified, no argument will be passed to `aws s3` command. Default: "AES256". * **logical_backup_s3_retention_time** - Specify a retention time for logical backups stored in S3. Backups older than the specified retention + Specify a retention time for logical backups stored in S3. Backups older than the specified retention time will be deleted after a new backup was uploaded. If empty, all backups will be kept. Example values are "3 days", "2 weeks", or "1 month". The default is empty. diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index e2fb21504..6012d9849 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -151,6 +151,7 @@ data: # spilo_runasuser: 101 # spilo_runasgroup: 103 # spilo_fsgroup: 103 + # pod_fs_group_change_policy: OnRootMismatch spilo_privileged: "false" storage_resize_mode: "pvc" super_username: postgres diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index 8582c866a..b29356bff 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -309,6 +309,11 @@ spec: pod_terminate_grace_period: type: string default: "5m" + pod_fs_group_change_policy: + type: string + enum: + - OnRootMismatch + - Always secret_name_template: type: string default: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go index b82aa30b6..81130693c 100644 --- a/pkg/apis/acid.zalan.do/v1/crds.go +++ b/pkg/apis/acid.zalan.do/v1/crds.go @@ -1429,6 +1429,17 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ "pod_terminate_grace_period": { Type: "string", }, + "pod_fs_group_change_policy": { + Type: "string", + Enum: []apiextv1.JSON{ + { + Raw: []byte(`"OnRootMismatch"`), + }, + { + Raw: []byte(`"Always"`), + }, + }, + }, "secret_name_template": { Type: "string", }, diff --git a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go index 4ff5ee81e..54678a8fe 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -60,6 +60,7 @@ type KubernetesMetaConfiguration struct { PodServiceAccountDefinition string `json:"pod_service_account_definition,omitempty"` PodServiceAccountRoleBindingDefinition string `json:"pod_service_account_role_binding_definition,omitempty"` PodTerminateGracePeriod Duration `json:"pod_terminate_grace_period,omitempty"` + PodFsGroupChangePolicy v1.PodFSGroupChangePolicy `json:"pod_fs_group_change_policy,omitempty"` SpiloPrivileged bool `json:"spilo_privileged,omitempty"` SpiloAllowPrivilegeEscalation *bool `json:"spilo_allow_privilege_escalation,omitempty"` SpiloRunAsUser *int64 `json:"spilo_runasuser,omitempty"` diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 3de5e430f..5651d6a57 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -778,6 +778,7 @@ func (c *Cluster) generatePodTemplate( nodeAffinity *v1.Affinity, schedulerName *string, terminateGracePeriod int64, + podFsGroupChangePolicy v1.PodFSGroupChangePolicy, podServiceAccountName string, kubeIAMRole string, priorityClassName string, @@ -807,6 +808,10 @@ func (c *Cluster) generatePodTemplate( securityContext.FSGroup = spiloFSGroup } + if len(podFsGroupChangePolicy) > 0 { + securityContext.FSGroupChangePolicy = &podFsGroupChangePolicy + } + podSpec := v1.PodSpec{ ServiceAccountName: podServiceAccountName, TerminationGracePeriodSeconds: &terminateGracePeriodSeconds, @@ -1284,6 +1289,8 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef effectiveFSGroup = spec.SpiloFSGroup } + fsGroupChangePolicy := c.OpConfig.PodFsGroupChangePolicy + volumeMounts := generateVolumeMounts(spec.Volume) // configure TLS with a custom secret volume @@ -1434,6 +1441,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef c.nodeAffinity(c.OpConfig.NodeReadinessLabel, spec.NodeAffinity), spec.SchedulerName, int64(c.OpConfig.PodTerminateGracePeriod.Seconds()), + fsGroupChangePolicy, c.OpConfig.PodServiceAccountName, c.OpConfig.KubeIAMRole, effectivePodPriorityClassName, @@ -2188,6 +2196,7 @@ func (c *Cluster) generateLogicalBackupJob() (*batchv1.CronJob, error) { c.nodeAffinity(c.OpConfig.NodeReadinessLabel, nil), nil, int64(c.OpConfig.PodTerminateGracePeriod.Seconds()), + "", c.OpConfig.PodServiceAccountName, c.OpConfig.KubeIAMRole, "", diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index a66ece2fa..d69099106 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -73,6 +73,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.PodEnvironmentConfigMap = fromCRD.Kubernetes.PodEnvironmentConfigMap result.PodEnvironmentSecret = fromCRD.Kubernetes.PodEnvironmentSecret result.PodTerminateGracePeriod = util.CoalesceDuration(time.Duration(fromCRD.Kubernetes.PodTerminateGracePeriod), "5m") + result.PodFsGroupChangePolicy = fromCRD.Kubernetes.PodFsGroupChangePolicy result.SpiloPrivileged = fromCRD.Kubernetes.SpiloPrivileged result.SpiloAllowPrivilegeEscalation = util.CoalesceBool(fromCRD.Kubernetes.SpiloAllowPrivilegeEscalation, util.True()) result.SpiloRunAsUser = fromCRD.Kubernetes.SpiloRunAsUser diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index df1cf6bb8..0c5155da8 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -25,42 +25,43 @@ type CRD struct { // Resources describes kubernetes resource specific configuration parameters type Resources struct { - ResourceCheckInterval time.Duration `name:"resource_check_interval" default:"3s"` - ResourceCheckTimeout time.Duration `name:"resource_check_timeout" default:"10m"` - PodLabelWaitTimeout time.Duration `name:"pod_label_wait_timeout" default:"10m"` - PodDeletionWaitTimeout time.Duration `name:"pod_deletion_wait_timeout" default:"10m"` - PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` - SpiloRunAsUser *int64 `name:"spilo_runasuser"` - SpiloRunAsGroup *int64 `name:"spilo_runasgroup"` - SpiloFSGroup *int64 `name:"spilo_fsgroup"` - PodPriorityClassName string `name:"pod_priority_class_name"` - ClusterDomain string `name:"cluster_domain" default:"cluster.local"` - SpiloPrivileged bool `name:"spilo_privileged" default:"false"` - SpiloAllowPrivilegeEscalation *bool `name:"spilo_allow_privilege_escalation" default:"true"` - AdditionalPodCapabilities []string `name:"additional_pod_capabilities" default:""` - ClusterLabels map[string]string `name:"cluster_labels" default:"application:spilo"` - InheritedLabels []string `name:"inherited_labels" default:""` - InheritedAnnotations []string `name:"inherited_annotations" default:""` - DownscalerAnnotations []string `name:"downscaler_annotations"` - IgnoredAnnotations []string `name:"ignored_annotations"` - ClusterNameLabel string `name:"cluster_name_label" default:"cluster-name"` - DeleteAnnotationDateKey string `name:"delete_annotation_date_key"` - DeleteAnnotationNameKey string `name:"delete_annotation_name_key"` - PodRoleLabel string `name:"pod_role_label" default:"spilo-role"` - PodToleration map[string]string `name:"toleration" default:""` - DefaultCPURequest string `name:"default_cpu_request" default:"100m"` - DefaultMemoryRequest string `name:"default_memory_request" default:"100Mi"` - DefaultCPULimit string `name:"default_cpu_limit" default:"1"` - DefaultMemoryLimit string `name:"default_memory_limit" default:"500Mi"` - MinCPULimit string `name:"min_cpu_limit" default:"250m"` - MinMemoryLimit string `name:"min_memory_limit" default:"250Mi"` - MaxCPURequest string `name:"max_cpu_request"` - MaxMemoryRequest string `name:"max_memory_request"` - PodEnvironmentConfigMap spec.NamespacedName `name:"pod_environment_configmap"` - PodEnvironmentSecret string `name:"pod_environment_secret"` - NodeReadinessLabel map[string]string `name:"node_readiness_label" default:""` - NodeReadinessLabelMerge string `name:"node_readiness_label_merge" default:"OR"` - ShmVolume *bool `name:"enable_shm_volume" default:"true"` + ResourceCheckInterval time.Duration `name:"resource_check_interval" default:"3s"` + ResourceCheckTimeout time.Duration `name:"resource_check_timeout" default:"10m"` + PodLabelWaitTimeout time.Duration `name:"pod_label_wait_timeout" default:"10m"` + PodDeletionWaitTimeout time.Duration `name:"pod_deletion_wait_timeout" default:"10m"` + PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` + PodFsGroupChangePolicy v1.PodFSGroupChangePolicy `name:"pod_fs_group_change_policy"` + SpiloRunAsUser *int64 `name:"spilo_runasuser"` + SpiloRunAsGroup *int64 `name:"spilo_runasgroup"` + SpiloFSGroup *int64 `name:"spilo_fsgroup"` + PodPriorityClassName string `name:"pod_priority_class_name"` + ClusterDomain string `name:"cluster_domain" default:"cluster.local"` + SpiloPrivileged bool `name:"spilo_privileged" default:"false"` + SpiloAllowPrivilegeEscalation *bool `name:"spilo_allow_privilege_escalation" default:"true"` + AdditionalPodCapabilities []string `name:"additional_pod_capabilities" default:""` + ClusterLabels map[string]string `name:"cluster_labels" default:"application:spilo"` + InheritedLabels []string `name:"inherited_labels" default:""` + InheritedAnnotations []string `name:"inherited_annotations" default:""` + DownscalerAnnotations []string `name:"downscaler_annotations"` + IgnoredAnnotations []string `name:"ignored_annotations"` + ClusterNameLabel string `name:"cluster_name_label" default:"cluster-name"` + DeleteAnnotationDateKey string `name:"delete_annotation_date_key"` + DeleteAnnotationNameKey string `name:"delete_annotation_name_key"` + PodRoleLabel string `name:"pod_role_label" default:"spilo-role"` + PodToleration map[string]string `name:"toleration" default:""` + DefaultCPURequest string `name:"default_cpu_request" default:"100m"` + DefaultMemoryRequest string `name:"default_memory_request" default:"100Mi"` + DefaultCPULimit string `name:"default_cpu_limit" default:"1"` + DefaultMemoryLimit string `name:"default_memory_limit" default:"500Mi"` + MinCPULimit string `name:"min_cpu_limit" default:"250m"` + MinMemoryLimit string `name:"min_memory_limit" default:"250Mi"` + MaxCPURequest string `name:"max_cpu_request"` + MaxMemoryRequest string `name:"max_memory_request"` + PodEnvironmentConfigMap spec.NamespacedName `name:"pod_environment_configmap"` + PodEnvironmentSecret string `name:"pod_environment_secret"` + NodeReadinessLabel map[string]string `name:"node_readiness_label" default:""` + NodeReadinessLabelMerge string `name:"node_readiness_label_merge" default:"OR"` + ShmVolume *bool `name:"enable_shm_volume" default:"true"` MaxInstances int32 `name:"max_instances" default:"-1"` MinInstances int32 `name:"min_instances" default:"-1"` @@ -177,75 +178,76 @@ type Config struct { SidecarContainers []v1.Container `name:"sidecars"` 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:""` - MasterPodMoveTimeout time.Duration `name:"master_pod_move_timeout" default:"20m"` - DbHostedZone string `name:"db_hosted_zone" default:"db.example.com"` - AWSRegion string `name:"aws_region" default:"eu-central-1"` - WALES3Bucket string `name:"wal_s3_bucket"` - LogS3Bucket string `name:"log_s3_bucket"` - KubeIAMRole string `name:"kube_iam_role"` - WALGSBucket string `name:"wal_gs_bucket"` - GCPCredentials string `name:"gcp_credentials"` - WALAZStorageAccount string `name:"wal_az_storage_account"` - AdditionalSecretMount string `name:"additional_secret_mount"` - AdditionalSecretMountPath string `name:"additional_secret_mount_path" default:"/meta/credentials"` - EnableEBSGp3Migration bool `name:"enable_ebs_gp3_migration" default:"false"` - EnableEBSGp3MigrationMaxSize int64 `name:"enable_ebs_gp3_migration_max_size" default:"1000"` - DebugLogging bool `name:"debug_logging" default:"true"` - EnableDBAccess bool `name:"enable_database_access" default:"true"` - EnableTeamsAPI bool `name:"enable_teams_api" default:"true"` - EnableTeamSuperuser bool `name:"enable_team_superuser" default:"false"` - TeamAdminRole string `name:"team_admin_role" default:"admin"` - RoleDeletionSuffix string `name:"role_deletion_suffix" default:"_deleted"` - EnableTeamMemberDeprecation bool `name:"enable_team_member_deprecation" default:"false"` - EnableAdminRoleForUsers bool `name:"enable_admin_role_for_users" default:"true"` - EnablePostgresTeamCRD bool `name:"enable_postgres_team_crd" default:"false"` - EnablePostgresTeamCRDSuperusers bool `name:"enable_postgres_team_crd_superusers" default:"false"` - EnableMasterLoadBalancer bool `name:"enable_master_load_balancer" default:"true"` - EnableMasterPoolerLoadBalancer bool `name:"enable_master_pooler_load_balancer" default:"false"` - EnableReplicaLoadBalancer bool `name:"enable_replica_load_balancer" default:"false"` - EnableReplicaPoolerLoadBalancer bool `name:"enable_replica_pooler_load_balancer" default:"false"` - CustomServiceAnnotations map[string]string `name:"custom_service_annotations"` - CustomPodAnnotations map[string]string `name:"custom_pod_annotations"` - EnablePodAntiAffinity bool `name:"enable_pod_antiaffinity" default:"false"` - PodAntiAffinityPreferredDuringScheduling bool `name:"pod_antiaffinity_preferred_during_scheduling" default:"false"` - PodAntiAffinityTopologyKey string `name:"pod_antiaffinity_topology_key" default:"kubernetes.io/hostname"` - StorageResizeMode string `name:"storage_resize_mode" default:"pvc"` - EnableLoadBalancer *bool `name:"enable_load_balancer"` // deprecated and kept for backward compatibility - ExternalTrafficPolicy string `name:"external_traffic_policy" default:"Cluster"` - MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{namespace}.{hostedzone}"` - MasterLegacyDNSNameFormat StringTemplate `name:"master_legacy_dns_name_format" default:"{cluster}.{team}.{hostedzone}"` - ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{namespace}.{hostedzone}"` - ReplicaLegacyDNSNameFormat StringTemplate `name:"replica_legacy_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"` - PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"` - EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"` - EnableInitContainers *bool `name:"enable_init_containers" default:"true"` - EnableSidecars *bool `name:"enable_sidecars" default:"true"` - SharePgSocketWithSidecars *bool `name:"share_pgsocket_with_sidecars" default:"false"` - Workers uint32 `name:"workers" default:"8"` - APIPort int `name:"api_port" default:"8080"` - RingLogLines int `name:"ring_log_lines" default:"100"` - ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"` - TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"` - PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` - PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"` - EnableReadinessProbe bool `name:"enable_readiness_probe" default:"false"` - ProtectedRoles []string `name:"protected_role_names" default:"admin,cron_admin"` - PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""` - SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"` - EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"` - EnableCrossNamespaceSecret bool `name:"enable_cross_namespace_secret" default:"false"` - EnablePgVersionEnvVar bool `name:"enable_pgversion_env_var" default:"true"` - EnableSpiloWalPathCompat bool `name:"enable_spilo_wal_path_compat" default:"false"` - EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"` - MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"` - MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""` - MinimalMajorVersion string `name:"minimal_major_version" default:"11"` - TargetMajorVersion string `name:"target_major_version" default:"15"` - PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"` - PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"` - EnablePatroniFailsafeMode *bool `name:"enable_patroni_failsafe_mode" default:"false"` + PodServiceAccountDefinition string `name:"pod_service_account_definition" default:""` + PodServiceAccountRoleBindingDefinition string `name:"pod_service_account_role_binding_definition" default:""` + MasterPodMoveTimeout time.Duration `name:"master_pod_move_timeout" default:"20m"` + DbHostedZone string `name:"db_hosted_zone" default:"db.example.com"` + AWSRegion string `name:"aws_region" default:"eu-central-1"` + WALES3Bucket string `name:"wal_s3_bucket"` + LogS3Bucket string `name:"log_s3_bucket"` + KubeIAMRole string `name:"kube_iam_role"` + WALGSBucket string `name:"wal_gs_bucket"` + GCPCredentials string `name:"gcp_credentials"` + WALAZStorageAccount string `name:"wal_az_storage_account"` + AdditionalSecretMount string `name:"additional_secret_mount"` + AdditionalSecretMountPath string `name:"additional_secret_mount_path" default:"/meta/credentials"` + EnableEBSGp3Migration bool `name:"enable_ebs_gp3_migration" default:"false"` + EnableEBSGp3MigrationMaxSize int64 `name:"enable_ebs_gp3_migration_max_size" default:"1000"` + DebugLogging bool `name:"debug_logging" default:"true"` + EnableDBAccess bool `name:"enable_database_access" default:"true"` + EnableTeamsAPI bool `name:"enable_teams_api" default:"true"` + EnableTeamSuperuser bool `name:"enable_team_superuser" default:"false"` + TeamAdminRole string `name:"team_admin_role" default:"admin"` + RoleDeletionSuffix string `name:"role_deletion_suffix" default:"_deleted"` + EnableTeamMemberDeprecation bool `name:"enable_team_member_deprecation" default:"false"` + EnableAdminRoleForUsers bool `name:"enable_admin_role_for_users" default:"true"` + EnablePostgresTeamCRD bool `name:"enable_postgres_team_crd" default:"false"` + EnablePostgresTeamCRDSuperusers bool `name:"enable_postgres_team_crd_superusers" default:"false"` + EnableMasterLoadBalancer bool `name:"enable_master_load_balancer" default:"true"` + EnableMasterPoolerLoadBalancer bool `name:"enable_master_pooler_load_balancer" default:"false"` + EnableReplicaLoadBalancer bool `name:"enable_replica_load_balancer" default:"false"` + EnableReplicaPoolerLoadBalancer bool `name:"enable_replica_pooler_load_balancer" default:"false"` + CustomServiceAnnotations map[string]string `name:"custom_service_annotations"` + CustomPodAnnotations map[string]string `name:"custom_pod_annotations"` + EnablePodAntiAffinity bool `name:"enable_pod_antiaffinity" default:"false"` + PodAntiAffinityPreferredDuringScheduling bool `name:"pod_antiaffinity_preferred_during_scheduling" default:"false"` + PodAntiAffinityTopologyKey string `name:"pod_antiaffinity_topology_key" default:"kubernetes.io/hostname"` + StorageResizeMode string `name:"storage_resize_mode" default:"pvc"` + EnableLoadBalancer *bool `name:"enable_load_balancer"` // deprecated and kept for backward compatibility + ExternalTrafficPolicy string `name:"external_traffic_policy" default:"Cluster"` + MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{namespace}.{hostedzone}"` + MasterLegacyDNSNameFormat StringTemplate `name:"master_legacy_dns_name_format" default:"{cluster}.{team}.{hostedzone}"` + ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{namespace}.{hostedzone}"` + ReplicaLegacyDNSNameFormat StringTemplate `name:"replica_legacy_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"` + PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"` + EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"` + EnableInitContainers *bool `name:"enable_init_containers" default:"true"` + EnableSidecars *bool `name:"enable_sidecars" default:"true"` + SharePgSocketWithSidecars *bool `name:"share_pgsocket_with_sidecars" default:"false"` + Workers uint32 `name:"workers" default:"8"` + APIPort int `name:"api_port" default:"8080"` + RingLogLines int `name:"ring_log_lines" default:"100"` + ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"` + TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"` + PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` + PodFsGroupChangePolicy v1.PodFSGroupChangePolicy `name:"pod_fs_group_change_policy"` + PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"` + EnableReadinessProbe bool `name:"enable_readiness_probe" default:"false"` + ProtectedRoles []string `name:"protected_role_names" default:"admin,cron_admin"` + PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""` + SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"` + EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"` + EnableCrossNamespaceSecret bool `name:"enable_cross_namespace_secret" default:"false"` + EnablePgVersionEnvVar bool `name:"enable_pgversion_env_var" default:"true"` + EnableSpiloWalPathCompat bool `name:"enable_spilo_wal_path_compat" default:"false"` + EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"` + MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"` + MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""` + MinimalMajorVersion string `name:"minimal_major_version" default:"11"` + TargetMajorVersion string `name:"target_major_version" default:"15"` + PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"` + PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"` + EnablePatroniFailsafeMode *bool `name:"enable_patroni_failsafe_mode" default:"false"` } // MustMarshal marshals the config or panics