From 723a34a01e6409fd8533dd390d9ceaf4385b0bfa Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sat, 13 Jun 2026 19:41:20 +0300 Subject: [PATCH 1/2] K8SPG-1053 make PMM sidecar work with readOnlyRootFilesystem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pmm-agent config (pmm-agent.yaml) was written to the container root filesystem, so the sidecar failed on pods enforcing readOnlyRootFilesystem: true (e.g. OpenShift): Config file /usr/local/percona/pmm/config/pmm-agent.yaml is not writable: read-only file system. The config is stateless — pmm-agent regenerates it on every start (PMM_AGENT_SETUP_FORCE=1) — so from crVersion 3.1.0 relocate it to the writable /tmp/pmm path (inside the /tmp emptyDir already mounted into the sidecar) for both PMM2 and PMM3, and align the PMM2 tempdir to /tmp/pmm. Older crVersions keep the previous paths to avoid changing running pods. --- percona/pmm/pmm.go | 26 +++++++++++++++++++++++--- percona/pmm/pmm_test.go | 30 +++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index c4e6b9f4b..07b255b83 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -34,6 +34,26 @@ func Container(secret *corev1.Secret, pgc *v2.PerconaPGCluster) (corev1.Containe } // sidecarContainerV2 refers to the construction of the PMM2 container. +// pmmConfigFile returns the path for the stateless pmm-agent.yaml. From v3.1.0 +// it is placed in the writable "/tmp" emptyDir so PMM works with +// readOnlyRootFilesystem. +func pmmConfigFile(pgc *v2.PerconaPGCluster, isPMM3 bool) string { + if pgc.CompareVersion("3.1.0") >= 0 { + return "/tmp/pmm/pmm-agent.yaml" + } + if isPMM3 { + return "/usr/local/percona/pmm/config/pmm-agent.yaml" + } + return "/usr/local/percona/pmm2/config/pmm-agent.yaml" +} + +func pmmTempDir(pgc *v2.PerconaPGCluster) string { + if pgc.CompareVersion("3.1.0") >= 0 { + return "/tmp/pmm" + } + return "/tmp" +} + func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { ports := []corev1.ContainerPort{{ContainerPort: 7777}} @@ -131,7 +151,7 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_CONFIG_FILE", - Value: "/usr/local/percona/pmm2/config/pmm-agent.yaml", + Value: pmmConfigFile(pgc, false), }, { Name: "PMM_AGENT_LOG_LEVEL", @@ -206,7 +226,7 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_PATHS_TEMPDIR", - Value: "/tmp", + Value: pmmTempDir(pgc), }, } @@ -332,7 +352,7 @@ func sidecarContainerV3(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_CONFIG_FILE", - Value: "/usr/local/percona/pmm/config/pmm-agent.yaml", + Value: pmmConfigFile(pgc, true), }, { Name: "PMM_AGENT_LOG_LEVEL", diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index b0459f832..dfeca641a 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -141,6 +141,30 @@ func TestContainer(t *testing.T) { } +func TestPMMConfigFile(t *testing.T) { + newPGC := func(crVersion string) *v2.PerconaPGCluster { + return &v2.PerconaPGCluster{ + Spec: v2.PerconaPGClusterSpec{CRVersion: crVersion}, + } + } + + t.Run("v3.1.0 PMM2", func(t *testing.T) { + assert.Equal(t, "/tmp/pmm/pmm-agent.yaml", pmmConfigFile(newPGC("3.1.0"), false)) + }) + t.Run("v3.1.0 PMM3", func(t *testing.T) { + assert.Equal(t, "/tmp/pmm/pmm-agent.yaml", pmmConfigFile(newPGC("3.1.0"), true)) + }) + t.Run("newer than 3.1.0", func(t *testing.T) { + assert.Equal(t, "/tmp/pmm/pmm-agent.yaml", pmmConfigFile(newPGC("3.2.0"), true)) + }) + t.Run("older than 3.1.0 PMM2", func(t *testing.T) { + assert.Equal(t, "/usr/local/percona/pmm2/config/pmm-agent.yaml", pmmConfigFile(newPGC("3.0.0"), false)) + }) + t.Run("older than 3.1.0 PMM3", func(t *testing.T) { + assert.Equal(t, "/usr/local/percona/pmm/config/pmm-agent.yaml", pmmConfigFile(newPGC("3.0.0"), true)) + }) +} + func TestSidecarContainerV2(t *testing.T) { pmmSpec := &v2.PMMSpec{ Image: "percona/pmm-client:pmm2-enabled", @@ -200,7 +224,7 @@ func TestSidecarContainerV2(t *testing.T) { "PMM_AGENT_LISTEN_PORT": "7777", "PMM_AGENT_PORTS_MIN": "30100", "PMM_AGENT_PORTS_MAX": "30105", - "PMM_AGENT_CONFIG_FILE": "/usr/local/percona/pmm2/config/pmm-agent.yaml", + "PMM_AGENT_CONFIG_FILE": "/tmp/pmm/pmm-agent.yaml", "PMM_AGENT_LOG_LEVEL": "info", "PMM_AGENT_DEBUG": "false", "PMM_AGENT_TRACE": "false", @@ -217,7 +241,7 @@ func TestSidecarContainerV2(t *testing.T) { "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source=pgstatements --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", - "PMM_AGENT_PATHS_TEMPDIR": "/tmp", + "PMM_AGENT_PATHS_TEMPDIR": "/tmp/pmm", "PMM_AGENT_SETUP_PROC_MOUNTS_PATH": "/proc/self/mounts", } @@ -309,7 +333,7 @@ func TestSidecarContainerV3(t *testing.T) { "PMM_AGENT_LISTEN_PORT": "7777", "PMM_AGENT_PORTS_MIN": "30100", "PMM_AGENT_PORTS_MAX": "30105", - "PMM_AGENT_CONFIG_FILE": "/usr/local/percona/pmm/config/pmm-agent.yaml", + "PMM_AGENT_CONFIG_FILE": "/tmp/pmm/pmm-agent.yaml", "PMM_AGENT_LOG_LEVEL": "info", "PMM_AGENT_DEBUG": "false", "PMM_AGENT_TRACE": "false", From 808852d24744346fb954ff2f49f145d0e55f7f4b Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Thu, 18 Jun 2026 18:14:24 +0300 Subject: [PATCH 2/2] fix tests --- ...aml => 10-deleted-from-server-inventory.yaml} | 0 percona/pmm/pmm.go | 16 +++++----------- percona/pmm/pmm_test.go | 12 ++++++------ 3 files changed, 11 insertions(+), 17 deletions(-) rename e2e-tests/tests/monitoring/{09-deleted-from-server-inventory.yaml => 10-deleted-from-server-inventory.yaml} (100%) diff --git a/e2e-tests/tests/monitoring/09-deleted-from-server-inventory.yaml b/e2e-tests/tests/monitoring/10-deleted-from-server-inventory.yaml similarity index 100% rename from e2e-tests/tests/monitoring/09-deleted-from-server-inventory.yaml rename to e2e-tests/tests/monitoring/10-deleted-from-server-inventory.yaml diff --git a/percona/pmm/pmm.go b/percona/pmm/pmm.go index 07b255b83..5151479a7 100644 --- a/percona/pmm/pmm.go +++ b/percona/pmm/pmm.go @@ -35,11 +35,12 @@ func Container(secret *corev1.Secret, pgc *v2.PerconaPGCluster) (corev1.Containe // sidecarContainerV2 refers to the construction of the PMM2 container. // pmmConfigFile returns the path for the stateless pmm-agent.yaml. From v3.1.0 -// it is placed in the writable "/tmp" emptyDir so PMM works with -// readOnlyRootFilesystem. +// it is placed directly in the writable "/tmp" emptyDir (pmm-agent does not +// create the config's parent dir, so a subdirectory cannot be used) so PMM +// works with readOnlyRootFilesystem. func pmmConfigFile(pgc *v2.PerconaPGCluster, isPMM3 bool) string { if pgc.CompareVersion("3.1.0") >= 0 { - return "/tmp/pmm/pmm-agent.yaml" + return "/tmp/pmm-agent.yaml" } if isPMM3 { return "/usr/local/percona/pmm/config/pmm-agent.yaml" @@ -47,13 +48,6 @@ func pmmConfigFile(pgc *v2.PerconaPGCluster, isPMM3 bool) string { return "/usr/local/percona/pmm2/config/pmm-agent.yaml" } -func pmmTempDir(pgc *v2.PerconaPGCluster) string { - if pgc.CompareVersion("3.1.0") >= 0 { - return "/tmp/pmm" - } - return "/tmp" -} - func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { ports := []corev1.ContainerPort{{ContainerPort: 7777}} @@ -226,7 +220,7 @@ func sidecarContainerV2(pgc *v2.PerconaPGCluster) corev1.Container { }, { Name: "PMM_AGENT_PATHS_TEMPDIR", - Value: pmmTempDir(pgc), + Value: "/tmp", }, } diff --git a/percona/pmm/pmm_test.go b/percona/pmm/pmm_test.go index dfeca641a..5fbf6781a 100644 --- a/percona/pmm/pmm_test.go +++ b/percona/pmm/pmm_test.go @@ -149,13 +149,13 @@ func TestPMMConfigFile(t *testing.T) { } t.Run("v3.1.0 PMM2", func(t *testing.T) { - assert.Equal(t, "/tmp/pmm/pmm-agent.yaml", pmmConfigFile(newPGC("3.1.0"), false)) + assert.Equal(t, "/tmp/pmm-agent.yaml", pmmConfigFile(newPGC("3.1.0"), false)) }) t.Run("v3.1.0 PMM3", func(t *testing.T) { - assert.Equal(t, "/tmp/pmm/pmm-agent.yaml", pmmConfigFile(newPGC("3.1.0"), true)) + assert.Equal(t, "/tmp/pmm-agent.yaml", pmmConfigFile(newPGC("3.1.0"), true)) }) t.Run("newer than 3.1.0", func(t *testing.T) { - assert.Equal(t, "/tmp/pmm/pmm-agent.yaml", pmmConfigFile(newPGC("3.2.0"), true)) + assert.Equal(t, "/tmp/pmm-agent.yaml", pmmConfigFile(newPGC("3.2.0"), true)) }) t.Run("older than 3.1.0 PMM2", func(t *testing.T) { assert.Equal(t, "/usr/local/percona/pmm2/config/pmm-agent.yaml", pmmConfigFile(newPGC("3.0.0"), false)) @@ -224,7 +224,7 @@ func TestSidecarContainerV2(t *testing.T) { "PMM_AGENT_LISTEN_PORT": "7777", "PMM_AGENT_PORTS_MIN": "30100", "PMM_AGENT_PORTS_MAX": "30105", - "PMM_AGENT_CONFIG_FILE": "/tmp/pmm/pmm-agent.yaml", + "PMM_AGENT_CONFIG_FILE": "/tmp/pmm-agent.yaml", "PMM_AGENT_LOG_LEVEL": "info", "PMM_AGENT_DEBUG": "false", "PMM_AGENT_TRACE": "false", @@ -241,7 +241,7 @@ func TestSidecarContainerV2(t *testing.T) { "DB_USER": v2.UserMonitoring, "DB_PASS": "", // secret reference is asserted separately "PMM_AGENT_PRERUN_SCRIPT": "pmm-admin status --wait=10s; pmm-admin add postgresql --username=$(DB_USER) --password='$(DB_PASS)' --host=127.0.0.1 --port=5432 --tls-cert-file=/pgconf/tls/tls.crt --tls-key-file=/pgconf/tls/tls.key --tls-ca-file=/pgconf/tls/ca.crt --tls-skip-verify --skip-connection-check --metrics-mode=push --service-name=$(PMM_AGENT_SETUP_NODE_NAME) --query-source=pgstatements --cluster=test-cluster --environment=dev-postgres; pmm-admin annotate --service-name=$(PMM_AGENT_SETUP_NODE_NAME) 'Service restarted'", - "PMM_AGENT_PATHS_TEMPDIR": "/tmp/pmm", + "PMM_AGENT_PATHS_TEMPDIR": "/tmp", "PMM_AGENT_SETUP_PROC_MOUNTS_PATH": "/proc/self/mounts", } @@ -333,7 +333,7 @@ func TestSidecarContainerV3(t *testing.T) { "PMM_AGENT_LISTEN_PORT": "7777", "PMM_AGENT_PORTS_MIN": "30100", "PMM_AGENT_PORTS_MAX": "30105", - "PMM_AGENT_CONFIG_FILE": "/tmp/pmm/pmm-agent.yaml", + "PMM_AGENT_CONFIG_FILE": "/tmp/pmm-agent.yaml", "PMM_AGENT_LOG_LEVEL": "info", "PMM_AGENT_DEBUG": "false", "PMM_AGENT_TRACE": "false",