Русский
Русский
English
Статистика
Реклама

Devops

Концепт декларативного IaC подхода для автоматизации инструментов CI

18.09.2020 18:11:01 | Автор: admin

Привет! Меня зовут Игорь Николаев, я пью за любовь работаю в отделе автоматизации процессов разработки Мир Plat.Form в НСПК. В этой статье я поделюсь тем, как наш отдел решал задачу по автоматизации предоставления различных ресурсов для команд разработки. Эта задача свойственна организациям с большим количеством проектов, инфраструктура которых состоит из распределенных и, возможно, слабо связанных сетевых сегментов.
В статье описан PoC (Proof of concept) решения задачи выделения ресурсов в рамках сервисов CI/CD (Continuous Integration & Continuous Delivery) и предоставления привилегий для пользователей этих сервисов.


Описание


Часто в организациях используются сложные и дорогостоящие IDM - класс систем Identity Management (как в рамках лицензирования, так и внедрения и обслуживания) для управления доступами. Нам хотелось совместить процессы запроса и предоставления ресурсов на сервисах CI/CD и предоставления доступов к этим ресурсам. Хотелось получить максимально прозрачное и простое в поддержке и реализации решение, которое обеспечивает следующий функционал:


  • Создание и управление сущностями сервисов CI/CD
  • Использование удобных для нас инструментов
  • Легкая интеграция с уже развернутыми у нас системами
  • Простота эксплуатации
  • Возможность тиражирования

Про тиражирование стоит сказать подробнее, у нас есть несколько сетевых сегментов с разными сервисами CI/CD, и иногда они имеют минимум сетевой связанности. Система должна с минимальными затратами обслуживать несколько окружений, которые могут отличаться друг от друга.


Что мы выбрали для PoC:


Как подход был выбран IaC (Infrastructure-as-Code) с описанием желаемых состояний в виде yaml файлов.
Python язык для написания автоматизации (подходящий вариант для прототипа);
Bitbucket веб-сервис для хостинга проектов и их совместной разработки;
Jenkins сервис непрерывной интеграции (необходим нам для визуализации выполнения задач).


Как пилотные системы для автоматизации были выбраны:


Active Directory всем известные службы каталогов (нам понадобятся группы и пользователи);
Bitbucket часто запрашивают создание проектов, предоставление привилегий;
Nexus 3 OSS (не реклама, нет страницы в Wiki) корпоративная система хранения артефактов, при появлении проектов создаются персональные репозитории проекта и выдаются привилегии.


Немного про Bitbucket и GitOps
(Перевод замечательной статьи про GitOps от коллег из Флант)


Разговор об автоматизации следует начать с описания общей концепции.
В Bitbucket есть две важные сущности: проект(project) и репозиторий (repository), который входит в состав проекта. Для описания доступов в рамках концепта мы решили ограничиться доступами к проекту (более сегментированное предоставление привилегий (на репозиторий) в рамках концепта не потребуется).
У project в Bitbucket есть параметр project key, который понадобится для дальнейших манипуляций, мы взяли его за связующую основу. Именно он и будет являться названием директории в git-репозитории meta. В директории проекта будут размещаться meta-файлы (карты) проекта описанные в формате yaml.
Проектов в Мир Plat.Form много, и у каждого есть своя специфика. Возникает мысль держать в одном месте информацию о группах, инструментах, требуемых проекту, стендах (наборах серверов) и прочего, что имеет отношение к проекту. Для этого отлично подходит git репозиторий.


Какие задачи это решает?


  • В первую очередь, мы получаем стандартный интерфейс описания, который создает однотипные сущности сервисов CI/CD.
  • В любой момент времени мы можем увидеть реальное описание пользователей и их привилегий в рамках проекта.
  • Выполняя автоматизацию по расписанию можно гарантированно получать именно то, что описано в проектных метаданных (защита от очумелых ручек).
  • Расширяя описание проекта в виде определенной структуры meta-данных, можно автоматизировать другие сущности.

Структура meta репозитория git:

DEV наименование сетевого сегмента
project1 ключ проекта в Bitbucket
project1_meta.yaml карта проекта
examples директория примера описания


Такая структура позволит описать несколько различных сетевых сегментов, при этом сохраняя гибкую возможность изменений и различий между ними.
Скрипты автоматизации в рамках концепта будут находиться в проекте в отдельных репозиториях (названия не принципиальны):



О назначении первых трех репозиториев легко догадаться. Последний репозиторий jjb-core репозиторий в котором мы будем хранить описание Jenkins Job в виде рецептов для Jenkins Job builder (о нем будет рассказано ниже).


Автоматизация Microsoft AD


Active Directory используется во многих организациях. Большое количество рабочих процессов организаций начинаются именно с него. У нас в Мир Plat.Form все сотрудники имеют учетные записи в AD и включены в различные группы.
За AD отвечает подразделение инфраструктуры. Для наших нужд была выделена техническая учетная запись (ТУЗ), которой делегировано управление одним из Organization unit (OU). Именно в нем с помощью простой автоматизации мы будем создавать группы и наполнять их пользователями.


Часть содержимого project1_meta.yaml, которая отвечает за AD:


---READY: True  # Защита от "дурака", если не True, то автоматизация проигнорирует весь файлTEAM:  # Описание состава команды (роли)  USER_LOCATION: ldap  # local or ldap  ROLES:    owner:      - owner1    developer:      - developer1      - developer2    qa:      - qa1      - qa2GLOBAL_PRIVILEGES: &global_privileges  # Базовый набор привилегий для каждой роли в команде  owner: [read, write, delete]  developer: [read, write]  qa: [read]

READY булево значение и позволяет, в случае необходимости, выключить автоматизацию обработки данного мета файла
TEAM секция, описывающая сущность проекта
ROLES произвольные названия ролей на проекте, отображающие суть
GLOBAL_PRIVELEGES секция описывает, какая роль будет обладать какими привилегиями
Пример мета репозитория


В рамках предоставления прав для окружения разработки, чтобы не усложнять пример, остановимся на 3х основных ролях: owner, developer, qa (в целом, количество и наименование ролей является произвольным). Для дальнейшей автоматизации эти роли позволят покрыть большую часть повседневных потребностей (у нас сразу появились роль tech, для ТУЗ, но для примера обойдемся без нее).
В рамках OU проекта будем автоматически, на основании meta-файлов проекта, создавать необходимые SG (Security group) и наполнять их пользователями.


На схеме структура выглядит так:


В AD используем плоскую иерархическую структуру, это позволит ее легко обслуживать, и выглядит она весьма наглядно.
Скрипт автоматизации получился очень простой. Он позволяет отслеживать изменения в составе групп (добавление/удаление пользователей) и создавать OU/SG.
Для запуска потребуется установить зависимости из requirements.txt (ldap3, PyYAML).


Пример скрипта


Автоматизация Sonatype Nexus3 OSS


Что такое Nexus? Nexus это менеджер репозиториев, позволяющий обслуживать разные типы и форматы репозиториев через единый интерфейс (Maven, Docker, NPM и другие).
На момент написания статьи версия была OSS 3.25.1-04


Почему именно Nexus?
Есть community версия, которая обладает богатым функционалом, достаточным для выполнения большинства задач, связанных с хранением артефактов и проксирования внешних репозиториев.
Процесс хранения артефактов является важным при проектировании конвейера тестирования и развертывания.


Что потребуется автоматизировать?
Blobstore
Все двоичные файлы, загружаемые через proxy репозитории (мы не предоставляем прямого доступа к интернет репозиториям, используем исключительно прокисрование через nexus), опубликованные в hosted (локальные репозитории) репозитории хранятся в хранилищах Blob-объектов, связанном с репозиторием. В базовом развертывании Nexus, с одним узлом, обычно связаны с локальным каталогом на файловой системе, как правило, а каталоге sonatype-work.
Nexus версии >= 3.19 поддерживает два типа хранилищ File и S3.


UI Blob stores:

Как мы видим, по умолчанию нам уже доступно хранилище default. Из информации выше мы можем понять, что данный blob находится на диске и ему доступен весь объем дискового раздела, на котором находится директория sonatype-work.


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


  1. В случае, если все репозитории будут привязаны к одному blob, у нас могут появиться проблемы с тем, что хранилище может побиться.
  2. Если мы предполагаем, что наш Nexus будет использоваться несколькими командами разработки, то стоит сразу задуматься о том, что в некоторых ситуациях чрезмерная генерация артефактов может забить весь раздел и проблема будет не только у команды, которая генерирует большой объем артефактов, но и у других команд.

Простое решение
Первое, что приходит в голову это создание отдельных blob stores. Очевидно, это не решает проблему расположения на одном дисковом разделе. Подходящим решением является "нарезать" разделы для каждого проекта. Забегая вперед, это решит еще и вопрос мониторинга и отправки уведомлений ответственным за проект. Удобное решение второго пункта описанных проблем.
По первому пункту наиболее правильным решением является создание отдельных blob store для каждого репозитория.


UI создания Blob stores:


Nexus позволяет настроить Soft quota, штука сомнительная. Она уведомляет о том, что с местом что-то не так, но не производит каких-либо действий. При правильном применении шагов, описанных выше, удается добиться большего функционала (Появляется простой способ отслеживания объема и обращений к диску, а переполнение не создает неприятности "соседям").
В поле path мы можем указать раздел, который примонтирован, например, как nfs.
Что позволяет держать раздел непосредственно на сетевом хранилище. Это может снизить скорость, но дает ряд преимуществ с точки зрения простоты.
Nexus у нас запускается в Docker, для этого используется compose файл. Для подключения новых точек монтирования, простым решением будет добавить в compose файле монтирование родительского каталога точек монтирования.


Пример docker-compose:


version: "3"services:  nexus3:    container_name: nexus3    image: sonatype/nexus3:3.27.0    ports:      - 8443:8443      - 50011:50011 # project1-docker-releases      - 20012:50012 # project2-docker-releases    volumes:      - /nexus/sonatyep-work:/nexus-data      - /mnt-blobs:/mnt-blobs      - /etc/timezione:/etc/timezone      - /etc/localtime:/etc/localtime    logging:      driver: "json-file"      options:        max-size: "10m"        max-file: "10"

Repositories
Nexus позволяет создавать репозитории почти всех распространенных форматов. Если идти в сторону идеального хранения, то целесообразно для каждого проекта создавать минимум release и snapshot репозиторий, хотя идеальный вариант может содержать еще и release-candidat репозиторий. Это позволит настроить удобный механизм чистки репозиториев.
Определенно, release репозиторий должен во многих случаях иметь максимальную глубину хранения, как требование, в релизах не должно оказаться "мусора". Напротив, с репозиториями snapshot мы должны иметь возможность очищать без опасений в любое удобное время и без рисков.
Ко всем форматам репозиториев доступ осуществляется по 80 и/или 443 портам, за исключением docker. Репозиторий Docker, для доступа к нему, должен иметь персональный порт. Это приводит к некоторым сложностям. Каждый раз публикуя новый порт, мы должны добавлять его публикацию в compose файле.


LDAP
Nexus имеет возможность реализации подключения к LDAP и использования его в качестве аутентификации пользователей. В нашем случае мы используем группы пользователей для предоставления прав.


Roles
Для удобства роли создаются под проект, лучше идти от минимума, и для себя мы выбрали три роли для каждого проекта:
qa обладают правами достаточными для read
developers read, write
owners read, write, delete
Группы из AD матчатся в локальные группы Nexus.


API
Начиная с версии Nexus OSS 3.19 появилось весьма удобное API для управления Nexus, это значимое нововведение, которое многие пользователи ждали позволит нам управлять Nexus и приводить его в нужное состояние.


Swagger UI API:


На момент написания статьи API, по большей части, в статусе beta, но не смотря на это, работает без больших проблем и позволяет автоматизировать почти все необходимое.


Часть содержимого project1_meta.yaml, которая отвечает за nexus:


RESURCES:  # Ресурсы, обслуживаемые автоматизацией  nexus:    repository:  # Сущности        # Maven        - name: test-maven-releases          locationType: hosted          repoType: maven        - name: test-maven-proxy          locationType: proxy          blobStoreName: test          remoteUrl: http://test.ru          repoType: maven        # Docker        - name: test-docker-releases          locationType: hosted          repoType: docker        - name: test-docker-proxy          locationType: proxy          blobStoreName: test-blob          remoteUrl: http://test.ru          repoType: docker        - name: test-docker-group          blobStoreName: test-blob          locationType: group          httpPort: 10555          repoType: docker          memberNames:            - test-docker-releases            - test-docker-proxy        # Npm        - name: test-npm-proxy          locationType: proxy          remoteUrl: http://test.ru          repoType: npm    blob:      - name: test-blob        path: test-blob    privileges:      <<: *global_privileges

На основании такого файла система автоматизации создает все обслуживаемые сущности. В наших командах принято, что teamlead отвечает за наполнение файла проекта, однако, создать его может любой желающий. После создания pull request следует согласование вовлеченными в процесс участниками, после мерджа с master веткой, отрабатывает автоматизация.


Стоит отметить, мы стремимся сделать процесс максимально простым для пользователя, что влечет к использованию шаблонов конфигураций, которые описаны в виде примитивных моделей. Система позволяет переопределить умолчания в случае возникновения необходимости в описании карты проекта.


Пример кода модели для maven hosted repository:


def maven_model_hosted(params):    model = {        'name': params.get('name'),        'online': params.get('online', True),        'storage': {            'blobStoreName': params.get('blobStoreName', params['name']),            'strictContentTypeValidation': params.get('strictContentTypeValidation', True),            'writePolicy': params.get('writePolicy', 'ALLOW')        },        'cleanup': {            'policyNames': params.get('policyNames', [])        },        'maven': {            'versionPolicy': params.get('versionPolicy', 'MIXED'),            'layoutPolicy': params.get('layoutPolicy', 'PERMISSIVE')        }    }    return model

Данный подход позволяет сократить описание создаваемой сущности до минимума. Идеологически, все что может использовать значения по умолчанию должно их использовать, но при необходимости может быть заменено в файле карты проекта.


Пример скрипта


Автоматизация Atlassian Bitbucket


Для концепта достаточно будет автоматизировать создание проекта и предоставление привилегий к нему.


Часть содержимого project1_meta.yaml, которая отвечает за Bitbucket:


...  bitbucket:    name: project1-bitbucket-project # Это не project key!                                                     # project_key получается из имени файла    description: "Описание проекта в свободной форме"    privileges:      <<: *global_privileges

Это все, что потребуется при заведении нового проекта. Project key будет взят из названия yaml файла (в данном примере project1).


Как это выглядит в UI:


Пример скрипта


Jenkins Job Builder


JJB является python утилитой для описания сущностей jenkins в виде yaml манифестов, которые преобразуются в понятные jenkins API запросы. Это позволяет великолепно решать задачу управления большим количеством однотипных задач.
Jenkins в данном контексте является интерфейсом для отображения успешности выполняемых задач автоматизации и контроля над ними. Сами задачи на первом этапе планируем выполнять по расписанию, например, каждый час. Это позволит избавиться большой части неконтролируемых ручных изменений и будет каждый час приводить систему к описанному состоянию.


Структура репозитория jjb-core:


Каждая директория содержит описание Jenkins job состоящее из двух файлов.


Yaml файл описывает шаблон jenkins job имеет следующее наполнение:


---- job:  # Создаем директорию CORE    name: CORE    project-type: folder- job:  # Создаем поддиректорию ad-core-automation в CORE    name: CORE/ad-core-automation    project-type: folder# Описание темплэйта- job-template:    name: 'CORE/ad-core-automation/{name}-{project_key}'    project-type: pipeline    job_description: Упралвение OU и SG для {project_key}    # Defaults    GIT_BRANCH: master    GIT_CRED_ID: jenkins-bitbucket-integration    triggers:        - timed: 'H * * * *'    parameters:        - string:            name: GIT_BRANCH            default: '{GIT_BRANCH}'            description: Git ref (branch/tag/SHA)        - string:            name: GIT_CRED_ID            default: '{GIT_CRED_ID}'            description: Jenkins credentials ID for BitBucket        - string:            name: META_LOCATION            default: 'DEV/{project_key}/{project_key}_meta.yaml'            description: Meta file location if CORE/meta repository    dsl: !include-raw-escape: ./ad-core-automation.groovy- project:    name: ad-ou    project_key:        - project1        - project2        - project3    jobs:        - 'CORE/ad-core-automation/{name}-{project_key}'

Файл groovy это простой jenkinsfile:


def meta_location = params.META_LOCATIONdef git_cred_id = params.GIT_CRED_IDdef git_branch = params.GIT_BRANCHpipeline {    agent {        label 'centos'    }    stages {        stage('Clone git repos') {            steps {                echo 'Clone meta'                dir('meta') {                    git credentialsId: "${git_cred_id}",                    url: 'ssh://git@bitbucket.mir/core/meta.git'                }                echo 'Clone ad-core-automation'                dir('auto') {                    git credentialsId: "${git_cred_id}",                    branch: git_branch,                    url: 'ssh://git@bitbucket/core/ad-core-automation.git'                }            }        }        stage('Install and run') {            steps {                echo 'Install requirements'                withDockerContainer('python:3.8.2-slim') {                    withEnv(["HOME=${env.WORKSPACE}"]) {                    sh 'pip install --user --upgrade -r auto/requirements.txt  &> /dev/null'                    echo 'Run automation'                    withCredentials([usernamePassword(credentialsId: 'ssp_ad_tech', passwordVariable: 'ad_pass', usernameVariable: 'ad_user')]) {                        dir('auto') {                                sh "./run.py -u $ad_user -p $ad_pass -f ../meta/${meta_location}"                            }                        }                    }                }            }        }    }}

Пример скрипта


Все это описывает создание следующей структуры Jenkins:


Общий алгоритм работы автоматизации:


  • Инициатор создает в репозитории meta новую директорию с картой проекта и создает pull-request в мастер ветку(1).
  • Pull-request попадает на проверку согласующих (2)
  • В случае, если проект новый, пока в ручном режиме инженер прописывает Bitbucket project key для JJB (данное действие нужно произвести единожды)
  • Автоматизация после внесения изменений в шаблоны JJB генерирует описанные job для проекта(4, 5).
  • Jenkins запускает автоматизацию AD(6), которая создает необходимые сущности в виде OU и SG в AD. В случае, если все сущности уже созданы, приводит состав пользователей к описанному (удаляет/добавляет)
  • Jenkins запускает автоматизацию Bitbucket(4), если проекта нет в Bitbucket, то создает его и предоставляет доступ для групп команды проекта. Если проект уже существует, то добавляет к нему группы AD с необходимыми привилегиями.
  • Jenkins запускает автоматизацию для Nexus(7). Создаются описанные сущности Nexus и к ним предоставляется доступ на основе групп AD

Результат и развитие


Результатом данного концепта стало появление базовой автоматизации описанных процессов. Интерфейс взаимодействия в виде yaml карт проектов оказался весьма удобен, появились запросы на улучшения. Главными показателями успешности стали простота и скорость предоставления необходимых проектам ресурсов. Показатель скорости улучшился в разы по сравнению с ручным подходом. Все стало однотипным, понятным и повторяемым. Избавились от ручных ошибок.


На текущий момент описанный PoC перешел в стадию промышленной эксплуатации и претерпел значительные доработки. Мы переписали core систему автоматизации, к которой в виде плагинов подключаются модули для автоматизации новых сервисов. Появились тесты.
Всего автоматизацией обслуживается около 50 проектов и подключаются новые. Планируем тиражирование в другие сетевые сегменты.

Подробнее..

Концепт подхода инфраструктура как код в автоматизации сервисов CICD

18.09.2020 20:23:44 | Автор: admin

Привет! Меня зовут Игорь Николаев, я пью за любовь работаю в отделе автоматизации процессов разработки Мир Plat.Form в НСПК. В этой статье я поделюсь тем, как наш отдел решал задачу по автоматизации предоставления различных ресурсов для команд разработки. Эта задача свойственна организациям с большим количеством проектов, инфраструктура которых состоит из распределенных и, возможно, слабо связанных сетевых сегментов.


В статье описан PoC (Proof of concept) решения задачи выделения ресурсов в рамках сервисов CI/CD (Continuous Integration & Continuous Delivery) и предоставления привилегий для пользователей этих сервисов.



Описание


Часто в организациях используются сложные и дорогостоящие IDM - класс систем Identity Management (как в рамках лицензирования, так и внедрения и обслуживания) для управления доступами. Нам хотелось совместить процессы запроса и предоставления ресурсов на сервисах CI/CD и предоставления доступов к этим ресурсам. Хотелось получить максимально прозрачное и простое в поддержке и реализации решение, которое обеспечивает следующий функционал:


  • Создание и управление сущностями сервисов CI/CD
  • Использование удобных для нас инструментов
  • Легкая интеграция с уже развернутыми у нас системами
  • Простота эксплуатации
  • Возможность тиражирования

Про тиражирование стоит сказать подробнее, у нас есть несколько сетевых сегментов с разными сервисами CI/CD, и иногда они имеют минимум сетевой связанности. Система должна с минимальными затратами обслуживать несколько окружений, которые могут отличаться друг от друга.


Что мы выбрали для PoC:


Как подход был выбран IaC (Infrastructure-as-Code) с описанием желаемых состояний в виде yaml файлов.
Python язык для написания автоматизации (подходящий вариант для прототипа);
Bitbucket веб-сервис для хостинга проектов и их совместной разработки;
Jenkins сервис непрерывной интеграции (необходим нам для визуализации выполнения задач).


Как пилотные системы для автоматизации были выбраны:


Active Directory всем известные службы каталогов (нам понадобятся группы и пользователи);
Bitbucket часто запрашивают создание проектов, предоставление привилегий;
Nexus 3 OSS (не реклама, нет страницы в Wiki) корпоративная система хранения артефактов, при появлении проектов создаются персональные репозитории проекта и выдаются привилегии.


Немного про Bitbucket и GitOps
(Перевод замечательной статьи про GitOps от коллег из Флант)


Разговор об автоматизации следует начать с описания общей концепции.


В Bitbucket есть две важные сущности: проект(project) и репозиторий (repository), который входит в состав проекта. Для описания доступов в рамках концепта мы решили ограничиться доступами к проекту (более сегментированное предоставление привилегий (на репозиторий) в рамках концепта не потребуется).


У project в Bitbucket есть параметр project key, который понадобится для дальнейших манипуляций, мы взяли его за связующую основу. Именно он и будет являться названием директории в git-репозитории meta. В директории проекта будут размещаться meta-файлы (карты) проекта описанные в формате yaml.


Проектов в Мир Plat.Form много, и у каждого есть своя специфика. Возникает мысль держать в одном месте информацию о группах, инструментах, требуемых проекту, стендах (наборах серверов) и прочего, что имеет отношение к проекту. Для этого отлично подходит git репозиторий.


Какие задачи это решает?


  • В первую очередь, мы получаем стандартный интерфейс описания, который создает однотипные сущности сервисов CI/CD.
  • В любой момент времени мы можем увидеть реальное описание пользователей и их привилегий в рамках проекта.
  • Выполняя автоматизацию по расписанию можно гарантированно получать именно то, что описано в проектных метаданных (защита от очумелых ручек).
  • Расширяя описание проекта в виде определенной структуры meta-данных, можно автоматизировать другие сущности.

Структура meta репозитория git:

DEV наименование сетевого сегмента
project1 ключ проекта в Bitbucket
project1_meta.yaml карта проекта
examples директория примера описания


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


Скрипты автоматизации в рамках концепта будут находиться в проекте в отдельных репозиториях (названия не принципиальны):



О назначении первых трех репозиториев легко догадаться. Последний репозиторий jjb-core репозиторий в котором мы будем хранить описание Jenkins Job в виде рецептов для Jenkins Job builder (о нем будет рассказано ниже).


Автоматизация Microsoft AD


Active Directory используется во многих организациях. Большое количество рабочих процессов организаций начинаются именно с него. У нас в Мир Plat.Form все сотрудники имеют учетные записи в AD и включены в различные группы.


За AD отвечает подразделение инфраструктуры. Для наших нужд была выделена техническая учетная запись (ТУЗ), которой делегировано управление одним из Organization unit (OU). Именно в нем с помощью простой автоматизации мы будем создавать группы и наполнять их пользователями.


Часть содержимого project1_meta.yaml, которая отвечает за AD:


---READY: True  # Защита от "дурака", если не True, то автоматизация проигнорирует весь файлTEAM:  # Описание состава команды (роли)  USER_LOCATION: ldap  # local or ldap  ROLES:    owner:      - owner1    developer:      - developer1      - developer2    qa:      - qa1      - qa2GLOBAL_PRIVILEGES: &global_privileges  # Базовый набор привилегий для каждой роли в команде  owner: [read, write, delete]  developer: [read, write]  qa: [read]

READY булево значение и позволяет, в случае необходимости, выключить автоматизацию обработки данного мета файла
TEAM секция, описывающая сущность проекта
ROLES произвольные названия ролей на проекте, отображающие суть
GLOBAL_PRIVELEGES секция описывает, какая роль будет обладать какими привилегиями
Пример мета репозитория


В рамках предоставления прав для окружения разработки, чтобы не усложнять пример, остановимся на 3х основных ролях: owner, developer, qa (в целом, количество и наименование ролей является произвольным). Для дальнейшей автоматизации эти роли позволят покрыть большую часть повседневных потребностей (у нас сразу появились роль tech, для ТУЗ, но для примера обойдемся без нее).


В рамках OU проекта будем автоматически, на основании meta-файлов проекта, создавать необходимые SG (Security group) и наполнять их пользователями.


На схеме структура выглядит так:


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


Скрипт автоматизации получился очень простой. Он позволяет отслеживать изменения в составе групп (добавление/удаление пользователей) и создавать OU/SG.


Для запуска потребуется установить зависимости из requirements.txt (ldap3, PyYAML).


Пример скрипта


Автоматизация Sonatype Nexus3 OSS


Что такое Nexus? Nexus это менеджер репозиториев, позволяющий обслуживать разные типы и форматы репозиториев через единый интерфейс (Maven, Docker, NPM и другие).


На момент написания статьи версия была OSS 3.25.1-04


Почему именно Nexus?


Есть community версия, которая обладает богатым функционалом, достаточным для выполнения большинства задач, связанных с хранением артефактов и проксирования внешних репозиториев.


Процесс хранения артефактов является важным при проектировании конвейера тестирования и развертывания.


Что потребуется автоматизировать?


Blobstore
Все двоичные файлы, загружаемые через proxy репозитории (мы не предоставляем прямого доступа к интернет репозиториям, используем исключительно прокисрование через nexus), опубликованные в hosted (локальные репозитории) репозитории хранятся в хранилищах Blob-объектов, связанном с репозиторием. В базовом развертывании Nexus, с одним узлом, обычно связаны с локальным каталогом на файловой системе, как правило, а каталоге sonatype-work.
Nexus версии >= 3.19 поддерживает два типа хранилищ File и S3.


UI Blob stores:



Как мы видим, по умолчанию нам уже доступно хранилище default. Из информации выше мы можем понять, что данный blob находится на диске и ему доступен весь объем дискового раздела, на котором находится директория sonatype-work.


Проблематика


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


  1. В случае, если все репозитории будут привязаны к одному blob, у нас могут появиться проблемы с тем, что хранилище может побиться.
  2. Если мы предполагаем, что наш Nexus будет использоваться несколькими командами разработки, то стоит сразу задуматься о том, что в некоторых ситуациях чрезмерная генерация артефактов может забить весь раздел и проблема будет не только у команды, которая генерирует большой объем артефактов, но и у других команд.

Простое решение


Первое, что приходит в голову это создание отдельных blob stores. Очевидно, это не решает проблему расположения на одном дисковом разделе. Подходящим решением является "нарезать" разделы для каждого проекта. Забегая вперед, это решит еще и вопрос мониторинга и отправки уведомлений ответственным за проект. Удобное решение второго пункта описанных проблем.
По первому пункту наиболее правильным решением является создание отдельных blob store для каждого репозитория.


UI создания Blob stores:



Nexus позволяет настроить Soft quota, штука сомнительная. Она уведомляет о том, что с местом что-то не так, но не производит каких-либо действий. При правильном применении шагов, описанных выше, удается добиться большего функционала (Появляется простой способ отслеживания объема и обращений к диску, а переполнение не создает неприятности "соседям").


В поле path мы можем указать раздел, который примонтирован, например, как nfs.
Что позволяет держать раздел непосредственно на сетевом хранилище. Это может снизить скорость, но дает ряд преимуществ с точки зрения простоты.


Nexus у нас запускается в Docker, для этого используется compose файл. Для подключения новых точек монтирования, простым решением будет добавить в compose файле монтирование родительского каталога точек монтирования.


Пример docker-compose:


version: "3"services:  nexus3:    container_name: nexus3    image: sonatype/nexus3:3.27.0    ports:      - 8443:8443      - 50011:50011 # project1-docker-releases      - 20012:50012 # project2-docker-releases    volumes:      - /nexus/sonatyep-work:/nexus-data      - /mnt-blobs:/mnt-blobs      - /etc/timezione:/etc/timezone      - /etc/localtime:/etc/localtime    logging:      driver: "json-file"      options:        max-size: "10m"        max-file: "10"

Repositories
Nexus позволяет создавать репозитории почти всех распространенных форматов. Если идти в сторону идеального хранения, то целесообразно для каждого проекта создавать минимум release и snapshot репозиторий, хотя идеальный вариант может содержать еще и release-candidat репозиторий. Это позволит настроить удобный механизм чистки репозиториев.


Определенно, release репозиторий должен во многих случаях иметь максимальную глубину хранения, как требование, в релизах не должно оказаться "мусора". Напротив, с репозиториями snapshot мы должны иметь возможность очищать без опасений в любое удобное время и без рисков.


Ко всем форматам репозиториев доступ осуществляется по 80 и/или 443 портам, за исключением docker. Репозиторий Docker, для доступа к нему, должен иметь персональный порт. Это приводит к некоторым сложностям. Каждый раз публикуя новый порт, мы должны добавлять его публикацию в compose файле.


LDAP
Nexus имеет возможность реализации подключения к LDAP и использования его в качестве аутентификации пользователей. В нашем случае мы используем группы пользователей для предоставления прав.


Roles
Для удобства роли создаются под проект, лучше идти от минимума, и для себя мы выбрали три роли для каждого проекта:
qa обладают правами достаточными для read
developers read, write
owners read, write, delete
Группы из AD матчатся в локальные группы Nexus.


API
Начиная с версии Nexus OSS 3.19 появилось весьма удобное API для управления Nexus, это значимое нововведение, которое многие пользователи ждали позволит нам управлять Nexus и приводить его в нужное состояние.


Swagger UI API:



На момент написания статьи API, по большей части, в статусе beta, но не смотря на это, работает без больших проблем и позволяет автоматизировать почти все необходимое.


Часть содержимого project1_meta.yaml, которая отвечает за nexus:


