From 1faf19581d2e0378e56e82775ef7d960cca197fc Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sat, 29 Nov 2025 21:45:08 +0200 Subject: [PATCH 1/3] K8SPSMDB-1528 Create multi-architecture Docker image for Fluent Bit --- cloud/jenkins/fluentbit_docker_build.groovy | 27 ++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/cloud/jenkins/fluentbit_docker_build.groovy b/cloud/jenkins/fluentbit_docker_build.groovy index f9193d101d..7a14bb04de 100644 --- a/cloud/jenkins/fluentbit_docker_build.groovy +++ b/cloud/jenkins/fluentbit_docker_build.groovy @@ -1,9 +1,13 @@ void build(String IMAGE_PREFIX){ - sh """ - cd ./source/ - docker build --no-cache --squash -t perconalab/percona-xtradb-cluster-operator:${GIT_PD_BRANCH}-${IMAGE_PREFIX} -f fluentbit/Dockerfile fluentbit - docker tag perconalab/percona-xtradb-cluster-operator:${GIT_PD_BRANCH}-${IMAGE_PREFIX} perconalab/fluentbit:${GIT_PD_BRANCH}-${IMAGE_PREFIX} - """ + withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), file(credentialsId: 'DOCKER_REPO_KEY', variable: 'docker_key')]) { + sh """ + cd ./source/ + docker login -u '${USER}' -p '${PASS}' + docker buildx create --use + docker buildx build --platform linux/amd64,linux/arm64 --progress plain -t perconalab/fluentbit:${GIT_PD_BRANCH}-${IMAGE_PREFIX} --push -f fluentbit/Dockerfile fluentbit + docker logout + """ + } } void checkImageForDocker(String IMAGE_PREFIX){ withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER')]) { @@ -19,6 +23,7 @@ void checkImageForDocker(String IMAGE_PREFIX){ """ } } + void pushImageToDocker(String IMAGE_PREFIX){ withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), file(credentialsId: 'DOCKER_REPO_KEY', variable: 'docker_key')]) { sh """ @@ -81,7 +86,7 @@ pipeline { stash includes: "cloud/**", name: "cloud" } } - stage('Build fluentbit docker images') { + stage('Build and push fluentbit docker images') { steps { sh ''' sudo rm -rf cloud @@ -98,11 +103,11 @@ pipeline { } } } - stage('Push Images to Docker registry') { - steps { - pushImageToDocker('logcollector') - } - } +// stage('Push Images to Docker registry') { +// steps { +// pushImageToDocker('logcollector') +// } +// } stage('Trivy Checks') { steps { checkImageForDocker('logcollector') From bfb606e89dc1644f831812d52e8a60b91ba3ef47 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sat, 29 Nov 2025 22:22:13 +0200 Subject: [PATCH 2/3] use snyk --- cloud/jenkins/fluentbit_docker_build.groovy | 101 +++++++++++++------- 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/cloud/jenkins/fluentbit_docker_build.groovy b/cloud/jenkins/fluentbit_docker_build.groovy index 7a14bb04de..42eee64e7b 100644 --- a/cloud/jenkins/fluentbit_docker_build.groovy +++ b/cloud/jenkins/fluentbit_docker_build.groovy @@ -1,3 +1,49 @@ +void checkImageForDocker(String IMAGE_SUFFIX){ + try { + withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), string(credentialsId: 'SNYK_ID', variable: 'SNYK_ID')]) { + sh """ + IMAGE_TAG=\$(echo ${IMAGE_SUFFIX} | sed 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]') + IMAGE_NAME="fluentbit" + PATH_TO_DOCKERFILE="/source/build/fluentbit" + + sg docker -c " + set -e + docker login -u '${USER}' -p '${PASS}' + + snyk container test --platform=linux/amd64 --exclude-base-image-vulns --file=./\${PATH_TO_DOCKERFILE}/Dockerfile \ + --severity-threshold=high --json-file-output=\${IMAGE_TAG}-report.json perconalab/\$IMAGE_NAME:\${IMAGE_TAG} + " + """ + } + } catch (Exception e) { + echo "Stage failed: ${e.getMessage()}" + sh """ + exit 1 + """ + } finally { + echo "Executing post actions..." + sh """ + IMAGE_TAG=\$(echo ${IMAGE_SUFFIX} | sed 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]') + snyk-to-html -i \${IMAGE_TAG}-report.json -o \${IMAGE_TAG}-report.html + """ + archiveArtifacts artifacts: '*.html', allowEmptyArchive: true + } +} + +void generateImageSummary(filePath) { + def images = readFile(filePath).trim().split("\n") + + def report = "

Image Summary Report

\n" + report += "

Total Images: ${images.size()}

