Глава 5. Программируемость и автоматизация

Введение

Программируемостью именуется возможность взаимодействовать с чем- то посредством программирования. API для NGINX Plus предоставляет именно это: способность общения с настройками и поведением NGINX Plus через интерфейс HTTP. Этот API предоставляет такую возможность для перенастройки NGINX Plus через добавление или удаление серверов восходящего потока посредством запросов HTTP. Имеющаяся в NGINX Plus функциональность хранилища ключ- значение делает возможной иной уровень динамической настройки - вы можете применять вызовы HTTP для встраивания информации, которую NGINX Plus может применять для маршрутизации или динамического контроля обмена. Данная глава будет изучать сам API NGINX Plus и выставляемый тем же самым API модуль хранилища ключ- значение.

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

API NGINX Plus

Задача

У вас имеется некая динамичная среда и вам требуется перенастроить NGINX Plus на лету.

Решение

Настройте имеющийся API NGINX Plus для разрешения добавления или удаления серверов через вызовы API:


upstream backend {
    zone http_backend 64k;
}
server {
    # ...
    location /api {
        api [write=on];
        # Directives limiting access to the API
        # See chapter 7
    }

    location = /dashboard.html {
        root /usr/share/nginx/html;
    }
}
 	   

Эта настройка NGINX Plus создаёт некий сервер восходящего потока с некой совместно применяемой зоной памяти, включает имеющийся API в своём блоке location /api и предоставляет некое местоположение для инструментальной панели NGINX Plus.

Вы можете применять этот API для добавления серверов когда они вступают в действие:


$ curl -X POST -d '{"server":"172.17.0.3"}' \
  'http://nginx.local/api/3/http/upstreams/backend/servers/'

{
  "id":0,
  "server":"172.17.0.3:80",
  "weight":1,
  "max_conns":0,
  "max_fails":1,
  "fail_timeout":"10s",
  "slow_start":"0s",
  "route":"",
  "backup":false,
  "down":false
}
		

Этот вызов curl в данном примере выполняет некий запрос к NGINX Plus для добавления какого- то нового сервера в имеющуюся конфигурацию основы восходящего потока. Методом HTTP является POST, а в качестве его тела передаётся какой- то объект JSON. Сам API NGINX Plus является RESTful; по этой причине в типичной запросе URI имеются параметры. Формат такого URI следующий:


/api/{version}/http/upstreams/{httpUpstreamName}/servers/
 	   

Для вывода списка имеющихся серверов в нашем пуле восходящих примеров вы можете воспользоваться API NGINX Plus:


$ curl 'http://nginx.local/api/3/http/upstreams/backend/servers/'
[
  {
    "id":0,
    "server":"172.17.0.3:80",
    "weight":1,
    "max_conns":0,
    "max_fails":1,
    "fail_timeout":"10s",
    "slow_start":"0s",
    "route":"",
    "backup":false,
    "down":false
  }
]
		

Данный вызов curl в этом примере выполняет некий запрос к NGINX Plus для перечисления всех имеющихся серверов в пуле восходящего потока с названием backend. В настоящее время у нас есть только один сервер, который мы добавили в предыдущем вызове к API от curl. Этот запрос возвратит некий объект сервера восходящего потока, который содержит все имеющиеся настроенными параметры для сервера.

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


$ curl -X PATCH -d '{"drain":true}' \
  'http://nginx.local/api/3/http/upstreams/backend/servers/0'
{
  "id":0,
  "server":"172.17.0.3:80",
  "weight":1,
  "max_conns":0,
  "max_fails":1,
  "fail_timeout":"10s",
  "slow_start":"0s",
  "route":"",
  "backup":false,
  "down":false,
  "drain":true
}
		

В этом вызове curl мы определяем что методом данного запроса является

Данный вызов PATCH, мы передаём некое тело JSON, указывающее как выполнять осушение подключение для данного сервера и задаём значение идентификатора сервера добавляя его в конец своего URI. Мы выясняли значение идентификатора для этого сервера перечисляя все серверы в своём пуле восходящего потока в предыдущей команде curl.