RESURCES:  # Ресурсы, обслуживаемые автоматизацией  nexus:    repository:  # Сущности        # Maven        - name: test-maven-releases          locationType: hosted          repoType: maven        - name: test-maven-proxy          locationType: proxy          blobStoreName: test          remoteUrl: http://test.ru          repoType: maven        # Docker        - name: test-docker-releases          locationType: hosted          repoType: docker        - name: test-docker-proxy          locationType: proxy          blobStoreName: test-blob          remoteUrl: http://test.ru          repoType: docker        - name: test-docker-group          blobStoreName: test-blob          locationType: group          httpPort: 10555          repoType: docker          memberNames:            - test-docker-releases            - test-docker-proxy        # Npm        - name: test-npm-proxy          locationType: proxy          remoteUrl: http://test.ru          repoType: npm    blob:      - name: test-blob        path: test-blob    privileges:      <<: *global_privileges

На основании такого файла система автоматизации создает все обслуживаемые сущности. В наших командах принято, что teamlead отвечает за наполнение файла проекта, однако, создать его может любой желающий. После создания pull request следует согласование вовлеченными в процесс участниками, после мерджа с master веткой, отрабатывает автоматизация.


Стоит отметить, мы стремимся сделать процесс максимально простым для пользователя, что влечет к использованию шаблонов конфигураций, которые описаны в виде примитивных моделей. Система позволяет переопределить умолчания в случае возникновения необходимости в описании карты проекта.


Пример кода модели для maven hosted repository:


def maven_model_hosted(params):    model = {        'name': params.get('name'),        'online': params.get('online', True),        'storage': {            'blobStoreName': params.get('blobStoreName', params['name']),            'strictContentTypeValidation': params.get('strictContentTypeValidation', True),            'writePolicy': params.get('writePolicy', 'ALLOW')        },        'cleanup': {            'policyNames': params.get('policyNames', [])        },        'maven': {            'versionPolicy': params.get('versionPolicy', 'MIXED'),            'layoutPolicy': params.get('layoutPolicy', 'PERMISSIVE')        }    }    return model

Данный подход позволяет сократить описание создаваемой сущности до минимума.
Идеологически, все что может использовать значения по умолчанию должно их использовать, но при необходимости может быть заменено в файле карты проекта.


Пример скрипта


Автоматизация Atlassian Bitbucket


Для концепта достаточно будет автоматизировать создание проекта и предоставление привилегий к нему.


Часть содержимого project1_meta.yaml, которая отвечает за Bitbucket:


...  bitbucket:    name: project1-bitbucket-project # Это не project key!                                                     # project_key получается из имени файла    description: "Описание проекта в свободной форме"    privileges:      <<: *global_privileges

Это все, что потребуется при заведении нового проекта. Project key будет взят из названия yaml файла (в данном примере project1).


Как это выглядит в UI:



Пример скрипта


Jenkins Job Builder


JJB является python утилитой для описания сущностей jenkins в виде yaml манифестов, которые преобразуются в понятные jenkins API запросы. Это позволяет великолепно решать задачу управления большим количеством однотипных задач.


Jenkins в данном контексте является интерфейсом для отображения успешности выполняемых задач автоматизации и контроля над ними. Сами задачи на первом этапе планируем выполнять по расписанию, например, каждый час. Это позволит избавиться большой части неконтролируемых ручных изменений и будет каждый час приводить систему к описанному состоянию.


Структура репозитория jjb-core:



Каждая директория содержит описание Jenkins job состоящее из двух файлов.


Yaml файл описывает шаблон jenkins job имеет следующее наполнение:


---- job:  # Создаем директорию CORE    name: CORE    project-type: folder- job:  # Создаем поддиректорию ad-core-automation в CORE    name: CORE/ad-core-automation    project-type: folder# Описание темплэйта- job-template:    name: 'CORE/ad-core-automation/{name}-{project_key}'    project-type: pipeline    job_description: Упралвение OU и SG для {project_key}    # Defaults    GIT_BRANCH: master    GIT_CRED_ID: jenkins-bitbucket-integration    triggers:        - timed: 'H * * * *'    parameters:        - string:            name: GIT_BRANCH            default: '{GIT_BRANCH}'            description: Git ref (branch/tag/SHA)        - string:            name: GIT_CRED_ID            default: '{GIT_CRED_ID}'            description: Jenkins credentials ID for BitBucket        - string:            name: META_LOCATION            default: 'DEV/{project_key}/{project_key}_meta.yaml'            description: Meta file location if CORE/meta repository    dsl: !include-raw-escape: ./ad-core-automation.groovy- project:    name: ad-ou    project_key:        - project1        - project2        - project3    jobs:        - 'CORE/ad-core-automation/{name}-{project_key}'

Файл groovy это простой jenkinsfile:


def meta_location = params.META_LOCATIONdef git_cred_id = params.GIT_CRED_IDdef git_branch = params.GIT_BRANCHpipeline {    agent {        label 'centos'    }    stages {        stage('Clone git repos') {            steps {                echo 'Clone meta'                dir('meta') {                    git credentialsId: "${git_cred_id}",                    url: 'ssh://git@bitbucket.mir/core/meta.git'                }                echo 'Clone ad-core-automation'                dir('auto') {                    git credentialsId: "${git_cred_id}",                    branch: git_branch,                    url: 'ssh://git@bitbucket/core/ad-core-automation.git'                }            }        }        stage('Install and run') {            steps {                echo 'Install requirements'                withDockerContainer('python:3.8.2-slim') {                    withEnv(["HOME=${env.WORKSPACE}"]) {                    sh 'pip install --user --upgrade -r auto/requirements.txt  &> /dev/null'                    echo 'Run automation'                    withCredentials([usernamePassword(credentialsId: 'ssp_ad_tech', passwordVariable: 'ad_pass', usernameVariable: 'ad_user')]) {                        dir('auto') {                                sh "./run.py -u $ad_user -p $ad_pass -f ../meta/${meta_location}"                            }                        }                    }                }            }        }    }}

Пример скрипта


Все это описывает создание следующей структуры Jenkins:



Общий алгоритм работы автоматизации:



  • Инициатор создает в репозитории meta новую директорию с картой проекта и создает pull-request в мастер ветку(1).
  • Pull-request попадает на проверку согласующих (2)
  • В случае, если проект новый, пока в ручном режиме инженер прописывает Bitbucket project key для JJB (данное действие нужно произвести единожды)
  • Автоматизация после внесения изменений в шаблоны JJB генерирует описанные job для проекта(4, 5).
  • Jenkins запускает автоматизацию AD(6), которая создает необходимые сущности в виде OU и SG в AD. В случае, если все сущности уже созданы, приводит состав пользователей к описанному (удаляет/добавляет)
  • Jenkins запускает автоматизацию Bitbucket(4), если проекта нет в Bitbucket, то создает его и предоставляет доступ для групп команды проекта. Если проект уже существует, то добавляет к нему группы AD с необходимыми привилегиями.
  • Jenkins запускает автоматизацию для Nexus(7). Создаются описанные сущности Nexus и к ним предоставляется доступ на основе групп AD

Результат и развитие


Результатом данного концепта стало появление базовой автоматизации описанных процессов. Интерфейс взаимодействия в виде yaml карт проектов оказался весьма удобен, появились запросы на улучшения. Главными показателями успешности стали простота и скорость предоставления необходимых проектам ресурсов. Показатель скорости улучшился в разы по сравнению с ручным подходом. Все стало однотипным, понятным и повторяемым. Избавились от ручных ошибок.


На текущий момент описанный PoC перешел в стадию промышленной эксплуатации и претерпел значительные доработки. Мы переписали core систему автоматизации, к которой в виде плагинов подключаются модули для автоматизации новых сервисов. Появились тесты.
Всего автоматизацией обслуживается около 50 проектов и подключаются новые. Планируем тиражирование в другие сетевые сегменты.

Подробнее..

Внедрение CICD и DevOps в Enterprise (в нашем случае Ростелеком)

22.09.2020 12:22:19 | Автор: admin

Тема до сих пор весьма хайповая, и админы, добавляющие в свои резюме словечко DevOps, автоматически рассчитывают на +100К к зарплате. Но мы не про это. Мы хотим рассказать про то, как Ростелеком ИТ внедряет CI/CD & DevOps в энтерпрайзовый ИТ-ландшафт и тяжелые монолитные Legacy-системы.

Первая часть нашего руководства будет про Почему, зачем, как получить на это денег от бизнеса и как получается внедрять CI/CD в десятки проектных команд очень большой компании. Это интересная практическая информация для руководителей ИТ-подразделений и лидов. Вторая часть статьи сугубо инженерная, с описанием прикладных подходов, инструментов и реализаций в зависимости от типа и технологического статуса проекта. И третий блок будет про процесс внедрения в рамках Karma Framework в круге. Поехали!

Ретро. Как всё начиналось

Примерно за год ИТ-разработка Ростелекома в определенном периметре выстроила современную инфраструктуру, основанную на микросервисной архитектуре с развертыванием в кластере OpenShift. Эту инфру мы потом назвали Платформой Цифровых Продуктов, далее ПЦП. Мы позже подробнее опишем состав ПЦП.

Внедрение ПЦП позволило существенно перестроить работу некоторых команд, которые были лоцированы в одном структурном подразделении, с одной точкой управления. Это важно, так как у нас получилось создать в определенной степени технологический и методологический анклав и выстроить новые практики, которые отличаются от остальной корпорации вплоть до того, что мы не поддержали промышленный корпоративный стандарт, и проекты, запускавшиеся в ПЦП, выводились в продакшн на конечных юзеров, но не передавались в общую эксплуатацию. По сути это означает, что продукты НЕ падали вообще и были вне контура эксплуатации. Но с СБ ИТ все договоренности мы имели и нужные мероприятия делали. Плюс несколько команд начали работать в продуктовом подходе по Agile. Разумеется, это стало возможным на определенном классе продуктов и сервисов, что мы запускали. В основном это были относительно легкие фронтовые и middleware-решения, которые легко создавались на основе микросервисов и быстро запускались web-проекты, но с интеграциями в глубокий корпоративный бэкенд. Часть функционала и интеграции запиливались в микросервисы, которые могли использовать другие проекты. Тем не менее, для большой корпорации это был космос оказывается, за 3-6 месяцев можно развернуть для конечных пользователей довольно большой проект или сервис с интеграцией в общий ИТ-ландшафт, опробовать бизнес-гипотезы и модели или просто включить в продуктовую линейку и возможности для клиентов. Сноска для понимания стартаперов: в больших компаниях со множеством региональных биллингов на миллионы людей раньше нельзя было взять и просто за 3-6 месяцев запустить на всю клиентскую базу новый продукт или сервис. Обычно успехом считалось, что это время уходит только на согласование бюджета и ТЗ. А продукт в коде появлялся не ранее чем через год. Еще здесь стоит заметить, что любой стартап через пару лет становится легаси ))

После года продуктивной работы ПЦП и запуска более двух десятков проектов в новом технологическом формате было принято корпоративное решение двигать новое и светлое в массы.

И вот тут-то оказалось, что массы это разнокалиберные монолитные легаси-системы глубокого залегания порой циклопического масштаба и набора функционала с историей, уходящей вглубь веков. Класс систем типа АСР, CRM, аналитические системы, хранилища тарифных планов, системы ордеринга в общем, чудный мир OSS/BSS. И вся наша микросервисная архитектура, весь наш DevOps, OpenShift и CI/CD как попытка научить стадо слонов синхронному плаванию. Причем как чисто технологически, так и коммуникационно. Примерно полгода у нас ушло на исследование: насколько вообще применим пусть не микросервисный, а хотя бы компонентный инфраструктурный подход к монолитным системам. Еще сложнее оказалось объяснить и вовлечь ИТ-хэдов проектов и команд в исследование на тему как и главное зачем распиливать на компоненты ядро, где вся логика зашита, например, в пакеты Oracle. Ну допустим. А далее эстафета достигает, достигает, достигает бизнес-заказчиков. И бизнес задает главный вопрос жизни, вселенной и всего такого а зачем мы будем платить за архитектурный рефакторинг систем, которые и так работают?

Аээ 42!

Обычно на этом дискуссия съеживается, и ИТ уходит в офлайн мариновать тему, а архитекторы наслаждаться интеллектом друг друга. Тоже прок и лекарство против выгорания.

Вот на этом этапе и возникают докладчики на DevOps-конференциях с заявлениями, что в энтерпрайзе все это не летит.

Практики внедрения CI/CD&DevOps в Ростелекоме

Не то чтобы мы самые умные или упоротые. Но мы все же решили посмотреть, что есть за горизонтом событий. Даа, мало, мало огня, мы хотим еще немного больше. Горит в Ростелекоме внутренний огонь!

Начали с простых внутрикорпоративных докладов и митапов для различных проектных ИТ-команд и для инхаус-бизнес-заказчиков. Это не дало результат с точки зрения конкретных внедрений CI/CD & практик DevOps в проекты за периметром ПЦП. Но когда ты этим занимаешься больше года, то повестка начинает проникать даже в весьма консервативные команды и дальние регионы компании. Дискурс меняется, и вдруг некоторые коллеги начинают козырять словом Kubernetes как своим! Это определенно шаг вперед.

Вскоре реплицировался инфраструктурный кластер с похожим на ПЦП подходом в макрорегиональном филиале Ростелекома в Краснодаре, где ребята стали внедрять практику DevOps и CI/CD процессы в новые проекты, но в более тяжелый класс систем, нежели web-решения. Появились общие подходы к автотестированию, юнит-тестированию, нагрузочному тестированию, подготовки к релизу, мониторингу. Потихоньку общий подход к архитектуре, основанной на микросервисах и компонентах, стал доминирующим для новых стартующих в разработку систем. Однако по-прежнему существующие монолитные легаси-системы жили своей жизнью.

Следующим шагом стала попытка организовать гильдии девопсеров. Это горизонтально организованный коммуникационный формат, где различные проектные команды обмениваются опытом и практиками внедрения DevOps и CI/CD. Различные гильдии были созданы и по другим ИТ-специализациям. Формат какое-то время успешно поработал в части дальнейшего проникновения актуальных практик в различные ИТ-команды. Десятки DevOps-инженеров Ростелекома объединились и выносили задачки и свой опыт в общее тематическое инфополе. Но в итоге данный формат затух. Прежде всего потому, что сложно самоподдерживать мотивацию без целеполагания, оформленного в роадмап. Второй веской причиной затухания гильдий стало то, что этот формат без обязательств так и не позволил на системном уровне внедрять CI/CD в большие проекты и легаси-системы. Как ни крути, но не DevOps-инженеры принимают решения о переформатировании всего технологического и релизного цикла разработки или о рефакторинге.

Примерно за три года миссионерской работы знание и принимаемость темы DevOps и CI/CD в компании вышли за порог отрицания. Проделанная работа в итоге начала все же приводить к тому, что по крайней мере IT-команды стали экспериментировать и что-то использовать из инструментов интеграции и развёртывания, особенно в части тестирования и работы с git. И, наконец, мы начали пробовать внедрять CI/CD на некоторых системах тяжелого класса с монолитным ядром в БД и легаси-кодом, которые оказались по разработке в прямом операционном управлении.

Важный кейс и настоящий профит от ПЦП, от сложившегося подхода к архитектуре, разработке и набора инструментов мы получили для сетапа самого яркого огонька в корпоративном ИТ в России 2020 это экосистемы. Концепция цифровых экосистем с кросс-связанностью и кросс-сервисами по всей продуктовой линейке отлично приземляется на микросервисную архитектуру. И у нас уже была готовая инфраструктура, откуда стали быстро расти экосистемные ростки Ростелекома. А что требуется для таких стейтмент-терминов как цифровая экосистема? Правильно quick win. Чайки, налетайте!

Несмотря на заметные результаты, как ни странно, целевое дело пошло на проектах, которые начинали делать не мы, и проекты пришли к нам в Центр Компетенции digital-разработки Ростелеком ИТ в тяжелом нестабильном состоянии. До 90% ресурса команд уходило на багфикс и латание дыр. Техдолг уходил за горизонт полугода. О функциональном развитии можно было забыть. При этом системы были чрезвычайно важны и нужны бизнесу. Вот здесь и случились прорывы. Возвращаясь к вопросу бизнеса: Зачем мы будем платить за архитектурный рефакторинг систем, которые и так работают?. А вот если системы еле ворочаются и критикал-баги зашкаливают, то разговор с бизнесом из томного превращается в конструктив. У вас как у ИТ-разработки появляется возможность найти у бизнеса понимание, что для сохранения жизнеспособности систем и затем их развития нужно не перепиливать все с нуля (на больших системах часто это вообще невозможно по технологическим или бюджетным причинам), а начать внедрять DevOps и CI/CD процессы с параллельным архитектурным рефакторингом, и начинать нужно с особенно критичных мест в системе и оптимизации релизного цикла. А внедрять можно даже в рамках существующего ресурса команды и бюджета. Мы, например, брали на себя коммиты, что через 3 месяца сократим затраты ресурса команды проекта на багфикс с состояния более 50% AS IS, в котором мы получили проект, до приемлемых в среднем по индустрии менее 20%. При том практически без роста бюджета и состава команды.

В общем, если вы хотите внедрить в энтерпрайзовую легаси-систему DevOps и CI/CD процессы, отдайте ее условным индусам. Верните ее потом себе назад в ужасном состоянии, и у вас появится возможность все исправить модными штучками! Шутка))

Что в итоге сработало. Круги и Karma Framework

Сработало, как всегда в длинных процессах и больших системах, не что-то одно, а совокупность усилий, множества шажков и шагов, которые подготовили контекст, создали терминологический дискурс внутри корпорации, конкретные внедрения на ряде проектов заинтересовали разработчиков и активных лидов других продуктовых команд.

Но реальный системный результат дало использование формата кругов в рамках Karma Framework. Поскольку Ростелеком ИТ не внешний вендор (тоже важный момент, кстати), а инхаус-разработчик в группе компаний ПАО Ростелеком, то мы работаем не за маржинальность, а за карму. Это не абстракция, а финансовая модель, помноженная на ключевые ценности. И, следуя фундаментальным ценностям, таким как открытость, честность, доверие и партнерство между ИТ и бизнес-заказчиками, мы как ИТ зарабатываем карму, или другими словами свою репутацию и лояльность бизнеса, стараясь делать продукты качественно, быстро и за адекватные бюджеты. Для последнего, собственно, и нужны Devops & CI/CD, с точки зрения технологий и процессов.

Karma Framework это оригинальная практика управления IT в Ростелекоме, которую мы внедряем последние годы, и даже Gartner включил Karma в число передовых мировых управленческих практик. Вполне заслуженно, надо сказать. Про Karma Framework можно рассказывать очень долго на разных уровнях абстракции, но для нашей темы достаточно пояснить, что суть фреймворка в плоской модели управления, где упор делается на самоорганизацию команд и горизонтальное взаимодействие команд посредством кругов. В одном круге с каким-либо предназначением может быть множество людей, представителей команд или целых проектных групп, которые объединены целью выполнить предназначение круга.

В нашем случае предназначение Круга DevOps стало очень простым: внедрить подходы Devops и практики CI/CD на корпоративном масштабе во множество проектных команд и сделать это технологическим промышленным стандартом.

В отличие от других форматов, круг позволил выстроить системную работу с роадмапами, инструментами, стандартами и учётом кастомных нюансов. И мы наконец ушли от прекрасного, но малорезультативного евангелизма и обмена опытом в чатах, и занялись предметным внедрением Devops & CI/CD в очень разные классы проектов и систем. Как работает круг и фреймворк в целом, мы расскажем в следующих частях про внедрение Devops&CI/CD в энтерпрайзе.

А пока же эту бизнесовую по сути часть темы резюмируем двумя блоками обоснования и ответом на вопрос, зачем нужно внедрять Devops&CI/CD и платить за это. Плюс несколько ключевых поинтов.

Для бизнеса:

  1. Ускорить Time-2-market вывода продукта в целом или обновлений по линейному развитию легаси.

  2. Экономия. Оплатить внедрение Devops&CI/CD и потратить N бюджета, чтобы на горизонте получить экономию в деньгах Y больше N. Или получить прибавку производительности команды, и это окупит N, а потом пойдет время чистоганом. Реальные горизонты наступления эффектов в энтерпрайзе 612 месяцев. Бывает, что и за пару месяцев на проектах с нулевой зрелостью CI/CD можно окупить потраченный ресурс команды.

  3. Сократить расходы на оплату ресурса команды, уходящего на багфиксы. В среднем по индустрии на зрелых проектах бизнес готов мириться с 20% затрат на саппорт на третьей ЛТП от бюджета развития. В целевом сокращается до 10%, а иногда уходит почти в ноль. И бизнес получает больше функционального развития.

  4. Гораздо более стабильные продукты и системы. Это автоматически ведет к росту бизнес-маркеров типа NPS, экономии на 1-2 линиях, колл-центрах и т.д.

  5. Нормализация работы и коммуникации бизнеса с ИТ. Исчезновение ментальных дисбалансов на темы Кто кому должен и кто плохо работает.

Для ИТ:

  1. Реальная оптимизация технологического цикла разработки. Можно сократить время и усилия почти на каждом участке от аналитики и постановок задач до подготовки релиза и вывода в продакшн. У нас есть кейсы, где вместо ночных многочасовых бдений вывод в продуктив стал занимать десятки минут и без тоскливого ощущения снова получить на регрессе кучу критикал-багов, иногда без возможности откатить.

  2. Частью идеологии DevOps является перестроение многих процессов как технологических, так и административных. Можно за счет нового технологического инструментария и настроек существенно менять формат работы с эксплуатацией и бизнесом и перестать тратить много сил на ПМИ/ПСИ, документацию, которой невозможно пользоваться, согласования в СЭДах и прочий мартышкин труд и бюрократию. Потому что снимаются риски потери контроля, многие вопросы зон ответственности и нестабильной работы системы.

  3. Разработчики занимаются программированием и кодом, творчеством, а не разбором инцидентов и поиском их причин. Вообще, внедрение CI/CD влечет за собой повышение квалификации команды и более точного состояния, когда каждый специалист занимается своим делом.

  4. Отсюда меньше многозадачности, потери перфоманса от частых переключений на нетипичные задачи. Общий рост производительности команды без повышения экстенсивного давления. Напротив, фокус в том, что перфоманс улучшается, а уровень стресса и напрягов уменьшается. Авральный менеджмент идет в топку. Счастье растет.

  5. Все нормальные айтишники хотят делать хорошие качественные продукты. Все хотят заниматься производительным трудом на благо продукту и использовать современные стеки и технологии. В энтерпрайзе это делать тяжелее. И внедрение Devops&CI/CD позволяет подкормить профессиональную совесть качественным нектаром.

Важные моменты:

  1. CI/CD начинается до технологического цикла. Мы рассматриваем CI/CD как процесс, который начинается с идеи в горнилах бизнеса. И важно операционные процессы с бизнесом выстроить так, чтобы сырые идеи не залетали в разработку, чтобы бизнес внутри себя договаривался, что конкретно и в каком порядке пойдет в разработку. По сути это качественная работа с бэклогом, чтобы он всегда был полон на пару месяцев вперед и приоритезирован.

  2. Devops&CI/CD можно внедрять на любом уровне зрелости продукта и команды. Целый ряд вещей вообще не технологического порядка, а логистического и операционного. Часть инструментов и подходов можно внедрить очень дешево во всех смыслах. Даже в старых, тяжелых легаси-системах.

  3. Devops&CI/CD не является синонимом Agile и вполне работает в классическом ватерфоле и фикспрайсовых моделях. Отдельные инструменты и подходы вполне можно использовать: ту же автоматизацию сборки, автотесты, Unit-тестирование, правильную настройку git(а) можно внедрять хоть где.

Однако, CI/CD наиболее эффективен в связке со Scrum или Канбан. По сути, это объединение продвинутых операционной и технологической методик работы с ИТ-конвейером. У нас есть несколько кейсов такого рода. И мы увидели большие перспективы наложения на Канбан-доску с ее этапами разработки, матрицы действий и инструментов CI/CD. Здесь просто золотая жила. И мы уже делаем оригинальный фреймворк о том, как поженить Devops&CI/CD с Канбан. В следующих частях темы Devops&CI/CD в энтерпрайзе мы расскажем и том, как устроена наша Платформа Цифровых Продуктов, и о том, как работают круг и фреймворк внедрения Devops&CI/CD в разные классы систем и проектов.

Ждите новостей от Ростелеком ИТ!

Подробнее..

Вернуть пропавший скутер, или история одного IoT мониторинга

23.09.2020 20:15:33 | Автор: admin

Год назад мы запустили пилотную версию промо проекта по децентрализованному прокату электроскутеров.


Изначально проект назывался Road-To-Barcelona, позже стал Road-To-Berlin (отсюда встречающиеся на скриншотах R2B), а в итоге и вовсе был назван xRide.


Основная идея проекта была в следующем: вместо того чтобы иметь централизованный сервис проката автомобилей или скутеров (речь пойдет о скутерах aka электро-мотоциклах, а не kickscooter/самокатах)
мы хотели сделать платформу для децентрализованной аренды. О сложностях с которыми мы столкнулись уже писали ранее.


Изначально проект ориентировался на автомобили, но из-за сроков, крайне долгих общений с производителями и огромного количества ограничений по безопасности, для пилота были выбраны электрические скутеры.


Пользователь устанавливал iOS или Android приложение на телефон, подходил к понравившемуся ему скутеру, после чего телефон и скутер устанавливали peer-to-peer соединение, происходил обмен ETH и пользователь мог начать поездку включив скутер через телефон. По завершении поездки так же можно было провести оплату поездки за счет эфира из кошелька пользователя на телефоне.


Помимо скутеров пользователь видел в приложении "умные зарядки", посетив которую пользователь мог сам сменить текущую батарею, если она разрядилась.


Так в целом и выглядел наш пилот, запущенный в сентябре прошлого года в двух городах Германии: Бонн и Берлин.



И вот, однажды, в Бонне, ранним утром наша команда поддержки (находящаяся в локации для поддержания скутеров в работоспособном состоянии) была поднята по тревоге: один из скутеров бесследно исчез.
Как его найти и вернуть?


В этой статье я расскажу об этом, но для начала о том как мы построили нашу собственную IoT платформу и как мы осуществляли мониторинг над ней.


Что и зачем мониторить: скутеры, инфраструктура, зарядки?


Итак, что же мы хотели мониторить в нашем проекте?
В первую очередь это сами скутеры электроскутеры сами по себе довольно дорогие, нельзя запускать такой проект не будучи достаточно подготовленными, по возможности хочется собирать как можно больше информации о скутерах: об их местоположении, уровне заряда, итд.


Помимо этого, хотелось бы отслеживать состояние нашей собственной IT инфраструктуры базы, сервисы и все что им необходимо для работы. Нужно было отслеживать и состояние "умных зарядок", на случай если они сломались или в них кончились полные батареи.


Скутеры


Что же из себя представляли наши скутеры и что мы хотели о них знать?


Первое, и самое существенное GPS координаты, так как благодаря им мы можем понимать, где они находятся и куда двигаются.


Далее заряд батареи, благодаря ему мы можем определять, что зарядка скутеров подходит к концу и отправить juicer'а или хотя бы предупредить пользователя.


Конечно, необходимо также проверять что происходит с нашими Hardware компонентами:


  • работает ли Bluetooth?
  • работает ли сам GPS модуль?
    • так же у нас была проблема с тем, что GPS мог отсылать неверные координаты и "залипать", а определить это можно было только на уровне дополнительных проверок на скутере,
      и нотифицировать поддержку как можно скорее для устранения проблемы

И последнее: проверки софтверной части, начиная с ОС и загрузки процессора, сети и диска, заканчивая уже более специфичными для нас проверками наших собственных модулей (jolocom, keycloak).


Hardware



Что же представляла наша "железная" часть?
Учитывая максимально сжатые сроки и необходимость быстрого прототипирования мы выбрали для себя максимально простой для реализации и подбора компонентов вариант Raspberry Pi.
Помимо самого Rpi мы имели кастомную борду (которые мы сами разработали и заказывали в Китае для ускорения процесса сборки конечного решения) и набор компонентов реле (для включения/выключения скутера), считыватель заряда батареи, модем, антенны. Все это было компактно укомплектовано в специальную коробочку "xRide box".


Следует также отметить, что вся коробочка питалась дополнительным павербанком, который в свою очередь питался от основной батареи скутера.
Это позволяло использовать мониторинг и включать скутер, даже после окончания поездки, так как основная батарея отключалась сразу после поворота ключа зажигания в положение "off".


Docker? Plain linux? и деплой


Вернемся к мониторингу, итак Raspberry что же мы имеем?


Одна из первых вещей которую мы хотели использовать для ускорения процесса деплоя, обновления и доставки компонентов на физические устройства был Docker.


К сожалению, довольно быстро стало ясно что Docker на RPi хоть и работает, но дает достаточно много накладных расходов, в частности по энергопотреблению.


Разница с использованием "нативной" ОС пусть и не была настолько сильной, но все же достаточной чтобы мы опасались возможности слишком быстрой потери заряда.


Второй причиной стала одна из библиотек наших партнеров на Node.js (sic!) единственный компонент системы, который не был написан на Go/C/C++.
Авторы библиотеки не успели вовремя предоставить рабочую версию на любом из "нативных" языков.
Мало того, что нода сама по себе не является самым элегантным решением для низкопроизводительных девайсов, так еще и сама библиотека была весьма прожорлива по ресурсам.


Мы поняли, что при всем желании использование Docker для нас будет слишком большим оверхедом. Был сделан выбор в пользу нативной OS и работы под ней напрямую.


OS


В итоге, качестве ОС мы, опять же, избрали самый простой вариант и использовали Raspbian (сборка Debian для Pi).
Весь наш софт мы пишем на Go, поэтому и основной hardware-агент модуль в нашей системе мы также написали на Go.
Именно он и отвечает за работу с GPS, Bluetooth, считывание заряда, включение скутера, итд.


Деплой

Тут же встал вопрос о необходимости реализации механизма доставки обновлений на девайсы (OTA) как обновлений самого нашего агента/приложения, так и обновления самой ОС/"прошивки"
(так как новые версии агента могли требовать обновлений ядра или компонентов системы, библиотек итд).


После довольно долгого анализа рынка выяснилось, что существует довольно много решений для доставки обновлений на девайс.
От относительно простых утилит, по большей части ориентированных на обновление/dual-boot вроде swupd/SWUpdate/OSTree до полноценных платформ вроде Mender и Balena.


В первую очередь мы решили, что нас интересуют именно end-to-end решения, поэтому выбор сразу пал на платформы.
Самым Balena была исключена ввиду того, что фактически использует тот же самый Docker внутри своего balenaEngine.
Но отмечу, что несмотря на это, в конечном итоге мы постоянно использовали их продукт Balena Etcher для флеша прошивок на SD карты простая и крайне удобная утилита для этого.


Поэтому в итоге выбор пал на Mender. Mender представляет из себя полноценную платформу для сборки, доставки и установки прошивок.
В целом платформа выглядит просто замечательно, но нам потребовалось около полутора недель только на то, чтобы собрать правильную версию нашей прошивки с помощью сборщика mender.
И чем больше мы погружались в тонкости его использования,
тем больше становилось ясно, что на полноценное его развертывание нам понадобилось бы сильно больше времени, чем у нас было.