\n" + report += "\n" + return report +} void build(String IMAGE_PREFIX){ withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), file(credentialsId: 'DOCKER_REPO_KEY', variable: 'docker_key')]) { sh """ @@ -9,20 +55,6 @@ void build(String IMAGE_PREFIX){ """ } } -void checkImageForDocker(String IMAGE_PREFIX){ - withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER')]) { - sh """ - IMAGE_PREFIX=${IMAGE_PREFIX} - IMAGE_NAME='percona-xtradb-cluster-operator' - TrivyLog="$WORKSPACE/trivy-hight-\$IMAGE_NAME-${IMAGE_PREFIX}.xml" - - sg docker -c " - docker login -u '${USER}' -p '${PASS}' - /usr/local/bin/trivy -q --cache-dir /mnt/jenkins/trivy-${JOB_NAME}/ image --format template --template @/tmp/junit.tpl -o \$TrivyLog --ignore-unfixed --timeout 10m --exit-code 0 --severity HIGH,CRITICAL perconalab/\$IMAGE_NAME:${GIT_PD_BRANCH}-${IMAGE_PREFIX} - " - """ - } -} void pushImageToDocker(String IMAGE_PREFIX){ withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), file(credentialsId: 'DOCKER_REPO_KEY', variable: 'docker_key')]) { @@ -57,6 +89,8 @@ pipeline { label 'docker' } environment { + PATH = "${WORKSPACE}/node_modules/.bin:$PATH" // Add local npm bin to PATH + SNYK_TOKEN=credentials('SNYK_ID') DOCKER_REPOSITORY_PASSPHRASE = credentials('DOCKER_REPOSITORY_PASSPHRASE') } options { @@ -69,13 +103,10 @@ pipeline { steps { git branch: 'master', url: 'https://github.com/Percona-Lab/jenkins-pipelines' sh """ - TRIVY_VERSION=\$(curl --silent 'https://api.github.com/repos/aquasecurity/trivy/releases/latest' | grep '"tag_name":' | tr -d '"' | sed -E 's/.*v(.+),.*/\\1/') - wget https://github.com/aquasecurity/trivy/releases/download/v\${TRIVY_VERSION}/trivy_\${TRIVY_VERSION}_Linux-64bit.tar.gz - sudo tar zxvf trivy_\${TRIVY_VERSION}_Linux-64bit.tar.gz -C /usr/local/bin/ - - if [ ! -f junit.tpl ]; then - wget --directory-prefix=/tmp https://raw.githubusercontent.com/aquasecurity/trivy/v\${TRIVY_VERSION}/contrib/junit.tpl - fi + curl -sL https://static.snyk.io/cli/latest/snyk-linux -o snyk + chmod +x snyk + sudo mv ./snyk /usr/local/bin/ + sudo npm install snyk-to-html -g # sudo is needed for better node recovery after compilation failure # if building failed on compilation stage directory will have files owned by docker user @@ -103,25 +134,27 @@ pipeline { } } } -// stage('Push Images to Docker registry') { -// steps { -// pushImageToDocker('logcollector') -// } -// } - stage('Trivy Checks') { + stage('Snyk CVEs Checks') { steps { - checkImageForDocker('logcollector') - } - post { - always { - junit allowEmptyResults: true, skipPublishingChecks: true, testResults: "*-logcollector.xml" - } + checkImageForDocker('\$GIT_BRANCH') } } } post { always { - archiveArtifacts artifacts: '*.pdf', allowEmptyArchive: true + script { + if (fileExists('./source/list-of-images.txt')) { + def summary = generateImageSummary('./source/list-of-images.txt') + + addSummary(icon: 'symbol-aperture-outline plugin-ionicons-api', + text: "
${summary}
" + ) + // Also save as a file if needed + writeFile(file: 'image-summary.html', text: summary) + } else { + echo 'No ./source/list-of-images.txt file found - skipping summary generation' + } + } sh ''' sudo docker rmi -f \$(sudo docker images -q) || true ''' From 25f2ef70582829966822d18b83d2b28fe7185350 Mon Sep 17 00:00:00 2001 From: Viacheslav Sarzhan Date: Sat, 29 Nov 2025 22:40:30 +0200 Subject: [PATCH 3/3] use docker-x64 --- cloud/jenkins/fluentbit_docker_build.groovy | 27 ++++----------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/cloud/jenkins/fluentbit_docker_build.groovy b/cloud/jenkins/fluentbit_docker_build.groovy index 42eee64e7b..cb14fa7e10 100644 --- a/cloud/jenkins/fluentbit_docker_build.groovy +++ b/cloud/jenkins/fluentbit_docker_build.groovy @@ -2,9 +2,10 @@ void checkImageForDocker(String IMAGE_SUFFIX){ try { withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), string(credentialsId: 'SNYK_ID', variable: 'SNYK_ID')]) { sh """ - IMAGE_TAG=\$(echo ${IMAGE_SUFFIX} | sed 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]') + IMAGE_SUFFIX=${IMAGE_SUFFIX} IMAGE_NAME="fluentbit" - PATH_TO_DOCKERFILE="/source/build/fluentbit" + IMAGE_TAG="\${GIT_PD_BRANCH}-\${IMAGE_SUFFIX}" + PATH_TO_DOCKERFILE="source/fluentbit" sg docker -c " set -e @@ -56,24 +57,6 @@ void build(String IMAGE_PREFIX){ } } -void pushImageToDocker(String IMAGE_PREFIX){ - withCredentials([usernamePassword(credentialsId: 'hub.docker.com', passwordVariable: 'PASS', usernameVariable: 'USER'), file(credentialsId: 'DOCKER_REPO_KEY', variable: 'docker_key')]) { - sh """ - IMAGE_PREFIX=${IMAGE_PREFIX} - sg docker -c " - if [ ! -d ~/.docker/trust/private ]; then - mkdir -p /home/ec2-user/.docker/trust/private - cp "${docker_key}" ~/.docker/trust/private/ - fi - - docker login -u '${USER}' -p '${PASS}' - docker push perconalab/percona-xtradb-cluster-operator:${GIT_PD_BRANCH}-${IMAGE_PREFIX} - docker push perconalab/fluentbit:${GIT_PD_BRANCH}-${IMAGE_PREFIX} - docker logout - " - """ - } -} pipeline { parameters { string( @@ -86,7 +69,7 @@ pipeline { name: 'GIT_PD_REPO') } agent { - label 'docker' + label 'docker-x64' } environment { PATH = "${WORKSPACE}/node_modules/.bin:$PATH" // Add local npm bin to PATH @@ -136,7 +119,7 @@ pipeline { } stage('Snyk CVEs Checks') { steps { - checkImageForDocker('\$GIT_BRANCH') + checkImageForDocker('logcollector') } } }