From 8a853e151d8ea27fe3a5c27ed1c670d41c6733b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Austerm=C3=BChle?= Date: Tue, 25 Oct 2022 11:55:20 +0200 Subject: [PATCH 1/5] Add support for fsGroupChangePolicy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stephan Austermühle --- manifests/operatorconfiguration.crd.yaml | 5 + pkg/apis/acid.zalan.do/v1/crds.go | 11 + .../v1/operator_configuration_type.go | 1 + pkg/cluster/k8sres.go | 9 + pkg/controller/operator_config.go | 1 + pkg/util/config/config.go | 212 +++++++++--------- 6 files changed, 134 insertions(+), 105 deletions(-) diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index 8582c866a..00e9d34a9 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_fsgroupchangepolicy: + 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..d93d13af3 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_fsgroupchangepolicy": { + 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..c3457b2c8 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_fsgroupchangepolicy,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..e9af9fad4 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_fsgroupchangepolicy"` + 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_fsgroupchangepolicy"` + 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 From 503365db9e9cd8b3e563cb02c9e9c5272fd54a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Austerm=C3=BChle?= Date: Tue, 25 Oct 2022 12:02:34 +0200 Subject: [PATCH 2/5] Rename pod_fsgroupchangepolicy to pod_fs_group_change_policy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stephan Austermühle --- manifests/operatorconfiguration.crd.yaml | 2 +- pkg/apis/acid.zalan.do/v1/crds.go | 2 +- pkg/apis/acid.zalan.do/v1/operator_configuration_type.go | 2 +- pkg/util/config/config.go | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index 00e9d34a9..b29356bff 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -309,7 +309,7 @@ spec: pod_terminate_grace_period: type: string default: "5m" - pod_fsgroupchangepolicy: + pod_fs_group_change_policy: type: string enum: - OnRootMismatch diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go index d93d13af3..81130693c 100644 --- a/pkg/apis/acid.zalan.do/v1/crds.go +++ b/pkg/apis/acid.zalan.do/v1/crds.go @@ -1429,7 +1429,7 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ "pod_terminate_grace_period": { Type: "string", }, - "pod_fsgroupchangepolicy": { + "pod_fs_group_change_policy": { Type: "string", Enum: []apiextv1.JSON{ { 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 c3457b2c8..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,7 +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_fsgroupchangepolicy,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/util/config/config.go b/pkg/util/config/config.go index e9af9fad4..0c5155da8 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -30,7 +30,7 @@ type Resources struct { 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_fsgroupchangepolicy"` + PodFsGroupChangePolicy v1.PodFSGroupChangePolicy `name:"pod_fs_group_change_policy"` SpiloRunAsUser *int64 `name:"spilo_runasuser"` SpiloRunAsGroup *int64 `name:"spilo_runasgroup"` SpiloFSGroup *int64 `name:"spilo_fsgroup"` @@ -230,7 +230,7 @@ type Config struct { 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_fsgroupchangepolicy"` + 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"` From e55edc60b2f215ad299b63b0d34fd278b60306d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Austerm=C3=BChle?= Date: Tue, 25 Oct 2022 14:17:14 +0200 Subject: [PATCH 3/5] Add pod_fs_group_change_policy to templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stephan Austermühle --- charts/postgres-operator/values.yaml | 6 ++++++ manifests/configmap.yaml | 1 + 2 files changed, 7 insertions(+) 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/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 From baa28b9d1d3358610909420e46b9d9f4192a4a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Austerm=C3=BChle?= Date: Tue, 25 Oct 2022 14:17:40 +0200 Subject: [PATCH 4/5] Update parameter reference docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stephan Austermühle --- docs/reference/operator_parameters.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) 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. From cf2dd64b48c541fb85250e5baae9513af9b0c2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Austerm=C3=BChle?= Date: Tue, 25 Oct 2022 15:14:04 +0200 Subject: [PATCH 5/5] Update Helm chart CRD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stephan Austermühle --- charts/postgres-operator/crds/operatorconfigurations.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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}"