NGINX Plus начнёт осушение указанных подключений. Это процесс может занять столько времени, сколько будут длиться сеансы данного приложения. Для проверки значения числа активных обслуживаемых конкретным сервером подключений, который нам придётся начинать осушать, воспользуйтесь следующим вызовом и отыскиваете значение атрибута active подлежащего осушению сервера.


$ curl 'http://nginx.local/api/3/http/upstreams/backend'
{
  "zone" : "http_backend",
  "keepalive" : 0,
  "peers" : [
    {
      "backup" : false,
      "id" : 0,
      "unavail" : 0,
      "name" : "172.17.0.3",
      "requests" : 0,
      "received" : 0,
      "state" : "draining",
      "server" : "172.17.0.3:80",
      "active" : 0,
      "weight" : 1,
      "fails" : 0,
      "sent" : 0,
      "responses" : {
      "4xx" : 0,
      "total" : 0,
      "3xx" : 0,
      "5xx" : 0,
      "2xx" : 0,
      "1xx" : 0
    },
    "health_checks" : {
      "checks" : 0,
      "unhealthy" : 0,
      "fails" : 0
    },
    "downtime" : 0
  }
  ],
  "zombies" : 0
}
		

После осушения всех подключений воспользуйтесь соответствующим API NGINX Plus для удаления этого сервера из имеющегося пула восходящего потока целиком:


$ curl -X DELETE \
  'http://nginx.local/api/3/http/upstreams/backend/servers/0'
[]
		

Эта команда curl делает некий запрос метод DELETE в том же самом методе URI, который мы применяли для обновления значения состояния серверов. Этот метод DELETE инструктирует NGINX удалить данный сервер. Этот вызов API возвращает все те серверы и значения их идентификаторов, которые всё ещё остаются в нашем пуле. По той причине что мы начинали с некого пустого пула, добавили через свой API только один сервер, осушили его, а затем удалили его, теперь у нас вновь имеется пустой пул.

Обсуждение

Имеющийся исключительно в NGINX Plus API делает возможным для динамических приложений серверов их собственное добавление и удаление в установленной конфигурации NGINX на лету. По мере того как серверы вступают в строй, они могут регистрировать себя в имеющемся пуле, а NGINX начнёт отправлять его для нагрузки. Когда требуется удалить некий сервер, этот сервер может запросить у NGINX Plus осушение себя в имеющемся пуле восходящего потока перед его остановом. Это делает возможной для такой инфраструктуры, посредством какой- никакой автоматизации уменьшать и увеличивать её масштаб без вмешательства персонала.

Также ознакомьтесь

NGINX Plus API Swagger Documentation

Хранилище ключ- значение

Задача

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

Решение

Установите осведомлённое о кластере хранилище ключ- значение и API, а затем добавляйте ключи и значения:


keyval_zone zone=blacklist:1M;
keyval $remote_addr $num_failures zone=blacklist;

server {
    # ...
        location / {
        if ($num_failures) {
            return 403 'Forbidden';
        }
        return 200 'OK';
    }
}
server {
    # ...
    # Directives limiting access to the API
    # See chapter 6
    location /api {
        api write=on;
    }
}
 	   

Данная конфигурация NGINX Plus применяет каталог keyval_zone для сборки некой разделяемой зоны памяти с названием blacklist и устанавливает предел памяти в 1 МБ. Затем соответствующая директива keyval устанавливает соответствие значения тому ключу, который сопоставлен идущему первым параметру $remote_addr для переменной с названием $num_failures из этой зоны. Эта новая переменная затем применяется для определения того должен ли NGINX Plus обслуживать этэт запрос или возвращать код 403 Forbidden.

После запуска этого сервера NGINX Plus с обсуждённой настройкой, вы можете curl эту локальную машину и ожидать получение отклика 200 OK.


