Когда говорим о высокой доступности (HA), мы имеем в виду системы, которые могут работать непрерывно без сбоев в течение длительного времени. Jenkins — один из ключевых компонентов DevOps, а потому критически важно, чтобы он оставался высокодоступным.

В статье разберём два способа настройки Jenkins в режиме высокой доступности с использованием IaC в IBM Cloud:

  • настройка Jenkins в режиме высокой доступности в IBM Cloud с помощью сценариев Terraform и Ansible;

  • использование шаблонов схем (schematics templates) на IBM Cloud в рамках template-based подхода.

Примечание: вы также можете адаптировать эти способы к другим облачным платформам.

Вам понадобится

  • аккаунт IBM Cloud;

  • Docker;

  • Jenkins;

  • репозиторий GitHub

  • базовые знания NGINX или HAProxy;

  • базовые знания Terraform и Ansible;

  • базовые знания CI/CD.

Расчётное время

Выполнение инструкций займёт около 30 минут.

Подготовьте NFS-хранилище в IBM Cloud

Общая схема архитектуры Jenkins с использованием IBM Cloud:

Пользователь отправляет трафик балансировщику нагрузки (NGINX или HAProxy). Балансировщик нагрузки отправляет трафик контроллеру Jenkins. Если контроллер не работает, трафик перенаправляется на резервный сервер Jenkins.

«CI/CD с Jenkins»

Для обеспечения высокой доступности любого приложения важно внутреннее хранилище, поэтому перейдём к подготовке внутреннего хранилища Jenkins:

  • В меню навигации IBM Cloud выберите «Classic Infrastructure» > «File Storage». 

  • Нажмите «Order File Storage».

  • Введите необходимые данные и подготовьте файловое хранилище. Вам нужно выбрать облачную часть хранилища файлов, размер хранилища файлов и способ оплаты — ежемесячно или ежечасно (мы выбрали общий тип хранения на длительный срок). После вы сможете посмотреть файловые хранилища, доступные в системе:

Подготовьте сервер балансировки нагрузки и два сервера Jenkins в IBM Cloud

Вы можете это, используя любой из следующих способов:

  • IBM Cloud CLI;

  • IBM SoftLayer Portal;

  • Terraform. 

В рамках этой статьи мы используем скрипты Terraform для подготовки трёх серверов: одного — для балансировки нагрузки, и двух — для Jenkins.

The main.tf script:

 data "ibm_compute_image_template" "centos" {
  name = var.os
}
resource "ibm_compute_vm_instance" "virtualguest" {
  count                = var.vm_count
  hostname             = "haproxypoc${count.index + 1}"
  domain               = "abc.com"
  image_id             = data.ibm_compute_image_template.centos.id
  datacenter           = var.datacenter
  private_vlan_id      = var.vlan_id
  network_speed        = 100
  ssh_key_ids          = ["11111"]
  hourly_billing       = true
  private_network_only = true
  flavor_key_name      = var.vm_flavor
  local_disk           = false
}

The variables.tf script:

variable "vip" {
  default = "10.114.128.14"
}
variable "vm_count" {
  default = "2"
}
variable "vm_flavor" {
  default = "B1_2X4X100"
}
variable "vlan_id" {
  default = "9999999"
}
variable "datacenter" {
  default = "tor01"
}
variable "os" {
  default = "centos"
}
variable "http_port" {
  default = {
    "0" = "80" #haproxy
  }
}

The provider.tf script:

variable "iaas_classic_username" {
  description = "Enter the user name to access IBM Cloud classic infrastructure. "
}

variable "iaas_classic_api_key" {
  description = "Enter the API key to access IBM Cloud classic infrastructure. "
}

variable "ibmcloud_api_key" {
  description = "Enter your IBM Cloud API Key "
}

provider "ibm" {
  iaas_classic_username = var.iaas_classic_username
  iaas_classic_api_key  = var.iaas_classic_api_key
  ibmcloud_api_key      = var.ibmcloud_api_key
}

The versions.tf script:

terraform {
  required_version = ">= 0.12"
}

Настройте HAProxy (сервер балансировки нагрузки)

Для запуска и настройки HAPproxy на каждом из серверов используйте роль Ansible. Основной модуль — playbook_haproxy.yml.

Плейбук Ansible для настройки сервера балансировки нагрузки:

---
- hosts: all
  remote_user: root
  become: yes

  roles:
    - haproxy

  tasks:
  - name: shutdown haproxy cluster
    shell: /usr/local/bin/docker-compose -f /app/haproxy/docker-compose.yml down

  - name: start haproxy
    shell: /usr/local/bin/docker-compose -f /app/haproxy/docker-compose.yml up -d haproxy

Более подробную информацию о HAProxy вы найдёте в репозитории configJenkins GitHub repo.

Ниже показан файл конфигурации для HAProxy. HAProxy принимает трафик через порт 80 и перенаправляет его на порт 8080 на сервере Jenkins.

