Автоматическое развертывание на основе Jenkins Pipeline

Jenkins

Общедоступная учетная запись WeChat «Back-end Advanced», ориентированная на совместное использование серверных технологий: Java, Golang, WEB-инфраструктура, распределенное промежуточное программное обеспечение, управление услугами и т. д.
Старый водитель научил тебя всем деньгам и довел до продвинутого уровня, я не успел объяснить и сесть в автобус!

В последнее время в процессе внедрения кластера Docker Swarm в компании нужно использовать Jenkins для автоматического развертывания.Существует много решений для Jenkins для реализации автоматического развертывания.Вы можете написать Job прямо на странице jenkins, и задать некоторые операции и скрипты через страницу.Скрипты конвейера пишутся непосредственно в каждом проекте, но для программистов, которые так же хороши, как я и стремятся к максимуму, ни одно из этих решений не может впечатлить мое беспокойное сердце.Далее я расскажу вам, как я реализовал это через Pipeline Автоматизированная схема развертывания, построение с несколькими ветками и совместное использование сценария Pipeline для всех проектов.

Некоторые настройки перед использованием Jenkins

Чтобы быстро собрать Jenkins, я использовал здесь установку Docker и работу Jenkins:

$ sudo docker run -it -d \
  --rm \
  -u root \
  -p 8080:8080 \
  -v jenkins-data:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v "$HOME":/home \
  --name jenkins jenkinsci/blueocean

В первый раз Jenkins используется для входа на страницу Jenkins, вам нужна проверка пароля, нам нужно войти в контейнер Docker для просмотра пароля:

$ sudo docker exec -it jenkins /bin/bash
$ vi /var/jenkins_home/secrets/initialAdminPassword

Jenkins, установленный Docker, имеет небольшой дефект. Версия оболочки несовместима с версией хоста CenOS. В настоящее время нам нужно войти в контейнер Jenkins, чтобы вручную установить оболочку:

$ sudo docker exec -it jenkins /bin/bash
$ ln -sf /bin/bash /bin/sh

Поскольку наш Pipeline также должен выполнять задачи на удаленном сервере и должен подключаться через ssh, то нам нужно сгенерировать открытый ключ ssh в Jenkins:

$ sudo docker exec -it jenkins /bin/bash
$ ssh-keygen -C "root@jenkins"

Добавьте открытый ключ jenkins (id_rsa.pub) в ~/.ssh/authorized_keys удаленного узла

Вам также необходимо установить некоторые необходимые плагины:

  1. Pipeline Maven Integration
  2. SSH Pipeline Steps

После установки плагина вам также нужно перейти в глобальный инструмент, чтобы добавить maven:

maven

Jenkinsfile пригодится здесь позже.

mutiBranch многоветвевые сборки

Поскольку наша разработка основана на многоветвевой разработке, каждая среда разработки имеет соответствующую ветку, поэтому обычное автоматизированное построение Pipeline не может удовлетворить существующие требования к разработке и развертыванию, поэтому нам нужно использовать Jenkins' mutiBranch Pipeline.

Во-первых, конечно, нужно создать новое многоветвевое задание сборки mutiBranch:

maven

Затем установите источник ветки, источником ветки является адрес git вашего проекта, выберите путь Jenkinsfile в проекте

maven

Затем Jenkins будет сканировать Jenkinsfile в каждой ветке в источнике ветки.Если в ветке есть Jenkinsfile, будет создано задание ветки.

maven

Вакансии филиала в рамках этой работы следующие:

maven

Здесь следует отметить, что Jenkinsfile добавляется только к ветви, которая должна быть развернута, в противном случае Jenkins также создаст валютную работу для остальных ветвей.

Обобщенный скрипт конвейера

Прежде чем вы доберетесь до этого, вы можете в основном автоматизировать развертывание на основе сценариев Pipeline, но если вы программист, который стремится к максимуму и не желает быть посредственным, вы должны думать, что по мере увеличения количества проектов количество сценариев Pipeline продолжает расти. увеличиваться, что будет вызывать все больше и больше проблем.Чем больше стоимость обслуживания, по мере роста бизнеса неизбежно изменение вещей в сценарии, что будет включать слишком много сценариев конвейера, а эти сценарии в основном одинаковы, поэтому для такой же хороший программист, как я могу не думать об этом Проблема, я впервые подумал об обобщении скрипта конвейера. К счастью, Дженкинс увидел мое беспокойное сердце, и Дженкинс дал мне общие библиотеки.

Что такое общие библиотеки? Как следует из названия, это разделяемая библиотека, ее основная функция — поместить общий Pipeline-скрипт в одно место, а другие проекты могут получить из него глобально-обобщенный Pipeline-скрипт, который передается между проектами через разные переменные параметры. достичь цели обобщения.

Далее давайте создадим репозиторий git для хранения общих скриптов Pipeline:

maven

Каталог склада добавляется не случайно, Jenkins имеет строгую спецификацию, официальное описание:

maven

Официальный представитель очень четко дал понять, что, вероятно, это означает, что каталог vars используется для хранения общих скриптов Pipeline, а ресурсы используются для хранения файлов, отличных от Groovy. Поэтому я поместил все скрипты сборки и файлы макета, необходимые для Pipeline, здесь, полностью спрятав их от бизнес-инженеров, чтобы не дать бизнес-инженерам внести несколько случайных изменений и вызвать ошибки.