$ curl 'http://127.0.0.1/'
OK
		

Теперь добавьте значение IP локальной машины в полученное хранилище ключ- значение со значением 1:


$ curl -X POST -d '{"127.0.0.1":"1"}' \
  'http://127.0.0.1/api/3/http/keyvals/blacklist'
		

Эта команда curl представляет некий запрос POST HTTP с каким- то содержащим объект ключ- значение объектом для его включения в зону совместной памяти blacklist. URI API данного хранилища ключ- значение имеет следующий формат:


/api/{version}/http/keyvals/{httpKeyvalZoneName}
 	   

Теперь в нашу зону ключ- значение с названием blacklist добавлен IP адрес локальной машины со значением 1. В своём следующем запросе NGINX Plus отыскивает в своей зоне переменную $remote_addr, находит значение этой записи и устанавливает соответствие полученного значения величине переменной $num_failures. Эта переменная затем вычисляется в необходимом операторе if. Когда данная переменная имеет некое значение, которое if вычисляет его как True, а NGINX Plus выдаёт код возврата 403 Forbidden:


$ curl 'http://127.0.0.1/'
Forbidden
		

Вы можете обновлять или удалять этот ключ выполняя запрос метода PATCH:


$ curl -X PATCH -d '{"127.0.0.1":null}' \
'http://127.0.0.1/api/3/http/keyvals/blacklist'
		

NGINX Plus удаляет имеющийся ключ если значением установлен null, а запросы снова будут возвращать 200 OK.

Обсуждение

Некая имеющаяся только в NGINX Plus функциональность ключ- значение позволяет приложениям вставлять информацию в NGINX Plus . В данном предоставленном примере для создания какого- то динамичного чёрного списка используется наша переменная $remote_addr. Вы имеете возможность напонять своё хранилище ключ- значение любыми имеющимися в NGINX Plus в виде переменных ключами - куки сеанса, к примеру - и снабжать в NGINX Plus неким внешним значением. В в NGINX Plus R16, имеющееся хранилище ключ- значение становится осведомлённым о сервере, что означает что вам приходится предоставлять своё обновление ключ- значение только одному серверу в NGINX Plus и все прочие получат эту информацию.

Также ознакомьтесь

Dynamic Bandwidth Limits

Установка при помощи Puppet

Задача

Вам требуется установить и настроить NGINX при помощи Puppet для управления конфигурациями NGINX в виде кода и согласования с остальной частью ваших настроек Puppet.

Решение

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


class nginx {
    package {"nginx": ensure => 'installed',}
    service {"nginx":
        ensure => 'true',
        hasrestart => 'true',
        restart => '/etc/init.d/nginx reload',
    }
    file { "nginx.conf":
        path => '/etc/nginx/nginx.conf',
        require => Package['nginx'],
        notify => Service['nginx'],
        content => template('nginx/templates/nginx.conf.erb'),
        user=>'root',
        group=>'root',
        mode='0644';
    }
}
 	   

Для обеспечения установки пакета NGINX этот модуль применяет утилиту управления пакетом. Это также гарантирует запуск и включение NGINX во время загрузки. Данная конфигурация информирует Puppet что данная команда имеет некую команду перезапуска с соответствующей директивой hasrestart и мы можем переопределить имеющуюся команду restart с перезагрузкой NGINX. Это файл ресурса будет управлять и выполнять шаблон имеющегося файла nginx.conf с применением языка шаблонов ERB (Embedded Ruby). Построение шаблона данного файла происходит после установки самого пакета NGINX благодаря директиве require. Тем не менее, данный файл ресурса будет уведомлять службу NGINX о необходимости перезагрузки благодаря директиве notify. Сам файл шаблона не включён. Однако это может быть просто установка некого устанавливаемого по умолчанию файла настроек NGINX или очень сложный файл когда применяются циклы языка шаблонов ERB или EPP, либо подстановка переменной.

Обсуждение