Увы, наши сжатые сроки привели к тому, что мы вынуждены были отказаться от использования Mender и выбрать еще более простой пусть.


Ansible

Самым простым решением в нашей ситуации оказалось использование Ansible. Пары playbook'ов для начала было вполне достаточно.
Суть их сводилась к тому, что мы просто подключались с хоста (CI сервер) по ssh к нашим расберри и разливали на них обновления.


В самом начале все было просто нужно было находиться в единой сети с устройствами, разливка шла через Wi-Fi.
В офисе просто находилось десяток тестовых малинок, подключенных к одной сети, каждое устройство имело статический IP адрес так же указанный в Ansible Inventory.


Именно Ansible доставлял наш мониторинг-агент на конечные устройства


3G/LTE


К сожалению, такой вариант использования Ansible мог работать только в режиме разработки, пока у нас еще не было реальных скутеров.
Потому что скутеры, как вы понимаете, не стоят подключенные к одному Wi-Fi роутеру постоянно ожидая обновления по сети.


В реальности у скутеров вообще не может быть никакого соединения кроме мобильного 3G/LTE (и то не постоянно).
Это накладывает сразу много проблем и ограничений, вроде низкой скорости соединения и нестабильной связи.


Но самое главное в 3G/LTE сети мы не можем просто надеяться на статичный IP присвоенный в сети.
Это частично решается некоторыми провайдерами SIM карт, есть даже специальные симки предназначенные для IoT устройств со статическими IP адресами. Но мы не имели доступа к таким SIM картам и не могли использовать IP адреса.


Конечно, были идеи делать некую регистрацию IP адресов aka service discovery где-то вроде Consul, но от подобных идей пришлось отказаться,
так как у нас в тестах IP адрес мог меняться слишком часто, что приводило к большой нестабильности работы.


По этой причине, наиболее удобное использование для доставки метрик было бы не с использованием pull модели, где мы ходили бы за нужными метриками на устройства,
а push с доставкой метрик с устройства напрямую на сервер


VPN


В качестве решения этой проблемы мы выбрали VPN а конкретно Wireguard.


Клиенты (скутеры) на старте системы подключались к VPN серверу и держали возможность подключения к ним. Этот туннель и использовался для доставки обновлений.



В теории, тот же туннель можно было использовать и для мониторинга, но такое подключение было сложнее и менее надежным чем простой push.


Облачные ресурсы


Последнее необходимо отслеживать наши облачные сервисы и БД, так как для них мы используем Kubernetes, в идеале чтобы разворачивание мониторинга в кластере было максимально простым. В идеале с использованием Helm, так как для деплоя, мы в большинстве случаев используем его. И, само собой, для мониторинга облака нужно использовать те же решения, что и для самих скутеров.


Дано


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


  • Быстрое решение, так как мониторить необходимо уже во время процесса разработки
  • Объем/количество нужно множество метрик
  • Сбор логов обязателен
  • Надежность данные критически важны для успеха запуска
  • Нельзя использовать pull модель нужен push
  • Нужен единый мониторинг не только железа, но и облака

Конечная картинка выглядела примерно так



Выбор стека


Итак, перед нами встал вопрос выбора стека для мониторинга.


В первую очередь, мы искали наиболее полноценное all-in-one решение, которое одновременно покрывало бы все наши требования, но при этом и было бы достаточно гибким чтобы подогнать его использование под наши нужды. Все-таки, у нас было много ограничений наложенных на нас железом, архитектурой и сроками.


Существует огромное множество решений для мониторинга,
начиная полноценными системами вроде Nagios, icinga или zabbix и заканчивая уже готовыми решениями по Fleet management.



Изначально, последние казались идеальным для нас решением, но в одних не было полноценного мониторинга, в других были сильно урезаны возможности бесплатных версий, а третьи просто не покрывали наши "хотелки" или не были достаточно гибкими для подгонки под наши сценарии. Некоторые просто устарели.


После анализа какого-то количества подобных решений мы быстро пришли к выводу, что проще и быстрее будет собрать схожий стек самостоятельно. Да, это будет чуть сложнее чем разворачивание полностью готовой Fleet management платформы, но зато нам не придется идти на компромиссы.
Почти наверняка, во всем огромном обилии решений и есть уже готовое которое полностью бы нам подошло,
но в нашем случае значительно быстрее было собрать некий стек самостоятельно и подогнать "под себя", нежели тестировать готовые продукты.


При всем этом, мы не стремились собирать целиковую платформу для мониторинга самостоятельно, а искали максимально функциональные "готовые" стеки, только с возможностью их гибко настраивать.


(B)ELK?


Первое решение, которое реально рассматривалось широко известный ELK стек.
На самом деле он должен называться BELK, ведь начинается все с Beats https://www.elastic.co/what-is/elk-stack



Конечно, ELK это одно из самых известных и мощных решений в области мониторинга, а уж в сборе и обработке логов, так и самое.


Мы подразумевали, что ELK будет использоваться для сбора логов и, так же как долговременное хранилище метрик полученных из Prometheus.
Для визуализации можно использовать Grafan'у.


На самом деле, свежий ELK стек умеет собирать метрики и самостоятельно (metricbeat), Kibana так же умеет показывать их.


Но все-таки изначально ELK вырос из логов и пока функционал метрик имеет ряд серьезных недостатков:


  • Значительно медленнее Prometheus
  • Интегрируется в куда меньшее количество мест чем Prometheus
  • Сложно настроить алертинг по ним
  • Метрики занимают большое количество места
  • Настройка дашбордов с метриками в Kiban'е значительно сложнее Grafan'ы

В общем, метрики в ELK тяжелые и пока не такие удобные как в других решениях, которых сейчас на самом деле значительно больше чем просто Prometheus: TSDB,
Victoria Metrics, Cortex итд итп. Конечно, очень бы хотелось иметь сразу полноценное all-in-one решение, но в случае с metricbeat выходило слишком много компромиссов.


Да и у самого ELK стека есть ряд непростых моментов:


  • Он тяжелый, порой даже очень, если у вас собирается довольно большое количество данных
  • Его нужно "уметь готовить" скалировать его необходимо, но делается это нетривиально
  • Урезанная бесплатная версия в бесплатной версии нет нормального алертинга, на момент выбора не было и аутентификации

Надо сказать, что в последнее время с последним пунктом стало получше и помимо вывода в open-source X-pack (в том числе аутентификация) начала меняться сама модель прайсинга.
Но на момент, когда мы собирались разворачивать это решение, алертинга не было совсем.
Возможно, можно было попробовать собрать что-то с использованием ElastAlert или других community решений, но все же решили рассмотреть другие альтернативы.


Loki Grafana Prometheus


На данный момент неплохим решением может быть сборка стека мониторинга на основе чисто Prometheus как поставщика метрик,
Loki для логов, а для визуализации можно использовать все ту же Grafana.
К сожалению, на момент старта прода пилота проекта (сентярбь-октябрь 19ого года) Loki еще находился в бета версии 0.3-0.4,
а на момент старта разработки и вовсе не мог рассматриваться как produtcion решение.


Я пока не имею опыта реального использования Loki в серьезных проектах, но могу сказать, что Promtail (агент для сбора логов) здорово работает как для bare-metal, так и для подов в kubernetes.


TICK


Пожалуй, наиболее достойной (единственной?) полнофункциональной альтернативой ELK стеку сейчас можно назвать только TICK стек Telegraf, InfluxDB, Chronograf, Kapacitor.



Я опишу все компоненты ниже более подробно, но в целом идея такая:


  • Telegraf агент для сборки метрик
  • InfluxDB база данных метрик
  • Kapacitor обработчик метрик в реальном времени для алертинга
  • Chronograf веб панель для визуализации

Для InfluxDB, Kapacitor и Chronograf есть официальные helm чарты, которые мы использовали для их разворачивания.


Надо отметить, что в свежей версии Influx 2.0 (beta) Kapacitor и Chronograf стали частью InfluxDB и больше не существуют отдельно


Telegraf



Telegraf это очень легковесный агент для сбора метрик на конечной машине.
Он умеет мониторить огромное количество всего, от nginx до
сервера minecraft.


У него есть ряд классных преимуществ:


  • Быстрый и легкий (написан на Go)
    • Ест минимальное количество ресурсов
  • Push метрик по умолчанию
  • Собирает все необходимые метрики
    • Системные метрики без каких-либо настроек
    • Хардварные метрики вроде информации с датчиков
    • Очень легко добавлять собственные метрики
  • Много плагинов "из коробки"
  • Собирает логи

Так как push метрик был для нас необходим, все остальные преимущества были более чем приятными дополнениями.


Сборка логов самим же агентом так же очень удобна, так как нет необходимости подключать дополнительные утилиты для тейлинга логов.
Influx предлагает максимально удобный опыт работы с логами если вы используете syslog.


Telegraf вообще отличный агент для сборки метрик, даже если вы не используете весь остальной ICK стек.
Многие скрещивают его и с ELK и с различными другими time-series базами по удобству, так как он умеет писать метрики почти куда угодно.


InfluxDB



InfluxDB основное ядро TICK стека, а именно time-series база данных для метрик.
Помимо метрик Influx также может хранить и логи, хотя, по сути логи для него это всего лишь такие же метрики,
только вместо обычных числовых показателей основную функцию несет строка текста лога.


InfluxDB тоже написан на Go и работает, по ощущениям, значительно быстрее в сравнении с ELK на нашем (не самом мощном) кластере.


К одним из крутых преимуществ Influx я бы также отнес очень удобное и богатое API для запросов к данным,
которые мы очень активно использовали.


Недостатки $$$ или скалирование ?

У TICK стека есть только один обнаруженный нами недостаток он дорогой. Даже очень.


А что есть в платной версии, чего нет в бесплатной?


Насколько нам удалось понять, единственное чем отличается платная версия TICK стека от бесплатной возможности скалирования.


А именно поднять кластер с High availability можно только в Enterprise версии.


Хотите полноценное HA нужно либо платить, либо городить какие-нибудь костыли. Есть пара решений сообщества например influxdb-ha похоже на грамотное решение, но написано что не подходит для продакшена, а так же
influx-spout простое решение с прокачкой данных через NATS (его тоже придется скалировать, но это решаемо).
Жаль, но оба они, похоже, заброшены нет свежих коммитов, предположу, что дело в скором ожидаемом выходе новой версии Influx 2.0 в которой многое будет иначе (пока информации о скалировании в ней нет).


Официально для бесплатной версии существует Relay фактически это примитивное HA, но только посредством балансировки,
так как все данные будут писаться во все инстансы InfluxDB за load balancer'ом.
У него есть некоторые недостатки вроде потенциальных проблем с перезаписью точек и необходимости создавать базы для метрик заранее
(что при обычной работе с InfluxDB происходит автоматически).
К тому же шардирование не поддерживается, это означает дополнительные накладные расходы на дуплицированные метрики (и обработка и хранение),
которые могли вам быть не нужны, но разделить их возможности нет.


Victoria Metrics?


В итоге, несмотря на то, что во всем помимо платного скалирования TICK стек нас полностью устраивал, мы решили посмотреть нет ли бесплатных решений, которыми можно заменить InfluxDB базу,
оставив при этом остальные компоненты T_CK.



Time-series баз немало, но наиболее подающая надежды Victoria Metrics, у нее целый ряд плюсов:


  • Быстрая и легкая, по крайней мере по результатам бенчмарков
  • Есть кластерная версия, про которую сейчас даже есть хорошие отзывы
    • Она можешь шардироваться
  • Поддерживает InfluxDB протокол

Мы не собирались строить полностью кастомный стек на основе Victoria и основная надежда была на то, что мы сможем воспользоваться ею как drop-in заменой для InfluxDB.


К сожалению, это невозможно, несмотря на то, что поддерживается протокол InfluxDB, это работает только для записи метрик "наружу" доступно только Prometheus API,
а значит натравить Chronograf на нее не получится.
Более того, для метрик поддерживаются только числовые значения (мы использовали строковые значения для кастомных метрик об этом в разделе админка).
Очевидно, по той же причине VM не может хранить логи, как это делает Influx.


Также, надо отметить, что на момент поиска оптимального решения Victoria Metrics еще не была так популярна, документация была значительно меньше и функционал был слабее
(не припоминаю подробного описания кластерной версии и шардирования).


Выбор базы

В результате было принято решение, что для пилота мы все же ограничимся одиночной нодой InfluxDB.


Основных причин такого выбора было несколько:


  • Нам очень нравился функционал TICK стека целиком
  • Мы уже успели его развернуть и оно отлично работало
  • Сроки поджимали и не оставалось много времени тестировать другие варианты
  • У нас не ожидалось такой большой нагрузки

Скутеров у нас для первой фазы пилота было не так много, и тестирование во время разработки не выявило каких-либо проблем с производительностью.
Поэтому мы решили, что для данного проекта нам вполне хватит и одно ноды Influx без необходимости скалирования (cм выводы в конце).


Со стеком и базой решили теперь об остальных компонентах TICK стека.


Kapacitor



Kapacitor это часть TICK стека, сервис который может следить за попадающими в базу метриками в реальном времени и выполнять на основе правил различные действия.


Вообще он позиционируется как тул для потенциального отслеживания аномалий и машинного обучения (не уверен что эти функции востребованы),
но наиболее популярный кейс его использования более банален это алертинг.


Так и мы его использовали для нотификаций. Мы настроили Slack оповещения о том, что тот или иной скутер отключился,
то же самое было сделано для умных зарядок и важных компонентов инфраструктуры.



Это позволяло быстро реагировать на проблемы, а также получать нотификации о том, что все пришло в норму.
Простой пример сломалась или по какой-то причине разрядилась дополнительная батарея для питания нашей "коробочки",
просто поставив новую мы должны через некоторое время получить нотификацию о восстановлении работоспособности скутера.


В Influx 2.0 Kapacitor стал частью DB


Chronograf



Я повидал много различных UI решений для мониторинга, но могу сказать, что по функционалу и UX ничто не сравнится с Chronograf'ом.


Начинали мы использовать TICK стек, как ни странно, с Grafan'ой в качестве веб-интерфейса.
Описывать ее функционал не буду, всем известны ее широкие возможности по настройке всего что угодно.


Однако, Grafana все же представляет из себя совсем универсальный инструмент, тогда как Chronograf в основном заточен под использование с Influx.
И конечно, благодаря этому, Chronograf может позволить себя куда более хитрый или удобный функционал.


Пожалуй, основное удобство работы с Chronograf в том, что вы можете смотреть внутренности вашей InfluxDB через Explore.


Казалось бы, в Grafana есть почти идентичный функционал, но в реальности настройка дашборда в Chronograf может осуществляться несколькими кликами мыши
(попутно смотря на визуализацию там же), тогда как в Grafana вам все равно рано или поздно придется редактировать JSON конфигурацию
(само собой Chronograf позволяет выгрузить ваши настроенные "руками" даши и редактировать в виде JSON если необходимо но мне никогда не приходилось их трогать после создания на UI).


В Kibana куда более богатые возможности по созданию дашбордов и контролов для них, но и UX для таких операций ну очень сложный.
Потребуется неплохо разобраться чтобы создать себе удобный дашборд. И хотя функционал дашбордов у Chronograf меньше, делать и настраивать их значительно проще.


Сами дашборды, помимо приятного визуального стиля, фактически ничем от дашбордов в Grafana или Kibana не отличаются:


Так выглядит то самое окно запросов:


Важно отметить, помимо прочего, что зная типы полей в базе InfluxDB хронограф иногда сам может
автоматически помогать вам с написанием Query или выбором правильной функции агрегации типа mean.


Ну и конечно же, Chronograf максимально удобен для просмотра логов. Выглядит это так:



По умолчанию Influx логи заточны под использование syslog и поэтому в них есть важный параметр severity.


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


Конечно, в идеале было бы настроить алертинг на такие ошибки, благо у нас уже было все для этого.
Мы даже на какое-то время включали это, но, в процессе подготовки пилота выяснилось, что у нас возникает довольно много ошибок
(в том числе системных вроде недоступности LTE сети), которые слишком сильно "спамят" в Slack канал, при этом не неся большой пользы.


Правильным решением было бы обработать большинство подобных типов ошибок, настроить для них severity и уже потом включить алертинг.
Таким образом в Slack попадали бы только новые или важные ошибки. На подобный сетап банально не хватило времени в условиях сжатых сроков.


Аутентификация


Отдельно стоит упомянуть то, что Chronograf поддерживает OAuth и OIDC в качестве аутентификации.
Это очень удобно, так как позволяет легко прикрутить его к вашему серверу и сделать полноценное SSO.


В нашем случае сервером был Keycloak он использовался для подключения к мониторингу,
но при этом тот же сервер использовался и для аутентификации скутеров и запросов на back-end.


Админка


Последний компонент, который я опишу это наша самописная "админка" на Vue.
В целом это просто отдельный сервис, который отображает информацию о скутерах одновременно из наших собственных баз данных, микросервисов и данные метрик из InfluxDB.


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


Также там были карты. Я уже упоминал, что начинали мы с Grafana вместо Chronograf потому что для Grafana в виде плагинов доступны карты, на которых можно было смотреть координаты скутеров. К сожалению, возможности виджетов карт для Grafana очень ограничены, и в результате было гораздо проще за несколько дней написать свое собственное веб приложение с картами, для того чтобы не только видеть координаты в данный момент, но и отображать пройденный скутером маршрут, уметь фильтровать данные на карте, итд (весь тот функционал, который мы не смогли бы настроить в простом дашборде).


Один из уже упомянутых плюсов Influx возможность легко создавать свои собственные метрики.
Это позволяет использовать его для огромного множества сценариев.
Мы старались записывать туда всю полезную информацию: заряд батареи, состояние замка, работоспособность датчиков, bluetooth, GPS, множество других healthcheck'ов.
Все это мы и отображали на админ панели.


Конечно, самым главным критерием для нас было состояние работы скутера фактически Influx проверяет это сам и показывает в разделе Nodes "зелеными лампочками".
Делается это функцией deadman мы использовали ее же для понимания работоспособности нашей коробочки и отсылки тех самых алертов в Slack.


Кстати, мы называли скутеры по именами персонажей из Симпсонов так их было удобно отличать друг от друга


Да и вообще так было веселее. Постоянно звучали фразы вроде "Ребята Смитерс умер!"



Строковые метрики


Важно, что InfluxDB позволяет хранить не только числовые значения, как в случае с Victoria Metrics.


Казалось бы, это не так важно ведь если не считать логов, любые метрики можно хранить в виде чисел (всего лишь добавить маппинг для известных состояний своего рода enum)?


В нашем случае, был как минимум один сценарий, когда строковые метрики были очень полезны.
Так уж получилось, что поставщик наших "умных зарядок" был сторонним, мы не имели никакого контроля над процессом разработки и информацией, которую эти зарядки могут поставлять.


В результате API зарядок было далеко от идеала, но основной проблемой было то, что мы не всегда могли понять их состояние.
Тут на помощь и пришел Influx. Мы просто-напросто записывали приходящий нам строковый status в поле базы InfluxDB без изменений.


Какое-то время туда попадали только значения вида "online" и "offline", на основе чего у нас в админке отображалась информация,
а в Slack приходили уведомления. Однако в какой-то момент туда стали попадать так же значения вида "disconnected".
Как позже выяснилось, этот статус высылался однократно после потери связи, если зарядка не могла установить соединение с сервером после какого-то количества попыток.


Таким образом, если бы мы использовали только фиксированный набор значений мы могли бы не увидеть этих изменений в прошивке в нужный момент времени.


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



Помимо обычных метрик, мы так же записывали в InfluxDB информацию о GPS локации. Это было невероятно удобно для мониторинга местонахождения скутеров в нашей админской панели.
Фактически, мы всегда знали где и какой скутер был в нужный нам момент времени.


Очень сильно нам это пригодилось, когда мы разыскивали скутер (смотри выводы в конце).


Мониторинг инфраструктуры


Помимо самих скутеров, нам было необходимо мониторить и всю нашу (довольно обширную) инфраструктуру.
Очень обобщенная архитектура выглядела примерно так:



Если выделить чисто стек мониторинга, то он выглядит следующим образом:


Из того что мы хотели бы проверять в облаке, это:


  • Базы данных
  • Keycloak
  • Микросервисы

Так как все наши облачные сервисы находятся в Kubernetes, то было бы неплохо собирать информацию и о его состоянии.
К счастью, Telegraf "из коробки" может собирать огромное количество метрик о состоянии Kubernetes кластера, а Chronograf сразу предлагает для этого красивые дашборды.


Мы следили в основном за работоспособностью подов и потреблением памяти. В случае падения алерты в Slack.


Для отслеживания подов в Kubernetes есть два пути: DaemonSet и Sidecar.
Оба способа подробно описаны в этом блог посте.
Мы использовали Telegraf Sidecar и помимо метрик собирали логи подов.
В нашем случае с логами пришлось повозится. Несмотря на то что Telegraf умеет вытаскивать логи из Docker API, мы хотели иметь единообразный сбор логов с нашими конечными устройствами и настраивали для этого syslog для контейнеров. Возможно, это решение не было красивым, но нареканий в его работе не было и логи хорошо отображались в Chronograf'e.


Мониторить мониторинг???

В конце концов встал извечный вопрос мониторинга систем мониторинга, но к счастью, или к сожалению, на это у нас просто не хватило времени.
Хотя Telegraf легко умеет отправлять свои собственные метрики или собирать метрики InfluxDB базы для отправки либо в тот же Influx, либо куда-то еще.


Выводы


Какие выводы мы сделали по результатам пилота?


Как можно делать мониторинг


В первую очередь TICK стек полностью оправдал наши ожидания, и дал нам даже больше возможностей, чем те на которые мы рассчитывали изначально.
Весь функционал, который был нам необходим, присутствовал. Все что мы с ним делали работало без проблем.


Производительность

Основная проблема TICK стека в бесплатной версии отсутствие возможностей по скалированию. Для нас это не стало проблемой.


Мы не собирали точных данных/цифр о нагрузке, но мы собирали данные с примерно 30и скутеров одновременно.
Каждый из них собирал более трех десятков метрик. Одновременно собирались логи с устройств. Сбор и отправка данных происходили каждые 10 секунд.


Важно отметить, что спустя полторы недели пилота, когда основную массу "детских болячек" удалось исправить и самые важные проблемы уже были решены,
нам пришлось снизить частоту отправки данных на сервер до 30и секунд. Это стало необходимо, потому что трафик на наших LTE SIM картах начал быстро таять.
Основную массу трафика съедали логи, сами метрики даже с 10и-секундным интервалом практически не тратили его.


В итоге, спустя еще какое-то время мы совсем отключили сбор логов на устройствах, так как конкретные проблемы уже были очевидны и без постоянного сбора.
В некоторых случаях, если просмотр логов все же был необходим мы просто подключались через WireGuard по VPN.


Еще добавлю, что каждый отдельный environment у нас был отделен друг от друга, и вышеописанная нагрузка была актуальна только для продакшен среды.
В среде разработчиков у нас был поднят отдельный инстанс InfluxDB который продолжал собирать данные раз в 10 секунд и мы не уткнулись в какие-либо проблемы с производительностью.


TICK идеально для небольших-средних проектов

На основе этой информации я бы сделал вывод, что TICK стек идеально подходит для относительно небольших проектов или проектов, у которых точно не ожидается какого-либо HighLoad.


Если у вас нет тысяч подов или сотен машин даже один инстанс InfluxDB прекрасно справится с нагрузкой.
В некоторых случаях вас может устроить Influx Relay как примитивное решение по High Availability.


И, само собой, никто не мешает вам настраивать "вертикальное" скалировние и просто выделить различные сервера под различные типы метрик.


Если же вы не уверены в ожидаемой нагрузке на сервисы мониторинга, или у вас гарантированно есть/будет очень "тяжелая" архитектура бесплатную версию TICK стека использовать я бы не порекомендовал.
Конечно, простым решением было бы приобретение InfluxDB Enterprise но тут я не могу как-то прокомментировать, так как сам не знаком с тонкостями. Кроме того, что это очень дорогои точно не подойдет для мелких компаний.


В таком случае, на сегодняшний день, я бы порекомендовал посмотреть в сторону сбора метрик через Victoria Metrics и логов с помощью Loki.
Правда, снова оговорюсь, что Loki/Grafana значительно менее удобны (в виду своей большей универсальности) чем готовый TICK, но зато они бесплатны.


Важно: вся описанная здесь информация актуальна для версии Influx 1.8, в данный момент вот-вот должен выйти в релиз Influx 2.0.
Пока не довелось попробовать его в боевых условиях и сложно делать выводы об улучшениях, точно еще лучше стал интерфейс, упростилась архитектура (без kapacitor и chronograf),
появились темплейты ("киллер фича" можно отслеживать игроков в Fortnite и получать нотификации когда твой любимый игрок выигрывает партию). Но, к сожалению, в данный момент в версии 2 нет ключевой вещи, по которой мы выбрали первую версию нет сбора логов.
Этот функционал в Influx 2.0 тоже появится, но каких-либо сроков, даже примерных, найти не удалось.


Как не нужно делать IoT платформы (теперь)


В конце концов, запустив пилот мы сами собрали свой полноценный IoT стек, за неимением подходящей по нашим меркам альтернативы.
Однако, с недавнего времени в Beta версии доступна OpenBalena жаль ее не было когда мы начинали делать проект.


Конечный результат и та платформа на основе Ansible + TICK + WireGuard, которую мы собрали самостоятельно нас полностью устраивает. Но на сегодняшний день, я бы порекомендовал внимательней посмотреть на Balena прежде чем пытаться собрать свою IoT платформу самим.


Потому что, в конечном итоге она умеет делать большую часть того, что мы делали, при этом OpenBalena бесплатна, а код открыт.
Оно уже умеет не просто рассылать обновления, но и VPN там уже вшит и заточен под использование в IoT среде.


А совсем недавно они и вовсе выпустили свою Hardware, которая легко подключается в их экосистему.


Эй, а что с пропавшим скутером?


Итак скутер, "Ральф", бесследно исчез.
Мы сразу побежали смотреть карту в нашей "админке", с данными GPS метрик из InfluxDB.


Благодаря данным мониторинга, мы легко определили, что парковку скутер покинул около 21:00 прошлого дня, проехал где-то полчаса до какого-то района и был запаркован до 5и утра рядом с каким-то немецким домом.
После 5и утра данных мониторинга не поступало это означало либо полный разряд дополнительной батареи, либо злоумышленник догадался-таки извлечь умную начинку из скутера.
Несмотря на это, по тому адресу, где находился скутер все же была вызвана полиция. Скутера там не оказалось.
Однако владелец дома тоже был этому удивлен, так как он действительно вчера вечером приехал на этом скутере из офиса домой.


Как выяснилось, один из сотрудников поддержки приехал рано утром и забрал скутер, увидев, что у него полностью разрядилась дополнительная батарея и повез его (пешком) на парковку. А дополнительная батарея вышла из строя из-за попадания влаги.


Мы украли скутер сами у себя. Не знаю, кстати, как и кто потом разруливал вопрос с делом в полиции, но мониторинг отработал отлично...

Подробнее..

Перевод DataHub универсальный инструмент поиска и обнаружения метаданных

28.09.2020 12:18:44 | Автор: admin

DataHub: универсальный инструмент поиска и обнаружения метаданных.


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


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


Масштабирование метаданных


Чтобы повысить продуктивность группы данных LinkedIn, мы ранее разработали и открыли исходный код WhereHows центральное хранилище метаданных и портал для наборов данных. Тип хранимых метаданных включает как технические метаданные (например, местоположение, схемы, разделы, владение), так и метаданные процесса (например, происхождение, выполнение задания). WhereHows также имеет поисковую систему, которая помогает находить интересующие вас наборы данных.


С момента нашего первого выпуска WhereHows в 2016 году, в отрасли наблюдается растущий интерес к повышению продуктивности специалистов по обработке данных с помощью метаданных. Например, инструменты, разработанные в этой области, включают Dataportal AirBnb, Databook Uber, Metacat Netflix, Amundsen Lyft и совсем недавно Data Catalog от Google. В LinkedIn мы также были заняты расширением объема сбора метаданных для новых вариантов использования при сохранении конфиденциальности. Однако мы пришли к выводу, что у WhereHows были фундаментальные ограничения, которые не позволяли удовлетворить наши растущие потребности в метаданных. Вот то, что мы смогли узнать во время работы с масштабированием WhereHows:


  1. Push лучше, чем pull: хотя получение метаданных непосредственно из источника кажется наиболее простым способом сбора метаданных. Более масштабируемым является использование отдельных поставщиков метаданных для передачи информации в центральный репозиторий через API или сообщения. Такой подход на основе push также обеспечивает более своевременное отображение новых и обновленных метаданных.
  2. Общее лучше, чем конкретное: WhereHows категорически придерживается мнения о том, как должны выглядеть метаданные для набора данных или задания. Это приводит к упрямому API, модели данных и формату хранения. Небольшое изменение модели метаданных приведет к каскаду необходимых изменений вверх и вниз по стеку. Он был бы более масштабируемым, если бы мы разработали общую архитектуру, не зависящую от модели метаданных, которую она хранит и обслуживает. Это, в свою очередь, позволило бы нам сосредоточиться на адаптации и развитии строго самоуверенных моделей метаданных, не беспокоясь о нижних уровнях стека.
  3. Онлайн так же важен, как и офлайн. После того, как метаданные собраны, естественно необходимо проанализировать эти метаданные, чтобы извлечь из них пользу. Одно из простых решений сбросить все метаданные в автономную систему, такую как Hadoop, где можно выполнять произвольный анализ. Однако вскоре мы обнаружили, что одной только поддержки автономного анализа недостаточно. Есть много вариантов использования, таких как управление доступом и обработка конфиденциальности данных, для которых необходимо запрашивать последние метаданные в Интернете.
  4. Взаимоотношения действительно важны. Метаданные часто передают важные взаимосвязи (например, происхождение, владение и зависимости), которые обеспечивают мощные возможности, такие как анализ воздействия, объединение данных, повышение релевантности поиска и т. д.
  5. Многоцентровая вселенная: мы поняли, что недостаточно просто моделировать метаданные, сосредоточенные вокруг одного объекта (набора данных). Существует целая экосистема данных, кода и человеческих сущностей (наборы данных, специалисты по обработке данных, команды, код, API микросервисов, показатели, функции ИИ, модели ИИ, информационные панели, записные книжки и т. Д.), Которые необходимо интегрировать и связать через единый граф метаданных.

Встречайте DataHub


Примерно год назад мы вернулись к чертежной доске и заново создали WhereHows с нуля, основываясь на этих знаниях. В то же время мы осознали растущую потребность LinkedIn в единообразном поиске и обнаружении различных объектов данных, а также в графе метаданных, которая соединяет их вместе. В результате мы решили расширить масштаб проекта, чтобы создать полностью обобщенный инструмент поиска и обнаружения метаданных, DataHub, с амбициозным видением: соединить сотрудников LinkedIn с данными, которые для них важны.


