
Hello, Habr!
" ", Jenkins . Jenkins , Docker-, Docker- . Jenkins , Helm ( ).
:
Spring Boot, Docker
: Java 11, Spring Boot, Docker, image optimization
Kubernetes Google Kubernetes Engine
: Kubernetes, GKE, resource management, autoscaling, secrets
Helm 3
: Helm 3, chart deployment
Jenkins
: Jenkins configuration, plugins, separate configs repository
Jenkins β , Java. - . Groovy, (Jenkinsfile) . , , .
GitHub .
Jenkins
Jenkins:
War- (β Apache Tomcat). , .
, Jenkins Docker. Jenkins , . β ( ), 'docker:dind', Jenkins'.
Jenkins Kubernetes. Jenkins, . , . . Jenkins Google Kubernetes Engine .
, Jenkins Docker . , stateful Kubernetes. Jenkins Kubernetes.
, Jenkins . , , Google Compute Engine. , Jenkins Raspberry Pi, - "" Docker-. Raspberry Pi .
docker network create jenkins
docker volume create jenkins-docker-certs
docker volume create jenkins-data
docker container run \
--name jenkins-docker \
--detach \
--privileged \
--network jenkins \
--network-alias docker \
--env DOCKER_TLS_CERTDIR=/certs \
--volume jenkins-docker-certs:/certs/client \
--volume jenkins-data:/var/jenkins_home \
--publish 2376:2376 \
docker:dind
docker container run \
--name jenkins-blueocean \
--detach \
--network jenkins \
--env DOCKER_HOST=tcp://docker:2376 \
--env DOCKER_CERT_PATH=/certs/client \
--env DOCKER_TLS_VERIFY=1 \
--publish 8080:8080 \
--publish 50000:50000 \
--volume jenkins-data:/var/jenkins_home \
--volume jenkins-docker-certs:/certs/client:ro \
jenkinsci/blueocean
Jenkins http://localhost:8080/ . Jenkins UI, . " " (IaC). β Groovy. . .
(Manage Jenkins -> Manage Plugins). . 'Blue Ocean', .
: Remote File Plugin Kubernetes CLI. Remote File Plugin Jenkinsfile , Kubernetes CLI kubectl .
Helm
Helm-, Helm. Helm , . (docker exec -it jenkins-blueocean bash
), /usr/bin. Helm-:
helm repo add msvc-repo https://anshelen.imtqy.com/microservices-deploy/
helm repo update
, . , . , , Jenkins. , β .
(Manage Jenkins -> Configure System -> Global properties -> Environment Variables):
- CLUSTER_URL β - Kubernetes.
kubectl cluster-info
- CLUSTER_NAMESPACE β
- HELM_PROJECT β Helm
- HELM_CHART β Helm-. 'msvc-repo/msvc-chart'
Jenkins , , -, , . Credentials -> System -> Global credentials -> Add Credentials:
NOTES.txt . , Helm- (helm status msvc-project
).
, Groovy, . .
Jenkins () (stage). (agent).
:
- Build.
- Test. . , Maven
- Package. jar-
- Push Images. Docker- . β latest
- Trigger Kubernetes. Kubernetes Docker-

