Jenkins — старый, но по-прежнему живой и очень гибкий инструмент для CI/CD. Написан на Java, ставится куда угодно и умеет собирать, тестировать и деплоить практически всё, что вы ему скормите. Главный плюс — расширяемость: pipeline-as-code через Jenkinsfile, куча плагинов, агенты, интеграции с Git, Docker, Kubernetes, Slack и ещё пол-интернета.
Что умеет Jenkins #
- Pipeline-as-Code: описание пайплайна в репозитории, в одном или нескольких Jenkinsfile — декларативный или скриптовый стиль на Groovy.
- Интеграции: системы контроля версий (Git, GitHub, GitLab, Bitbucket), облака (AWS, GCP, Azure), контейнеры (Docker, Kubernetes), нотификации (Slack, Email, Mattermost) и т.д.
- Автоматизация всего конвейера: от юнит-тестов и сборки артефактов до статического анализа и деплоя.
- Плагины: тысячи расширений — от простых уведомлений до интеграции с Helm, Terraform, CDK и прочими штуками.
- Параллельные и распределённые сборки: мастер раздаёт задачи агентам, можно масштабироваться горизонтально.
- Гибкая конфигурация: через веб-интерфейс, REST API, Groovy-скрипты или подход Jenkins Configuration as Code (JCasC).
Пример декларативного Jenkinsfile #
pipeline {
agent any
environment {
IMAGE_TAG = "${env.BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
git 'https://github.com/my-org/my-app.git'
}
}
stage('Test') {
steps {
sh 'npm ci && npm test'
}
}
stage('Build Docker Image') {
steps {
sh "docker build -t my-app:${IMAGE_TAG} ."
}
}
stage('Push to Registry') {
steps {
withCredentials([usernamePassword(credentialsId: 'docker-creds', passwordVariable: 'PASS', usernameVariable: 'USER')]) {
sh "echo $PASS | docker login -u $USER --password-stdin"
sh "docker push my-app:${IMAGE_TAG}"
}
}
}
}
}
По сути, тут стандартная цепочка: забрали код, прогнали тесты, собрали Docker-образ и запушили его в реестр.
Где обычно крутят Jenkins #
- На физических/виртуальных серверах под Linux, Windows или macOS.
- В Kubernetes — через оператор или Helm-чарт, с агентами в виде pod'ов.
- В облаках — на VM в AWS, GCP, Azure, либо поверх решений вроде Jenkins X.
- На агентах с Docker-in-Docker, если нужна жёсткая изоляция джоб.
Почему его до сих пор используют #
- Очень высокая гибкость: можно собрать довольно извращённые пайплайны, если это того требует проект.
- Огромная экосистема плагинов на все случаи жизни.
- Всё работает в вашей инфраструктуре: никакой завязки на чужой SaaS, что важно для компаний с жёсткими требованиями.
- Поддерживаются GitOps-подходы, multibranch-пайплайны, триггеры по webhook, cron и куча других сценариев.
В итоге Jenkins остаётся таким «швейцарским ножом» для DevOps-инфраструктуры, особенно там, где нужно много кастомизаций и полный контроль.
Jenkinsfile с деплоем в Kubernetes через Helm #
pipeline {
agent any
environment {
CHART_DIR = 'helm/my-app'
IMAGE_TAG = "${env.BUILD_NUMBER}"
RELEASE_NAME = "my-app-prod"
KUBE_CONTEXT = "kubernetes-context"
}
stages {
stage('Checkout') {
steps {
git 'https://github.com/my-org/my-app.git'
}
}
stage('Build and Push Docker') {
steps {
sh """
docker build -t ghcr.io/my-org/my-app:${IMAGE_TAG} .
echo "${DOCKER_TOKEN}" | docker login ghcr.io -u "${DOCKER_USER}" --password-stdin
docker push ghcr.io/my-org/my-app:${IMAGE_TAG}
"""
}
}
stage('Helm Deploy to Kubernetes') {
steps {
withKubeConfig([credentialsId: 'kubeconfig-credentials']) {
sh """
helm upgrade --install ${RELEASE_NAME} ${CHART_DIR}
--namespace production
--set image.repository=ghcr.io/my-org/my-app
--set image.tag=${IMAGE_TAG}
"""
}
}
}
}
}
Здесь Jenkins делает всё по цепочке: клонирует проект, билдит образ, отправляет его в реестр и раскатывает релиз в Kubernetes через Helm.
Пример JCasC-конфига (jenkins.yaml) #
jenkins:
systemMessage: "Jenkins — CI/CD via as-code"
numExecutors: 2
mode: NORMAL
securityRealm:
local:
allowsSignup: false
users:
- id: admin
password: admin123
authorizationStrategy:
loggedInUsersCanDoAnything:
allowAnonymousRead: false
tools:
jdk:
installations:
- name: "OpenJDK"
home: "/usr/lib/jvm/java-11-openjdk"
nodes:
- name: "k8s-agent"
remoteFS: "/home/jenkins"
launcher:
kubernetes:
yaml: |
apiVersion: v1
kind: Pod
metadata:
labels:
jenkins: agent
spec:
containers:
- name: jnlp
image: jenkins/inbound-agent
args: ["$(JENKINS_SECRET)", "$(JENKINS_NAME)"]
Такой файл поднимает Jenkins с базовой конфигурацией, локальным пользователем и агентом, который будет запускаться в Kubernetes как pod.