Puppet является инструментом управления настройками на основе языка программирования Ruby. Модули собираются на основе специфичного для области языка и вызываются через файл манифеста, который определяет необходимую конфигурацию для какого- то заданного сервера. Puppet может исполняться в конфигурациях хозяин- подчинённый или без хозяина. С применением Puppet определённый манифест запускается в имеющемся хозяине и затем отправляется его подчинённому. Это важно, так как обеспечивает что такой подчинённый получает только предназначенную для него конфигурацию никакие прочие предназначенные для прочих серверов конфигурации. Имеется великое множество доступных для Puppet чрезвычайно развитых общедоступных модулей. Начало с таких модулей поможет вам вам дать прикурить вашим настройкам. Общедоступный модуль NGINX от voxpupuli в GitHub послужит вам шаблоном настроек NGINX.

Также ознакомьтесь

Puppet Documentation

Puppet Package Documentation

Puppet Service Documentation

Puppet File Documentation

Puppet Templating Documentation

Voxpupuli NGINX Module

Установка при помощи Chef

Задача

Вам требуется установить и настроить NGINX при помощи Chef для управления конфигурациями NGINX в виде кода и согласования с остальной частью ваших настроек Chef.

Решение

Создайте некий кукбук с каким- то рецептом установки NGINX и настройки файлов конфигурации через шаблоны и обеспечьте перезагрузки NGINX после того как эта настройка помещена на своё место. Ниже приводится пример такого рецепта:


package 'nginx' do
  action :install
end

service 'nginx' do
  supports :status => true, :restart => true, :reload => true
  action   [ :start, :enable ]
end

template 'nginx.conf' do
  path   "/etc/nginx.conf"
  source "nginx.conf.erb"
  owner  'root'
  group  'root'
  mode   '0644'
  notifies :reload, 'service[nginx]', :delayed
end
 	   

Первый блок package устанавливает NGINX. Следующий блок service обеспечивает что NGINX запущен и включён при загрузке, затем объявляет всему остальному Chef, что данная служба nginx будет поддерживаться для действий. Последний блок template устанавливает шаблон некого файла ERB и помещает его в /etc/nginx.conf с root в качестве владельца и группы. Данный блок template также настраивает значение mode в 644 и уведомляет саму службу nginx о необходимости reload, однако ожидает пока не будет достигнут конец исполнения данного Chef, определяемого оператором :delayed. Сам шаблон файла настроек не включён. Тем не менее, он может быть таким же простым как установленный по умолчанию файл настроек NGINX либо очень сложным циклами языка шаблонов ERB и подстановкой переменных.

Обсуждение

Chef является инструментом управления настройками на основе Ruby. Chef может исполняться в конфигурациях хозяин- подчинённый или без партнёров (solo), также именуемого как Chef Zero. Chef имеет очень большое сообщество с большим числом кубуков с названием Supermarket. Общедоступные кукбуки Supermarket может быть установлен и далее управляться через утилиту командной строки с названием Berkshelf. Chef чрезвычайно развит, а то что мы показали всего лишь небольшой пример. Имеющиеся в Supermarket кукбуки NGINX чрезвычайно гибкая и предоставляет возможности лёгкой установки NGINX из диспетчера пакетов или из исходного кода, а также общую возможность компилировать и устанавливать множество различных модулей и создавать шаблоны из имеющихся базовых конфигураций.

Также ознакомьтесь

Chef documentation

Chef Package

Chef Service

Chef Template

Chef Supermarket for NGINX

Установка при помощи Ansible

Задача

Вам требуется установить и настроить NGINX при помощи Ansible для управления конфигурациями NGINX в виде кода и согласования с остальной частью ваших настроек Ansible.

Решение

Создайте некий плейбук Ansible для установки NGINX и управления имеющимся файлом nginx.conf. Ниже приводится некий пример файла задач для того плейбука, который устанавливает NGINX. проверьте что он работает и создаёт шаблон необходимого файла конфигурации:


- name: NGINX | Installing NGINX
  package: name=nginx state=present

- name: NGINX | Starting NGINX
  service:
    name: nginx
    state: started
    enabled: yes

- name: Copy nginx configuration in place.
  template:
    src: nginx.conf.j2
    dest: "/etc/nginx/nginx.conf"
    owner: root
    group: root
    mode: 0644
  notify:
    - reload nginx
 	   

Первый блок package устанавливает NGINX. Следующий блок service обеспечивает запуск и разрешение NGINX при загрузке. Последний блок template устанавливает некий файл шаблона Jinja2 и размещает получаемый результат в /etc/nginx.conf с root в качестве владельца и группы. Данный блок template также устанавливает значение mode в 644 и уведомляет nginx о необходимости reload. Шаблонный файл настроек не включён. Тем не менее, он может настолько же простым как некий устанавливаемый по умолчанию файл настроек NGINX,так и очень сложным с циклами и подстановкой переменных языка шаблонов Jinja2.

Обсуждение

Ansible является широко распространённым и мощным инструментом управления настройками на основе Python. Все задачи настройки представляются в YAML, а также для файлов шаблонов вы применяете язык шаблонов Jinja2. Ansible предоставляет некого хозяина с названием Ansible Tower в модели с подпиской. Тем не менее, широко распространено пр использовании в локальных машинах или для построения серверов напрямую применять клиента или модель без хозяина. Ansible отправляет пакеты SSH в свои серверы и запускает эти конфигурации. Во многом также как и для прочих инструментов настройки конфигураций, существует большое сообщество общедоступных ролей. Ansible именует его Ansible Galaxy. Вы можете отыскать очень искушённые роли для использования в своих плейбуках.

Также ознакомьтесь

Ansible documentation

Ansible Package

Ansible Service

Ansible Template

Ansible Galaxy

Полное руководство Ansible, 3 изд.

Установка при помощи SaltStack

Задача

Вам требуется установить и настроить NGINX при помощи SaltStack для управления конфигурациями NGINX в виде кода и согласования с остальной частью ваших настроек SaltStack.

Решение

Установите NGINX посредством своего модуля управления пакетами и управляйте по своему желанию необходимыми файлами настройки. Ниже приводится образец файла состояния (sls), который установит требуемый пакет nginx и обеспечит запуск его службы, причём разрешаемую при загрузке, а также перезагружающий её в случае внесения изменений в имеющемся файле настроек:


nginx:
  pkg:
    - installed
  service:
    - name: nginx
    - running
    - enable: True
    - reload: True
    - watch:
      - file: /etc/nginx/nginx.conf

/etc/nginx/nginx.conf:
  file:
    - managed
    - source: salt://path/to/nginx.conf
    - user: root
    - group: root
    - template: jinja
    - mode: 644
    - require:
      - pkg: nginx
 	   

Это некий базовый пример установки NGINX через утилиту упралвения пакетами и управления имеющимся файлом nginx.conf. Устанавливается сам пакет NGINX, а его служба запускается и разрешается при загрузке. С помощью SaltStack вы можете определить некий управляемый Salt файл, который показан в данном примере и шаблоны на множестве различных языков шаблонов. Файл шаблонных настроек не представлен. Тем не менее, он может быть настолько же простым как и файл настроек NGINX по умолчанию, так и чрезвычайно сложным с циклами и подстановкой переменных языка шаблонов Jinja2. Данная конфигурация также определяет, что NGINX следует установить до управления данным файлом благодаря имеющемуся оператору require. После помещения данного файла на его место, NGINX перезагружается благодаря установленной в его службе директиве watch и перезагружается, а не перезапускается, так как значение директивы reload установлено в True.

Обсуждение