После создания репозитория git нам также необходимо создатьManage Jenkins » Configure System » Global Pipeline LibrariesОпределите глобальную библиотеку в:

maven

На это имя можно ссылаться в файле jenkins с помощью следующей команды:

@Library 'objcoding-pipeline-library'

Давайте взглянем на правила написания универсальных скриптов Pipeline:

#!groovy

def getServer() {
    def remote = [:]
    remote.name = 'manager node'
    remote.user = 'dev'
    remote.host = "${REMOTE_HOST}"
    remote.port = 22
    remote.identityFile = '/root/.ssh/id_rsa'
    remote.allowAnyHosts = true
    return remote
}

def call(Map map) {

    pipeline {
        agent any

        environment {
            REMOTE_HOST = "${map.REMOTE_HOST}"
            REPO_URL = "${map.REPO_URL}"
            BRANCH_NAME = "${map.BRANCH_NAME}"
            STACK_NAME = "${map.STACK_NAME}"
            COMPOSE_FILE_NAME = "docker-compose-" + "${map.STACK_NAME}" + "-" + "${map.BRANCH_NAME}" + ".yml"
        }

        stages {
            stage('获取代码') {
                steps {
                    git([url: "${REPO_URL}", branch: "${BRANCH_NAME}"])
                }
            }

            stage('编译代码') {
                steps {
                    withMaven(maven: 'maven 3.6') {
                        sh "mvn -U -am clean package -DskipTests"
                    }
                }
            }

            stage('构建镜像') {
                steps {
                    sh "wget -O build.sh https://git.x-vipay.com/docker/jenkins-pipeline-library/raw/master/resources/shell/build.sh"
                    sh "sh build.sh ${BRANCH_NAME} "
                }
            }

            stage('init-server') {
                steps {
                    script {
                        server = getServer()
                    }
                }
            }

            stage('执行发版') {
                steps {
                    writeFile file: 'deploy.sh', text: "wget -O ${COMPOSE_FILE_NAME} " +
                        " https://git.x-vipay.com/docker/jenkins-pipeline-library/raw/master/resources/docker-compose/${COMPOSE_FILE_NAME} \n" +
                        "sudo docker stack deploy -c ${COMPOSE_FILE_NAME} ${STACK_NAME}"
                    sshScript remote: server, script: "deploy.sh"
                }
            }
        }
    }
}
  1. Поскольку нам необходимо выполнять задачи на удаленном сервере, определите информацию об удаленном сервере, в которойremote.identityFile— адрес ключа, который мы сгенерировали выше в контейнере;
  2. Определите метод call(), который называется Jenkinsfile для каждого проекта, внимание должно получить его вызов;
  3. Определите конвейер в методе call();
  4. Параметр среды является переменным общим параметром, и его значение задается путем передачи параметра Map, который является параметром, определенным для каждого проекта;
  5. Следующий шаг — пошаговая операция.На этапе «компилировать код» необходимо заполнить maven, который мы установили в глобальном классе инструментов выше, а скрипт сборки «собрать образ» ловко использует wget, чтобы получить его с удаленного компьютера. Склад, «выполнить отправку». Файл макета «версия» также выполняется таким же образом. Шаг «инициализация-сервер» в основном предназначен для инициализации объекта сервера для «выполнения и выпуска».

Из сценария мы можем увидеть тип мышления, который Дженкинс будет продвигать в будущем: конфигурация — это код.

После написания общего сценария конвейера нам нужно создать новый сценарий Jenkinsfile в корневом каталоге каждой ветки проекта, который необходимо автоматически развернуть:

maven

Далее позвольте мне объяснить содержимое Jenkinsfile:

#!groovy

// 在多分支构建下,严格规定Jenkinsfile只存在可以发版的分支上

// 引用在jenkins已经全局定义好的library
library 'objcoding-pipeline-library'
def map = [:]

// 远程管理节点地址(用于执行发版)
map.put('REMOTE_HOST','xxx.xx.xx.xxx')
// 项目gitlab代码地址
map.put('REPO_URL','https://github.com/objcoding/docker-jenkins-pipeline-sample.git')
// 分支名称
map.put('BRANCH_NAME','master')
// 服务栈名称
map.put('STACK_NAME','vipay')

// 调用library中var目录下的build.groovy脚本
build(map)
  1. пройти черезlibrary 'objcoding-pipeline-library'Обратитесь к глобальной библиотеке, которую мы определили в Jenkins, и определите параметр карты;
  2. Следующим шагом является сохранение конкретных параметров проекта на карте и вызов метода build() для передачи их в общий скрипт Pipeline.

Общая библиотека Shared Libraries значительно повышает универсальность скрипта Pipeline, позволяет избежать проблем, вызванных слишком большим количеством скриптов, а также соответствует эстетике превосходного программиста.Если вы начинающий программист, вы обязательно влюбитесь в нее. Это.

Схема архитектуры:

maven

демо-адрес git:

Сценарий трубопровода:GitHub.com/obj coding/ просто…

Развертывание одного проекта:GitHub.com/obj кодирование/…

Развертывание нескольких проектов:GitHub.com/obj кодирование/…

公众号「后端进阶」,专注后端技术分享!