Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions config/crd/bases/multigres.com_multigresclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5139,8 +5139,7 @@ spec:
fsGroup:
description: |-
FSGroup sets the pod-level fsGroup for shared volume and socket access across
pool containers. When unset, the operator does not set pod fsGroup and runtime
defaults apply.
pool containers. When unset, runtime defaults apply.
format: int64
minimum: 1
type: integer
Expand Down Expand Up @@ -7586,8 +7585,7 @@ spec:
fsGroup:
description: |-
FSGroup sets the pod-level fsGroup for shared volume and socket access across
pool containers. When unset, the operator does not set pod fsGroup and runtime
defaults apply.
pool containers. When unset, runtime defaults apply.
format: int64
minimum: 1
type: integer
Expand Down
3 changes: 1 addition & 2 deletions config/crd/bases/multigres.com_shards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2428,8 +2428,7 @@ spec:
fsGroup:
description: |-
FSGroup sets the pod-level fsGroup for shared volume and socket access across
pool containers. When unset, the operator does not set pod fsGroup and runtime
defaults apply.
pool containers. When unset, runtime defaults apply.
format: int64
minimum: 1
type: integer
Expand Down
3 changes: 1 addition & 2 deletions config/crd/bases/multigres.com_shardtemplates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2062,8 +2062,7 @@ spec:
fsGroup:
description: |-
FSGroup sets the pod-level fsGroup for shared volume and socket access across
pool containers. When unset, the operator does not set pod fsGroup and runtime
defaults apply.
pool containers. When unset, runtime defaults apply.
format: int64
minimum: 1
type: integer
Expand Down
3 changes: 1 addition & 2 deletions config/crd/bases/multigres.com_tablegroups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2592,8 +2592,7 @@ spec:
fsGroup:
description: |-
FSGroup sets the pod-level fsGroup for shared volume and socket access across
pool containers. When unset, the operator does not set pod fsGroup and runtime
defaults apply.
pool containers. When unset, runtime defaults apply.
format: int64
minimum: 1
type: integer
Expand Down
1 change: 1 addition & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,6 @@ rules:
resources:
- storageclasses
verbs:
- get
- list
- watch
41 changes: 25 additions & 16 deletions pkg/resource-handler/controller/shard/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,17 @@ func buildPgctldContainer(
}

return corev1.Container{
Name: "postgres",
Image: image,
Command: []string{"/usr/local/bin/pgctld"},
Args: args,
Resources: pool.Postgres.Resources,
Env: env,
SecurityContext: buildContainerSecurityContext(pool.FSGroup),
VolumeMounts: volumeMounts,
Name: "postgres",
Image: image,
Command: []string{"/usr/local/bin/pgctld"},
Args: args,
Resources: pool.Postgres.Resources,
Env: env,
SecurityContext: buildContainerSecurityContext(
pool.FSGroup,
defaultPostgresRunAsUserUID,
),
VolumeMounts: volumeMounts,
StartupProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Expand Down Expand Up @@ -280,7 +283,10 @@ func buildPostgresExporterContainer(
},
},
},
SecurityContext: buildContainerSecurityContext(pool.FSGroup),
SecurityContext: buildContainerSecurityContext(
pool.FSGroup,
defaultPostgresExporterRunAsUserUID,
),
}
}

Expand Down Expand Up @@ -337,13 +343,16 @@ func buildMultiPoolerSidecar(
}