Мы разделили монолитный стек WhereHows на два отдельных стека: интерфейс модульного пользовательского интерфейса и бэкэнд общей архитектуры метаданных. Новая архитектура позволила нам быстро расширить сферу сбора метаданных, не ограничиваясь только наборами данных и заданиями. На момент написания DataHub уже хранит и индексирует десятки миллионов записей метаданных, которые охватывают 19 различных сущностей, включая наборы данных, показатели, задания, диаграммы, функции ИИ, людей и группы. Мы также планируем в ближайшем будущем внедрить метаданные для моделей и меток машинного обучения, экспериментов, информационных панелей, API микросервисов и кода.


Модульный интерфейс


Веб-приложение DataHub это то, как большинство пользователей взаимодействуют с метаданными. Приложение написано с использованием Ember Framework и работает на среднем уровне Play. Чтобы сделать разработку масштабируемой, мы используем различные современные веб-технологии, включая ES9, ES.Next, TypeScript, Yarn with Yarn Workspaces, а также инструменты качества кода, такие как Prettier и ESLint. Уровни представления, управления и данных разделены на пакеты, так что определенные представления в приложении построены на основе композиции соответствующих пакетов.


Структура обслуживания компонентов


Применяя модульную инфраструктуру пользовательского интерфейса, мы создали веб-приложение DataHub как серию связанных компонентов, согласованных по функциям, которые сгруппированы в устанавливаемые пакеты. Эта архитектура пакета использует в основе Yarn Workspaces и надстройки Ember и разбита на компоненты с использованием компонентов и сервисов Ember. Вы можете думать об этом как о пользовательском интерфейсе, который построен с использованием небольших строительных блоков (например, компонентов и сервисов) для создания более крупных строительных блоков (например, надстроек Ember и пакетов npm / Yarn), которые при объединении в конечном итоге составляют веб-приложение DataHub .


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


Взаимодействие с DataHub


На самом высоком уровне интерфейс обеспечивает три типа взаимодействия: (1) поиск, (2) просмотр и (3) просмотр / редактирование метаданных. Вот несколько примеров скриншотов из реального приложения:








Как и в обычной поисковой системе, пользователь может искать один или несколько типов объектов, предоставляя список ключевых слов. Они могут далее нарезать и нарезать результаты, фильтруя список аспектов. Опытные пользователи также могут использовать такие операторы, как OR, NOT и регулярное выражение, для выполнения сложного поиска.


Сущности данных в DataHub могут быть организованы и просматриваться в виде дерева, где каждой сущности разрешено появляться в нескольких местах дерева. Это дает пользователям возможность просматривать один и тот же каталог разными способами, например, с помощью конфигурации физического развертывания или функциональной организации бизнеса. Может быть даже выделенная часть дерева, показывающая только сертифицированные объекты, которые курируются в рамках отдельного процесса управления.


Последнее взаимодействие просмотр / редактирование метаданных также является наиболее сложным. У каждого объекта данных есть страница профиля, на которой показаны все связанные метаданные. Например, страница профиля набора данных может содержать метаданные о его схеме, владении, соответствии, работоспособности и происхождении. Он также может показать, как объект связан с другими, например, задание, которое создало набор данных, метрики или диаграммы, которые вычисляются из этого набора данных, и т. Д. Для метаданных, которые доступны для редактирования, пользователи также могут обновлять их непосредственно через пользовательский интерфейс.


Обобщенная архитектура метаданных


Чтобы полностью реализовать видение DataHub, нам нужна была архитектура, способная масштабироваться с помощью метаданных. Проблемы масштабируемости бывают четырех разных форм:


  1. Моделирование: моделируйте все типы метаданных и отношений в удобной для разработчиков манере.
  2. Прием: прием большого количества изменений метаданных в любом масштабе как через API, так и через потоки.
  3. Обслуживание: обслуживайте собранные необработанные и производные метаданные, а также множество сложных запросов к метаданным в любом масштабе.
  4. Индексирование: индексируйте метаданные в масштабе, а также автоматически обновляйте индексы при изменении метаданных.

Моделирование метаданных


Проще говоря, метаданные это данные, которые предоставляют информацию о других данных. Когда дело доходит до моделирования метаданных, это предъявляет два различных требования:


  1. Метаданные это также данные: для моделирования метаданных нам нужен язык, который по крайней мере так же многофункциональн, как те, которые используются для моделирования данных общего назначения.
  2. Метаданные распределены: нереально ожидать, что все метаданные поступают из одного источника. Например, система, которая управляет списком управления доступом (ACL) набора данных, скорее всего, будет отличаться от той, которая хранит метаданные схемы. Хорошая среда моделирования должна позволять нескольким командам независимо развивать свои модели метаданных, одновременно представляя единое представление всех метаданных, связанных с объектом данных.

Вместо того, чтобы изобретать новый способ моделирования метаданных, мы решили использовать Pegasus, хорошо зарекомендовавший себя язык схем данных с открытым исходным кодом, созданный LinkedIn. Pegasus разработан для моделирования данных общего назначения и поэтому хорошо работает с большинством метаданных. Однако, поскольку Pegasus не предоставляет явного способа моделирования отношений или ассоциаций, мы ввели некоторые специальные расширения для поддержки этих вариантов использования.


Чтобы продемонстрировать, как использовать Pegasus для моделирования метаданных, давайте рассмотрим простой пример, проиллюстрированный следующей измененной диаграммой сущностей-отношений (ERD).



Пример содержит три типа сущностей Пользователь, Группа и Набор данных представленных синими кружками на диаграмме. Мы используем стрелки для обозначения трех типов отношений между этими объектами, а именно OwnedBy, HasMember и HasAdmin. Другими словами, группа состоит из одного администратора и нескольких членов пользователя, которые, в свою очередь, могут владеть одним или несколькими наборами данных.


В отличие от традиционного ERD, мы помещаем атрибуты сущности и отношения непосредственно внутри круга и под именем отношения, соответственно. Это позволяет нам присоединять к объектам новый тип компонента, известный как аспекты метаданных. Разные команды могут владеть и развивать различные аспекты метаданных для одного и того же объекта, не мешая друг другу, таким образом выполняя требование моделирования распределенных метаданных. Три типа аспектов метаданных: владение, профиль и членство включены в приведенный выше пример в виде зеленых прямоугольников. Связь аспекта метаданных с сущностью обозначается пунктирной линией. Например, профиль может быть связан с пользователем, а владение может быть связано с набором данных и т. д.


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


Чтобы смоделировать пример в Pegasus, мы переведем каждую из сущностей, отношений и аспектов метаданных в отдельный файл схемы Pegasus (PDSC). Для краткости мы включим сюда только по одной модели из каждой категории. Во-первых, давайте взглянем на PDSC для объекта User:


{  "type": "record",  "name": "User",  "fields": [    {      "name": "urn",      "type": "com.linkedin.common.UserUrn",    },    {      "name": "firstName",      "type": "string",      "optional": true    },    {      "name": "lastName",      "type": "string",      "optional": true    },    {      "name": "ldap",      "type": "com.linkedin.common.LDAP",      "optional": true    }  ]}

Каждая сущность должна иметь глобально уникальный идентификатор в форме URN, который можно рассматривать как типизированный GUID. Сущность User имеет атрибуты, включая имя, фамилию и LDAP, каждое из которых соответствует необязательному полю в записи пользователя.


Далее следует модель PDSC для отношения OwnedBy:


{  "type": "record",  "name": "OwnedBy",  "fields": [    {      "name": "source",      "type": "com.linkedin.common.Urn",    },    {      "name": "destination",      "type": "com.linkedin.common.Urn",    },    {      "name": "type",      "type": "com.linkedin.common.OwnershipType",    }  ],  "pairings": [    {      "source": "com.linkedin.common.urn.DatasetUrn",      "destination": "com.linkedin.common.urn.UserUrn"    }  ]}

Каждая модель отношений, естественно, содержит поля источник и место назначения, которые указывают на конкретные экземпляры сущности с использованием их URN. Модель может дополнительно содержать другие поля атрибутов, например, в данном случае тип. Здесь мы также вводим настраиваемое свойство, называемое пары, чтобы ограничить отношения конкретными парами исходных и целевых типов URN. В этом случае отношение OwnedBy может использоваться только для подключения набора данных к пользователю.


Наконец, ниже вы найдете модель аспекта метаданных владения. Здесь мы решили смоделировать владение как массив записей, содержащих поля type и ldap. Однако при моделировании аспекта метаданных практически нет ограничений, если это действительная запись PDSC. Это позволяет удовлетворить требование метаданные это также данные, сформулированное ранее.


{  "type": "record",  "name": "Ownership",  "fields": [    {      "name": "owners",      "type": {        "type": "array",        "items": {          "name": "owner",          "type": "record",          "fields": [            {              "name": "type",              "type": "com.linkedin.common.OwnershipType"            },            {              "name": "ldap",              "type": "string"            }          ]        }      }    }  ]}

После того, как все модели созданы, возникает следующий логический вопрос: как связать их вместе, чтобы сформировать предлагаемый ERD. Мы отложим это обсуждение до раздела Индексирование метаданных в более поздней части этого сообщения.


Получение метаданных


DataHub предоставляет две формы приема метаданных: либо через прямые вызовы API, либо через поток Kafka. Первый предназначен для изменений метаданных, которые требуют согласованности чтения после записи, тогда как второй больше подходит для обновлений, ориентированных на факты.


API DataHub основан на Rest.li, масштабируемой строго типизированной сервисной архитектуре RESTful, широко используемой в LinkedIn. Поскольку Rest.li использует Pegasus в качестве определения интерфейса, все модели метаданных, определенные в предыдущем разделе, могут использоваться дословно. Прошли те времена, когда требовалось преобразование нескольких уровней моделей от API до хранилища API и модели всегда будут синхронизироваться.


Ожидается, что для приема на основе Kafka производители метаданных будут генерировать стандартизированное событие изменения метаданных (MCE), которое содержит список предлагаемых изменений конкретных аспектов метаданных, введенных с помощью соответствующего URN объекта. Схема для MCE находится в Apache Avro, но автоматически создается из моделей метаданных Pegasus.


Использование одной и той же модели метаданных для схем событий API и Kafka позволяет нам легко развивать модели без кропотливого обслуживания соответствующей логики преобразования. Однако, чтобы добиться истинной непрерывной эволюции схемы, нам нужно ограничить все изменения схемы, чтобы они всегда были обратно совместимы. Это применяется во время сборки с дополнительной проверкой совместимости.


В LinkedIn мы склонны больше полагаться на поток Kafka из-за слабой связи, которую он обеспечивает между производителями и потребителями. Ежедневно мы получаем миллионы MCE от различных производителей, и ожидается, что их объем будет расти экспоненциально только по мере того, как мы расширяем объем нашей коллекции метаданных. Чтобы построить конвейер приема потоковых метаданных, мы использовали Apache Samza в качестве нашей платформы обработки потоковой информации. Задание Samza приема специально разработано, чтобы быть быстрым и простым для достижения высокой пропускной способности. Он просто преобразует данные Avro обратно в Pegasus и вызывает соответствующий API Rest.li для завершения приема.



Обслуживание метаданных


После того, как метаданные были получены и сохранены, важно эффективно обслуживать необработанные и производные метаданные. DataHub поддерживает четыре типа часто встречающихся запросов к большому количеству метаданных:


  1. Документно-ориентированные запросы
  2. Графические запросы
  3. Сложные запросы, включающие соединения
  4. Полнотекстовый поиск

Для этого DataHub необходимо использовать несколько типов систем данных, каждая из которых специализируется на масштабировании и обслуживании ограниченных типов запросов. Например, Espresso это база данных NoSQL LinkedIn, которая особенно хорошо подходит для масштабируемого документально-ориентированного CRUD. Точно так же Galene может легко индексировать и обслуживать полнотекстовый поиск в Интернете. Когда дело доходит до нетривиальных запросов к графам, неудивительно, что специализированная графовая БД может выполнять на порядки лучше, чем реализации на основе СУБД. Однако оказывается, что структура графа также является естественным способом представления отношений внешнего ключа, позволяя эффективно отвечать на сложные запросы соединения.


DataHub дополнительно абстрагирует базовые системы данных с помощью набора общих объектов доступа к данным (DAO), таких как DAO ключ-значение, запрос DAO и поиск DAO. После этого реализация DAO для конкретной системы данных может быть легко заменена, без изменения какой-либо бизнес-логики в DataHub. В конечном итоге это позволит нам открыть DataHub с открытым исходным кодом с эталонными реализациями для популярных систем с открытым исходным кодом, в то же время используя все преимущества проприетарных технологий хранения LinkedIn.



Еще одно ключевое преимущество абстракции DAO стандартизированный сбор данных об изменениях (CDC). Независимо от типа базовой системы хранения данных, любая операция обновления через DAO ключ-значение автоматически генерирует событие аудита метаданных (MAE). Каждый MAE содержит URN соответствующего объекта, а также изображения до и после определенного аспекта метаданных. Это позволяет использовать лямбда-архитектуру, в которой MAE могут обрабатываться как пакетами, так и потоками. Подобно MCE, схема MAE также автоматически генерируется из моделей метаданных.


Индексирование метаданных


Последний недостающий элемент головоломки конвейер индексации метаданных. Это система, которая объединяет модели метаданных и создает соответствующие индексы в графической БД и поисковой системе для облегчения эффективных запросов. Эти бизнес-логики фиксируются в форме построителя индексов и построителей графиков и выполняются как часть задания Samza, обрабатывающего MAE. Каждый разработчик зарегистрировал свой интерес к конкретным аспектам метаданных в задании и будет вызван с соответствующим MAE. Затем построитель возвращает список идемпотентных обновлений, которые будут применяться к БД индекса поиска или графа.


Конвейер индексации метаданных также хорошо масштабируется, поскольку его можно легко разделить на основе URN объекта каждого MAE для поддержки упорядоченной обработки для каждого объекта.



Заключение и с нетерпением жду


В этом посте мы представили DataHub, нашу последнюю эволюцию в путешествии по метаданным в LinkedIn. Проект включает в себя интерфейс модульного пользовательского интерфейса и серверную часть архитектуры обобщенных метаданных.


DataHub работает в LinkedIn в течение последних шести месяцев. Каждую неделю его посещают более 1500 сотрудников, которые поддерживают поиск, обнаружение и различные рабочие процессы для конкретных действий. График метаданных LinkedIn содержит более миллиона наборов данных, 23 системы хранения данных, 25 тысяч показателей, более 500 функций искусственного интеллекта и, что наиболее важно, всех сотрудников LinkedIn, которые являются создателями, потребителями и операторами этого графика.


Мы продолжаем улучшать DataHub, добавляя в продукт больше интересных пользовательских историй и алгоритмов релевантности. Мы также планируем добавить встроенную поддержку GraphQL и использовать язык Pegasus Domain Specific Language (PDL) для автоматизации генерации кода в ближайшем будущем. В то же время мы активно работаем над тем, чтобы поделиться этой эволюцией WhereHows с сообществом разработчиков ПО с открытым исходным кодом, а после публичного выпуска DataHub мы сделаем объявление.

Подробнее..

Обзор возможностей Kubespray Отличие оригинальной версии и нашего форка

20.09.2020 14:22:27 | Автор: admin

23 сентября 20.00 МСК Сергей Бондарев проведёт бесплатный вебинар Обзор возможностей Kubespray, где расскажет, как готовят kubespray, чтобы получилось быстро, эффективно и отказоустойчиво.


Сергей Бондарев расскажет отличие оригинальной версии и нашего форка:



Отличие оригинальной версии и нашего форка.


Те, кто с кубспреем уже сталкивался, наверное сейчас недоумевают, почему я kubeadm противопоставляю кубспрею, ведь кубспрей для создания кластера, как раз и вызывает кубадм и на первый взгляд выглядит, как скрипт установки пакетов и автоматизированного запуска.


Но так было не всегда, изначально кубспрей устанавливал все компоненты самостоятельно:


  • собирал кластер etcd;
  • устанавливал кублеты, генерил сертификаты, конфиги и токены доступа для статик подов контролплейна и прочих служебных компонентов;
  • создавал сервис аккаунты для рабочих узлов и подключал их в кластер.

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


В итоге разница между кластерами, созданными моим форком и оригинальным это kube-proxy и сроки действия сертификатов.


В моем форке все осталось, как было раньше куб-прокси запускается, как статик под, сертификаты выписываются на 100 лет.


В Kubeadm куб-прокси запускается, как daemonset, а сертификаты выписываются на 1 год, и их надо периодически продлевать. kubeadm наконец-то научился это делать одной командой.


Разница небольшая, и на сегодня мы используем оба варианта.


Особенности (недостатки) при промышленной эксплуатации:


Сценарий универсальный, поэтому не очень быстрый. Собственный можно значительно ускорить, выкинув проверки, запускаясь из готового образа.


Сценарий сложный, есть нелогичные места, тяжелое наследие legacy. Установка доп. контроллеров и софта через кубспрей хороша для обучения и тестов. В пром. эксплуатации зависеть от кубспрея не очень здравая идея, плюс обновление софта реализовано методом "убил-сделал новый" значит перерыв в обслуживании.


Может добавлять только рабочие узлы, с мастерами есть некоторые нюансы с сертификатами, и сценарий не отрабатывает всех возможных проблем, которые могут возникнуть.


Например у меня была проблема с кубадмом, когда он падал в момент добавления второго и третьего мастера, и после этого кубспрей делал kubeadm reset на узле, и пробовал добавить мастер еще раз.


Вот только проблема была в том, что к моменту сбоя второй инстанс etcd уже успевал зарегистрироваться, и так как он тоже удалялся после ресета, то получали кошмар кластер etcd из двух узлов, один из которых удалили, а второй больше не принимает клиентов. В итоге кластер умер, не родившись.


Opensource как он есть.


Всё это и многое другое на бесплатном вебинаре Обзор возможностей Kubespray 23 сентября 20.00 МСК.


Присоединяйтесь!

Подробнее..

Перевод 3 года с Kubernetes в production вот что мы поняли

21.09.2020 12:22:00 | Автор: admin
Прим. перев.: в очередной статье из категории lessons learned DevOps-инженер австралийской компании делится главными выводами по итогам продолжительного использования Kubernetes в production для нагруженных сервисов. Автор затрагивает вопросы Java, CI/CD, сетей, а также сложности K8s в целом.

Свой первый кластер Kubernetes мы начали создавать в 2017 году (с версии K8s 1.9.4). У нас было два кластера. Один работал на bare metal, на виртуальных машинах RHEL, другой в облаке AWS EC2.

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

В конечном итоге Kubernetes упростил нам жизнь, однако путь к этому был тернистым и требовал полной смены парадигмы. Произошла тотальная трансформация не только набора навыков и инструментов, но и подхода к проектированию, мышления. Нам пришлось осваивать множество новых технологий и вкладывать значительные средства в развитие инфраструктуры и повышение квалификации команд.

Вот ключевые уроки, которые мы вынесли из опыта использования Kubernetes в production на протяжении трех лет.

1. Занимательная история с Java-приложениями


Когда речь заходит о микросервисах и контейнеризации, инженеры, как правило, избегают использования Java, прежде всего из-за ее печально известного несовершенного управления памятью. Впрочем, сегодня ситуация обстоит иначе и совместимость Java с контейнерами в последние годы улучшилась. В конце концов, даже такие популярные системы, как Apache Kafka и Elasticsearch, работают на Java.

В 20172018 годах некоторые наши приложения работали на Java восьмой версии. Частенько они отказывались функционировать в контейнерных средах вроде Docker и падали из-за проблем с heap-памятью и неадекватной работы сборщиков мусора. Как оказалось, эти проблемы были вызваны неспособностью JVM работать с механизмами контейнеризации Linux (cgroups и namespaces).

С тех пор Oracle приложила значительные усилия, чтобы повысить совместимость Java с миром контейнеров. Уже в 8-ой версии Java появились экспериментальные флаги JVM для решения этих проблем: XX:+UnlockExperimentalVMOptions и XX:+UseCGroupMemoryLimitForHeap.

Но, несмотря на все улучшения, никто не будет спорить, что у Java по-прежнему плохая репутация из-за чрезмерного потребления памяти и медленного запуска по сравнению с Python или Go. В первую очередь это связано со спецификой управления памятью в JVM и ClassLoader'ом.

Сегодня, если нам приходится работать с Java, мы по крайней мере стараемся использовать версию 11 или выше. И наши лимиты на память в Kubernetes на 1 Гб выше, чем ограничение на максимальный объем heap-памяти в JVM (-Xmx) (на всякий случай). То есть, если JVM использует 8 Гб под heap-память, лимит в Kubernetes на память для приложения будет установлен на 9 Гб. Благодаря этим мерам и улучшениям жизнь стала чуточку легче.

2. Обновления, связанные с жизненным циклом Kubernetes


Управление жизненным циклом Kubernetes (обновления, дополнения) вещь громоздкая и непростая, особенно если кластер базируется на bare metal или виртуальных машинах. Оказалось, что для перехода на новую версию гораздо проще поднять новый кластер и потом перенести в него рабочие нагрузки. Обновление существующих узлов попросту нецелесообразно, поскольку связано со значительными усилиями и тщательным планированием.

Дело в том, что в Kubernetes слишком много движущихся частей, которые необходимо учитывать при проведении обновлений. Для того, чтобы кластер мог работать, приходится собирать все эти компоненты вместе начиная с Docker и заканчивая CNI-плагинами вроде Calico или Flannel. Такие проекты, как Kubespray, KubeOne, kops и kube-aws, несколько упрощают процесс, однако все они не лишены недостатков.

Свои кластеры мы разворачивали в виртуальных машинах RHEL с помощью Kubespray. Он отлично себя зарекомендовал. В Kubespray были сценарии для создания, добавления или удаления узлов, обновления версии и почти все, что необходимо для работы с Kubernetes в production. При этом сценарий обновления сопровождался предостережением о том, что нельзя пропускать даже второстепенные (minor) версии. Другими словами, чтобы добраться до нужной версии, пользователю приходилось устанавливать все промежуточные.

Главный вывод здесь в том, что если вы планируете использовать или уже используете Kubernetes, продумайте свои шаги, связанные с жизненным циклом K8s и то, как он вписывается в ваше решение. Создать и запустить кластер часто оказывается проще, чем поддерживать его в актуальном состоянии.

3. Сборка и деплой


Будьте готовы к тому, что придется пересмотреть пайплайны сборки и деплоя. При переходе на Kubernetes у нас прошла радикальная трансформация этих процессов. Мы не только реструктурировали пайплайны Jenkins, но с помощью инструментов, таких как Helm, разработали новые стратегии сборки и работы с Git'ом, тегирования Docker-образов и версионирования Helm-чартов.

Вам понадобится единая стратегия для поддержки кода, файлов с deploymentами Kubernetes, Dockerfiles, образов Docker'а, Helm-чартов, а также способ связать все это вместе.

После нескольких итераций мы остановились на следующей схеме:

  • Код приложения и его Helm-чарты находятся в разных репозиториях. Это позволяет нам версионировать их независимо друг от друга (семантическое версионирование).
  • Затем мы сохраняем карту с данными о том, какая версия чарта к какой версии приложения привязана, и используем ее для отслеживания релиза. Так, например, app-1.2.0 развертывается с charts-1.1.0. Если меняется только файл с параметрами (values) для Helm, то меняется только patch-составляющая версии (например, с 1.1.0 на 1.1.1). Все требования к версиям описываются в примечаниях к релизу (RELEASE.txt) в каждом репозитории.
  • К системным приложениям, таким как Apache Kafka или Redis (чей код мы не собирали и не модифицировали), у нас иной подход. Нам не были нужны два репозитория, поскольку Docker-тег был просто частью версионирования Helm-чартов. Меняя Docker-тег для обновления, мы просто увеличиваем основную версию в теге чарта.

(Прим. перев.: сложно пройти мимо такой трансформации и не указать на нашу Open Source-утилиту для сборки и доставки приложений в Kubernetes werf как один из способов упростить решение тех проблем, с которыми столкнулись авторы статьи.)

4. Тесты Liveliness и Readiness (обоюдоострый меч)


Проверки работоспособности (liveliness) и готовности (readiness) Kubernetes отлично подходят для автономной борьбы с системными проблемами. Они могут перезапускать контейнеры при сбоях и перенаправлять трафик с нездоровых экземпляров. Но в некоторых условиях эти проверки могут превратиться в обоюдоострый меч и повлиять на запуск и восстановление приложения (это особенно актуально для stateful-приложений, таких как платформы обмена сообщениями или базы данных).

Наш Kafka стал их жертвой. У нас был stateful set из 3 Broker'ов и 3 Zookeeper'ов с replicationFactor = 3 и minInSyncReplica = 2. Проблема возникала при перезапуске Kafka после случайных сбоев или падений. Во время старта Kafka запускал дополнительные скрипты для исправления поврежденных индексов, что занимало от 10 до 30 минут в зависимости от серьезности проблемы. Такая задержка приводила к тому, что liveliness-тесты постоянно завершались неудачей, из-за чего Kubernetes убивал и перезапускал Kafka. В результате Kafka не мог не только исправить индексы, но даже стартовать.

Единственным решением на тот момент виделась настройка параметра initialDelaySeconds в настройках liveliness-тестов, чтобы проверки проводились только после запуска контейнера. Главная сложность, конечно, в том, чтобы решить, какую именно задержку установить. Отдельные запуски после сбоя могут занимать до часа времени, и это необходимо учитывать. С другой стороны, чем больше initialDelaySeconds, тем медленнее Kubernetes будет реагировать на сбои во время запуска контейнеров.

В данном случае золотой серединой является значение initialDelaySeconds, которое лучше всего удовлетворяет вашим требованиям к устойчивости и в то же время дает приложению достаточно времени для успешного запуска во всех сбойных ситуациях (отказы диска, проблемы с сетью, системные сбои и т.д.)

Обновление: в свежих версиях Kubernetes появился третий тип тестов под названием startup probe. Он доступен как альфа-версия, начиная с релиза 1.16, и как бета-версия с 1.18.

Startup probe позволяет решить вышеописанную проблему, отключая readiness и liveliness-проверки до тех пор, пока контейнер не запустится, тем самым позволяя приложению нормально стартовать.

5. Работа с внешними IP


Как оказалось, использование статических внешних IP для доступа к сервисам оказывает серьезное давление на механизм отслеживания соединений системного ядра. Если его не продумать тщательно, он может сломаться.

В своем кластере мы используем Calico как CNI и BGP в качестве протокола маршрутизации, а также для взаимодействия с пограничными маршрутизаторами. В Kube-proxy задействован режим iptables. Доступ к нашему очень загруженному сервису в Kubernetes (ежедневно он обрабатывает миллионы подключений) открываем через внешний IP. Из-за SNAT и маскировки, проистекающих от программно-определяемых сетей, Kubernetes нуждается в механизме отслеживания всех этих логических потоков. Для этого K8s задействует такие инструменты ядра, как сonntrack и netfilter. С их помощью он управляет внешними подключениями к статическому IP, который затем преобразуется во внутренний IP сервиса и, наконец, в IP-адрес pod'а. И все это делается с помощью таблицы conntrack и iptables.

Однако возможности таблицы conntrack небезграничны. При достижении лимита кластер Kubernetes (точнее, ядро ОС в его основе) больше не сможет принимать новые соединения. В RHEL этот предел можно проверить следующим образом:

$  sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_count = 167012net.netfilter.nf_conntrack_max = 262144

Один из способов обойти это ограничение объединить несколько узлов с пограничными маршрутизаторами, чтобы входящие соединения на статический IP распределялись по всему кластеру. В случае, если у вас в кластере большой парк машин, такой подход позволяет значительно увеличить размер таблицы conntrack для обработки очень большого числа входящих соединений.

Это полностью сбило нас с толку, когда мы только начинали в 2017 году. Однако сравнительно недавно (в апреле 2019-го) проект Calico опубликовал подробное исследование под метким названием Why conntrack is no longer your friend (есть такой её перевод на русский язык прим. перев.).

Действительно ли вам нужен Kubernetes?


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

С другой стороны, работа в облаке и возможность использовать Kubernetes как услугу избавит вас от большинства забот, связанных с обслуживанием платформы (вроде расширения CIDR внутренней сети и обновления Kubernetes).

Сегодня мы пришли к пониманию того, что главный вопрос, который следует задать себе действительно ли вам нужен Kubernetes? Он поможет оценить, насколько глобальна имеющаяся проблема и поможет ли с ней справиться Kubernetes.

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

Помните, что технология исключительно ради технологии бессмысленна.

P.S. от переводчика


Читайте также в нашем блоге:

Подробнее..

АйТиБалаган! 3 Зачем DevOps-инженеру программирование и что такое виртуализация

21.09.2020 14:20:44 | Автор: admin

IT-балаганят, спорят, делятся кейсами:



Темы:


  • Что такое DevOps;
  • Зачем разработчику уметь в DevOps;
  • Зачем DevOps-инженеру уметь в программирование?
  • Виртуализация VS контейнеризация;
  • Минимальный набор знаний по DevOps в 2к20;
  • Будущее DevOps;
  • VMWare юзкейсы;
  • VMWorld 2020 онлайн что за зверь?

Навигация:


О DevOps и всём-всём-всём...

0:00 Начало;
3:35 Представление гостей;
7:38 Что такое DevOps;
33:30 Зачем DevOps-инженеру программирование;
41:40 Фреймворки в DevOps;
49:50 Как уживаться разработчикам и девопсеру;
1:12:40 Будущее DevOps;
1:19:30 Минимальный набор знаний для девопсера;
1:26:30 Перерыв;
1:32:20 Девопс это сисадмин для программистов?
1:34:40 Про зарплаты;
1:38:00 Про контейнеризацию;
1:47:55 Про продукты VWware и виртуализацию;
1:57:15 Про VMWorld;
2:00:20 Конференции и ресурсы по девопсу;
2:10:00 Как быть с большим объемом информации в профессии;
2:23:23 Про безопасность и DevOps;
2:48:10 Куда развиваться девопсеру.


P.S. В АйТиБалагане раз и не два поминался SRE. Если тема вам интересна, и есть желания стать SRE-инженером, то есть смысл присмотреться к онлайн-интенсиву SRE. На три дня вы погрузитесь в теорию и практику SRE: разработаете и будете поддерживать сайт, состоящий из нескольких микросервисов. Научитесь правильно распределять ограниченные ресурсы для обеспечения быстродействия, отказоустойчивости и доступности сайта для максимальной надежности, достаточной, чтобы были довольны пользователи. 1113 декабря сего года wellcome!


Спикеры курса SRE

Подробнее..

Наиболее интересные факты о Ceph по результатам опроса пользователей в 2019 году

23.09.2020 00:14:39 | Автор: admin
TL;DR: наиболее интересные факты о Ceph в таблицах и графиках, полученных из результатов опроса пользователей Ceph в 2019 году.



Какой у вас тип организации?


Ответили на вопрос: 405
Пропустили вопрос: 0
Ответ Ответили %
Коммерческая 257 63.46
Правительственная 19 4.69
Военная 0 0
Образовательная 57 14.07
Некоммерческая 16 3.95
Другая 56 13.82