SaltStack является мощным инструментом управления настройками, который задаёт состояния сервера в YAML. Модули для SaltStack могут быть написаны на Python. Salt выставляет для состояний, как и для файлов, язык шаблонов Jinja2. Тем не менее, для файлов также имеется множество прочих вариантов, как то: Mako, Python сам по себе и ряд иных. Salt работает как в конфигурации хозяин- подчинённый, так и без хозяина. Подчинённые именуются миньонами (minions, фаворитами). Транспорт взаимодействия хозяин- подчинённый, однако, отличается от прочих, выставляя SaltStack особняком. Для передачи в имеющийся агент Salt у вас имеется возможность выбора из ZeroMQ, TCP или Reliable Asynchronous Event Transport (RAET); либо вы можете не применять агента, а вместо этого мастер может осуществлять SSH. Благодаря тому что имеющийся транспортный уровень по умолчанию является асинхронным, SaltStack построен быть способным доставлять свои сообщения большому числу миньонов при низкой нагрузке на сам сервер хозяина.

Также ознакомьтесь

SaltStack

Installed Packages

Managed Files

Templating with Jinja

Автоматизация настроек через шаблоны Consul

Задача

Вам требуется автоматизировать свою настройку NGINX для отклика на изменения в вашей среде посредством применения Consul.

Решение

Воспользуйтесь демоном consul-template и неким файлом шаблона для построения по вашему выбору шаблона необходимого файла конфигурации NGINX:


upstream backend { {{range service "app.backend"}}
    server {{.Address}};{{end}}
}
 	   

Этот пример является неким файлом Consul Template, который представляет шаблон восходящего блока настроек. Этот шаблон обойдёт в цикле все узлы в Cinsul с идентификатором app.backend. Для каждого узла в Consul этот шаблон произведёт некую директиву server с IP адресом этого узла.

Имеющийся демон consul-template запускается из командной строки и может применяться для перезагрузки NGINX при каждом изменении установленного шаблона файла настройки:


# consul-template -consul consul.example.internal -template \
 template:/etc/nginx/conf.d/upstream.conf:"nginx -s reload"
 	   

Данная команда инструктирует демон consul-template подключиться к некому кластеру Consul в consul.example.internal и применять файл с названием template в текущем рабочем каталоге для выработки необходимого файла шаблона и вывода его сгенерированного содержимого в /etc/nginx/conf.d/upstream.conf с последующей перезагрузкой NGINX при каждом изменении данного файла шаблона. Значение флага -template принимает некую строку названия файла шаблона, значение местоположения вывода и ту команду, которую запускать после наличия процесса выработки шаблона; эти три переменные разделяются двоеточием. В случае наличия пробелов в подлежащей исполнению строке убедитесь что она заключена в двойные кавычки. Значение флага -consul сообщает данному демону к какому кластеру Consul ему следует подключаться.

Обсуждение

Consul является мощным инструментом обнаружения служб и хранения конфигураций. Consul хранит информацию об узлах, а также пары ключ- значение в некой структуре наподобие каталога и допускает API взаимодействия restful. Consul также предоставляет каждому клиенту взаимодействие DNS, которое позволяет выполнять поиск названия домена подключённых к данному кластеру узлов. Неким обособленным проектом который применяет кластеры Consul является демон consul-template; этот инструмент вырабатывает шаблоны файлов в ответ на изменения в узлах, службах или парах ключ- значение Consul. Это превращает Consul в очень мощную альтернативу для автоматизации NGINX. При помощи consul-template вы имеете возможность инструктировать запущенный демон выполнять некую команду после того как имеет место некое изменение в отслеживаемом шаблоне. При помощи этого мы можем перезагружать установленную конфигурацию NGINX, что позволяет вашей настройке NGINX вступать в действие по всей вашей среде. Применяя Consul вы способны настраивать проверки жизнеспособности каждого клиента для выяснения степени живучести предназначенной ему службы. Применяя такое выявление отказов вы способны снабжать шаблонами свои конфигурации NGINX надлежащим образом отправляя обмен только в жизнеспособные хосты.

Также ознакомьтесь

Consul Home Page

Introduction to Consul Template

Consul Template GitHub