defaults
  log global
  maxconn 2000
  mode http
  option redispatch
  option forwardfor
  option http-server-close
  retries 3
  timeout http-request 10s
  timeout queue 1m
  timeout connect 10s
  timeout client 1m
  timeout server 1m
  timeout check 10s

frontend ft_jenkins
 bind *:80
 acl host_cicdprod hdr(host) -i cicdprod.abc.com
 use_backend bk_jenkins if host_cicdprod
 default_backend bk_jenkins
 reqadd X-Forwarded-Proto:\ http

backend bk_jenkins
  server jenkins1 {{ cicdhostprod1.stdout }}:8080 check
  server jenkins2 {{ cicdhostprod2.stdout }}:8080 check backup

Настройте Jenkins

Основной модуль — playbook_jenkins.yml. Он использует Docker Compose для запуска Jenkins.

version: '2'
services:

  jenkins:
    image: jenkins:lts
    container_name: jenkins
    ports:
      - "8080:8080"
      - "50000:50000"
    restart: always
    environment:
      - TZ=America/Toronto
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

    network_mode: "host"

Назначьте cron job для синхронизации файлов между серверами Jenkins

Jenkins работает на двух серверах. Вам необходимо синхронизировать логи на обеих нодах. Для этого используйте shell script на обеих нодах, а также используйте cron для назначения джобы каждую минуту.

Cron добавится как часть playbook_jenkins.yml:

#!/bin/bash
crumb_id=$(curl -s 'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)',-u admin:admin)
curl -s -XPOST 'http://localhost:8080/reload' -u admin:admin -H "$crumb_id"

Скрипт будет вызывать Jenkins reload API для перезагрузки конфигурации Jenkins каждую минуту.

Автоматизируйте с помощью IBM Cloud Schematics и DevOps-инструментов 

Terraform

1. Загрузите main.tf, provider.tf, variable.tf и version.tf в свой репозиторий GitHub.

2. В консоли IBM Cloud нажмите > «Schematics» > «Create a Schematics Workspace». 3. Введите уникальное имя рабочего пространства и нажмите «Create».

3. Введите URL-адрес репозитория GitHub и нажмите «Save template information».

4. Настройте переменные для проверки подлинности ключей API и учётных данных пользователя и сохраните изменения. Это те же самые переменные, которые были объявлены в файлах variable.tf и provider.tf

5. Нажмите «Enable continuous delivery», чтобы создать цепочку инструментов DevOps.

6. Введите данные для цепочки инструментов:

  • Toolchain name: имя создаваемой цепочки инструментов.

  • Region: область, где должна быть создана цепочка инструментов.

  • Resource group: выберите группу ресурсов.

  • Repository type: Новый.

  • IBM Cloud API key: IAM key for IBM Cloud.

7. В меню навигации IBM Cloud нажмите «Schematics» > «Workspaces». Выберите местоположение из раскрывающегося списка:

8. Нажмите «Generate plan»:

9. Нажмите «View log»:

10. Если в журнале нет ошибок, нажмите «Apply plan».

11. В меню навигации выберите «DevOps», чтобы просмотреть цепочку инструментов:

Ansible

Ansible — один из самых простых инструментов управления конфигурацией, который не требует установки агента.

1. Загрузите плейбук Ansible на GitHub:

 ---
 - hosts: all
   remote_user: root
   become: yes

   roles:
     - haproxy

   tasks:
   - name: shutdown haproxy cluster
     shell: /usr/local/bin/docker-compose -f /app/haproxy/docker-compose.yml down

   - name: start haproxy
     shell: /usr/local/bin/docker-compose -f /app/haproxy/docker-compose.yml up -d haproxy

Вы создаёте два действия: одно для Jenkins (hajenkins), а другое для nginx (loadbalancer).

2. В меню навигации консоли IBM Cloud нажмите «Schematics».

3. В поле Управление конфигурацией выберите «Create action».

4. Заполните форму, чтобы создать действие.

5. Введите URL-адрес GitHub и нажмите «Retrieve playbooks»:

6. Нажмите на раскрывающийся список «Playbook», чтобы выбрать плэйбук.

7. Нажмите «Verbosity», чтобы выбрать уровень логирования.

8. В поле «Key» введите дополнительные переменные и нажмите «Save»:

9. Нажмите «Create Inventory», чтобы создать файл инвентаризации, в котором будут хосты в IBM Cloud Classic Infrastructure. Вы также можете ввести IP-адрес хоста-бастиона и закрытый ключ, который плэйбук использует для входа на хосты.

10. Нажмите «Run Action» для выполнения плейбука:

11. Просмотрите журнал Ansible:

Повторите шаги, чтобы создать действие для Jenkins.

Коротко о главном

Из этой статьи вы узнали, как настроить Jenkins в режиме высокой доступности в IBM Cloud. Описанный метод считается cloud-agonistic — его можно использовать с другими облачными провайдерами с учётом различий платформ. При этом применяется IaC, поэтому конфигурацию можно поддерживать на GitHub или в репозитории на основе Git.

«DevOps Tools для разработчиков»