Автостопом по Python.

Системное администрирование.

Инструменты, показанные в этом разделе, предназначены для наблюдения за системами и управления ими (автоматизация сервера, наблюдение за системами и управление потоком выполнения).

Travis-CI.

Travis-CI (https://travis-ci.org/) — распределенный сервер непрерывной интеграции, позволяющий создавать тесты для проектов с открытым исходным кодом бесплатно. Предоставляет несколько рабочих процессов, которые запускают тесты Python, и бесшовно интегрируется с GitHub. Вы даже можете указать ему оставлять комментарии для ваших запросов на включение[96], если этот конкретный набор изменений сломает сборку. Поэтому, если вы размещаете свой код на GitHub, Travis-CI — отличное средство, чтобы начать использовать непрерывную интеграцию. Travis-CI может собрать ваш код на виртуальной машине, на которой запущены Linux, OS X или iOS.

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

Language: python.

Python:

··- "2.6".

··- "2.7".

··- "3.3".

··- "3.4".

Script: python tests/test_all_of_the_units.py.

Branches:

··only:

····- master.

Этот код указывает протестировать ваш проект для всех перечисленных версий Python путем запуска заданного сценария, сборка будет выполнена только для ветки master. Существует множество доступных параметров вроде уведомлений, предыдущих и последующих шагов и многих других (http://about.travis-ci.org/docs/). Для того чтобы использовать Tox вместе с Travis-CI, добавьте сценарий Tox в ваш репозиторий и измените строку с конструкцией script:; файл должен выглядеть так:

Install:

··- pip install tox.

Script:

··- tox.

Чтобы активизировать тестирование для вашего проекта, перейдите на сайт https://travis-ci.org/ и авторизуйтесь с помощью вашей учетной записи для GitHub. Далее активизируйте ваш проект в настройках профиля, и вы готовы к работе. С этого момента тесты для вашего проекта будут запускаться после каждой отправки кода в GitHub.

Jenkins.

Jenkins CI (http://jenkins.io/) — это расширяемый движок непрерывной интеграции, в данный момент он считается самым популярным. Работает на Windows, Linux и OS X, его можно подключить к «каждому существующему инструменту управления исходным кодом». Jenkins является сервлетом Java (эквивалент приложений WSGI в Java), который поставляется с собственным контейнером сервлетов, что позволяет вам запускать его с помощью команды java — jar jenkins.war. Для получения более подробной информации обратитесь к инструкциям по установке Jenkins (https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins); на странице Ubuntu содержится информация о том, как разместить Jenkins на базе обратного прокси Apache или Nginx.

Вы взаимодействуете с Jenkins с помощью информационной панели или его RESTful API[97], основанного на НТТР (например, по адресу http://myServer:8080/api), что означает, что можно использовать HTTP для того, чтобы общаться с Jenkins с удаленных машин. Например, взгляните на Jenkins Dashboard (https://builds.apache.org/) для Apache или Pylons (http://jenkins.pylonsproject.org/).

Для взаимодействия с Jenkins API в Python наиболее часто применяется python-jenkins (https://pypi.python.org/pypi/python-jenkins), созданный командой OpenStack[98] (https://www.openstack.org/). Большинство пользователей Python конфигурируют Jenkins так, чтобы он запускал сценарий Tox как часть процесса сборки. Для получения более подробной информации обратитесь к документации по адресу http://tox.readthedocs.io/en/latest/example/jenkins.html, где рассказывается об использовании Tox для Jenkins, а также к руководству http://tinyurl.com/jenkins-setup-master-slave по настройке Jenkins для работы с несколькими машинами.

Buildbot.

Buildbot (http://docs.buildbot.net/current/) — это система Python, предназначенная для автоматизации цикла компиляции/тестирования, проверяющего изменения кода. Похож на Jenkins тем, что опрашивает менеджер системы контроля версий на наличие изменений, выполняет сборку и тестирование вашего кода на нескольких компьютерах в соответствии с вашими инструкциями (имеет встроенную поддержку для Tox), а затем говорит вам, что произошло. Он работает на базе веб-сервера Twisted. Если вам нужен пример того, как будет выглядеть веб-интерфейс, взгляните на общедоступную информационную панель buildbot от Chromium (https://build.chromium.org/p/chromium/waterfall) (с помощью Chromium работает браузер Chrome).

Поскольку Buildbot написан на чистом Python, его можно установить с помощью pip:

$ pip install buildbot.

Версия 0.9 имеет REST API (http://docs.buildbot.net/latest/developer/apis.html), но она все еще находится на стадии бета-тестирования, поэтому вы не сможете ее использовать, если только явно не укажете номер версии (например, pip install buildbot==0.9.00.9.0rc1). Buildbot имеет репутацию самого мощного и самого сложного инструмента непрерывной интеграции. Для начала работы с ним обратитесь к этому отличному руководству: http://docs.buildbot.net/current/tutorial.

Автоматизация сервера.

Salt, Ansible, Puppet, Chef и CFEngine — это инструменты для автоматизации сервера, которые предоставляют системным администраторам элегантный способ управлять их флотом физических и виртуальных машин. Все они могут управлять машинами, на которых установлены Linux, Unix-подобные системы, а также Windows.

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

Автостопом по Python. Разработчики Docker ожидают, что инструменты по автоматизации систем вроде Salt, Ansible и прочих будут дополнены Docker, а не заменены им. Взгляните на статью http://stackshare.io/posts/how-docker-fits-into-the-current-devops-landscape о том, как Docker работает с остальным ПО для DevOps.

Salt.

Salt (http://saltstack.org/) называет свой главный узел мастером, а узлы-агенты — миньонами или хостами-миньонами. Его основная цель — высокая скорость; работа с сетью по умолчанию выполняется с помощью ZeroMQ, между мастером и миньонами устанавливается соединение TCP. Члены команды разработчиков Salt написали свой (необязательный) протокол передачи данных RAET (https://github.com/saltstack/raet), который работает быстрее, чем TCP, и теряет не так много данных, как UDP.

Salt поддерживает версии Python 2.6 и 2.7, его можно установить с помощью команды pip:

$ pip install salt # Для Python 3 версии пока нет…

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

$ salt '*' test.ping.

Вы можете отфильтровать хосты-миньоны либо по их идентификатору, либо с помощью системы grains (http://docs.saltstack.org/en/latest/topics/targeting/grains.html), которая использует статическую информацию хоста вроде версии операционной системы или архитектуры ЦП, чтобы предоставить таксономию хостов для модулей Salt. Например, следующая команда применяет систему grains для перечисления только тех миньонов, на которых запущена CentOS:

$ salt — G 'os: CentOS' test.ping.

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

Apache:

··pkg:

····- installed.

Service:

····- running.

····- enable: True.

····- require:

······- pkg: apache.

Файлы состояний могут быть написаны с помощью YAML, дополненной системой шаблонов Jinja2, или же могут быть чистыми модулями Python. Для получения более подробной информации обратитесь к документации Salt по адресу http://docs.saltstack.com/.

Ansible.

Самое большое преимущество Ansible (http://ansible.com/) перед другими системами автоматизации — для ее установки на клиентских машинах не требуется ничего (кроме Python). Все другие варианты[99] поддерживают на клиентах демонов, которые опрашивают мастера. Их конфигурационные файлы имеют формат YAML. Сценарии — это документы для конфигурирования, развертывания и управления для Ansible, они написаны на YAML и используют для шаблонов язык Jinja2. Ansible поддерживает версии Python 2.6 и 2.7, ее можно установить с помощью pip:

$ pip install ansible # Для Python 3 версии пока нет…

Ansible требует наличия файла инвентаря, в котором описывается, к каким хостам он имеет доступ. В следующем фрагменте кода показывается пример хоста и сценария, который опрашивает все хосты в файле инвентаря. Рассмотрим пример файла инвентаря (hosts.yml):

[server_name].

127.0.0.1.

Рассмотрим пример сценария (ping.yml):

-

- hosts: all.

··tasks:

····- name: ping.

····action: ping.

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

$ ansible-playbook ping.yml — i hosts.yml — ask-pass.

Сценарий Ansible будет опрашивать все серверы, перечисленные в файле hosts.yml. С помощью Ansible вы можете выбрать группы серверов. Для получения более подробной информации об Ansible прочтите документацию к ней (http://docs.ansible.com/). Руководство по Ansible Servers for Hackers (https://serversforhackers.com/an-ansible-tutorial/) также содержит подробную информацию.

Puppet.

Puppet написан на Ruby и предоставляет собственный язык — PuppetScript — для конфигурирования. Имеет выделенный сервер Puppet Master, который отвечает за управление узлами-агентами. Модули — это небольшие разделяемые единицы кода, написанные для автоматизации или определения состояния системы. Puppet Forge (https://forge.puppetlabs.com/) — это репозиторий для модулей, написанных сообществом для Open Source Puppet и Puppet Enterprise.

Узлы-агенты отправляют основную информацию о системе (например, операционную систему, ядро, архитектуру, IP-адрес и имя хоста) Puppet Master. Puppet Master компилирует на ее основе каталог данных о том, как нужно конфигурировать каждый узел, и пересылает его агенту. Агент выполняет изменения на основе того, что указано в каталоге, и отправляет Puppet Master отчет о проделанной работе.

Facter (да, его имя заканчивается на — er) — весьма интересный инструмент, который поставляется с Puppet и получает основную информацию о системе. Вы можете сослаться на эти факты как на переменные при написании модулей Puppet:

$ facter kernel.

Linux.

$

$ facter operatingsystem.

Ubuntu.

Процесс написания модулей в Puppet довольно прямолинеен: манифесты Puppet (файлы с расширением *.pp) формируют модули Puppet. Рассмотрим пример приложения Hello World для Puppet:

Notify { 'Hello World, this message is getting logged into the agent node':

····#As nothing is specified in the body, the resource title.

····#is the notification message by default.

}

Перед вами еще один пример, использующий логику системы. Чтобы обратиться к другим фактам, добавьте знак $ к имени переменной, например $hostname (в нашем случае $operatingsystem):

Notify{ 'Mac Warning':

····message => $operatingsystem? {

········'Darwin' => 'This seems to be a Mac.',

········default => 'I am a PC.',

····},

}

Для Puppet существует несколько типов ресурсов, но парадигма «пакет-файл-сервис» — это все, что вам нужно для выполнения большинства задач по управлению конфигурацией. Следующий код Puppet позволяет убедиться, что пакет OpenSSH-Server устанавливается в системе. Сервису sshd (демон сервера SSH) указывается выполнять перезапуск каждый раз, когда изменяется конфигурационный файл sshd:

Package { 'openssh-server':

····ensure => installed,

}

File { '/etc/ssh/sshd_config':

····source => 'puppet:///modules/sshd/sshd_config',

····owner => 'root',

····group => 'root',

····mode => '640',

····notify => Service['sshd'], # sshd перезапустится.

·······························# после каждого изменения этого файла.

····require => Package['openssh-server'],

}

·

Service { 'sshd':

····ensure => running,

····enable => true,

····hasstatus => true,

····hasrestart=> true,

}

Для получения более подробной информации обратитесь к документации к Puppet Labs (http://docs.puppetlabs.com/).

Chef.

Если для управления конфигурацией вы выбираете Chef (https://www.chef.io/chef/), то для написания кода инфраструктуры будете использовать язык Ruby. Chef похож на Puppet, но разработан с противоположной философией: Puppet предоставляет фреймворк, который упрощает работу за счет гибкости, а Chef практически не предоставляет фреймворка (его цель — быть очень гибким, поэтому его сложнее использовать).

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

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

Chef для работы использует пользовательские рецепты (элементы конфигурации), реализованные в cookbooks.Cookbooks, которые, по сути, являются пакетами для инфраструктурного выбора и обычно хранятся на сервере Chef. Прочтите серию руководств от DigitalOcean, посвященных Chef (http://tinyurl.com/digitalocean-chef-tutorial), чтобы узнать, как создать просто сервер Chef.

Используйте команду knife для создания поваренной книги:

$ knife cookbook create cookbook_name.

Статья Энди Гейла (Andy Gale) Getting started with Chef (http://gettingstartedwithchef.com/first-steps-with-chef.html) — хорошая стартовая точка для тех, кто начинает работать с Chef.

Множество поваренных книг сообщества вы можете найти в Chef Supermarket — с их помощью вы легко сможете начать писать собственные поваренные книги. Для получения более подробной информации обратитесь к полной документации Chef (https://docs.chef.io/).

CFEngine.

CFEngine имеет крошечный отпечаток, поскольку написан на C. Основная цель ее проекта — отказоустойчивость. Она достигается с помощью автономных агентов, работающих в распределенной сети (в противоположность архитектуре мастер/клиент), которые общаются с использованием теории обещаний (https://en.wikipedia.org/wiki/Promise_theory). Если вам нужна архитектура без мастера, попробуйте эту систему.

Наблюдение за системами и задачами.

Следующие библиотеки помогут всем системным администраторам наблюдать запущенные задачи, но их приложения значительно отличаются друг от друга: Psutil предоставляет информацию в Python, которая может быть получена вспомогательными функциями Unix, Fabric позволяет легко определить и выполнить команды для набора удаленных хостов с помощью SSH, а Luigi помогает планировать запуск и наблюдение за долгоиграющими пакетными процессами вроде цепочек команд Hadoop.

Psutil.

Psutil (https://pythonhosted.org/psutil/) — это кросс-платформенный (включая Windows) интерфейс для разного рода системной информации (например, ЦП, памяти, дисков, сети, пользователей и процессов). Позволяет с помощью Python получить доступ к информации, которую многие из нас привыкли получать, используя команды Unix (https://en.wikipedia.org/wiki/List_of_Unix_commands) вроде top, ps, df и netstat. Установите его с помощью pip:

$ pip install psutil.

Рассмотрим пример, который наблюдает за перегрузкой сервера (если какой-то тест — сети или ЦП — даст сбой, он отправит электронное письмо):

# Функции для получения значений системы:

From psutil import cpu_percent, net_io_counters.

# Функции для перерыва:

From time import sleep.

# Пакет для сервисов электронной почты:

Import smtplib.

Import string.

MAX_NET_USAGE = 4 00000.

MAX_ATTACKS = 4.

Attack = 0.

Counter = 0.

While attack <= MAX_ATTACKS:

····sleep(4).

····counter = counter + 1.

····# Проверяем использование ЦП.

····if cpu_percent(interval = 1) > 70:

········attack = attack + 1.

····# Проверяем использование сети.

····neti1 = net_io_counters()[1].

····neto1 = net_io_counters()[0].

····sleep(1).

····neti2 = net_io_counters()[1].

····neto2 = net_io_counters()[0].

····# Рассчитываем байты в секунду.

····net = ((neti2+neto2) — (neti1+neto1))/2.

····if net > MAX_NET_USAGE:

········attack = attack + 1.

····if counter > 25:

········attack = 0.

········counter = 0.

# Пишем очень важное электронное письмо, если значение параметра attack больше 4.

TO = "you@your_email.com".

FROM = "webmaster@your_domain.com".

SUBJECT = "Your domain is out of system resources!".

Text = "Go and fix your server!".

BODY = string.join(

·····("From: %s" %FROM,"To: %s" %TO,"Subject: %s" %SUBJECT, "",text), "\r\n").

Server = smtplib.SMTP('127.0.0.1').

Server.sendmail(FROM, [TO], BODY).

Server.quit().

Хорошим примером использования Psutil является glances (https://github.com/nicolargo/glances/) — полностью консольное приложение, которое ведет себя как расширенная версия top (перечисляет запущенные процессы, упорядочивая их по использованию ЦП или другим способом, указанным пользователем) и имеет возможность наблюдать за клиентом и сервером.

Fabric.

Fabric (http://docs.fabfile.org/) — это библиотека, предназначенная для упрощения задач системного администратора. Позволяет соединяться с помощью SSH с несколькими хостами и выполнять задачи для каждого из них. Это удобно для системных администраторов, а также для тех, кто развертывает приложения. Чтобы установить Fabric, используйте pip:

$ pip install fabric.

Рассмотрим полный модуль Python, определяющий две задачи Fabric: memory_usage и deploy:

# fabfile.py.

From fabric.api import cd, env, prefix, run, task.

Env.hosts = ['my_server1', 'my_server2'] # С чем соединяться по SSH.

@task.

Def memory_usage():

····run('free — m').

@task.

Def deploy():

····with cd('/var/www/project-env/project'):

········with prefix('../bin/activate'):

············run('git pull').

············run('touch app.wsgi').

Оператор with вкладывает команды друг в друга, поэтому в конечном счете метод deploy() для каждого хоста начинает выглядеть так:

$ ssh имя_хоста cd /var/ww/project-env/project &&../bin/activate && git pull.

$ ssh имя_хоста cd /var/ww/project-env/project &&../bin/activate && \

> touch app.wsgi.

Учитывая предыдущий код, сохраненный в файле fabfile.py (имя модуля по умолчанию, которое ищет fab), мы можем проверить использование памяти с помощью нашей новой задачи memory_usage:

$ fab memory_usage.

[my_server1] Executing task 'memory'.

[my_server1] run: free — m [my_server1] out:················ total···· used···· free·· shared· buffers·· cached.

[my_server1] out: Mem:··········· 6964···· 1897···· 5067······· 0····· 166····· 222.

[my_server1] out: — /+ buffers/cache:······ 1509···· 5455.

[my_server1] out: Swap:············· 0······· 0······· 0.

[my_server2] Executing task 'memory'.

[my_server2] run: free — m [my_server2] out:················ total···· used···· free·· shared· buffers·· cached.

[my_server2] out: Mem:··········· 1666····· 902····· 764······· 0····· 180····· 572.

[my_server2] out: — /+ buffers/cache:······· 148···· 1517.

[my_server2] out: Swap:··········· 895······· 1····· 894.

И мы можем выполнить развертывание:

$ fab deploy.

Дополнительная функциональность включает параллельное исполнение, взаимодействие с удаленными программами и группирование хостов. В документации к Fabric (http://docs.fabfile.org/) приведены понятные примеры.

Luigi.

Luigi (https://pypi.python.org/pypi/luigi) — это инструмент для управления конвейером, разработанный и выпущенный компанией Spotify. Помогает разработчикам управлять целым конвейером крупных долгоиграющих пакетных задач, объединяя запросы Hive, запросы к базе данных, задачи Hadoop Java, задачи pySpark и многие другие задачи, которые вы можете написать самостоятельно. Они не должны быть приложениями, работающими с большими данными, API позволяет запланировать что угодно. Spotify позволил запускать задачи с помощью Hadoop, поэтому разработчики предоставляют все необходимые вспомогательные программы в пакете luigi.contrib (http://luigi.readthedocs.io/en/stable/api/luigi.contrib.html). Установите его с помощью pip:

$ pip install luigi.

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