c := corev1.Container{
Name: "multipooler",
Image: image,
Args: args,
Ports: buildMultiPoolerContainerPorts(),
Resources: pool.Multipooler.Resources,
RestartPolicy: &sidecarRestartPolicy,
SecurityContext: buildContainerSecurityContext(pool.FSGroup),
Name: "multipooler",
Image: image,
Args: args,
Ports: buildMultiPoolerContainerPorts(),
Resources: pool.Multipooler.Resources,
RestartPolicy: &sidecarRestartPolicy,
SecurityContext: buildContainerSecurityContext(
pool.FSGroup,
defaultMultiPoolerRunAsUserUID,
),
StartupProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
HTTPGet: &corev1.HTTPGetAction{
Expand Down
8 changes: 8 additions & 0 deletions pkg/resource-handler/controller/shard/containers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ func TestBuildMultiPoolerSidecar(t *testing.T) {
RestartPolicy: &sidecarRestartPolicy,
SecurityContext: &corev1.SecurityContext{
RunAsNonRoot: ptr.To(true),
RunAsUser: ptr.To(defaultMultiPoolerRunAsUserUID),
RunAsGroup: ptr.To(defaultMultiPoolerRunAsUserUID),
},
StartupProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
Expand Down Expand Up @@ -177,6 +179,8 @@ func TestBuildMultiPoolerSidecar(t *testing.T) {
RestartPolicy: &sidecarRestartPolicy,
SecurityContext: &corev1.SecurityContext{
RunAsNonRoot: ptr.To(true),
RunAsUser: ptr.To(defaultMultiPoolerRunAsUserUID),
RunAsGroup: ptr.To(defaultMultiPoolerRunAsUserUID),
},
StartupProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
Expand Down Expand Up @@ -298,6 +302,8 @@ func TestBuildMultiPoolerSidecar(t *testing.T) {
RestartPolicy: &sidecarRestartPolicy,
SecurityContext: &corev1.SecurityContext{
RunAsNonRoot: ptr.To(true),
RunAsUser: ptr.To(defaultMultiPoolerRunAsUserUID),
RunAsGroup: ptr.To(defaultMultiPoolerRunAsUserUID),
},
StartupProbe: &corev1.Probe{
ProbeHandler: corev1.ProbeHandler{
Expand Down Expand Up @@ -403,6 +409,8 @@ func TestBuildPostgresExporterContainer(t *testing.T) {
},
SecurityContext: &corev1.SecurityContext{
RunAsNonRoot: ptr.To(true),
RunAsUser: ptr.To(defaultPostgresExporterRunAsUserUID),
RunAsGroup: ptr.To(defaultPostgresExporterRunAsUserUID),
},
}

Expand Down
20 changes: 16 additions & 4 deletions pkg/resource-handler/controller/shard/pool_pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ const (
// connections and set NOT_SERVING in etcd before SIGKILL.
defaultTerminationGracePeriod int64 = 30

// Default container UIDs used when fsGroup is not provided.
defaultPostgresRunAsUserUID int64 = 999
defaultPostgresExporterRunAsUserUID int64 = 65534
defaultMultiPoolerRunAsUserUID int64 = 999

// DefaultPoolReplicas is the default number of replicas for a pool cell if not specified.
DefaultPoolReplicas int32 = 1
)
Expand Down Expand Up @@ -134,17 +139,24 @@ func buildPoolPodSecurityContext(poolSpec multigresv1alpha1.PoolSpec) *corev1.Po
}
}

// buildContainerSecurityContext returns a non-root SecurityContext. When fsGroup
// is set, RunAsUser and RunAsGroup are pinned to that value so all containers
// in the pod share the same filesystem identity on shared volumes.
func buildContainerSecurityContext(fsGroup *int64) *corev1.SecurityContext {
// buildContainerSecurityContext returns a non-root SecurityContext.
//
// If fsGroup is set, RunAsUser and RunAsGroup are pinned to that value so all
// containers in the pod share the same filesystem identity on shared volumes.
// Otherwise, a container-specific fallback UID is used to ensure kubelet can
// verify runAsNonRoot against a numeric user.
func buildContainerSecurityContext(fsGroup *int64, fallbackUID int64) *corev1.SecurityContext {
sc := &corev1.SecurityContext{
RunAsNonRoot: ptr.To(true),
}
if fsGroup != nil {
sc.RunAsUser = fsGroup
sc.RunAsGroup = fsGroup
return sc
}

sc.RunAsUser = ptr.To(fallbackUID)
sc.RunAsGroup = ptr.To(fallbackUID)
return sc
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/resource-handler/controller/shard/pool_pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,21 +198,21 @@ func TestBuildPoolPod_SecurityContextWithFSGroup(t *testing.T) {

func TestBuildContainerSecurityContext(t *testing.T) {
t.Run("nil fsGroup", func(t *testing.T) {
sc := buildContainerSecurityContext(nil)
sc := buildContainerSecurityContext(nil, defaultPostgresRunAsUserUID)
assert.True(t, *sc.RunAsNonRoot)
assert.Nil(t, sc.RunAsUser)
assert.Nil(t, sc.RunAsGroup)
assert.Equal(t, defaultPostgresRunAsUserUID, *sc.RunAsUser)
assert.Equal(t, defaultPostgresRunAsUserUID, *sc.RunAsGroup)
})

t.Run("with fsGroup", func(t *testing.T) {
sc := buildContainerSecurityContext(ptr.To(int64(999)))
sc := buildContainerSecurityContext(ptr.To(int64(999)), defaultPostgresRunAsUserUID)
assert.True(t, *sc.RunAsNonRoot)
assert.Equal(t, int64(999), *sc.RunAsUser)
assert.Equal(t, int64(999), *sc.RunAsGroup)
})

t.Run("alpine fsGroup", func(t *testing.T) {
sc := buildContainerSecurityContext(ptr.To(int64(70)))
sc := buildContainerSecurityContext(ptr.To(int64(70)), defaultPostgresRunAsUserUID)
assert.True(t, *sc.RunAsNonRoot)
assert.Equal(t, int64(70), *sc.RunAsUser)
assert.Equal(t, int64(70), *sc.RunAsGroup)
Expand Down