:
pipeline {
agent none
options { ... }
environment { ... }
stages {
stage("Prepare container") {
agent {
docker {
image 'openjdk:11.0.5-slim'
args '-v $HOME/.m2:/root/.m2'
}
}
stages {
stage('Build') { ... }
stage('Test') { ... }
stage('Package') { ... }
}
}
stage('Push images') {
agent any
when { branch 'master' }
steps { ... }
}
stage('Trigger kubernetes') {
agent any
when { branch 'master' }
steps { ... }
}
}
}
Jenkins "" β , . pipeline . , . pipeline 'none'. , - .
Build, Test Package Docker- . Docker- Java 11 (Jenkins Java 8). , 'Prepare container' 'docker'. args .m2 Jenkins'. .m2 Maven, , .
Push Images Trigger Kubernetes 'any'. , . Jenkins'. - (when { branch 'master' }
).
, options environment.
options {
skipStagesAfterUnstable()
skipDefaultCheckout()
}
. :
skipStagesAfterUnstable Jenkins , e . UNSTABLE . .
skipDefaultCheckout . Jenkins force ( Prepare Checkout, Push images Trigger Kubernetes). . . β Build. skipDefaultCheckout, . , Jenkins . , , Build Test.
environment {
IMAGE_BASE = 'anshelen/microservices-backend'
IMAGE_TAG = "v$BUILD_NUMBER"
IMAGE_NAME = "${env.IMAGE_BASE}:${env.IMAGE_TAG}"
IMAGE_NAME_LATEST = "${env.IMAGE_BASE}:latest"
DOCKERFILE_NAME = "Dockerfile-packaged"
}
, . , - . Docker-.
latest , , - . , , . IMAGE_TAG , BUILD_NUMBER. , ( ). BUILD_NUMBER , "". β . , .
, ,
stage("Prepare container") {
agent {
docker {
image 'openjdk:11.0.5-slim'
args '-v $HOME/.m2:/root/.m2'
}
}
stages {
stage('Build') {
steps {
checkout scm
sh './mvnw compile'
}
}
stage('Test') {
steps {
sh './mvnw test'
junit '**/target/surefire-reports/TEST-*.xml'
}
}
stage('Package') {
steps {
sh './mvnw package -DskipTests'
}
}
}
}
, , . Maven , .
checkout scm
. , Jenkins. bash- .
junit '**/target/surefire-reports/TEST-*.xml'
Jenkins' . -.
jar- .
Docker-
Docker- . Jenkins, Maven-.
- , . - . , Jenkins. Dockerfile-packaged.
DockerfileFROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine as builder
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests
FROM alpine:3.10.3 as packager
RUN apk --no-cache add openjdk11-jdk openjdk11-jmods
ENV JAVA_MINIMAL="/opt/java-minimal"
# build minimal JRE
RUN /usr/lib/jvm/java-11-openjdk/bin/jlink \
--verbose \
--add-modules \
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
--compress 2 --strip-debug --no-header-files --no-man-pages \
--release-info="add:IMPLEMENTOR=radistao:IMPLEMENTOR_VERSION=radistao_JRE" \
--output "$JAVA_MINIMAL"
FROM alpine:3.10.3
LABEL maintainer="Anton Shelenkov anshelen@yandex.ru"
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY --from=builder /src/target/microservices-backend-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
Dockerfile-packaged:
FROM alpine:3.10.3 as packager
RUN apk --no-cache add openjdk11-jdk openjdk11-jmods
ENV JAVA_MINIMAL="/opt/java-minimal"
# build minimal JRE
RUN /usr/lib/jvm/java-11-openjdk/bin/jlink \
--verbose \
--add-modules \
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
--compress 2 --strip-debug --no-header-files --no-man-pages \
--release-info="add:IMPLEMENTOR=radistao:IMPLEMENTOR_VERSION=radistao_JRE" \
--output "$JAVA_MINIMAL"
FROM alpine:3.10.3
LABEL maintainer="Anton Shelenkov anshelen@yandex.ru"
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY /target/microservices-backend-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
- .
Push Images:
stage('Push images') {
agent any
when {
branch 'master'
}
steps {
script {
def dockerImage = docker.build("${env.IMAGE_NAME}", "-f ${env.DOCKERFILE_NAME} .")
docker.withRegistry('', 'dockerhub-creds') {
dockerImage.push()
dockerImage.push("latest")
}
echo "Pushed Docker Image: ${env.IMAGE_NAME}"
}
sh "docker rmi ${env.IMAGE_NAME} ${env.IMAGE_NAME_LATEST}"
}
}
Jenkins , . Jenkins , script
.
docker.build
. ( ) ${env.IMAGE_NAME}
. docker.build
, -.
docker.withRegistry('', 'dockerhub-creds')
, 'dockerhub-creds'. , 'latest'. echo
.
.
Kubernetes
Kubernetes, , .
stage('Trigger kubernetes') {
agent any
when {
branch 'master'
}
steps {
withKubeConfig([credentialsId: 'kubernetes-creds', serverUrl: "${CLUSTER_URL}", namespace: "${CLUSTER_NAMESPACE}"]) {
sh "helm upgrade ${HELM_PROJECT} ${HELM_CHART} --reuse-values --set backend.image.tag=${env.IMAGE_TAG}"
}
}
}
withKubeConfig
Kubernetes CLI kubectl . Helm-. Jenkins, , , ${CLUSTER_URL}
.
Jenkinsfile
Jenkins-backendpipeline {
agent none
options {
skipStagesAfterUnstable()
skipDefaultCheckout()
}
environment {
IMAGE_BASE = 'anshelen/microservices-backend'
IMAGE_TAG = "v$BUILD_NUMBER"
IMAGE_NAME = "${env.IMAGE_BASE}:${env.IMAGE_TAG}"
IMAGE_NAME_LATEST = "${env.IMAGE_BASE}:latest"
DOCKERFILE_NAME = "Dockerfile-packaged"
}
stages {
stage("Prepare container") {
agent {
docker {
image 'openjdk:11.0.5-slim'
args '-v $HOME/.m2:/root/.m2'
}
}
stages {
stage('Build') {
steps {
checkout scm
sh './mvnw compile'
}
}
stage('Test') {
steps {
sh './mvnw test'
junit '**/target/surefire-reports/TEST-*.xml'
}
}
stage('Package') {
steps {
sh './mvnw package -DskipTests'
}
}
}
}
stage('Push images') {
agent any
when {
branch 'master'
}
steps {
script {
def dockerImage = docker.build("${env.IMAGE_NAME}", "-f ${env.DOCKERFILE_NAME} .")
docker.withRegistry('', 'dockerhub-creds') {
dockerImage.push()
dockerImage.push("latest")
}
echo "Pushed Docker Image: ${env.IMAGE_NAME}"
}
sh "docker rmi ${env.IMAGE_NAME} ${env.IMAGE_NAME_LATEST}"
}
}
stage('Trigger kubernetes') {
agent any
when {
branch 'master'
}
steps {
withKubeConfig([credentialsId: 'kubernetes-creds', serverUrl: "${CLUSTER_URL}", namespace: "${CLUSTER_NAMESPACE}"]) {
sh "helm upgrade ${HELM_PROJECT} ${HELM_CHART} --reuse-values --set backend.image.tag=${env.IMAGE_TAG}"
}
}
}
}
}
Jenkinsfile .
Jenkins . Multibranch pipeline. , .
, Jenkins. New Item -> Multibranch Pipeline. :
Branch sources. GitHub, 'Credentials' / URL .
Build Configuration. Mode 'by Remote File Plugin', β Repository URL, Jenkinsfile, Script Path .

Scan Repository Triggers. , Jenkins , - . , Jenkins , . β -. . , , Jenkins ( , Jenkins IP-). - .
, . Blue Ocean (Open Blue Ocean). , Maven-. , (helm get values msvc-project
).
Jenkins .
Jenkins is a very flexible system that allows implementing the process of continuous integration and deployment of any complexity. In this article, we just touched on this tool, creating a simple pipeline for microservices of our project. In the future, this pipeline can be significantly improved and improved, for example, by adding notifications, additional steps, web hooks and much, much more.