mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-03-09 12:12:21 +01:00
fix: resolve WAL archiving performance and memory issues (#746)
The barman-cloud plugin experienced significant performance degradation and memory growth compared to the embedded solution. WAL archiving was noticeably slower and memory consumption grew over time. Root cause: The sidecar uses a read-only filesystem which prevents Python from creating bytecode at runtime. When Python finds missing or stale bytecode (.pyc files), it attempts to recompile on every invocation, causing high CPU usage and memory consumption. The previous approach pre-compiled bytecode in a separate base image, but the bytecode was marked as stale when copied between Docker stages, triggering runtime recompilation attempts. This change eliminates bytecode staleness by ensuring all Python bytecode is properly compiled in the final image before the sidecar starts. The image is now fully distroless and based on trixie (previously it was distroless-based but copied unnecessary files from the build stage), reducing size from 463MB to 270MB and package count from 188 to 35, while maintaining zero HIGH/CRITICAL vulnerabilities. Closes #656 Closes #711 Closes #735 Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
This commit is contained in:
parent
064eac2199
commit
378c76a526
38
.github/workflows/barman-base-image.yml
vendored
38
.github/workflows/barman-base-image.yml
vendored
@ -1,38 +0,0 @@
|
|||||||
name: Barman Base Image
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * 0"
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- 'containers/sidecar-requirements.txt'
|
|
||||||
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
packages: write
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Install QEMU static binaries
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
- name: Install Task
|
|
||||||
uses: arduino/setup-task@v2
|
|
||||||
- name: Install Dagger
|
|
||||||
env:
|
|
||||||
# renovate: datasource=github-tags depName=dagger/dagger versioning=semver
|
|
||||||
DAGGER_VERSION: 0.19.10
|
|
||||||
run: |
|
|
||||||
curl -L https://dl.dagger.io/dagger/install.sh | BIN_DIR=$HOME/.local/bin sh
|
|
||||||
- name: Publish a barman-base
|
|
||||||
env:
|
|
||||||
REGISTRY_USER: ${{ github.actor }}
|
|
||||||
REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
task publish-barman-base
|
|
||||||
28
Taskfile.yml
28
Taskfile.yml
@ -381,34 +381,6 @@ tasks:
|
|||||||
build --dir . --file containers/Dockerfile.sidecar --platform linux/amd64 --platform linux/arm64
|
build --dir . --file containers/Dockerfile.sidecar --platform linux/amd64 --platform linux/arm64
|
||||||
publish --ref {{.SIDECAR_IMAGE_NAME}} --tags {{.IMAGE_VERSION}}
|
publish --ref {{.SIDECAR_IMAGE_NAME}} --tags {{.IMAGE_VERSION}}
|
||||||
|
|
||||||
publish-barman-base:
|
|
||||||
desc: Build and publish a barman-cloud base container image
|
|
||||||
vars:
|
|
||||||
BARMAN_BASE_IMAGE_NAME: ghcr.io/{{.GITHUB_REPOSITORY}}-base{{if not (hasPrefix "refs/heads/main" .GITHUB_REF)}}-testing{{end}}
|
|
||||||
BARMAN_VERSION:
|
|
||||||
sh: grep "^barman" containers/sidecar-requirements.in | sed -E 's/.*==([^ ]+)/\1/'
|
|
||||||
BUILD_DATE:
|
|
||||||
sh: date +"%Y%m%d%H%M"
|
|
||||||
requires:
|
|
||||||
# We expect this to run in a GitHub workflow, so we put a few GitHub-specific vars here
|
|
||||||
# to prevent running this task locally by accident.
|
|
||||||
vars:
|
|
||||||
- CI
|
|
||||||
- GITHUB_REPOSITORY
|
|
||||||
- GITHUB_REF
|
|
||||||
- GITHUB_REF_NAME
|
|
||||||
- REGISTRY_USER
|
|
||||||
- REGISTRY_PASSWORD
|
|
||||||
env:
|
|
||||||
# renovate: datasource=git-refs depName=docker lookupName=https://github.com/purpleclay/daggerverse currentValue=main
|
|
||||||
DAGGER_DOCKER_SHA: ee12c1a4a2630e194ec20c5a9959183e3a78c192
|
|
||||||
cmds:
|
|
||||||
- >
|
|
||||||
dagger call -m github.com/purpleclay/daggerverse/docker@${DAGGER_DOCKER_SHA}
|
|
||||||
--registry ghcr.io --username $REGISTRY_USER --password env:REGISTRY_PASSWORD
|
|
||||||
build --dir . --file containers/Dockerfile.barmanbase --platform linux/amd64 --platform linux/arm64
|
|
||||||
publish --ref {{.BARMAN_BASE_IMAGE_NAME}} --tags "{{.BARMAN_VERSION}}-{{.BUILD_DATE}}"
|
|
||||||
|
|
||||||
controller-gen:
|
controller-gen:
|
||||||
desc: Run controller-gen
|
desc: Run controller-gen
|
||||||
run: once
|
run: once
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
FROM python:3.13-slim-bookworm
|
|
||||||
COPY containers/sidecar-requirements.txt .
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y postgresql-common build-essential && \
|
|
||||||
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y && \
|
|
||||||
apt-get install -y libpq-dev && \
|
|
||||||
pip install -r sidecar-requirements.txt
|
|
||||||
@ -10,7 +10,7 @@ ARG TARGETOS
|
|||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
# Copy the Go Modules manifests
|
|
||||||
COPY ../go.mod go.mod
|
COPY ../go.mod go.mod
|
||||||
COPY ../go.sum go.sum
|
COPY ../go.sum go.sum
|
||||||
# cache deps before building and copying source so that we don't need to re-download as much
|
# cache deps before building and copying source so that we don't need to re-download as much
|
||||||
@ -20,35 +20,73 @@ RUN go mod download
|
|||||||
ENV GOCACHE=/root/.cache/go-build
|
ENV GOCACHE=/root/.cache/go-build
|
||||||
ENV GOMODCACHE=/go/pkg/mod
|
ENV GOMODCACHE=/go/pkg/mod
|
||||||
|
|
||||||
# Copy the go source
|
|
||||||
COPY ../cmd/manager/main.go cmd/manager/main.go
|
COPY ../cmd/manager/main.go cmd/manager/main.go
|
||||||
COPY ../api/ api/
|
COPY ../api/ api/
|
||||||
COPY ../internal/ internal/
|
COPY ../internal/ internal/
|
||||||
|
|
||||||
# Build
|
# Build Go binary for target platform (TARGETOS/TARGETARCH)
|
||||||
# the GOARCH has not a default value to allow the binary be built according to the host where the command
|
# Docker BuildKit sets these based on --platform flag or defaults to the build host platform
|
||||||
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
|
|
||||||
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
|
|
||||||
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
|
|
||||||
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \
|
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build \
|
||||||
CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/manager/main.go
|
CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/manager/main.go
|
||||||
|
|
||||||
# Use plugin-barman-cloud-base to get the dependencies.
|
# Build Python virtualenv with all dependencies
|
||||||
# pip will build everything inside /usr, so we copy every file into a new
|
FROM debian:trixie-slim AS pythonbuilder
|
||||||
# destination that will then be copied into the distroless container
|
WORKDIR /build
|
||||||
FROM ghcr.io/cloudnative-pg/plugin-barman-cloud-base:3.17.0-202601131704 AS pythonbuilder
|
|
||||||
# Prepare a new /usr/ directory with the files we'll need in the final image
|
|
||||||
RUN mkdir /new-usr/ && \
|
|
||||||
cp -r --parents /usr/local/lib/ /usr/lib/*-linux-gnu/ /usr/local/bin/ \
|
|
||||||
/new-usr/
|
|
||||||
|
|
||||||
# Joint process
|
# Install postgresql-common and setup pgdg repository first
|
||||||
# Now we put everything that was build from the origin into our
|
RUN apt-get update && \
|
||||||
# distroless container
|
apt-get install -y --no-install-recommends postgresql-common && \
|
||||||
FROM gcr.io/distroless/python3-debian12:nonroot
|
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
python3 \
|
||||||
|
python3-venv \
|
||||||
|
python3-dev \
|
||||||
|
build-essential \
|
||||||
|
libpq-dev \
|
||||||
|
liblz4-dev \
|
||||||
|
libsnappy-dev
|
||||||
|
|
||||||
|
COPY containers/sidecar-requirements.txt .
|
||||||
|
|
||||||
|
# Create virtualenv and install dependencies
|
||||||
|
RUN python3 -m venv /venv && \
|
||||||
|
/venv/bin/pip install --upgrade pip setuptools wheel && \
|
||||||
|
/venv/bin/pip install --no-cache-dir -r sidecar-requirements.txt
|
||||||
|
|
||||||
|
# Download and extract runtime library packages and their dependencies
|
||||||
|
# Using apt-cache to automatically resolve dependencies, filtering out packages
|
||||||
|
# already present in the distroless base image.
|
||||||
|
# Distroless package list from: https://github.com/GoogleContainerTools/distroless/blob/main/base/config.bzl
|
||||||
|
# and https://github.com/GoogleContainerTools/distroless/blob/main/python3/config.bzl
|
||||||
|
RUN mkdir -p /dependencies /build/downloads && \
|
||||||
|
cd /build/downloads && \
|
||||||
|
DISTROLESS_PACKAGES="libc6 libssl3t64 libzstd1 zlib1g libgcc-s1 libstdc++6 \
|
||||||
|
libbz2-1.0 libdb5.3t64 libexpat1 liblzma5 libsqlite3-0 libuuid1 \
|
||||||
|
libncursesw6 libtinfo6 libcom-err2 libcrypt1 libgssapi-krb5-2 \
|
||||||
|
libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libnsl2 \
|
||||||
|
libreadline8t64 libtirpc3t64 libffi8 libpython3.13-minimal \
|
||||||
|
libpython3.13-stdlib python3.13-minimal python3.13-venv" && \
|
||||||
|
apt-cache depends --recurse --no-recommends --no-suggests \
|
||||||
|
--no-conflicts --no-breaks --no-replaces --no-enhances \
|
||||||
|
$DISTROLESS_PACKAGES 2>/dev/null | grep "^\w" | sort -u > /tmp/distroless.txt && \
|
||||||
|
apt-cache depends --recurse --no-recommends --no-suggests \
|
||||||
|
--no-conflicts --no-breaks --no-replaces --no-enhances \
|
||||||
|
libpq5 liblz4-1 libsnappy1v5 2>/dev/null | grep "^\w" | sort -u | \
|
||||||
|
grep -v -F -x -f /tmp/distroless.txt > /tmp/packages.txt && \
|
||||||
|
apt-get download $(cat /tmp/packages.txt) && \
|
||||||
|
for deb in *.deb; do \
|
||||||
|
dpkg -x "$deb" /dependencies; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# Final sidecar image using distroless base for minimal size and fewer packages
|
||||||
|
FROM gcr.io/distroless/python3-debian13:nonroot
|
||||||
|
|
||||||
ENV SUMMARY="CloudNativePG Barman plugin" \
|
ENV SUMMARY="CloudNativePG Barman plugin" \
|
||||||
DESCRIPTION="Container image that provides the barman-cloud sidecar"
|
DESCRIPTION="Container image that provides the barman-cloud sidecar" \
|
||||||
|
PATH="/venv/bin:$PATH"
|
||||||
|
|
||||||
LABEL summary="$SUMMARY" \
|
LABEL summary="$SUMMARY" \
|
||||||
description="$DESCRIPTION" \
|
description="$DESCRIPTION" \
|
||||||
@ -60,7 +98,13 @@ LABEL summary="$SUMMARY" \
|
|||||||
version="" \
|
version="" \
|
||||||
release="1"
|
release="1"
|
||||||
|
|
||||||
COPY --from=pythonbuilder /new-usr/* /usr/
|
COPY --from=pythonbuilder /venv /venv
|
||||||
|
COPY --from=pythonbuilder /dependencies/usr/lib /usr/lib
|
||||||
COPY --from=gobuilder /workspace/manager /manager
|
COPY --from=gobuilder /workspace/manager /manager
|
||||||
|
|
||||||
|
# Compile all Python bytecode as root to avoid runtime compilation
|
||||||
|
USER 0:0
|
||||||
|
RUN ["/venv/bin/python3", "-c", "import sysconfig, compileall; compileall.compile_dir(sysconfig.get_path('stdlib'), quiet=1); compileall.compile_dir('/venv', quiet=1)"]
|
||||||
|
|
||||||
USER 26:26
|
USER 26:26
|
||||||
ENTRYPOINT ["/manager"]
|
ENTRYPOINT ["/manager"]
|
||||||
|
|||||||
@ -79,12 +79,6 @@
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
packageRules: [
|
packageRules: [
|
||||||
{
|
|
||||||
matchPackageNames: [
|
|
||||||
'ghcr.io/cloudnative-pg/plugin-barman-cloud-base',
|
|
||||||
],
|
|
||||||
versioning: 'loose',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
matchDatasources: [
|
matchDatasources: [
|
||||||
'go',
|
'go',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user