Почему используете Ceph?


Ответили на вопрос: 405
Пропустили вопрос: 0
Ответ Ответили %
Открытый исходный код 367 90.62
Масштабируемость 326 80.49
Стоимость 247 60.99
Функционал 223 55.06
Отказоустойчивость 309 76.30
Надежность\живучесть\целостность данных 279 68.89
Производительность 125 30.86
Возможность внедрения со смежными технологиями 120 29.63
Другое 13 3.21



Как давно используете Ceph?


Ответили на вопрос: 405
Пропустили вопрос: 0
Ответ Ответили %
Менее года 72 17.78
1-2 года 65 16.05
2-5 лет 203 50.12
Более 5 лет 58 14.32
Не пользуюсь 7 1.73



В каких странах у вас развернут Ceph?


Ответили на вопрос: 405
Пропустили вопрос: 0
Ответ Ответили %
Другая 249 61.48
США 87 21.48
Германия 73 18.02
Китай 30 7.41
Великобритания 29 7.16
Россия 26 6.42
Франция 20 4.94



Как устанавливаете Ceph?


Ответили на вопрос: 344
Пропустили вопрос: 61
Ответ Ответили %
Пакеты от разработчиков 170 49.42
Пакеты из дистрибутивов 131 38.08
Пакеты от производителей 93 27.03
Собираем свои пакеты 26 7.56
Собираем свою версию 12 3.49



N.B. Если всё ещё немного плаваете в вопросах, как устанавливать и разворачивать правильно Ceph c 15 октября запускается курс по Ceph от практиков. Вы изначально получите системные знания по базовым понятиям и терминам, а по окончании курса научитесь полноценно устанавливать, настраивать и управлять Ceph.


Как разворачиваете?


Ответили на вопрос: 312
Пропустили вопрос: 93
Ответ Ответили %
Ansible 134 42.95
ceph-deploy 133 42.63
Другое (тут Proxmox + CLI) 75 24.04



Применяемая операционная система


Ответили на вопрос: 344
Пропустили вопрос: 61
Ответ Ответили %
Ubuntu 131 38.08
Debian 101 29.36
CentOS 125 36.34
RHEL 34 9.88
SLES\OpenSuse 21 6.10
Другая 55 15.99



Какое оборудование применяете?


Ответили на вопрос: 343
Пропустили вопрос: 62
Ответ Ответили %
Supermicro 171 50.00
Dell 131 38.30
HPE 89 26.02
Другое 162 47.23



Какие накопители применяете?


Ответили на вопрос: 342
Пропустили вопрос: 63
Ответ Ответили %
HDD 305 89.18
SSD (SAS, SATA) 261 76.32
NVMe 161 47.08
Другие 21 6.14



Используете отдельную сеть для OSD?


Ответили на вопрос: 342
Пропустили вопрос: 63
Ответ Ответили %
Да 249 72.81
Нет 93 27.19


Какое ПО используете совместно с Ceph?


Ответили на вопрос: 340
Пропустили вопрос: 65
Ответ Ответили %
RBD на Linux серверах 123 36.18
Proxmox 114 33.53
KVM 105 30.88
OpenStack 97 28.53
Kubernetes 88 25.88
Другое 178 52.35



Для чего используете RBD?


Ответили на вопрос: 295
Пропустили вопрос: 110
Ответ Ответили %
Виртуализация 232 78.64
Резервное копирование 133 45.08
Облака 122 41.36
Контейнеры 117 39.66
Архивное хранилище 94 31.86



Для чего используете RGW?


Ответили на вопрос: 163
Пропустили вопрос: 242
Ответ Ответили %
Архивное хранение 105 64.42
Резервное копирование 92 56.44
Big data и аналитика 61 37.42



Для чего используете CephFS?


Ответили на вопрос: 184
Пропустили вопрос: 221
Ответ Ответили %
NAS общего назначения 98 53.26
Резервное копирование 87 47.28
Домашние каталоги 63 34.24
Архивное хранение 54 29.35
Media\Streaming 44 23.91



Какой мониторинг используете?


Ответили на вопрос: 312
Пропустили вопрос: 93
Ответ Ответили %
Ceph Dashboard 170 54.49
Grafana (свои настройки) 135 43.27
Prometheus 126 40.38
Proxmox 91 29.17
Zabbix 60 19.23
Nagios\Icinga 54 17.31



N.B. Если есть необходимость подтянуть, а то и научиться правильному логированию и мониторингу, добро пожаловать на курс Мониторинг и логирование инфраструктуры в Kubernetes. Сейчас можно приобрести курс с существенной скидкой. На курсе узнаете Узнаете, что именно мониторить, какие метрики собирать и как настраивать алерты для оперативного поиска и устранения проблем в кластере. Какие метрики стоит собирать с помощью Prometheus? Как визуализировать мониторинг с помощью Grafana и как грамотно настроить алерты?
Данные для графиков взяты отсюда.
Подробнее..

Перевод Наши выводы за год миграции GitLab.com на Kubernetes

23.09.2020 10:08:04 | Автор: admin
Прим. перев.: адаптацию Kubernetes в GitLab считают одним из двух главных факторов, способствующих росту компании. Тем не менее, до недавнего времени инфраструктура онлайн-сервиса GitLab.com была построена на виртуальных машинах, и только около года назад началась её миграция в K8s, которая до сих пор не завершена. Рады представить перевод недавней статьи SRE-инженера GitLab о том, как это происходит и какие выводы делают инженеры, участвующие в проекте.



Вот уже около года наше инфраструктурное подразделение занимается миграцией всех сервисов, работающих на GitLab.com, в Kubernetes. За это время мы столкнулись с проблемами, связанными не только к перемещением сервисов в Kubernetes, но и с управлением гибридным deployment'ом во время перехода. О ценных уроках, полученных нами, и пойдет речь в этой статье.

С самого начала GitLab.com его серверы работали в облаке на виртуальных машинах. Этими виртуальными машинами управляет Chef, а их установка происходит с помощью нашего официального Linux-пакета. Стратегия развертывания на случай, если нужно обновить приложение, состоит в простом обновлении парка серверов скоординированным последовательным образом с помощью CI-пайплайна. Этот метод пусть медленный и чуточку скучный гарантирует, что GitLab.com применяет те же способы установки и конфигурирования, что и пользователи автономных (self-managed) инсталляций GitLab, применяющие для этого наши Linux-пакеты.

Мы используем такой метод, поскольку исключительно важно ощутить на себе все печали и радости, которые испытывают рядовые представители сообщества, когда устанавливают и настраивают свои копии GitLab. Этот подход хорошо работал в течение некоторого времени, однако когда число проектов на GitLab перевалило за 10 млн, мы поняли, что он больше не удовлетворяет нашим потребностям в масштабировании и развертывании.

Первые шаги к Kubernetes и cloud-native GitLab


В 2017-м был создан проект GitLab Charts для подготовки GitLab к развертыванию в облаке, а также для того, чтобы дать пользователям возможность устанавливать GitLab в кластеры Kubernetes. Тогда мы знали, что перенос GitLab в Kubernetes увеличит возможности масштабирования SaaS-платформы, упростит развертывания и повысит эффективность использования вычислительных ресурсов. В то же время многие функции нашего приложения зависели от примонтированных NFS-разделов, что замедляло переход с виртуальных машин.

Стремление к cloud native и Kubernetes позволило нашим инженерам планировать постепенный переход, в ходе которого мы отказались от некоторых зависимостей приложения от сетевых хранилищ, попутно продолжая разрабатывать новые функции. С тех пор, как мы начали планировать миграцию летом 2019-го, многие из этих ограничений были устранены, и процесс перевода GitLab.com на Kubernetes теперь идет полным ходом!

Особенности работы GitLab.com в Kubernetes


Для GitLab.com мы используем единый региональный кластер GKE, обрабатывающий весь трафик приложения. Чтобы минимизировать сложность (без того мудреной) миграции, мы концентрируемся на сервисах, которые не зависят от локального хранилища или NFS. GitLab.com использует преимущественно монолитную кодовую базу на Rails, и мы направляем трафик в зависимости от характеристик рабочей нагрузки на различные endpoint'ы, изолированные в свои собственные пулы узлов.

В случае фронтенда эти типы делятся на запросы к web, API, Git SSH/HTTPS и Registry. В случае бэкенда мы разбиваем job'ы в очереди по различным характеристикам в зависимости от предопределенных границ ресурсов, которые позволяют нам устанавливать целевые показатели уровня обслуживания (Service-Level Objectives, SLOs) для различных нагрузок.

Все эти сервисы GitLab.com настроены с помощью немодифицированного Helm-чарта GitLab. Конфигурация проводится в субчартах, которые могут быть выборочно включены по мере того, как мы постепенно переносим сервисы в кластер. Даже с учетом того, что было решено не включать в миграцию некоторые из наших stateful-сервисов, такие как Redis, Postgres, GitLab Pages и Gitaly, использование Kubernetes позволяет радикально сократить число VM, которыми управляет Chef в настоящее время.

Прозрачность и управление конфигурацией Kubernetes


Все настройки управляются самим GitLab'ом. Для этого используются три конфигурационных проекта на основе Terraform и Helm. Мы стараемся везде по возможности использовать сам GitLab для запуска GitLab'а, но для эксплуатационных задач у нас функционирует отдельная инсталляция GitLab. Она нужна для того, чтобы не зависеть от доступности GitLab.com при проведении развертываний и обновлений GitLab.com.

Хотя наши пайплайны для кластера Kubernetes работают на отдельной инсталляции GitLab, есть у репозиториев кода есть зеркала, публично доступные по следующим адресам:

  • k8s-workloads/gitlab-com конфигурационная обвязка GitLab.com для Helm-чарта GitLab;
  • k8s-workloads/gitlab-helmfiles содержит конфигурации для сервисов, которые не связаны с приложением GitLab непосредственно. В их число входят конфигурации для ведения логов и мониторинга кластера, а также для интегрированных инструментов вроде PlantUML;
  • Gitlab-com-infrastructure конфигурация Terraform для Kubernetes и старой (legacy) VM-инфраструктуры. Здесь настраиваются все ресурсы, необходимые для запуска кластера, включая сам кластер, пулы узлов, учетные записи служб, резервирование IP-адресов.


При внесении изменений показывается общедоступное краткое резюме со ссылкой на подробный diff, который SRE анализирует перед внесением изменений в кластер.

Для SRE ссылка ведет на подробный diff в инсталляции GitLab, которая используется для эксплуатации и доступ к которой ограничен. Это позволяет сотрудникам и сообществу без доступа к эксплуатационному проекту (он открыт только для SRE) просматривать предлагаемые изменения в конфигурации. Сочетая общедоступный экземпляр GitLab'а для кода с закрытым экземпляром для CI-пайплайнов, мы сохраняем единый рабочий процесс, в то же время гарантируя независимость от GitLab.com при обновлениях конфигурации.

Что мы выяснили за время миграции


В процессе переезда был накоплен опыт, который мы применяем к новым миграциям и deploymentам в Kubernetes.

1. Рост расходов из-за трафика между зонами доступности



Посуточная egress-статистика по парку Git-хранилищ на GitLab.com

Google делит свою сеть на регионы. Те, в свою очередь, разбиваются на зоны доступности (AZ). Git-хостинг связан с большими объемами данных, поэтому нам важно контролировать сетевой egress. В случае внутреннего трафика egress бесплатен только в том случае, если он остается в границах одной зоны доступности. На момент написания этой статьи мы отдаем примерно 100 Тб данных в обычный рабочий день (и это только для Git-репозиториев). Сервисы, которые в нашей старой топологии, основанной на VM, находились на одних и тех же виртуальных машинах, теперь работают в разных pod'ах Kubernetes. Это означает, что некоторая часть трафика, которая раньше была локальной для VM, может потенциально выходить за пределы зон доступности.

Региональные кластеры GKE позволяют охватывать несколько зон доступности для резервирования. Мы рассматриваем возможность разделить региональный кластер GKE на однозонные кластеры для сервисов, которые генерируют большие объемы трафика. Это позволит сократить расходы на egress при сохранении резервирования на уровне кластера.

2. Limit'ы, request'ы ресурсов и масштабирование



Число реплик, обрабатывающих production-трафик на registry.gitlab.com. Трафик достигает своего пика в ~15:00 UTC.

Наша история с миграцией началась в августе 2019-го, когда мы перенесли первый сервис реестр контейнеров GitLab (GitLab Container Registry) в Kubernetes. Этот критически важный сервис с высоким трафиком хорошо подошел для первой миграции, поскольку представляет собой stateless-приложение с малым числом внешних зависимостей. Первой проблемой, с которой мы столкнулись, стало большое число вытесненных pod'ов из-за нехватки памяти на узлах. Из-за этого нам пришлось менять request'ы и limit'ы.

Было обнаружено, что в случае приложения, у которого потребление памяти растет со временем, низкие значения для request'ов (резервирующих память для каждого pod'а) вкупе с щедрым жестким limit'ом на использование приводили к насыщению (saturation) узлов и высокому уровню вытеснений. Чтобы справиться с этой проблемой, было решено увеличить request'ы и снизить limit'ы. Это сняло давление с узлов и обеспечило жизненный цикл pod'ов, который не оказывал слишком высокого давления на узел. Теперь мы начинаем миграции с щедрыми (и почти одинаковыми) значениями request'ов и limit'ов, корректируя их по необходимости.

3. Метрики и логи



Инфраструктурное подразделение фокусируется на задержках, проценте ошибок и сатурации с установленными целями по уровню обслуживания (SLO), привязанными к общей доступности нашей системы.

За прошедший год одним из ключевых событий в инфраструктурном подразделении стали улучшения в мониторинге и работе с SLO. SLO позволили нам устанавливать цели по отдельным сервисам, за которыми мы пристально следили во время миграции. Но даже с такой улучшенной наблюдаемостью не всегда можно сразу увидеть проблемы, используя метрики и алерты. Например, сосредоточившись на задержках и проценте ошибок, мы не полностью охватываем все сценарии использования сервиса, проходящего миграцию.

Эта проблема была обнаружена почти сразу после переноса части рабочих нагрузок в кластер. Особенно остро она заявила о себе, когда пришлось проверять функции, число запросов к которым невелико, но у которых очень специфические конфигурационные зависимости. Одним из ключевых уроков по итогам миграции стала необходимость учитывать при мониторинге не только метрики, но также логи и длинный хвост (речь идёт о таком их распределении на графике прим. перев.) ошибок. Теперь для каждой миграции мы включаем детальный список запросов к логам (log queries) и планируем четкие процедуры отката, которые в случае возникновения проблем можно передавать от одной смены к другой.

Параллельное обслуживание одних и тех же запросов на старой VM-инфраструктуре и новой, основанной на Kubernetes, представляло собой уникальную задачу. В отличие от миграции типа lift-and-shift (быстрый перенос приложений как есть в новую инфраструктуру; подробнее можно прочитать, например, здесь прим. перев.), параллельная работа на старых VM и Kubernetes требует, чтобы инструменты для мониторинга были совместимы с обеими средами и умели объединять метрики в один вид. Важно, что мы используем одни и те же dashboardы и запросы к логам, чтобы добиться согласованной наблюдаемости во время переходного периода.

4. Переключение трафика на новый кластер


Для GitLab.com часть серверов выделяется под канареечную (canary) стадию. Канареечный парк обслуживает наши внутренние проекты, а также может включаться пользователями. Но в первую очередь он предназначен для проверки изменений, вносимых в инфраструктуру и приложение. Первый перенесенный сервис начал с приема ограниченного объема внутреннего трафика, и мы продолжаем использовать этот метод, чтобы убедиться в соблюдении SLO перед тем, как направить весь трафик в кластер.

В случае миграции это означает, что сначала в Kubernetes направляются запросы к внутренним проектам, а затем мы постепенно переключаем на кластер остальной трафик путем изменения веса для бэкенда через HAProxy. В процессе перехода с VM на Kubernetes стало понятно, что очень выгодно иметь в запасе простой способ перенаправления трафика между старой и новой инфраструктурой и, соответственно, держать старую инфраструктуру наготове для отката в первые несколько дней после миграции.

5. Резервные мощности pod'ов и их использование


Почти сразу была выявлена следующая проблема: pod'ы для сервиса Registry стартовали быстро, однако запуск pod'ов для Sidekiq занимал до двух минут. Продолжительный запуск pod'ов для Sidekiq стал проблемой, когда мы приступили к миграции в Kubernetes рабочих нагрузок для worker'ов, которым нужно быстро обрабатывать job'ы и быстро масштабироваться.

В данном случае урок заключался в том, что, хотя Horizontal Pod Autoscaler (HPA) в Kubernetes хорошо справляется с ростом трафика, важно принимать во внимание характеристики рабочих нагрузок и выделять резервные мощности pod'ов (особенно в условиях неравномерного распределения спроса). В нашем случае наблюдался внезапный всплеск job'ов, влекущий за собой стремительное масштабирование, что приводило к насыщению ресурсов CPU до того, как мы успевали масштабировать пул узлов.

Всегда есть соблазн как можно больше выжать из кластера, однако мы, изначально столкнувшись с проблемами с производительностью, теперь начинаем с щедрого pod budget'а и уменьшаем его впоследствии, пристально следя за SLO. Запуск pod'ов для сервиса Sidekiq значительно ускорился и теперь в среднем занимает около 40 секунд. От сокращения времени запуска pod'ов выиграл как GitLab.com, так и наши пользователи инсталляций self-managed, работающие с официальным Helm-чартом GitLab.

Заключение


После переноса каждого сервиса мы радовались преимуществам использования Kubernetes в production: более быстрому и безопасному деплою приложения, масштабированию и более эффективному распределению ресурсов. Причем плюсы миграции выходят за рамки сервиса GitLab.com. От каждого улучшения официального Helm-чарта выигрывают и его пользователи.

Надеюсь, вам понравилась история о наших приключениях с миграцией в Kubernetes. Мы продолжаем переносить все новые сервисы в кластер. Дополнительную информацию можно почерпнуть из следующих публикаций:


P.S. от переводчика


Читайте также в нашем блоге:

Подробнее..

Перевод Пять промахов при развертывании первого приложения на Kubernetes

23.09.2020 18:06:49 | Автор: admin
Fail by Aris-Dreamer

Многие считают, что достаточно перенести приложение на Kubernetes (либо с помощью Helm, либо вручную) и будет счастье. Но не всё так просто.

Команда Mail.ru Cloud Solutions перевела статью DevOps-инженера Джулиана Гинди. Он рассказывает, с какими подводными камнями его компания столкнулась в процессе миграции, чтобы вы не наступали на те же грабли.

Шаг первый: настройка запросов пода и лимитов


Начнем с настройки чистого окружения, в котором будут работать наши поды. Kubernetes великолепно справляется с планированием подов и обработкой состояний отказа. Но оказалось, что планировщик иногда не может разместить под, если затрудняется оценить, сколько ресурсов ему нужно для успешной работы. Именно здесь всплывают запросы на ресурсы и лимиты. Ведется много споров о наилучшем подходе к настройке запросов и лимитов. Иногда кажется, что это действительно скорее искусство, чем наука. Вот наш подход.

Запросы пода (pod requests) это основное значение, используемое планировщиком для оптимального размещения пода.

Из документации Kubernetes: на шаге фильтрации определяется набор узлов, где можно запланировать под. Например, фильтр PodFitsResources проверяет, достаточно ли на узле ресурсов для удовлетворения конкретных запросов пода на ресурсы.

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

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

Лимиты пода (pod limits) это более четкое ограничение для пода. Оно представляет собой максимальный объем ресурсов, который кластер выделит контейнеру.

Опять же, из официальной документации: если для контейнера установлен лимит памяти 4 ГиБ, то kubelet (и среда выполнения контейнера) введет его принудительно. Среда выполнения не позволяет контейнеру использовать больше заданного лимита ресурсов. Например, когда процесс в контейнере пытается использовать больше допустимого объема памяти, ядро системы завершает этот процесс с ошибкой out of memory (OOM).

Контейнер всегда может использовать больше ресурсов, чем указано в запросе на ресурсы, но никогда не может использовать больше, чем указано в ограничении. Это значение сложно установить правильно, но оно очень важно.

В идеале мы хотим, чтобы требования к ресурсам пода изменялись в течение жизненного цикла процесса, не вмешиваясь в другие процессы в системе это цель установления лимитов.

К сожалению, я не могу дать конкретные указания, какие значения устанавливать, но мы сами придерживаемся следующих правил:

  1. Используя инструмент нагрузочного тестирования, моделируем базовый уровень трафика и наблюдаем за использованием ресурсов пода (памяти и процессора).
  2. Устанавливаем запросы пода на произвольно низкое значение (с ограничением ресурсов примерно в 5 раз больше значения запросов) и наблюдаем. Когда запросы на слишком низком уровне, процесс не может начаться, что часто вызывает загадочные ошибки времени выполнения Go.

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

Представьте ситуацию, когда у вас легковесный веб-сервер с очень высоким ограничением ресурсов, например 4 ГБ памяти. Вероятно, этот процесс придется масштабировать горизонтально и каждый новый модуль придется планировать на узле с доступным объемом памяти не менее 4 ГБ. Если такого узла не существует, кластер должен ввести новый узел для обработки этого пода, что может занять некоторое время. Важно добиться минимальной разницы между запросами ресурсов и лимитами, чтобы обеспечить быстрое и плавное масштабирование.

Шаг второй: настройка тестов Liveness и Readiness


Это еще одна тонкая тема, которая часто обсуждается в сообществе Kubernetes. Важно хорошо разбираться в тестах жизнеспособности (Liveness) и готовности (Readiness), поскольку они обеспечивают механизм устойчивой работы программного обеспечения и минимизируют время простоя. Однако они могут нанести серьезный удар по производительности вашего приложения, если не настроены правильно. Ниже приводится краткое изложение, что из себя представляют обе пробы.

Liveness показывает, работает ли контейнер. Если она выходит из строя, kubelet убивает контейнер, и для него включается политика перезапуска. Если контейнер не оснащен Liveness-пробой, то состоянием по умолчанию будет успех так говорится в документации Kubernetes.

Пробы Liveness должны быть дешевыми, то есть не потреблять много ресурсов, потому что они запускаются часто и должны информировать Kubernetes, что приложение запущено.

Если вы установите параметр для запуска каждую секунду, то это добавит 1 запрос в секунду, так что примите во внимание, что для обработки этого трафика понадобятся дополнительные ресурсы.

У нас в компании тесты Liveness проверяют основные компоненты приложения, даже если данные (например, из удаленной базы данных или кэша) не полностью доступны.

Мы настроили в приложениях конечную точку работоспособности, которая просто возвращает код ответа 200. Это показатель того, что процесс запущен и способен обрабатывать запросы (но еще не трафик).

Проба Readiness указывает, готов ли контейнер к обслуживанию запросов. Если проба готовности выходит из строя, контроллер конечных точек удаляет IP-адрес пода из конечных точек всех служб, соответствующих поду. Это также говорится в документации Kubernetes.

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

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

Если вы решите делать запрос к базе данных для проверки готовности приложения, убедитесь, что он обходится как можно дешевле. Возьмем такой запрос:

SELECT small_item FROM table LIMIT 1

Вот пример, как мы настраиваем эти два значения в Kubernetes:

livenessProbe:  httpGet:      path: /api/liveness       port: http readinessProbe:   httpGet:       path: /api/readiness       port: http  periodSeconds: 2

Можно добавить некоторые дополнительные параметры конфигурации:

  • initialDelaySeconds сколько секунд пройдет между запуском контейнера и началом запуска проб.
  • periodSeconds интервал ожидания между запусками проб.
  • timeoutSeconds количество секунд, по истечении которых под считается аварийным. Обычный тайм-аут.
  • failureThreshold количество отказов тестов, прежде чем в под будет отправлен сигнал перезапуска.
  • successThreshold количество успешных проб, прежде чем под переходит в состояние готовности (после сбоя, когда под запускается или восстанавливается).

Шаг третий: настройка дефолтных сетевых политик пода


В Kubernetes плоская сетевая топография, по умолчанию все поды взаимодействуют друг с другом напрямую. В некоторых случаях это нежелательно.

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

Например, ниже приведена простая политика, которая запрещает весь входящий трафик для конкретного пространства имен:

---apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:   name: default-deny-ingressspec:   podSelector: {}   policyTypes:     - Ingress

Визуализация этой конфигурации:


(http://personeltest.ru/aways/miro.medium.com/max/875/1*-eiVw43azgzYzyN1th7cZg.gif)
Более подробно здесь.

Шаг четвертый: нестандартное поведение с помощью хуков и init-контейнеров


Одной наших из главных задач было обеспечение деплоев в Kubernetes без простоя для разработчиков. Это трудно из-за того, что существует множество вариантов завершения работы приложений и освобождения ими использованных ресурсов.

Особые трудности возникли с Nginx. Мы заметили, что при последовательном развертывании этих подов активные соединения прерывались до успешного завершения.

После обширных изысканий в интернете выяснилось, что Kubernetes не ждет, пока соединения Nginx исчерпают себя, прежде чем завершить работу пода. С помощью pre-stop хука мы внедрили такую функциональность и полностью избавились от даунтайма:

lifecycle:  preStop:   exec:     command: ["/usr/local/bin/nginx-killer.sh"]

А вот nginx-killer.sh:

#!/bin/bashsleep 3PID=$(cat /run/nginx.pid)nginx -s quitwhile [ -d /proc/$PID ]; do   echo "Waiting while shutting down nginx..."   sleep 10done

Еще одна чрезвычайно полезная парадигма использование init-контейнеров для обработки запуска конкретных приложений. Это особенно полезно в случае, если у вас есть ресурсоемкий процесс миграции базы данных, который следует запустить до запуска приложения. Для этого процесса вы также можете указать более высокий лимит ресурсов, не устанавливая такой лимит для основного приложения.

Другой распространенной схемой является доступ к секретам в init-контейнере, который предоставляет эти учетные данные главному модулю, что предотвращает несанкционированный доступ к секретам из самого основного модуля приложения.

Как обычно, цитата из документации: init-контейнеры безопасно запускают пользовательский код или утилиты, которые иначе снизят безопасность образа контейнера приложения. Храня отдельно ненужные инструменты, вы ограничиваете поверхность атаки образа контейнера приложения.

Шаг пятый: настройка ядра


Напоследок расскажем о более продвинутой технике.

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

Однако Kubernetes позволяет запустить привилегированный контейнер, который изменяет параметры ядра только для конкретного пода. Вот что мы использовали для изменения максимального количества открытых соединений:

initContainers:  - name: sysctl     image: alpine:3.10     securityContext:         privileged: true      command: ['sh', '-c', "sysctl -w net.core.somaxconn=32768"]

Это более продвинутая техника, которая часто не нужна. Но если ваше приложение еле справляется с большой нагрузкой, можете попробовать настроить некоторые из этих параметров. Более подробная информация об этом процессе и настройке различных значений как всегда в официальной документации.

В заключение


Хотя Kubernetes может показаться готовым решением из коробки, для бесперебойной работы приложений необходимо предпринять несколько ключевых шагов.

На протяжении всей миграции на Kubernetes важно следовать циклу нагрузочного тестирования: запускаете приложение, тестируете его под нагрузкой, наблюдаете за метриками и поведением при масштабировании, настраиваете конфигурацию на основе этих данных, затем снова повторяете этот цикл.

Реалистично оцените ожидаемый трафик и попробуйте выйти за его предел, чтобы посмотреть, какие компоненты сломаются первыми. С таким итерационным подходом для достижения успеха может хватить лишь нескольких из перечисленных рекомендаций. Либо может потребоваться более глубокая настройка.

Всегда задавайте себе такие вопросы:

  1. Сколько ресурсов потребляют приложения и как изменится этот объем?
  2. Каковы реальные требования к масштабированию? Сколько трафика в среднем будет обрабатывать приложение? А как насчет пикового трафика?
  3. Как часто сервису потребуется горизонтальное масштабирование? Как быстро нужно вводить в строй новые поды, чтобы принимать трафик?
  4. Насколько корректно завершается работа подов? Нужно ли это вообще? Можно ли добиться развертывания без даунтайма?
  5. Как минимизировать риски для безопасности и ограничить ущерб от любых скомпрометированных подов? Есть ли у каких-то сервисов разрешения или доступы, которые им не требуются?

Kubernetes предоставляет невероятную платформу, которая позволяет использовать лучшие практики для развертывания тысяч сервисов в кластере. Тем не менее все приложения разные. Иногда внедрение требует немного больше работы.

К счастью, Kubernetes предоставляет необходимые настройки для достижения всех технических целей. Используя комбинацию запросов ресурсов и лимитов, проб Liveness и Readiness, init-контейнеров, сетевых политик и нестандартной настройки ядра, вы можете добиться высокой производительности наряду с отказоустойчивостью и быстрой масштабируемостью.

Что еще почитать:

  1. Лучшие практики и рекомендации для запуска контейнеров и Kubernetes в производственных средах.
  2. 90+ полезных инструментов для Kubernetes: развертывание, управление, мониторинг, безопасность и не только.
  3. Наш канал Вокруг Kubernetes в Телеграме.
Подробнее..

1113 декабря онлайн-интенсив SRE Одна из самых востребованных IT-профессий в мире

24.09.2020 14:19:46 | Автор: admin

Как совсем недавно была мода и высокий спрос на DevOps-инженеров, так сейчас рекрутеры крупнейших компаний ищут Site Reliability Engineer. Достаточно зайти на сайты крупнейших компаний, лидеров IT-рынка, чтобы в этом убедиться. Apple, Google, Booking, Amazon.


Site Reliability Engineering это билет в открытый мир IT. Любая страна, любая IT-компания.


От Apple до Google






На три дня вы погрузитесь в теорию и практику SRE: разработаете и будете поддерживать сайт, состоящий из нескольких микросервисов.


Научитесь правильно распределять ограниченные ресурсы для обеспечения быстродействия, отказоустойчивости и доступности сайта для максимальной надежности, достаточной, чтобы были довольны пользователи.



Что будет на курсе:


Строить


Сформулируете показатели SLO, SLI, SLA для сайта, состоящего из нескольких
микросервисов, разработаете архитектуру и инфраструктуру, которая их обеспечит,
соберете, протестируете и задеплоите сайт, настроите мониторинг и алертинг.


Ломать


Рассмотрите внутренние и внешние факторы ухудшения SLO: ошибки разработчиков, отказы инфраструктуры, наплыв посетителей, DoS-атаки. Разберетесь в устойчивости, error budget, практике тестирования, управлении прерываниями и операционной
нагрузкой.


Чинить


Организуете работу группы по ликвидации аварии в минимальные сроки: подключение коллег, оповещение интересантов (stakeholders), выстраивание приоритетов. Имитация реальных условий: восстановление работоспособности сервиса в условиях предельно ограниченного времени.


Изучать


Разберете подход к сайту с точки зрения SRE. Проанализируете инциденты (причины возникновения, ход устранения). Примете решение по их дальнейшему предотвращению: улучшить мониторинг, изменить архитектуру, подход к разработке и эксплуатации, регламенты. Автоматизируете процессы.


Преподавать вам будут спикеры-практики:



Интенсив пройдёт в декабре 2020, а именно 1113 декабря. Каждый день начинаем в 10:00, проверка связи в 9:45. По расписанию занятия идут до 19:00 с перерывом на обед.


Детальную программу курса и условия вы можете увидеть на сайте курса по SRE.


Пока ещё действует акционное предложение. Осталось 28 мест из 30.


Никогда не поздно всё поменять!

Подробнее..

Перевод Как меняется бизнес Docker для обслуживания миллионов разработчиков, часть 1 Хранилище

24.09.2020 16:22:36 | Автор: admin


В этой серии статей мы подробно рассмотрим, почему и как недавно были внесены изменения в наши Условия обслуживания. Эта статья подробно опишет политику хранения неактивных образов, а также то, как она повлияет на команды разработчиков, использующих Docker Hub для управления образов контейнеров. Во второй части мы сосредоточимся на новой политике по ограничению частоты скачивания образов.


Цель компании Docker дать возможность разработчикам по всему миру воплотить их идеи в реальности, упрощая процесс разработки приложений. На сегодня Docker пользуются более 6.5 миллионов зарегистрированных разработчиков, мы хотим расширить наш бизнес до десятков миллионов разработчиков, которые только сейчас узнали о Docker. Краеугольным камнем нашей миссии является предложение бесплатных инструментов и сервисов, финансируемых за счет наших платных услуг по подписке.


Подробный анализ образов Docker Hub


Доставка приложений переносимым, безопасным и ресурсоэффективным способом требует инструменты и сервисы для безопасного хранения и совместного использования для вашей команды разработчиков. На сегодняшний день Docker с гордостью предлагает крупнейший в мире registry для образов контейнеров, Docker Hub, используемый более 6.5 миллионов разработчиков по всему миру. В настоящее время в Docker Hub хранится более 15ПБ образов контейнеров, охватывающих всё, начиная от популярнейших баз данных с хранением данных в оперативной памяти, и заканчивая платформами поточной передачи событий, тщательно отобранных и доверенных официальных образов Docker, а также порядка 150 миллионов образов, созданных сообществом Docker.


Согласно отчету, полученному нашими внутренними аналитическими инструментами, из 15 ПБ образов, хранящихся в Docker Hub, более 10ПБ не использовалось более полугода. Мы обнаружили, копнув глубже, что более 4.5ПБ этих неактивных образов связаны с бесплатными учетными записями. Многие такие образы использовались короткое время, включая образы, полученные из конвейеров CI с Docker Hub, настроенных так, что удаление временных образов игнорировалось.


Из-за большого объема неактивных данных, простаивающих в Docker Hub, команда столкнулась со сложным вопросом: как ограничить эти данные, за которые Docker ежемесячно платит, не влияя при этом на остальных клиентов Docker?


Основные принципы, принятые для решения проблемы были такими:


  • Продолжить поставку полноценного набора бесплатных инструментов и сервисов, которые разработчики, включая тех, кто работает над проектами с открытым исходным кодом, могут использовать для сборки, совместного использования и запуска приложений.
  • Убедиться, что Docker может масштабироваться для удовлетворения запросов новых разработчиков, ограничивая текущие неограниченные затраты на хранилище, один из наиболее значимых операционных расходов для Docker Hub.

Помощь разработчикам в управлении неактивными образами


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


В соответствии с новой политикой, с 1 ноября 2020 года, образы, размещенные в бесплатных репозиториях Docker Hub, манифест которых не обновлялся последние полгода, будут удалены. Данная политика не применима к образам, хранимых на платных учетных записях Docker Hub, или учетных записях проверенных издателей образов Docker, а также официальным образам Docker.


  • Пример 1: Молли, пользователь бесплатной учетной записи, закачала в Docker Hub 1 января 2019 года образ с меткой molly/hello-world:v1. Этот образ никогда не скачивался с момента публикации. Этот помеченный образ будет считаться неактивным начиная с 1 ноября 2020 года, когда новая политика начнет действовать. Образ и любая метка, указывающая на него, будут удалены 1 ноября 2020 года.
  • Пример 2: У Молли есть образ без метки molly/myapp@sha256:c0ffee, закачан 1 августа 2018 года. Последнее скачивание было 1 августа 2020 года. Этот образ считается активным, и не будет удален 1 ноября 2020 года.

Минимизация влияния на сообщество разработчиков


Для бесплатных учетных записей Docker предлагает бесплатное хранение неактивных образов в течение полугода. Для тех, кому надо хранить неактивные образы, Docker предлагает неограниченное хранение образов в качестве особенности планов Pro или Team.


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



Наконец, в рамках поддержки сообщества разработчиков ПО с открытым исходным кодом, до 1 ноября мы предоставим новые тарифные планы для открытого исходного кода. Чтобы подать заявку надо заполнить форму тут.


Для получения дополнительной информации о последних изменениях условий обслуживания обратитесь к FAQ.


Следите за сообщениями по e-mail касательно любых образов с истекающим сроком действия, либо перейдите на тарифные планы Pro или Team для хранения неактивных образов без ограничений.


Хотя мы пытаемся минимизировать влиание на разработчиков, возможно у вас есть не рассмотренные вопросы или варианты использования. Как обычно мы ждем обратную связь и вопросы здесь.


P.S. Учитывая то, что технология Docker не теряет актуальности, как заверяют её создатели, совсем не лишним было бы изучить эту технологию от и до. Тем более это всегда в пользу, когда вы выработаете с Kubernetes. Если хотите познакомиться с best practice кейсами, чтобы понять, где и как лучше использовать Docker, рекомендую комплексный видеокурс по Docker, в котором мы разберем все его инструменты. Полная программа курса на странице курса.

Подробнее..

Краткий обзор операторов PostgreSQL для Kubernetes, наш выбор и опыт

25.09.2020 10:10:53 | Автор: admin


Всё чаще от клиентов поступают такие запросы: Хотим как Amazon RDS, но дешевле; Хотим как RDS, но везде, в любой инфраструктуре. Чтобы реализовать подобное managed-решение на Kubernetes, мы посмотрели на текущее состояние наиболее популярных операторов для PostgreSQL (Stolon, операторы от Crunchy Data и Zalando) и сделали свой выбор.

Эта статья полученный нами опыт и с теоретической точки зрения (обзор решений), и с практической стороны (что было выбрано и что из этого получилось). Но для начала давайте определимся, какие вообще требования предъявляются к потенциальной замене RDS

Что же такое RDS


Когда люди говорят про RDS, по нашему опыту, они подразумевают управляемый (managed) сервис СУБД, которая:

  1. легко настраивается;
  2. имеет возможность работы со снапшотами и восстанавливаться из них (желательно с поддержкой PITR);
  3. позволяет создавать топологии master-slave;
  4. имеет богатый список расширений;
  5. предоставляет аудит и управление пользователями/доступами.

Если говорить вообще, то подходы к реализации поставленной задачи могут быть весьма разными, однако путь с условным Ansible нам не близок. (К схожему выводу пришли и коллеги из 2GIS в результате своей попытки создать инструмент для быстрого развертывания отказоустойчивого кластера на основе Postgres.)

Именно операторы общепринятый подход для решения подобных задач в экосистеме Kubernetes. Подробнее о них применительно к базам данных, запускаемым внутри Kubernetes, уже рассказывал техдир Фланта, distol, в одном из своих докладов.

NB: Для быстрого создания несложных операторов рекомендуем обратить внимание на нашу Open Source-утилиту shell-operator. Используя её, можно это делать без знаний Go, а более привычными для сисадминов способами: на Bash, Python и т.п.

Для PostgreSQL существует несколько популярных K8s-операторов:

  • Stolon;
  • Crunchy Data PostgreSQL Operator;
  • Zalando Postgres Operator.

Посмотрим на них более внимательно.

Выбор оператора


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

  • деплой из Git и с Custom Resources;
  • поддержку pod anti-affinity;
  • установку node affinity или node selector;
  • установку tolerations;
  • наличие возможностей тюнинга;
  • понятные технологии и команды.

Не вдаваясь в детали по каждому из пунктов (спрашивайте в комментариях, если останутся вопросы по ним после прочтения всей статьи), отмечу в целом, что эти параметры нужны для более тонкого описания специализации узлов кластера с тем, чтобы заказывать их под конкретные приложения. Так мы можем добиться оптимального баланса в вопросах производительности и стоимости.

Теперь к самим операторам PostgreSQL.

1. Stolon


Stolon от итальянской компании Sorint.lab в уже упомянутом докладе рассматривался как некий эталон среди операторов для СУБД. Это довольно старый проект: первый его публичный релиз состоялся еще в ноябре 2015 года, а GitHub-репозиторий может похвастать почти 3000 звёздами и 40+ контрибьюторами.

И действительно, Stolon отличный пример продуманной архитектуры:



С устройством этого оператора в подробностях можно ознакомиться в докладе или документации проекта. В целом же, достаточно сказать, что он умеет всё описанное: failover, прокси для прозрачного доступа клиентов, бэкапы. Причем прокси предоставляют доступ через один сервис endpoint в отличие от двух других решений, рассмотренных дальше (у них по два сервиса для доступа к базе).

Однако у Stolon нет Custom Resources, из-за чего его нельзя так деплоить, чтобы просто и быстро как горячие пирожки создавать экземпляры СУБД в Kubernetes. Управление осуществляется через утилиту stolonctl, деплой через Helm-чарт, а пользовательские пароли задаются через ConfigMap.

С одной стороны, получается, что оператор не очень-то является оператором (ведь он не использует CRD). Но с другой это очень гибкая система, которая позволяет настраивать ресурсы в K8s так, как вам удобно.

Но лично для нас не показался оптимальным путь заводить отдельный чарт под каждую БД. Поэтому мы стали искать альтернативы.

2. Crunchy Data PostgreSQL Operator


Оператор от Crunchy Data, молодого американского стартапа, выглядел логичной альтернативой. Его публичная история начинается с первого релиза в марте 2017 года, с тех пор GitHub-репозиторий получил чуть менее 1300 звёзд и 50+ контрибьюторов. Последний релиз от сентября был протестирован на работу с Kubernetes 1.151.18, OpenShift 3.11+ и 4.4+, GKE и VMware Enterprise PKS 1.3+.

Архитектура Crunchy Data PostgreSQL Operator также соответствует нашим требованиям:



Управление происходит через утилиту pgo, однако она в свою очередь генерирует Custom Resources для Kubernetes. Поэтому с точки зрения потенциальных пользователей оператор нас порадовал:

  • есть управление через CRD;
  • удобное управление пользователями (тоже через CRD);
  • интеграция с другими компонентами Crunchy Data Container Suite специализированной коллекции образов контейнеров для PostgreSQL и утилит для работы с ней (включая pgBackRest, pgAudit, расширения из contrib и т.д.).

Однако попытки начать использовать оператор выявили несколько проблем:

  • Не оказалось возможности tolerations предусмотрен только nodeSelector.
  • Создаваемые podы были частью Deploymentа, несмотря на то, что мы деплоили stateful-приложение. В отличие от StatefulSet, Deploymentы не умеют создавать диски.

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

Еще одной особенностью этого оператора является его готовая интеграция с различными вспомогательными системами. Например, легко установить поставить pgAdmin и pgBounce, а в документации рассматриваются преднастроенные Grafana и Prometheus. В недавнем релизе 4.5.0-beta1 отдельно отмечается улучшенная интеграция с проектом pgMonitor, с которой оператор предлагает визуализацию метрик по PgSQL из коробки.

Тем не менее, странный выбор генерируемых Kubernetes-ресурсов привел нас к необходимости найти иное решение.

3. Zalando Postgres Operator


Продукты Zalando нам известны давно: есть опыт использования Zalenium и, конечно, мы пробовали Patroni их популярное HA-решение для PostgreSQL. О подходе компании к созданию Postgres Operator рассказывал один из его авторов Алексей Клюкин в эфире Postgres-вторника 5, и нам он приглянулся.

Это самое молодое решение из рассматриваемых в статье: первый релиз состоялся в августе 2018 года. Однако, даже несмотря на небольшое количество формальных релизов, проект прошёл большой путь, уже опередив по популярности решение от Crunchy Data (1300+ звёзд на GitHub) и максимальное число контрибьюторов (70+). Под капотом этого оператора используются решения, проверенные временем: Patroni и Spilo для управления, WAL-E для бэкапов, PgBouncer в качестве пула подключений.

Вот как представлена архитектура оператора от Zalando:



Оператор полностью управляется через Custom Resources, автоматически создает StatefulSet из контейнеров, которые затем можно кастомизировать, добавляя в pod различные sidecarы. Всё это значительный плюс в сравнении с оператором от Crunchy Data.

Поскольку именно решение от Zalando мы выбрали среди 3 рассматриваемых вариантов, дальнейшее описание его возможностей будет представлено ниже, сразу вместе с практикой применения.

Практика с Postgres Operator от Zalando


Деплой оператора происходит очень просто: достаточно скачать актуальный релиз с GitHub и применить YAML-файлы из директории manifests. Как вариант, можно также воспользоваться OperatorHub.

После установки стоит озаботиться настройкой хранилищ для логов и бэкапов. Она производится через ConfigMap postgres-operator в пространстве имен, куда вы установили оператор. Когда хранилища настроены, можно развернуть первый кластер PostgreSQL.

Например, стандартный деплой у нас выглядит следующим образом:

apiVersion: acid.zalan.do/v1kind: postgresqlmetadata: name: staging-dbspec: numberOfInstances: 3 patroni:   synchronous_mode: true postgresql:   version: "12" resources:   limits:     cpu: 100m     memory: 1Gi   requests:     cpu: 100m     memory: 1Gi sidecars: - env:   - name: DATA_SOURCE_URI     value: 127.0.0.1:5432   - name: DATA_SOURCE_PASS     valueFrom:       secretKeyRef:         key: password         name: postgres.staging-db.credentials   - name: DATA_SOURCE_USER     value: postgres   image: wrouesnel/postgres_exporter   name: prometheus-exporter   resources:     limits:       cpu: 500m       memory: 100Mi     requests:       cpu: 100m       memory: 100Mi teamId: staging volume:   size: 2Gi

Данный манифест деплоит кластер из 3 экземпляров с sidecar в виде postgres_exporter, с которого мы снимаем метрики приложения. Как видите, всё очень просто, и при желании можно сделать буквально неограниченное количество кластеров.

Стоит обратить внимание и на веб-панель для администрирования postgres-operator-ui. Она поставляется вместе с оператором и позволяет создавать и удалять кластеры, а также позволяет работать с бэкапами, которые делает оператор.


Список кластеров PostgreSQL


Управление бэкапами

Другой интересной особенностью является поддержка Teams API. Данный механизм автоматически создаёт роли в PostgreSQL, исходя из полученного списка имён пользователей. После этого API позволяет вернуть список пользователей, для которых автоматически создаются роли.

Проблемы и их решение


Однако использование оператора вскоре выявило несколько весомых недостатков:

  1. отсутствие поддержки nodeSelector;
  2. невозможность отключить бэкапы;
  3. при использовании функции создания баз не создаются привилегии по умолчанию;
  4. периодически не хватает документации или же она находится в неактуальном состоянии.

К счастью, многие из них могут быть решены. Начнём с конца проблем с документацией.

Скорее всего вы столкнетесь с тем, что не всегда ясно, как прописать бэкап и как подключить бэкапный бакет к Operator UI. Об этом в документации говорится вскользь, а реальное описание есть в PR:

  1. нужно сделать секрет;
  2. передать его оператору в параметр pod_environment_secret_name в CRD с настройками оператора или в ConfigMap (зависит от того, как вы решили устанавливать оператор).

Однако, как оказалось, на текущий момент это невозможно. Именно поэтому мы собрали свою версию оператора с некоторыми дополнительными сторонними наработками. Подробнее о ней см. ниже.

Если передавать оператору параметры для бэкапа, а именно wal_s3_bucket и ключи доступа в AWS S3, то он будет бэкапить всё: не только базы в production, но и staging. Нас это не устроило.

В описании параметров к Spilo, что является базовой Docker-обёрткой для PgSQL при использовании оператора, выяснилось: можно передать параметр WAL_S3_BUCKET пустым, тем самым отключив бэкапы. Более того, к большой радости нашёлся и готовый PR, который мы тут же приняли в свой форк. Теперь достаточно просто добавить enableWALArchiving: false в ресурс кластера PostgreSQL.

Да, была возможность сделать иначе, запустив 2 оператора: один для staging (без бэкапов), а второй для production. Но так мы смогли обойтись одним.

Ок, мы научились передавать в базы доступ для S3 и бэкапы начали попадать в хранилище. Как заставить работать страницы бэкапов в Operator UI?



В Operator UI потребуется добавить 3 переменные:

  • SPILO_S3_BACKUP_BUCKET
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

После этого управление бэкапами станет доступно, что в нашем случае упростит работу со staging, позволив доставлять туда срезы с production без дополнительных скриптов.

В качестве еще одного плюса называлась работа с Teams API и широкие возможности для создания баз и ролей средствами оператора. Однако создаваемые роли не имели прав по умолчанию. Соответственно, пользователь с правами на чтение не мог читать новые таблицы.

Почему так? Несмотря на то, что в коде есть необходимые GRANT, они применяются далеко не всегда. Есть 2 метода: syncPreparedDatabases и syncDatabases. В syncPreparedDatabases несмотря на то, что в секции preparedDatabases есть есть условие defaultRoles и defaultUsers для создания ролей, права по умолчанию не применяются. Мы в процессе подготовки патча, чтобы данные права автоматически применялись.

И последний момент в актуальных для нас доработках патч, добавляющий Node Affinity в создаваемый StatefulSet. Наши клиенты зачастую предпочитают сокращать расходы, используя spot-инстансы, а на них явно не стоит размещать сервисы БД. Этот вопрос можно было бы решить и через tolerations, но наличие Node Affinity даёт большую уверенность.

Что получилось?


По итогам решения перечисленных проблем мы форкнули Postgres Operator от Zalando в свой репозиторий, где он собирается со столь полезными патчами. А для пущего удобства собрали и Docker-образ.

Список PR, принятых в форк:


Будет здорово, если сообщество поддержит эти PR, чтобы они попали в следующую версию оператора (1.6).

Бонус! История успеха с миграцией production


Если вы используете Patroni, на оператор можно мигрировать живой production с минимальным простоем.

Spilo позволяет делать standby-кластеры через S3-хранилища с Wal-E, когда бинарный лог PgSQL сначала сохраняется в S3, а затем выкачивается репликой. Но что делать, если у вас не используется Wal-E в старой инфраструктуре? Решение этой проблемы уже было предложено на хабре.

На помощь приходит логическая репликация PostgreSQL. Однако не будем вдаваться в детали, как создавать публикации и подписки, потому что наш план потерпел фиаско.

Дело в том, что в БД было несколько нагруженных таблиц с миллионами строк, которые, к тому же, постоянно пополнялись и удалялись. Простая подписка с copy_data, когда новая реплика копирует всё содержимое с мастера, просто не успевала за мастером. Копирование контента работало неделю, но так и не догнало мастер. В итоге, разобраться с проблемой помогла статья коллег из Avito: можно перенести данные, используя pg_dump. Опишу наш (немного доработанный) вариант этого алгоритма.

Идея заключается в том, что можно сделать выключенную подписку, привязанную к конкретному слоту репликации, а затем исправить номер транзакции. В наличии были реплики для работы productionа. Это важно, потому что реплика поможет создать консистентный dump и продолжить получать изменения из мастера.

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

  1. master исходный сервер;
  2. replica1 потоковая реплика на старом production;
  3. replica2 новая логическая реплика.

План миграции


1. Создадим на мастере подписку на все таблицы в схеме public базы dbname:

psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"

2. Cоздадим слот репликации на мастере:

psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"

3. Остановим репликацию на старой реплике:

psql -h replica1 -c "select pg_wal_replay_pause();"

4. Получим номер транзакции с мастера:

psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"

5. Снимем dump со старой реплики. Будем делать это в несколько потоков, что поможет ускорить процесс:

pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname

6. Загрузим dump на новый сервер:

pg_restore -h replica2 -F d -j 8 -d dbname dump/

7. После загрузки дампа можно запустить репликацию на потоковой реплике:

psql -h replica1 -c "select pg_wal_replay_resume();"

7. Создадим подписку на новой логической реплике:

psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"

8. Получим oid подписки:

psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"

9. Допустим, был получен oid=1000. Применим номер транзакции к подписке:

psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"

10. Запустим репликацию:

psql -h replica2 -d dbname -c "alter subscription oldprod enable;"

11. Проверим статус подписки, репликация должна работать:

psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"

12. После того, как репликация запущена и базы синхронизированы, можно совершать переключение.

13. После отключения репликации надо исправить последовательности. Это хорошо описано в статье на wiki.postgresql.org.

Благодаря такому плану переключение прошло с минимальными задержками.

Заключение


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

Рассмотрев три самых популярных Kubernetes-оператора для PostgreSQL, мы остановили свой выбор на проекте от Zalando. И с ним пришлось преодолеть определенные трудности, но результат действительно порадовал, так что мы планируем расширить этот опыт и на некоторые другие инсталляции PgSQL. Если у вас есть опыт использования схожих решений будем рады увидеть подробности в комментариях!

P.S.


Читайте также в нашем блоге:

Подробнее..

Перевод Как масштабируется бизнес Docker для обслуживания миллионов разработчиков, часть 2 Исходящие данные

26.09.2020 12:23:55 | Автор: admin


Это вторая статья из серии статей, в ней будут рассмотрены ограничения при скачивании образов контейнеров.


В первой части мы подробно рассмотрели образы, хранимые в Docker Hub, крупнейшем registry образов контейнеров. Мы пишем об этом для того, чтобы вы лучше понимали, как наши обновленные Условия обслуживания повлияют на команды разработчиков, использующих Docker Hub для управления образами контейнеров и конвейерами CI\CD.


Об ограничениях по частоте скачивания было объявлено ранее в наших Условиях обслуживания. Мы подробнее рассмотрим ограничения по частоте, которые вступят в силу с 1 ноября 2020 года:


Бесплатный тарифный план, анонимные пользователи: 100 скачиваний за 6 часов
Бесплатный тарифный план, авторизованные пользователи: 200 скачиваний за 6 часов
Тарифный план Pro: без ограничений
Тарифный план Team: без ограничений


Частота скачиваний со стороны Docker определяется как число запросов манифестов к Docker Hub. Ограничения по частоте скачивания образов зависят от типа учетной записи, запрашивающей образ, а не от типа учетной записи владельца образа. Для анонимных (неавторизованных) пользователей частота скачивания привязана к ip-адресу.


N.B. Больше тонкостей и best practice кейcов вы получите на курсе Docker от практиков. Причём вы можете проходить его, когда вам удобно и по времени, и по настрою.


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


Подробный анализ частот скачивания образов Docker Hub


Мы потратили много времени анализируя скачивание образов из Docker Hub, чтобы определить причину ограничения скорости, а также как именно нужно ограничивать. То, что мы увидели, подтвердило, что фактически все пользователи скачивают образы с предсказуемой скоростью для типовых рабочих процессов. Однако есть заметное влияние небольшого числа анонимных пользователей, например порядка 30% всех скачиваний исходят только от 1% анонимных пользователей.



Новые ограничения основаны на этом анализе, так что большинство наших пользователей не пострадают. Эти ограничения сделаны для отображения обычного использования разработчиками изучения Docker, разработки кода, создания образов и т.п.


Помощь разработчикам для лучшего понимания ограничения частоты скачивания


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


К примеру, если у вас уже есть образ, Docker Engine выдаст запрос на манифест, поймет, что у него уже есть все необходимые слои на основе принятого манифеста, после чего остановится. С другой стороны если вы скачиваете образ, поддерживающий несколько архитектур, запрос на манифест вернет список манифестов образов для каждой поддерживаемой архитектуры. Затем Docker Engine выдаст еще один запрос на манифест касательно конкретной архитектуры, на которой он работает, в ответ получит список всех слоев образа. Затем он будет запрашивать каждый отсутствующий слой (blob).


N.B. Более широко эта тема раскрыта на курсе Docker, в котором мы разберем все его инструменты: от основных абстракций до параметров сети, нюансов работы с различными ОС и языками программирования. Вы познакомитесь с технологией и поймете, где и как лучше использовать Docker.


Получается, что скачивание образа это на самом деле один или два запроса манифеста, а также от нуля и до бесконечности запросы слоев (blob). Исторически Docker отслеживал частоту скачивания на основе слоев, поскольку это наиболее связано с использованием полосы пропускания. Но тем не менее, мы прислушались к сообществу, что так сложнее, ведь нужно отслеживать запрашиваемое число слоев, что приведет к игнорированию best practices касательно работы с Dockerfile, а также интуитивно непонятнее для пользователей, желающих просто работать с registry, не сильно разбираясь в деталях.


Так что мы ограничиваем число запросов на основе запросов на манифесты. Это напрямую связано с скачиванием образов, что легко понять пользователям. Есть правда небольшой нюанс если вы пробуете скачать образ, который уже есть, запрос все равно будет учтен, даже если вы и не будете качать слои. В любом случае мы надеемся, что такой метод ограничения частоты скачивания будет и справедливым, и удобным для пользователей.


Ждем ваши отзывы


Мы будем следить за ограничениями и вносить соотвествующие правки на основе типовых вариантов использования, чтобы быть уверенными, что ограничения подходят каждому типу пользователей, а также, в частности, мы постараемся никогда не мешать разработчикам выполнить их работу.


Следите за сообщениями в ближайшие недели, будет еще одна статья о настройке CI и боевых систем в свете этих изменений.


Наконец, в рамках поддержки сообщества разработчиков ПО с открытым исходным кодом, до 1 ноября мы предоставим новые тарифные планы для открытого исходного кода. Чтобы подать заявку надо заполнить форму тут.


Для получения дополнительной информации о последних изменениях условий обслуживания обратитесь к FAQ.


Тем, кому надо поднять ограничения на частоту скачивания образов, Docker предлагает неограниченное скачивание образов в качестве особенности планов Pro или Team. Как всегда, мы ждем обратную связь и вопросы здесь.

Подробнее..

Перевод Автоскейлинг приложений Kubernetes при помощи Prometheus и KEDA

28.09.2020 18:04:45 | Автор: admin
Balloon Man by Cimuanos

Масштабируемость ключевое требование для облачных приложений. С Kubernetes масштабировать приложение так же просто, как и увеличить количество реплик для соответствующего развертывания или ReplicaSet но это ручной процесс.

Kubernetes позволяет автоматически масштабировать приложения (то есть Pod в развертывании или ReplicaSet) декларативным образом с использованием спецификации Horizontal Pod Autoscaler. По умолчанию критерий для автоматического масштабирования метрики использования CPU (метрики ресурсов), но можно интегрировать пользовательские метрики и метрики, предоставляемые извне.

Команда Kubernetes aaS от Mail.ru перевела статью о том, как использовать внешние метрики для автоматического масштабирования приложения Kubernetes. Чтобы показать, как все работает, автор использует метрики запросов HTTP-доступа, они собираются с помощью Prometheus.

Вместо горизонтального автомасштабирования подов, применяется Kubernetes Event Driven Autoscaling (KEDA) оператор Kubernetes с открытым исходным кодом. Он изначально интегрируется с Horizontal Pod Autoscaler, чтобы обеспечить плавное автомасштабирование (в том числе до/от нуля) для управляемых событиями рабочих нагрузок. Код доступен на GitHub.

Краткий обзор работы системы




На схеме краткое описание того, как все работает:

  1. Приложение предоставляет метрики количества обращений к HTTP в формате Prometheus.
  2. Prometheus настроен на сбор этих показателей.
  3. Скейлер Prometheus в KEDA настроен на автоматическое масштабирование приложения на основе количества обращений к HTTP.

Теперь подробно расскажу о каждом элементе.

KEDA и Prometheus


Prometheus набор инструментов для мониторинга и оповещения систем с открытым исходным кодом, часть Cloud Native Computing Foundation. Собирает метрики из разных источников и сохраняет в виде данных временных рядов. Для визуализации данных можно использовать Grafana или другие инструменты визуализации, работающие с API Kubernetes.

KEDA поддерживает концепцию скейлера он действует как мост между KEDA и внешней системой. Реализация скейлера специфична для каждой целевой системы и извлекает из нее данные. Затем KEDA использует их для управления автоматическим масштабированием.

Скейлеры поддерживают нескольких источников данных, например, Kafka, Redis, Prometheus. То есть KEDA можно применять для автоматического масштабирования развертываний Kubernetes, используя в качестве критериев метрики Prometheus.

Тестовое приложение


Тестовое Golang-приложение предоставляет доступ по HTTP и выполняет две важные функции:

  1. Использует клиентскую библиотеку Prometheus Go для инструментирования приложения и предоставления метрики http_requests, которая содержит счетчик обращений. Конечная точка, по которой доступны метрики Prometheus, расположена по URI /metrics.

    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{       Name: "http_requests",       Help: "number of http requests",   })
    
  2. В ответ на запрос GET приложение увеличивает значение ключа (access_count) в Redis. Это простой способ выполнить работу как часть обработчика HTTP, а также проверить метрики Prometheus. Значение метрики должно быть таким же, как значение access_count в Redis.

    func main() {       http.Handle("/metrics", promhttp.Handler())       http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {           defer httpRequestsCounter.Inc()           count, err := client.Incr(redisCounterName).Result()           if err != nil {               fmt.Println("Unable to increment redis counter", err)               os.Exit(1)           }           resp := "Accessed on " + time.Now().String() + "\nAccess count " + strconv.Itoa(int(count))           w.Write([]byte(resp))       })       http.ListenAndServe(":8080", nil)   }
    

Приложение развертывается в Kubernetes через Deployment. Также создается служба ClusterIP, она позволяет серверу Prometheus получать метрики приложения.

Вот манифест развертывания для приложения.

Сервер Prometheus


Манифест развертывания Prometheus состоит из:

  • ConfigMap для передачи конфига Prometheus;
  • Deployment для развертывания Prometheus в Kubernetes-кластере;
  • ClusterIP сервис для доступа к UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount для работы автоопределения сервисов в Kubernetes (Auto-discovery).

Вот манифест для запуска Prometheus.

KEDA Prometheus ScaledObject


Скейлер действует как мост между KEDA и внешней системой, из которой нужно получать метрики. ScaledObject настраиваемый ресурс, его необходимо развернуть для синхронизации развертывания с источником событий, в данном случае с Prometheus.

ScaledObject содержит информацию о масштабировании развертывания, метаданные об источнике события (например, секреты для подключения, имя очереди), интервал опроса, период восстановления и другие данные. Он приводит к соответствующему ресурсу автомасштабирования (определение HPA) для масштабирования развертывания.

Когда объект ScaledObject удаляется, соответствующее ему определение HPA очищается.

Вот определение ScaledObject для нашего примера, в нем используется скейлер Prometheus:

apiVersion: keda.k8s.io/v1alpha1kind: ScaledObjectmetadata: name: prometheus-scaledobject namespace: default labels:   deploymentName: go-prom-appspec: scaleTargetRef:   deploymentName: go-prom-app pollingInterval: 15 cooldownPeriod:  30 minReplicaCount: 1 maxReplicaCount: 10 triggers: - type: prometheus   metadata:     serverAddress: http://prometheus-service.default.svc.cluster.local:9090     metricName: access_frequency     threshold: '3'     query: sum(rate(http_requests[2m]))

Учтите следующие моменты:

  1. Он указывает на Deployment с именем go-prom-app.
  2. Тип триггера Prometheus. Адрес сервера Prometheus упоминается вместе с именем метрики, пороговым значением и запросом PromQL, который будет использоваться. Запрос PromQL sum(rate(http_requests[2m])).
  3. Согласно pollingInterval, KEDA запрашивает цель у Prometheus каждые пятнадцать секунд. Поддерживается минимум один под (minReplicaCount), а максимальное количество подов не превышает maxReplicaCount (в данном примере десять).

Можно установить minReplicaCount равным нулю. В этом случае KEDA активирует развертывание с нуля до единицы, а затем предоставляет HPA для дальнейшего автоматического масштабирования. Возможен и обратный порядок, то есть масштабирование от единицы до нуля. В примере мы не выбрали ноль, поскольку это HTTP-сервис, а не система по запросу.

Магия внутри автомасштабирования


Пороговое значение используют в качестве триггера для масштабирования развертывания. В нашем примере запрос PromQL sum(rate (http_requests [2m])) возвращает агрегированное значение скорости HTTP-запросов (количество запросов в секунду), ее измеряют за последние две минуты.

Поскольку пороговое значение равно трем, значит, будет один под, пока значение sum(rate (http_requests [2m])) меньше трех. Если же значение возрастает, добавляется дополнительный под каждый раз, когда sum(rate (http_requests [2m])) увеличивается на три. Например, если значение от 12 до 14, то количество подов четыре.

Теперь давайте попробуем настроить!

Предварительная настройка


Всё, что вам нужно кластер Kubernetes и настроенная утилита kubectl. В этом примере используется кластер minikube, но вы можете взять любой другой. Для установки кластера есть руководство.

Установить последнюю версию на Mac:

curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \&& chmod +x minikubesudo mkdir -p /usr/local/bin/sudo install minikube /usr/local/bin/

Установите kubectl, чтобы получить доступ к кластеру Kubernetes.

Поставить последнюю версию на Mac:

curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -shttps://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"chmod +x ./kubectlsudo mv ./kubectl /usr/local/bin/kubectlkubectl version

Установка KEDA


Вы можете развернуть KEDA несколькими способами, они перечислены в документации. Я использую монолитный YAML:

kubectl apply -fhttps://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml

KEDA и ее компоненты устанавливаются в пространство имен keda. Команда для проверки:

kubectl get pods -n keda

Дождитесь, когда под KEDA Operator стартует перейдет в Running State. И после этого продолжайте.

Установка Redis при помощи Helm


Если у вас не установлен Helm, воспользуйтесь этим руководством. Команда для установки на Mac:

brew install kubernetes-helmhelm init --history-max 200

helm init инициализирует локальный интерфейс командной строки, а также устанавливает Tiller в кластер Kubernetes.

kubectl get pods -n kube-system | grep tiller

Дождитесь перехода пода Tiller в состояние Running.

Примечание переводчика: Автор использует Helm@2, который требует установки серверного компонента Tiller. Сейчас актуален Helm@3, для него серверная часть не нужна.

После установки Helm для запуска Redis достаточно одной команды:

helm install --name redis-server --set cluster.enabled=false --set usePassword=false stable/redis

Убедиться, что Redis успешно запустился:

kubectl get pods/redis-server-master-0

Дождитесь, когда под Redis перейдет в состояние Running.

Развертывание приложения


Команда для развертывания:

kubectl apply -f go-app.yaml//outputdeployment.apps/go-prom-app createdservice/go-prom-app-service created

Проверить, что все запустилось:

kubectl get pods -l=app=go-prom-app

Дождитесь перехода Redis в состояние Running.

Развертывание сервера Prometheus


Манифест Prometheus использует Kubernetes Service Discovery для Prometheus. Он позволяет динамически обнаруживать поды приложения на основе метки службы.

kubernetes_sd_configs:   - role: service   relabel_configs:   - source_labels: [__meta_kubernetes_service_label_run]     regex: go-prom-app-service     action: keep

Для развертывания:

kubectl apply -f prometheus.yaml//outputclusterrole.rbac.authorization.k8s.io/prometheus createdserviceaccount/default configuredclusterrolebinding.rbac.authorization.k8s.io/prometheus createdconfigmap/prom-conf createddeployment.extensions/prometheus-deployment createdservice/prometheus-service created

Проверить, что все запустилось:

kubectl get pods -l=app=prometheus-server

Дождитесь, пока под Prometheus перейдет в состояние Running.

Используйте kubectl port-forward для доступа к пользовательскому интерфейсу Prometheus (или серверу API) по адресу http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Развертывание конфигурации автомасштабирования KEDA


Команда для создания ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Проверьте логи оператора KEDA:

KEDA_POD_NAME=$(kubectl get pods -n keda -o=jsonpath='{.items[0].metadata.name}')kubectl logs $KEDA_POD_NAME -n keda

Результат выглядит примерно так:

time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:default/prometheus-scaledobject"time="2019-10-15T09:38:28Z" level=info msg="Created HPA with namespace default and name keda-hpa-go-prom-app"

Проверьте под приложения. Должен быть запущен один экземпляр, поскольку minReplicaCount равно 1:

kubectl get pods -l=app=go-prom-app

Проверьте, что ресурс HPA успешно создан:

kubectl get hpa

Вы должны увидеть что-то вроде:

NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGEkeda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s

Проверка работоспособности: доступ к приложению


Чтобы получить доступ к конечной точке REST нашего приложения, запустите:

kubectl port-forward service/go-prom-app-service 8080

Теперь вы можете получить доступ к приложению Go, используя адрес http://localhost:8080. Для этого выполните команду:

curl http://localhost:8080/test

Результат выглядит примерно так:

Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC m=+406004.817901246Access count 1

На этом этапе также проверьте Redis. Вы увидите, что ключ access_count увеличен до 1:

kubectl exec -it redis-server-master-0 -- redis-cli get access_count//output"1"

Убедитесь, что значение метрики http_requests такое же:

curl http://localhost:8080/metrics | grep http_requests//output# HELP http_requests number of http requests# TYPE http_requests counterhttp_requests 1

Создание нагрузки


Мы будем использовать hey утилиту для генерации нагрузки:

curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 && chmod a+x hey

Вы можете также скачать утилиту для Linux или Windows.

Запустите ее:

./hey http://localhost:8080/test

По умолчанию утилита отправляет 200 запросов. Вы можете убедиться в этом, используя метрики Prometheus, а также Redis.

curl http://localhost:8080/metrics | grep http_requests//output# HELP http_requests number of http requests# TYPE http_requests counterhttp_requests 201kubectl exec -it redis-server-master-0 -- redis-cli get access_count//output201

Подтвердите значение фактической метрики (возвращенной запросом PromQL):

curl -g 'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'//output{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}

В этом случае фактический результат равен 1,686057971014493 и отображается в поле value. Этого недостаточно для масштабирования, поскольку установленный нами порог равен 3.

Больше нагрузки!


В новом терминале следите за количеством подов приложения:

kubectl get pods -l=app=go-prom-app -w

Давайте увеличим нагрузку с помощью команды:

./hey -n 2000 http://localhost:8080/test

Через некоторое время вы увидите, что HPA масштабирует развертывание и запускает новые поды. Проверьте HPA, чтобы в этом убедиться:

kubectl get hpaNAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGEkeda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s

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

curl -g 'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'

Очистка


//Delete KEDAkubectl delete namespace keda//Delete the app, Prometheus server and KEDA scaled objectkubectl delete -f .//Delete Redishelm del --purge redis-server

Заключение


KEDA позволяет автоматически масштабировать ваши развертывания Kubernetes (до/от нуля) на основе данных из внешних метрик. Например, на основе метрик Prometheus, длины очереди в Redis, задержки потребителя в теме Kafka.

KEDA выполняет интеграцию с внешним источником, а также предоставляет его метрики через Metrics Server для Horizontal Pod Autoscaler.

Успехов!

Что еще почитать:

  1. Лучшие практики и рекомендации для запуска контейнеров и Kubernetes в производственных средах.
  2. 90+ полезных инструментов для Kubernetes: развертывание, управление, мониторинг, безопасность и не только.
  3. Наш канал Вокруг Kubernetes в Телеграме.
Подробнее..

Двадцать интервью за две недели. Краткие выводы длинным текстом

18.09.2020 22:22:25 | Автор: admin

image


Пятница, вечер, настало время удивительных историй :-)
Две недели назад я нашел новую работу, чему не перестаю радоваться до сих пор)
Но пост не об этом. Сначала была фаза активного поиска работы и прохождения собеседований. Опыта и выводов набралось много. Я хочу этим поделиться, потому что мне кажется, эти выводы будут полезны обоим сторонам (как соискателям, так и рекрутерам).
Дальше будет много сухого и солёного текста.


Вводная


Сразу скажу, мой опыт относится к позиции "senior devops / sre". На этом рынке спрос больше, чем предложение. Всего со мной контактировало около 20 компаний. Где-то я выходил в финал, где-то сходил с дистанции после первого интервью.


Я разместил резюме на трех сайтах и в одном телеграм канале.
Это дало огромный поток входящих звонков и сообщений. Дело даже не дошло до изучения вакансий на сайтах. И я просто не успевал смотреть компании, которые только жали кнопочку "интересный кандидат".
Вывод для HR: Пишите и звоните первыми (наверное, все HR и так это знают).
Вывод для соискателей: Необязательно публиковать свое резюме везде. Пара тройка главных мест и приготовьтесь к общению.
Вывод для обоих: Запаситесь вежливостью и постарайтесь отвечать всем. Вежливый отказ лучше игнора. А вежливый фидбек то, что делает мир лучше.


Общие условия


Где-то 90% компаний предлагают рыночный уровень ЗП и похожие условия: тк рф, белую ЗП в рублях, дмс (почти у всех), что-то пожевать в офисе.


ДМС есть, но не все ДМС одинаково хороши. Спрашивайте, не только есть ли ДМС, но и от какой компании. От себя могу порекомендовать ту, которая начинается на "best" и заканчивается на "doctor" :-). Интересные исключения: у кого-то ситуация "нет ДМС, зато есть фитнес". В одной компании оплачивают 50% медицинских расходов.


Удаленка. Многие не имели удаленки вообще, но сейчас вынужденно работают удаленно и даже готовы думать об этом после пандемии. Мне показалось, что кто-то думает "удаленка = другой формат договора". Поэтому, кроме вопроса "есть ли удаленка", спрашивайте "в каком формате".


Размер компании


Что можно ожидать от большой компании по дефолту: ДМС, внутренняя автоматизация, налаженые системы вкусняшек, питания и обучения.
То есть, компания хорошо выстроила те процессы, которые нужны всем сотрудникам. Ей просто пришлось их выстроить, чтобы продолжать работать. Ну, ещё вокруг вас будет много людей)


Все остальное: рабочее место, техника, денежные бонусы, выстроенные процессы внутри команды, и т.д. зависит целиком и полностью от вашего "начальника" (тимлида, менеджера).
Вывод для соискателей: смотрите на не бренд, а на тех, кто проводит интервью. Спрашивайте их, как устроена работа в этой команде, а не в общем в компании.
Вывод для HR: если в какой-то команде беда с кадрами, соберите фидбек и дайте его начальнику команды (и, может быть, начальнику начальника. Сверху всегда лучше работает :-)


Уровень ЗП


В целом, есть рыночный уровень ЗП, но он не лежит на поверхности.
Нужно почитать аналитику и просмотреть много вакансий, чтобы понимать верхнюю планку.
Мне показалось, что хорошим мидлам готовы платить, как сеньорам, а хорошим сеньорам как лидам. Но это не от хорошей жизни, а скорее от отчаяния.
В целях экономии денег, компании используют простую тактику: не публикуют вилку в вакансиях, а просто спрашивают, сколько я хочу. После этого говорят "ок" (кто-то проговаривается "да, это в нашей вилке"). И на первых этапах общения к вопросу денег больше не возвращаются. Все стараются нанять "по нижней планке ожиданий".
Вывод: Не надо комплексовать и слишком занижать зарплатные ожидания. На рынке полно компаний, которые готовы предложить больше. Но если вы поставите небольшую сумму, вам начнут писать те, у которых эта сумма максимум.
Лайфхак: попробуйте вежливо спросить "можно ли узнать вилку". Обычно говорят: "столько-то столько-то". Иногда добавляют, что готовы обсуждать и большие суммы.


Я шел на эксперименты и повышал зарплатные ожидания в резюме на сайтах, но мне продолжали звонить (причем я уточнял, какую сумму они видели в резюме). Торг в большую сторону начинался, когда мне были готовы дать оффер, но я говорил, что у меня уже есть оффер от другой компании. Торга в меньшую сторону, "указать в резюме много, а потом согласиться на меньше" не было вообще. Мне сразу говорили, что не готовы столько платить.
Вывод: Слишком завышать зарплатные ожидания тоже не надо. У вас не будет шанса доказать, что вы стоите этих денег. А так же не будет шанса поторговаться вниз.
Лучше поставить среднюю или чуть выше и торговаться вверх, на этапе оффера.
Лайфхак: Но если много звонят повышайте ожидания. Если мало звонят понижайте.


Строчки "высокая ЗП", "конкурентная ЗП", "хорошие финансовые условия".
Их вставляют в резюме, но они ничего не значат, когда разговор идет в стиле: "сколько вы хотите?". Даже строчка "бонусы" может означать следующее: "По договору, ваш оклад будет 85%, но вы всегда будете получать 15% бонус".


Денежные бонусы


У некоторых компаний они есть. Где-то ежегодные, где-то раз в 6 месяцев, а где-то и ещё чаще.
Здесь рекомендую детально расспросить, что за бонусы, по какой логике они даются и т.д.
Некоторые компании предлагают поистине шикарные бонусы, но дьявол может крыться в деталях.


Например, есть бонус или пересмотр ЗП в фиксированный месяц (например, раз в год, в декабре). Но если вы устроитесь незадолго до такого месяца, вашего стажа будет нехватать, и нужно будет ждать следующий год. Т.е. оно вроде как и есть, но по факту окажется ещё не скоро. И опять-таки, "большая компания" не значит "бонусы". Все зависит от отдела. Поверьте, я был в большой компании, я знаю. Даже обидно.


Странные условия


Иногда бывают компании с условиями, которые я бы назвал странными для моего случая. Например, строгий дресс код. Или 85% ЗП на этапе испытательного срока. Если там была рыночная ЗП, я отказывался, но старался дать честный фидбек.
Совет соискателям: Если что-то вам кажется странным или недопустимым, не тратьте время. Но не бойтесь давать фидбек и честно указывайте странности, как причину отказа. Возможно, компания готова меняться и ваш фидбек ей в этом поможет. Например, мне сказали "забудьте про 85%".
Вопрос компаниям: Какой смысл в странных условиях? Есть куча компаний, которые готовые платить N денег. Соискатель будет получать свои N денег в одном месте, на одних условиях, или те же N денег в другом месте на других условиях.


Иногда есть странные компании, которые готовы платить сильно выше рынка. В таких случаях надо быть крайне осторожным, как сапёр на минном поле. Надо смотреть очень внимательно, будет ли вам там комфортно работать. Потому что вы рискуете стать заложником компании с такой ЗП. А, если уйдете, будет очень больно переходить на меньшую зп.
Логика простая: Если вы три-шесть месяцев будете получать на 30-50% выше рынка, но сожжете кучу нервных клеток, это вам аукнется сильнее, чем заработанные деньги. Прибавьте к этому стресс от падения уровня дохода, когда вы перейдете на работу с рыночной ЗП. Одним словом, четыре буквы.


Фидбек


Каждый раз после интервью я просил дать фидбек. Просил сказать, что бы они рекомендовали мне подтянуть, чтобы стать более интересным для них. Если я не подойду, как кандидат, естественно. Я думал, что это станет уберфичей моего поиска работы data driven career и все такое :-)


На самом деле, именно недостаток конкретных знаний почти не всплывал, как причина. Незнание одной-двух технологий не являлось проблемой. Чаще проблемой являлось незнание всего стека. Так что фидбек показал, что дело не в технической части. Этого я не ожидал :-)
Поэтому, я продолжаю быть убежден, что фидбек полезная вещь и его всегда надо просить. Просто нужно быть готовым к тому, что он будет отличаться от того, что вы себе придумали. Кстати, почти все HR просили меня оставить фидбек, когда я сам снимал свою кандидатуру с вакансии.


По технологиям


Это мой личный взгляд и, конечно же, я капитаню, ошибаюсь, да и вообще ничего не понимаю)
Но я вижу запрос на знание современных технологий: виртуализация/облака, docker, ci/cd, пайплайны, ansible, python, kubernetes, prometheus, ELK и т.д.
Это то, что я видел в первых строчках большого количества вакансий, в блоке "обязательно". Похоже, это то, куда все движутся, и уже давно.
Я очень хочу двигаться в одном направлении со всеми, поэтому выставил вот такие приоритеты при выборе компании:


  1. Те, кто уже давно там.
  2. Те, кто ещё не там, но хочет.
  3. Те, кому это и не надо.

История одного парня


Расскажу историю одного парня. Он был большим профессионалом в классических технологиях и подходах. Но строчки в его резюме про "большой опыт в таких-то технологиях" больше совпадали с блоком "дополнительные пожелания" в вакансиях работодателей (там, где обычно про highload опыт). С блоком "обязательные требования" все было не так хорошо опыта в современных технологиях было не так много. А зарплатные ожидания были неплохие)


В результате не так много компаний были готовы платить много денег.
Парень сделал для себя простой вывод, который может пригодится таким же "старичкам".
Большой опыт в старых highload технологиях это хороший бонус. Но одного его недостаточно без знания современных технологий. То есть, работу найти можно, но очень большую ЗП вам не предложат. Если хотите быть востребованными, необходимо иметь или набирать опыт в современном стеке. А такой опыт проще всего получить в компаниях первого типа ("те, кто уже давно там")


Интересные случаи


Все их ждали, полагаю :-)


В одной компании очень заботились об атмосфере и уважении внутри команды. Поэтому сходу спросили про мою национальность и религию. А потом стали спрашивать про то, как я отношусь к другим национальностям и религиям. Сначала я подумал, что они просто не хотят нанимать токсичных людей и борются за равенство. Но потом вопросы пошли про отношение только к одной этнической группе и к одной религии. Что ж, компании есть куда расти в плане равенства :-) Но, хозяин барин.


В одной компании мне предложили серую ЗП, как вариант увеличения части "на руки". Причем компания немаленькая и международная. При втором общении я указал на то, что это вовлечение сотрудников в незаконную деятельность (нарушение закона же идет с обоих сторон). Там "дали задний ход" и сказали, что это была ошибка и компания работает по закону. Вывод: иногда достаточно просто намекнуть, что это ай-яй-яй :-)


Вместо резюме


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


А ещё я увидел готовность к честному обсуждению. Мы честно поднимали и обсуждали скользкие вопросы с обоих сторон. Если что-то казалось мне неприемлемым, с той стороны это принимали и иногда были готовы обсуждать.


Поэтому я сделал вывод для себя: на моем рынке труда спокойно можно найти то, что нравится, и не тратить свое время на странные собеседования. Возможно, этому помогает армия наемных HR, которые двигают культуру найма вперед. Они сглаживают острые углы неадекватности с обоих сторон. Возможно, на вашем рынке труда всё тоже не так уж плохо.

Подробнее..

Практика vs Теория или зачем нужно высшее образование?

28.09.2020 16:10:09 | Автор: admin

Дмитрий Симонов, CTO, создатель канала Техдирские заметки задал интересную дискуссию. Практика vs Теория или зачем нужно высшее образование?


Битвы вокруг практики vs теории хватает. Не менее, чем на ганзах", что лучше AК или AR-15, или Кольт 1911 или Глок 17. Чем мы, айтишники хуже?



У меня на одном проекте был менеджер, который свои теории пытался внедрять в работу, чем ужасно её удорожал. Получал он от этого извращённое удовольствие или нет истории не известно. Про него крутили пальцем у виска, так и называя: теоретик. Получалось, прямо как в D&G нет, не Дольче и Габбана, а дорого и глупо. Хоть и работало в итоге, если не мешать его шаловливым рукам. Что только что через его руки не прошло в первые недели появления и Kubernetes, и Prometheus, и Ceph.


На другом проекте есть мужик, который вместо того, чтобы правильно настроить всё чтобы работало. Так вот кидается во все процессы и сам всё делает. Так как он практик и знает, как правильно. Но работа в целом стоИт, потому что чувака на всё не хватает. Две руки, две ноги, посередине гвоздик. Но голова светлая, что лампочка Ильича. Ж### полная (это не про размер, а про наполненность!)


Практики это те, кто прошёл поля граблей и накопил в голове набор кейсов, которые знает как решать.


Теоретики, это те, кто знают, как вообще всё устроено, но практики нет.


Практики это те, кто умеют ловить известные проблемы.


А теоретики это те, кто могут подсказать практикам, как решать неизвестные проблемы.


Что важнее? Решать известные проблемы и неизвестные?


Подискутируем?

Подробнее..

Jenkins Pipeline заметки об оптимизации. Часть 1

28.09.2020 16:10:09 | Автор: admin


Меня зовут Илья Гуляев, я занимаюсь автоматизацией тестирования в команде Post Deployment Verification в компании DINS.

В DINS мы используем Jenkins во многих процессах: от сборки билдов до запуска деплоев и автотестов. В моей команде мы используем Jenkins в качестве платформы для единообразного запуска смоук-проверок после деплоя каждого нашего сервисов от девелоперских окружений до продакшена.

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

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


Что за зверь Jenkins Pipeline


Jenkins Pipeline мощный инструмент, который позволяет автоматизировать различные процессы. Jenkins представляет собой набор плагинов, которые позволяют описывать действия в виде Groovy DSL, и является приемником плагина Build Flow.

Скрипт для плагина Build Flow исполнялся напрямую на мастере в отдельном Java-потоке, который выполнял Groovy-код без барьеров, препятствующих доступу к внутреннему API Jenkins. Данный подход представлял угрозу безопасности, что впоследствии стало одной из причин отказа от Build Flow, но послужило предпосылкой для создания безопасного и масштабируемого инструмента для запуска скриптов Jenkins Pipeline.

Подробнее об истории создания Jenkins Pipeline можно узнать из статьи автора Build Flow или доклада Олега Ненашева о Groovy DSL в Jenkins.

Как работает Jenkins Pipeline


Теперь разберемся, как работают пайплайны изнутри. Обычно говорят, что Jenkins Pipeline совершенно другой вид заданий в Jenkins, непохожий на старые добрые freestyle-джобы, которые можно накликать в веб-интерфейсе. С точки зрения пользователя это, может, и выглядит так, но со стороны Jenkins пайплайны набор плагинов, которые позволяют перенести описание действий в код.

Сходства Pipeline и Freestyle джобы


  • Описание джобы (не шагов) хранится в файле config.xml
  • Параметры хранятся в config.xml
  • Триггеры тоже хранятся в config.xml
  • И даже некоторые опции хранятся в config.xml

Так. Стоп. В официальной документации сказано, что параметры, триггеры и опции можно задавать непосредственно в Pipeline. Где же правда?

Правда в том, что параметры, описанные в Pipeline, автоматически добавятся в раздел настройки в веб-интерфейсе при запуске джобы. Верить мне можно потому, что этот функционал в последней редакции писал я, но об этом подробнее во второй части статьи.

Отличия Pipeline и Freestyle джобы


  • На момент старта джобы Jenkins ничего не знает про агента для выполнения джобы
  • Действия описываются в одном groovy-скрипте


Запуск Jenkins Declarative Pipeline



Процесс запуска Jenkins Pipeline состоит из следующих шагов:
  1. Загрузка описания задания из файла config.xml
  2. Старт отдельного потока (легковесного исполнителя) для выполнения задания
  3. Загрузка скрипта пайплайна
  4. Построение и проверка синтаксического дерева
  5. Обновления конфигурации задания
  6. Объединение параметров и свойств заданных в описании задания и в скрипте
  7. Сохранение описания задания в файловую систему
  8. Выполнение скрипта в groovy-песочнице
  9. Запрос агента для всего задания или отдельного шага




При старте pipeline-джобы Jenkins создает отдельный поток и направляет задание в очередь на выполнение, а после загрузки скрипта определяет, какой агент нужен для выполнения задачи.

Для поддержки данного подхода используется специальный пул потоков Jenkins (легковесных исполнителей). Можно заметить, что они выполняются на мастере, но не затрагивают обычный пул исполнителей:


Количество потоков в данном пуле не ограничено (на момент написания статьи).

Работа параметров в Pipeline. А также триггеров и некоторых опций



Обработку параметров можно описать формулой:



Из параметров джобы, которые мы видим при запуске, сначала удаляются параметры Pipeline из предыдущего запуска, а уже потом добавляются параметры заданные в Pipeline текущего запуска. Это позволяет удалить параметры из джобы, если они были удалены из Pipeline.

Как это работет изнутри?
Рассморим пример config.xml (файл, в котором хранится конфигурация джобы):
<?xml version='1.1' encoding='UTF-8'?><flow-definition plugin="workflow-job@2.35">  <actions>    <org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobAction plugin="pipeline-model-definition@1.5.0"/>    <org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction plugin="pipeline-model-definition@1.5.0">      <jobProperties>        <string>jenkins.model.BuildDiscarderProperty</string>      </jobProperties>      <triggers/>      <parameters>        <string>parameter_3</string>      </parameters>    </org.jenkinsci.plugins.pipeline.modeldefinition.actions.DeclarativeJobPropertyTrackerAction>  </actions>  <description></description>  <keepDependencies>false</keepDependencies>  <properties>    <hudson.model.ParametersDefinitionProperty>      <parameterDefinitions>        <hudson.model.StringParameterDefinition>          <name>parameter_1</name>          <description></description>          <defaultValue></defaultValue>          <trim>false</trim>        </hudson.model.StringParameterDefinition>        <hudson.model.StringParameterDefinition>          <name>parameter_2</name>          <description></description>          <defaultValue></defaultValue>          <trim>false</trim>        </hudson.model.StringParameterDefinition>        <hudson.model.StringParameterDefinition>          <name>parameter_3</name>          <description></description>          <defaultValue></defaultValue>          <trim>false</trim>        </hudson.model.StringParameterDefinition>      </parameterDefinitions>    </hudson.model.ParametersDefinitionProperty>    <jenkins.model.BuildDiscarderProperty>      <strategy class="org.jenkinsci.plugins.BuildRotator.BuildRotator" plugin="buildrotator@1.2">        <daysToKeep>30</daysToKeep>        <numToKeep>10000</numToKeep>        <artifactsDaysToKeep>-1</artifactsDaysToKeep>        <artifactsNumToKeep>-1</artifactsNumToKeep>      </strategy>    </jenkins.model.BuildDiscarderProperty>    <com.sonyericsson.rebuild.RebuildSettings plugin="rebuild@1.28">      <autoRebuild>false</autoRebuild>      <rebuildDisabled>false</rebuildDisabled>    </com.sonyericsson.rebuild.RebuildSettings>  </properties>  <definition class="org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition" plugin="workflow-cps@2.80">    <scm class="hudson.plugins.filesystem_scm.FSSCM" plugin="filesystem_scm@2.1">      <path>/path/to/jenkinsfile/</path>      <clearWorkspace>true</clearWorkspace>    </scm>    <scriptPath>Jenkinsfile</scriptPath>    <lightweight>true</lightweight>  </definition>  <triggers/>  <disabled>false</disabled></flow-definition>


В секции properties находятся параметры, триггеры и опции, с которыми будет запускаться джоба. Дополнительная секция DeclarativeJobPropertyTrackerAction служит для хранения параметров, заданных только в пайплайне.

При удалении параметра из пайплайна, он будет удлён как из DeclarativeJobPropertyTrackerAction так и из properties, так как Jenkins будет знать, что параметр был определён только в пайплайне.

При добавлении параметра ситуация обратная, параметр добавится DeclarativeJobPropertyTrackerAction и properties, но только в момент исполнения пайплайна.

Именно поэтому если задать параметры только в пайплайне, то они будут недоступны при первом запуске.

Выполнение Jenkins Pipeline


Когда Pipeline-скрипт загружен и скомпилирован, начинается процесс выполнения. Но этот процесс состоит не только из выполнения groovy. Я выделил основные тяжеловесные операции, которые выполняются в момент исполнения джобы:

Выполнение Groovy-кода
Скрипт пайплайна всегда выполняется на мастере об этом нельзя забывать, чтобы не создавать лишнюю нагрузку на Jenkins. На агенте исполняются только шаги, которые взаимодействуют с файловой системой агента или системными вызовами.



В пайплайнах есть замечательный плагин, который позволяет делать HTTP запросы. В добавок ответ можно сохранять в файл.

httpRequest  url: 'http://localhost:8080/jenkins/api/json?pretty=true', outputFile: 'result.json'


Изначально может показаться, что данный код должен полностью выполняться на агенте, послать с агента запрос, а ответ сохранить в файл result.json. Но всё происходит наоборот, и запрос выполняется с самого дженкинса, а для сохранения содержимое файла копируется на агент. Если дополнительная обработка ответа в пайплайне не требуется, то советую заменять такие запросы на curl:

sh  'curl "http://localhost:8080/jenkins/api/json?pretty=true" -o "result.json"'


Работа с логами и артефактами
Независимо от того, на каком агенте выполняются команды, логи и артефакты обрабатываются и сохраняются на файловую систему мастера в режиме реального времени.

Если в пайплайне используются секреты (credentials), то перед сохранением логи дополнительно фильтруются на мастере.



Сохранение шагов (Pipeline Durability)
Jenkins Pipeline позиционирует себя как задача, которая стоит из отдельных кусочков, которые независимы и могут быть воспроизведены при падении мастера. Но за это приходится платить дополнительными записями на диск, потому что в зависимости от настроек задачи шаги с различной степенью детализации сериализуются и сохраняются на диск.



В зависимости от параметра живучести (pipeline durability) шаги графа пайплайна будут храниться в одном или нескольких файлах для каждого запуска джобы. Выдержка из документации:

В плагине workflow-support для хранения степов (FlowNode) используется класс FlowNodeStorage и его реализации SimpleXStreamFlowNodeStorage и BulkFlowNodeStorage.
  • FlowNodeStorage использует кэширование в памяти для объединения операций записи на диск. Буфер автоматически записывается во время выполнения. Как правило, вам не нужно беспокоиться об этом, но имейте в виду, что сохранение FlowNode не гарантирует, что он будет немедленно записан на диске.
  • SimpleXStreamFlowNodeStorage использует по одному небольшому XML-файлу для каждого FlowNode хотя мы используем кеш с soft-reference в памяти для узлов, это приводит к гораздо худшей производительности при первом прохождении через степы (FlowNodes).
  • BulkFlowNodeStorage использует один XML-файл большего размера со всеми FlowNodes в нем. Этот класс используется в режиме живучести PERFORMANCE_OPTIMIZED, который записывает гораздо реже. Как правило, это намного эффективнее, потому что одна большая потоковая запись выполняется быстрее, чем группа небольших записей, и сводит к минимуму нагрузку на ОС для управления всеми крошечными файлами.


Оригинал
Storage: in the workflow-support plugin, see the 'FlowNodeStorage' class and the SimpleXStreamFlowNodeStorage and BulkFlowNodeStorage implementations.
  • FlowNodeStorage uses in-memory caching to consolidate disk writes. Automatic flushing is implemented at execution time. Generally, you won't need to worry about this, but be aware that saving a FlowNode does not guarantee it is immediately persisted to disk.
  • The SimpleXStreamFlowNodeStorage uses a single small XML file for every FlowNode although we use a soft-reference in-memory cache for the nodes, this generates much worse performance the first time we iterate through the FlowNodes (or when)
  • The BulkFlowNodeStorage uses a single larger XML file with all the FlowNodes in it. This is used in the PERFORMANCE_OPTIMIZED durability mode, which writes much less often. It is generally much more efficient because a single large streaming write is faster than a bunch of small writes, and it minimizes the system load of managing all the tiny files.




Сохранённые шаги можно найти в директории:
$JENKINS_HOME/jobs/$JOB_NAME/builds/$BUILD_ID/workflow/


Пример файла:
<?xml version='1.1' encoding='UTF-8'?><Tag plugin="workflow-support@3.5">  <node class="cps.n.StepStartNode" plugin="workflow-cps@2.82">    <parentIds>      <string>4</string>    </parentIds>    <id>5</id>    <descriptorId>org.jenkinsci.plugins.workflow.support.steps.StageStep</descriptorId>  </node>  <actions>    <s.a.LogStorageAction/>    <cps.a.ArgumentsActionImpl plugin="workflow-cps@2.82">      <arguments>        <entry>          <string>name</string>          <string>Declarative: Checkout SCM</string>        </entry>      </arguments>      <isUnmodifiedBySanitization>true</isUnmodifiedBySanitization>    </cps.a.ArgumentsActionImpl>    <wf.a.TimingAction plugin="workflow-api@2.40">      <startTime>1600855071994</startTime>    </wf.a.TimingAction>  </actions></Tag>


Итоги


Надеюсь, данный материал был интересен и помог лучше понять, что из себя представляют пайплайны и как они работают изнутри. Если у вас остались вопросы делитесь ими ниже, буду рад ответить!

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

Из песочницы Индюшатина, как ее готовят

19.09.2020 22:22:49 | Автор: admin

GoooGooo
Привет! Сегодня мы поговорим с ребятами из Literal Team, которые делают игру Sovereign's Will об их страданиях, мучениях и победах при разработке индюшатины. Есть много замечательных игр, от больших и богатых студий играй и переигрывай. Но тем не менее люди берутся создавать свои, в гараже, на коленке, тратя сотни часов личного времени и кучу денег, без каких либо гарантий успеха. Мы живём в удивительное время, когда каждый, у кого хватит упорства, может на коленке собрать игру своей мечты или почти каждый или мало кто. Большинство таких проектов не доживают даже до стадии дизайн концепта. Ребятам из LT есть чем похвастаться, они обошли многие подводные камни инди разработки, проделали огромную работу на чистом энтузиазме, создали альфу, отказались от нее, создали другую альфу и продолжают упорно работать дальше. Видеть, как люди в режиме реального времени превращают свою мечту в реальность очень прикольно и вдохновляет, об этом мы с ними и поговорим.


Lesich
Привет! Я Алексей, один из участников LT, занимаюсь геймдизайном, кодингом и другими вещами по мере их поступления.


graphomant
Привет! Меня зовут Артём, я отвечаю за сценарий и текстовое наполнение игры


GoooGooo
Расскажите пожалуйста, почему вы решили этим заняться?


graphomant
Я всегда интересовался двумя вещами: играми и литературой. Совместить эти два занятия идея, лежащая на поверхности, но, к сожалению, в моё время (мне 31) информации о геймдеве было куда меньше, чем теперь. И казалось, что игры делают какие-то небожители, причём преимущественно англоговорящие. Но само желание никуда не девалось. Несколько лет назад я стал пробовать себя в качестве писателя, и вот чуть больше года назад мы с Literal Team нашли друг друга)


Lesich
Давно, еще с 2007 года, я читал бумажный журнал (такое нынче редкость) "Игромания". Помимо статей с обзорами игр и новостями индустрии там также был раздел "Игрострой", в котором рассказывалось о разработке игр, предлагались руководства и приложения для этого. Тогда я начал понимать, что в современном мире есть возможность создавать игры самостоятельно, и это захватило мое воображение.


Но тогда особо ничего не выгорело (кроме того, что я случайно удалил кучу нужных файлов с родительского компьютера, пытаясь установить какую-то программу для создания 3д-моделей), и вернулся я к идее создать игру уже через десяток лет, когда мы с товарищами решили попытаться создать что-то свое. Так началась история Sovereign's Will точнее, тогда еще King's Ambitions.


GoooGooo
Сколько вас человек в команде?


Lesich
После трех изменений состава команды, сейчас у нас двое разработчиков (я и Артем) и переводчик @Arsonium. Недавно мы также договорились о сотрудничестве с Gloomy тоже в плане перевода.
Но ветераны команды остаются с нами и периодически дают ценные идеи!


GoooGooo
Насколько я понимаю это ваш первый проект. Почему сразу был выбран такой сложный жанр как РПГ стратегия/интерактивная новелла, а не платформер например? Когда вы за это брались, вы представляли насколько трудоёмко это будет?


Lesich
Мы руководствовались целью сделать то, что будет интересным и будет выделяться в огромном море инди в Стиме. Да, мы предполагали, что сразу начинать со стратегии будет сложно, но всё равно остановились на это выборе по двум критериям. Во-первых, мы решили, что таким образом избегаем кучу других сложностей скажем, анимирования или разработки ИИ противников. Именно стратегия лучше всего покрывалась умениями участников команды. А во-вторых, проект изначально задумывался как небольшая бесплатная игра, проба сил и оценка отклика. Но мы не смогли вовремя определить круг работ и остановиться..


graphomant
О выборе жанра вам расскажет Алексей я-то присоединился к разработке, когда проекту было уже несколько лет. Но что до меня, то я вообще не понимал, в какую сложную историю ввязываюсь ;) Я знал, что ребята делают стратегию, и поначалу мне казалось, что я буду, скажем, делать какие-нибудь описания зданий и юнитов. Очень боялся, что придётся рыться в исторических книгах %) Потом слово за слово выяснилось, что сеттинг около-фентезийный, что писать нужно будет гораздо больше, чем я думал (вдобавок переписывать всё, что было написано до меня). Но, если бы даже я всё это сразу знал, то согласился бы, даже с большей охотой. Такой формат даёт огромный простор для "литературщины" здесь тебе и сценарий, и биографии, и описания локаций, и ветвистые квесты о большем и желать не приходится! Это настоящая проверка для меня как для автора.


Lesich
Не несколько лет, а всего полтора года, это важно!


graphomant
(смеётся)


GoooGooo
Для своей игры вы создали целый мир, расскажите пожалуйста о нем вкратце.


Lesich
О, я расскажу, с чего все начиналось, а Артем расскажет, к чему пришло.


graphomant
Валяй


Lesich
Сейчас будет инсайд: изначально сеттингом игры должна была быть Русь. Примерно с Рюрика и до 18 века. Мы хотели сделать игру, раскрывающую детали российской истории и позволяющую проверить "а что, если". Скажем, а что, если центром объединения русских земель стал бы Новгород? А что, если бы в России установилась аристократическая республика?


Но когда мы начали с этим работать, то поняли, что выбрали очень опасный путь. С одной стороны, делать слишком исторично не выходило у нас просто не хватало квалификации, чтобы продумать реалистичные альтернативные пути развития. С другой четкое следование истории превращало игру в учебник, лишало сценариста возможности разгуляться.


Поэтому на общем совете было решено делать свой средневековый мир. Точнее, даже не совсем делать. Один из участников команды, Солар ведущий в форумных стратегических играх (это что-то вроде ДнД с мастером, но в виде стратегии). Он взял за основу придуманный им мир Владения империи, подчинившей весь мир. И дальше была долгая дорога с доработками и адаптацией.
Солар примерно через 6-7 месяцев покинул команду, какое-то время мы по инерции работали с его материалом, а дальше к команде присоединился Графомант. Тогда мы и начали прорабатывать то, к чему пришли сейчас.


graphomant
Когда я подключился к разработке, главной сложностью для меня было вникнуть в уже накопленный материал от других авторов. Написано было уже довольно много, в общих чертах был прописан мир, персонажи и взаимоотношения, поэтому первые несколько недель я в основном читал, читал, читал. И попутно шлифовал тексты с точки зрения той самой "литературщины", ничего не меняя по сути. Редактура мне даётся очень просто, я могу делать это практически не задумываясь и не тратя сил слово туда, слово сюда, уточнить, перефразировать, и так далее


Просмотрев весь материал, я, разумеется, захотел устроить его немного по-своему. К тому времени я был уже, фактически, единственным нарративщиком в команде, и меня ничто не сдерживало) Поначалу я хотел лишь систематизировать материал, но в конечном итоге переписано было в той или иной степени абсолютно всё, каждый текст в игре, включая контекстные подсказки.


Что касается создания сеттинга, то здесь у меня уже был небольшой опыт я придумывал сеттинги для своих произведений. Но здесь было одновременно и проще и сложнее. Проще потому что уже имелся утверждённый каркас в виде единой империи человечества. Сложнее потому что жанр игры, формат подачи информации и многие другие мелочи поначалу сильно сковывали. Каждую идею приходилось по многу раз обсуждать. Большая часть, разумеется, летела в корзину. Но я вполне доволен тем, что получилось в итоге. Мы хорошо ориентируемся в созданном мире и можем обсуждать его между собой так, как будто он существовал отдельно от нас всегда по-моему, это неплохое достижение.


GoooGooo
О_о, т.е. вы изначально замахивались на что то типа стратегий Парадоксов?


Lesich
Сейчас это выглядит смешно и самонадеянно, но да, замахивались. Я сам, бывает, посмеиваюсь над людьми, которые собираются на форумах, чтобы сделать "убийцу WoW" или ААА-шутер с открытым миром и грабежом корованов. Но мы сами действительно хотели сделать что-то вроде Europa Universalis, но с упором не на "песочницу", а на историю одного конкретного региона. Наивно было полагать, что если в ЕУ дать возможность играть только за одну страну, то она станет гораздо проще в разработке, но мы это поняли не сразу.
Поделюсь, что один из первых диздоков-игры иронично был сохранен как "Клон ЕУ.docx"


GoooGooo
Когда мечта начинает воплощаться, сталкиваешься с серьезными ограничениями. Понимаешь что все, о чем так мечталось сделать не удастся, потому что свободное время, которое можно посвятить разработке, не резиновое и есть ограничения в финансах и человеческих ресурсах которые можно привлечь. У вас есть классная статья на ДТФ, где вы рассказываете о "Суверене". Там вы пишите о том что с самого начала в разработке вы задали себе четкие рамки. Расскажите пожалуйста об этом подробнее.


Lesich
Конечно, говорить о том, что эти рамки были установлены "с самого начала" это несколько лукавить) Мы прошли долгий путь перед тем, как поняли, какую именно игру будем делать. Если бы мы делали платформер или, скажем, шутер, то было бы достаточно просто определить рамки того, что нам нужно создать. Скажем, в шутере это механика стрельбы, враги, уровни. Но в Суверене мы и сами не могли очертить жанр игры, поэтому простор был действительно безграничный. И это было большим минусом.
В итоге мы много обсуждали, пытаясь выявить суть игры, то, что мы можем дать игрокам на хорошем уровне, и что может выделить нас из тысяч других игр. Так и остановились на четырех критериях: нелинейности, феодализме, последствиях решений и политической борьбе. Обсуждая добавление какого-то элемента, мы оцениваем его соответствие этим критериям: поможет ли он раскрыть их? Не будет ли он чуждым в системе остальных элементов? Это здорово помогает понять, стоит ли овчинка выделки в каждом конкретном случае.


graphomant
Кстати, что касается рамок, то разработка игры заставила меня иначе посмотреть на творческий процесс в принципе. В своё время я попал в типичную ловушку автора-перфекциониста, когда одно произведение создаётся, по сути, бесконечно. Дедлайнов нет, зато есть искреннее желание делать на пределе возможностей. Как результат долгострой, нервные срывы, язва и банальное самоубийство во цвете лет. В случае же разработки игры я не могу позволить себе лениво рассуждать о сценарии или элементах сеттинга, рассматривая их так и эдак, пока не буду точно уверен, что нашёл идеальную формулу. Есть сроки, есть технические ограничения, есть ответственность перед фанбазой. Поэтому приходится оценивать свои силы трезво, от отдельных задумок отказываться, ставить дедлайны, а иногда да идти на компромиссы. Но удивительным образом это только только обогащает и двигает процесс вперёд. Именно так и шлифуется навык. По крайней мере, так я сейчас ощущаю.


Lesich
вот так выглядит начало уже четвертого диздока по игре
imagehttps://i.imgur.com/uWU8eBF.png


GoooGooo
У вас в игре основной носитель информации это текст, хотя есть и весьма достойная графика, со своим уникальным стилем. Как вы решали какими средствами рассказывать вашу историю и каков должен быть их баланс?


Lesich
В основном исходя из наших возможностей, хах. У нас в команде нет художников, но, к счастью, и целевая аудитория нашей игры достаточно благосклонно относится в том числе к играм без мощной графической части. Если бы такой аудитории не было, нам не было бы и смысла что-то делать...


graphomant
О, мы это до сих пор решаем! В опросе, который прикреплён к демо-версии, мы отдельно спрашиваем, не показалось ли игроку, что текста слишком мало или слишком много. На самом деле, очень тяжело определить ту тонкую грань между твитом и простынёй текста. Люди читают очень по-разному, с разной скоростью, с разной, скажем так, толерантностью к словесным изыскам. Очень простой текст одному покажется приятным и понятным, а другого может разочаровать как слишком примитивный. Здесь мы опираемся только на собственное чутьё, потому что объективного критерия нет.


Lesich
В любом случае, мы постепенно стараемся сократить объем текстов.
Изначальные тексты ивентов, написанные еще Соларом, могли занимать две страницы текста...


GoooGooo
Вы сделали альфу, в которой было несколько интересных ивентов и персонажей, которые наверняка стоили вам многих часов работы. Но в следующей версии альфы вы от них отказались (и некоторые преданные фанаты вам не могут этого простить). Почему это произошло? И как вы решаете что стоит переделать, а что достойно того чтоб оставить? graphomant Вам не приходится от этого рыдать в подушку и есть горстями антидепрессанты?


Lesich
Могу заметить, что "урезанная часть", о которой жалеют некоторые фанаты это меньше половины от всего вырезанного контента) К сожалению, реалии разработки игр таковы, что очень сложно заранее понять, будет ли интересно играться какой-то эпизод. Поэтому практически единственный вариант это итерирование. Мы что-то делаем, проверяем, работает ли оно. Если не работает, то оцениваем, есть ли смысл пытаться это доработать или лучше и безболезненнее выбросить.


Да, это грустно, но необходимо. Лучше так, чем продолжать вкладывать силы в элемент, от которого все равно придется отказаться.
Но и не стоит рассматривать вырезанный контент как пустую трату сил. Пока мы над ним работали, мы приобрели новые навыки, проверили какие-то гипотезы. Да и кто знает, может, мы задействуем эти элементы в платных ДЛС будущих играх!


graphomant
Мне рыдать пока не приходилось, потому что вырезано было только то, что писали до меня ;) Эти сокращения мы делали по разным причинам. Некоторые тексты были хороши по сути, но непомерно огромны приходилось делать выжимку. Некоторые не укладывались в рамки обновлённого сеттинга. А ещё была отдельная часть игры, которую мы вырезали. Она посвящена борьбе с голодом, и мы решили, что по тону этот отрезок сюжета не подходит для самого начала игры.


Lesich
graphomant, ну ты морально готовься на всякий случай


GoooGooo
Lesich мы знаем что Вы по профессии профессор и Ваша работа заключается в том, что Вы гоняете на входе в ВУЗ студентов без масок.
graphomant а чем занимаетесь Вы?


graphomant
У меня скучнейшая офисная работа возможно, поэтому меня так и тянет к творчеству ;) Сейчас я работаю в интернет-рекламе.


GoooGooo
У вас ограниченные ресурсы, ваше личное время которое вы можете отдать разработке и которое вам никто не оплачивает, у вас нет никакого финансирования со стороны для того чтоб заплатить сторонним специалистам, приходится это делать на свои и тем не менее постройка игры идёт полным ходом. Расскажите пожалуйста о планировании, как вы распределяете свои ресурсы, как решаете, что нужно сделать в первую очередь, во вторую, от чего вообще отказаться?


Lesich
В основном совещаниями. Мы используем доску в Trello для отслеживания задач и их приоритетности. Это выглядит вот так:
imagehttps://i.imgur.com/c3h7hS6.png
Задачи сортируются по сферам, чем выше задача в списке тем выше ее приоритет.
Одно время я пользовался приложением Todoist, но через какое-то время оповещения "15 задач на сегодня, 72 просроченных" начали меня угнетать. Пришлось удалить.


graphomant
Это, конечно, отдельная боль. Когда я утром составляю план на день (да, я правда так делаю), у меня в списке вперемешку оказываются задачи по основной работе, задачи по разработке игры, бытовые задачи, покупки, какие-то личные дела. Как расставлять приоритеты вопрос вечный и нерешаемый. Иногда я больше отдаюсь разработке, иногда личным делам. Когда в одной сфере наступает перенапряжение, я просто переключаюсь на другую.


GoooGooo
Сколько часов в неделю вы посвящяете разработке?


Lesich
О, тут всегда по-разному. Иногда наступает такая апатия, что выходит всего 2-3 часа в неделю. А, например, перед выходом демо в Steam я сидел над ним по 4-6 часов в день. Последние два дня перед выходом по 10.
И в такие моменты ты кажешься себе просто властелином продуктивности, но не рекомендую таким злоупотреблять. Уже через несколько дней ты чувствуешь себя настолько опустошенным, что не будешь ничего делать совсем. И всё преимущество от этих переработок нивелируется.


graphomant
Поддерживаю предыдущего оратора это очень сильно зависит от того, что конкретно нужно писать и как у меня с основной работой и личными делами. Например, когда я переписывал биографии персонажей и описания локаций, то занимался этим по нескольку часов в день на протяжении двух или трёх недель довольно интенсивно. Но бывают и периоды простоя.


GoooGooo
И как на такое массивное использование свободного времени реагируют жены/подруги?


Lesich
Нет жён нет проблем


graphomant
Мне в этом смысле повезло семья, друзья и подруги всецело одобряют мои художества.


Lesich
Между прочим, жена разработчика Stardew Valley несколько лет работала за двоих, пока он клепал свой инди-шедевр!


GoooGooo
Как вы можете оценить свою работу, что уже сделано, за что вы себя определенно можете похвалить, над чем работаете и что предстоит сделать?


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


graphomant
Мне кажется, что для столь маленькой команды, которая работает на идею и не имеет опыта разработки игр, мы держимся очень даже неплохо)


Lesich
Самое наглядное наше достижение, это то, как мы перешли от этого:
imagehttps://i.imgur.com/5c6jgwG.png
через это:
imagehttps://i.imgur.com/7sFT4np.png
к этому:
imagehttps://i.imgur.com/b5jKQcu.png


graphomant
К сожалению, прогресс текстовой части так наглядно не покажешь, но там тоже стало слегка получше, чем было


GoooGooo
graphomant Вы говорили что постоянно работаете над сокращением текстов, чтоб они лучше воспринимались игроком. Не жалко резать? Как Вы решаете, что и насколько сократить?


graphomant
Нет, не жалко. Помогает то, что я вожусь с текстами уже много лет и успел привыкнуть к тому, что резать и переписывать необходимо. Если человеку жаль редактировать свои тексты, то он либо не успел набраться опыта, либо просто графоман. Тут двух мнений быть не может редактировать и сокращать тексты так же естественно, как, скажем, заниматься монтажом отснятого материала для кино.
Сколько сокращать и что переделывать. Здесь ты либо видишь избыточность можно выразить ту же мысль более кратко, либо замечаешь какую-нибудь "занозу". Занозы бывают очень разные: неудачный ритм фразы, прорыв другого стиля в текст (например, канцеляризма), и так далее. По сути приходится многократно перечитывать текст, чтобы выровнять их все.


GoooGooo
Насколько я понимаю вы пытаетесь добиться того чтоб каждый персонаж, с которым будет взаимодействовать игрок был объемным, живым. Как вы это делаете?


Lesich
В основном это вопрос к Артёму, конечно. В целом мы работали примерно так: оценивали роль этого персонажа в геймплее и сюжете, на ее основе определяли его основные черты и особенности, а дальше Графомант добавлял множество деталей, дополняя до полноценного человеческого образа.


И, конечно, мы поломали много копий на этом этапе!
imagehttps://i.imgur.com/qqsyRx7.png
Зато каждый персонаж теперь как родной.


graphomant
Любой автор к этому стремится. Благо, посредством текста можно очень подробно очертить образ происхождение, характер, реакции на события. Сейчас у нас 15 основных (геймплейных) персонажей, не считая закадровых. Мои предшественники собрали хороший набор архетипов: суровый военачальник, бюрократ, разбойник, рыжуха-пиратка Мне оставалось только создать им новые биографии в соответствии с архетипом и особенностями их вотчин. Некоторые нужно было только слегка подправить (творчество других нарративщиков иногда конфликтовало между собой, и тогда я выбирал вектор). Для некоторых написались целые небольшие рассказы об их детстве, юношестве и зрелости.


GoooGooo
О, я вижу в биографии много деталей, они играют какую то роль в прохождении игры?


Lesich
Конечно. Фактически, у каждого персонажа есть две биографии. Одна, краткая, отображается в окне взаимодействия с ним и содержит наиболее важные моменты, которые играют роль в сюжете и геймплее. Например, если внимание акцентировано на том, что персонаж соблюдает закон, а игрок попытается подкупить его подчиненных, могут быть серьезные последствия.


Есть также расширенная биография в Кодексе со множеством деталей, которые как могут подсказать тактику поведения с этим персонажем (например, использовать его происхождение), так и служат для общего наполнения лора игрового мира.


GoooGooo
Выше вы писали о нелинейности геймплея, как об отличительной особенности игры. По нынешним временам это очень редкий зверь для игр в которых нет процедурной генерации обьектов. Расскажите пожалуйста об этом подробнее.


graphomant
Мне кажется, что сделать сюжет нелинейным это такой священный грааль любого нарративщика. В случае дорогостоящих ААА-игр сделать это очень трудно, слишком уж велики затраты на контент, который отдельно взятый игрок может никогда не увидеть (хотя и тут есть редкие удачи например, Ведьмак 2 с двумя принципиально разными игровыми актами в зависимости от сделанного игроком выбора). В нашем же случае нелинейность всего лишь означает, что сценаристу нужно продумать и написать не один вариант развития событий, а, скажем, пять. нервно хихикает
Если говорить о конкретном воплощении, то здесь мы проделали некий путь. Поначалу мы пытались чертить огромные блок-схемы, но скоро стало понятно, что это очень неэффективно и трудозатратно само по себе. По сути ты становишься заложником инструмента, каким бы хорошим он не был. Разные студии решают эту проблему по-своему некоторые даже пишут собственные софты, чтобы держать и сопоставлять куски истории.


Lesich
Да, поддерживаю. У нас есть большое преимущество в этом плане. Сценарист Даинг Лайт и Мафии 3 как-то сказал: "Игры, над которыми я работаю, не состоят исключительно из текста. Как только в дело вступают арт, анимация и так далее, возможность постоянно разветвлять историю в духе книжек Выбери своё приключение у тебя немедленно пропадает".


Так вот, в отличие от его игр, у нас такая возможность не пропала.
Плюс мы используем разные инструменты для ветвления. Например, ветвим не в зависимости от каждого решения, а в зависимости от общего вектора, созданного несколькими решениями игрока. Это позволяет сохранить значимость решений меньшими усилиями.


graphomant
Если говорить ещё конкретнее, то нам пришло в голову адаптировать систему из игр Failbetter Fallen London, Sunless Sea и Sunless Skies. Там по мере прохождения персонаж получает условные "метки" побывал там-то, познакомился с тем-то, взял такое-то задание. Сейчас мы взяли курс на то, чтобы строить нелинейность на основе таких вот меток. К примеру, если игрок познакомился на балу с определенным персонажем, то он получает метку, и затем факт наличия (или отсутствия) этой метки выступает как триггер для события или эффекта. Это избавляет нас от необходимости создавать эти сумасшедшие блок-схемы. По сути вся нелинейность может укладываться в ассортимент таких вот меток.


Lesich
Вот, на этом скриншоте в правом окне часть меток события "Коронация":
image


GoooGooo
Но нелинейность в таком случае предполагает, что многие сюжетные линии пройдут мимо игрока. Вам не жалко затраченного труда?


Lesich
Лично мне бывает жалко. Я сам, как игрок, стараюсь посмотреть все сюжетные ветки, которые есть в играх, и мне немного грустно от того, что игрок увидит только небольшую часть контента. Но, во-первых, он зато получит классное осознание нелинейности происходящего, а во-вторых, возможно, это сподвигнет его на перепрохождение другим способом.


graphomant
Безусловно жаль. Но без этого никак. Мне как игроку бывает очень приятно, когда я встречаю в играх реальный исход своего собственного выбора. Чтобы вызвать у игрока это чувство, мы должны либо дать реальное пространство выбора, либо как-то хитро его имитировать. Пока что мне кажется, что имитировать сложнее. Но посмотрим, как мы дальше заговорим)))


Lesich
"хитро его имитировать"
Я так Волкинг Дэд от ТеллТейлов бросил...


GoooGooo
Хм т.е. у вас мир квази живёт своей жизнью?


Lesich
Жизнь мира строится фактически из двух элементов: это длань сюжета, которая перетасовывает персонажей и события, и некоторая полуавтоматическая системность: мы постараемся, чтобы персонажи взаимодействовали друг с другом, фракции боролись с игроком, а мировая обстановка влияла на состояние дел внутри маркграфства. Но пока эта система сыровата, и мы не выкатили ее тестерам. Кто знает, может, еще придется ее вырезать!


graphomant
Нет-нет, под имитацией я имел в виду такую систему, в которой реального выбора или нет вообще, или его пространство значительно уже, чем преподносится игроку. Например, когда в начальной точке даётся огромное множество вариантов, которые очень скоро ведут к одной и той же точке. Игроки уже давно научились такое видеть и это определённо не то, что нам хотелось бы создать.


GoooGooo
Скажите, над чем вы работаете прямо сейчас и какие у вас виды на разработку игры в обозримом будущем?


Lesich
О, мы планируем сделать пост в Стим с описанием наших планов на ближайшие месяцы разработки, но могу выдать инсайды!


Сейчас мы работаем над глобальным событием "Заговор", в котором игрок будет противостоять, собственно, заговорщикам, а заодно посетит разные уголки своей страны. Это будет весьма нелинейно, потому что персонажей целых 15, а посетить можно успеть 4-5 максимум, и от того, кого игрок выберет, будет зависеть многое.


Также в планах доработка системы взаимодействия с персонажами (сейчас оно ограничивается только взятками. Это весьма реалистично для игры про огромную бюрократическую империю, но скучновато для игрока), создание полноценного древа указов (что-то вроде национальных фокусов в ХоИ) и системы взаимодействия игрового мира, которую я раньше упомянул. И это не говоря о туче менее важных, но запланированных доработок. Как можно видеть, с того момента, как мы начали делать игру, амбиции не сильно уменьшились!


graphomant
Прямо сейчас мы, наконец, закончили с проработкой сеттинга и дописали кодекс. Теперь предстоит снова начать с начала мы хотим сильно расширить и углубить первые игровые ивенты. В первую очередь они должны рассказать игроку о мире игры и персонажах и желательно не нудными выкладками-лекциями, а геймплеем. Для этого мы отправляем главного героя в поездку по его владениям. В связи с некими обстоятельствами ему будет нужно посетить нескольких персонажей, с каждым из которых будет связан отдельный нелинейный ивент. А все эти ивенты послужат решением одной глобальной проблемы. Об этом трудно говорить без спойлеров я надеюсь, скоро сами всё увидите.


Lesich
Глобальная цель выпустить таки эту игру! Потом, возможно, перейдем к следующей, потому что я втянулся в это. Инди-разработка это, всё-таки, больше не про цель, а про процесс, на мой взгляд. С каждой неделей я узнаю что-то новое о программировании, геймдизайне, графике. Я многому научился за это время. Собственно, это и путь постоянно развиваться и улучшать то, что мы делаем. А там посмотрим, к чему придем.
Очень вдохновляют отзывы и мнения об игре. Некоторые игроки не поленились и написали несколько абзацев с замечаниями и предложениями в форму для отзыва или в нашем чате. Каждый такой отзыв мотивирует продолжать работать.


graphomant
Поддерживаю. Я ничего не узнал о программировании и графике, но кое-что узнал о геймдизайне, а также, возможно, стал чуть лучше писать.


GoooGooo
Спасибо за интересный рассказ. И завершающий вопрос, на который вы уже частично ответили: инди разработка штука сложная, требующая больших затрат личного времени, самодисциплины, личных средств, которых и так наверняка не много. Почему вы продолжаете этим заниматься?


graphomant
Потому что искренне любим игры и хотим их делать) Наверное, вот так просто. Да и заработать вроде как можно, за книги-то вообще не платят!


Lesich
Ну, есть подозрение, что мы не совсем нормальные


А так да, я уже очертил причины: мне нравится делать игру, в которую я бы сам играл; меня очень поддерживают отзывы и мнения; я чувствую, как учусь на этой разработке и становлюсь лучше. Наверное, без разработки я уже не буду чувствовать себя целостным. Знаю, звучит как зависимость, но это не хуже зависимости от ММОРПГ!


Да, финансовый аспект тоже есть, было бы нечестно его отрицать. Но для меня это не "заработать миллионы", а "зарабатывать на разработке игр достаточно, чтобы заниматься этим как основной деятельностью".


graphomant
И да, мы определённо не совсем нормальные. И это нормально.


Интервью происходило в дискорде Literal Team https://discord.gg/gEjr7WB
Стим: https://store.steampowered.com/app/1047560/Sovereigns_Will/
Рассказ об игре: https://dtf.ru/indie/125620-on-eto-zapomnit-milord-nelineynost-i-intrigi-v-indi-proekte

Подробнее..

Категории

Последние комментарии

© 2006-2020, personeltest.ru