А АMonday, 2 November 2020

Ускоряем Ansible #1.

Всем привет.

Рано или поздно возникает потребность в ускорении выполнения сценариев Ansible. 

Для реализации этого есть несколько путей:

-мультиплексирование SSН, 

-конвейерный режим, 

-кэширование фактов, 

-параллельное выполнения задач, 

-асинхронное выполнения задач.

Рассмотрим их подробнее. В подготовке статьи использовались материалы из книги "Запускаем Ansible" авторов Мозер Р. и Хоштейн Л., 2018.

#1 Мультиплексирование SSH и ControlPersist.

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

OpenSSH - наиболее распространенная реализация SSH и SSH-клиент по умолчанию, который установлен на вашей локальной машине, если вы работаете в Linux или Mac OS X. OpenSSH поддерживает вид оптимизации с названием мультиплексирование каналов SSH, который также называют ControlPersist. Когда используется мультиплексирование, несколько SSH-сеансов с одним и тем же хостом использует одно и то же TCP-соединение, то есть ТСР­-соединение устанавливается лишь однажды.

Когда активируется мультиплексирование:

- при первом подключении к хосту OpenSSH устанавливает основное соединение;

- OpenSSH создает сокет домена Unix (управляющий сокет), связанный с удаленным хостом;

- при следующем подключении к хосту вместо нового ТСР­-подключения OpenSSH использует контрольный сокет.

Основное соединение остается открытым в течение заданного пользователем интервала времени, а затем закрывается SSH-клиентом. По умолчанию Ansible устанавливает интервал, равный 60 секундам.

1) Включение мультиплексирования SSH вручную

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

В примере 1 показаны настройки мультиплексирования из файла ~/.ssh/ con fig для ту server.example.сот.

Пример 1 Включение мультиплексирования в ssh/config

Host myserver.example.con 

ControlMaster auto 

ControlPath /tmp/%r@%h:%p 

ControlPersist 10m

Строка ControlMaster auto включает мультиплексирование SSH и сообщает SSH о необходимости создать основное соединение и управляющий сокет, если они еще не существуют.

Строка ControlPath /tnp/%r@%h:%p сообщает SSH, где расположить файл сокета домена Unix в файловой системе. %h - имя целевого хоста, %г - имя пользователя для удаленного доступа, и %р - порт. Если соединение осуществляется от имени пользователя ubuntu:

$ ssh ubuntu@nyserver.example.con

В этом случае SSH создаст файл управляющего сокета /tmp/ubuntu@myserver.example.соm:22 при первом подключении к серверу.

Строка ControlPersist 10m требует от SSH разорвать основное соединение, если в течение 10 минут не производилось попыток создать SSH-подключение.

Проверить состояние основного соединения можно с помощью параметра -0 check:

$ ssh -0 check ubuntu@myserver.example.con

Если основное соединение активно, эта команда вернет следующее:

Master running (pid=4388)

Вот так выглядит основной управляющий процесс в выводе команды ps 4388:

РID ТТ STAT TIME COMMAND

4388 ?? Ss 0:00.00 ssh: /tmp/ubuntu@myserver.example.com:22 [mux]

Разорвать основное соединение можно с помощью параметра -0 exit:

$ ssh -0 exit ubuntu@myserver.example.com

Больше деталей об этих настройках можно найти на странице ssh_config руководства man.

Можно протестировать скорость создания SSH-соединения:

$ time ssh ubuntu@myserver.example.com /bin/true

Эта команда вернет время, которое требуется для SSH-подключения и выполнения программы /bin/true, которая завершается с кодом 0.

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

0.01s user 0.01s system 2% сри 0.911 total

Наибольший интерес для нас представляет общее время: 0.911 total. Это говорит о том, что на выполнение всей команды потребовалось 0.911 секунды. Общее время иногда также называют астрономическим временем, поскольку оно показывает, сколько прошло времени, как если бы его измеряли по настенным часам.

Во второй раз результат выглядел так:

0.00s user 0.00s system 8% сри 0.074 total

Общее время сократилось до 0.074 секунды, то есть экономия составляет примерно 0.81 секунды для каждого SSH-соединения, начиная со второго. Напомним, что для выполнения задачи Ansible открывает, по крайней мере, два SSH-сеанса: один - для копирования файла модуля на хост, второй - для запуска модуля на хосте2. Это означает, что мультиплексирование может сэкономить порядка одной или двух секунд на каждой задаче в сценарии.

2) Параметры мультиплексирования SSH в Ansible

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

Параметр Значение

ControlMaster auto

ControlPath $HOME/.ansible/cp/ansible-ssh-%h-%p-%r 

ControlPersist 60s

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

Управляющую машину можно протестировать вручную, устанавливая SSH-соединение с помощью того же значения ControlPath, что использует Ansible:

$ CP=~/.ansible/cp/ansible-ssh-%h-%p-%r 

$ ssh -о ControlMaster=auto -о ControlPerslst=60s -о ControlPath=$CP \

ubuntu@ec2-203-0-113-12.conpute-l.aPiazonaws.com /bin/true

Если строка ControlPath окажется слишком длинной, вы увидите сообщение об ошибке, как показано в примере 2.

Пример 2 Слишком длинная строка ControlPath 

ControlPath

"/Users/lorinhochstein/.ansible/cp/ansible-ssh-ec2-203-0-113-12.conpute-l.anazonaws.com-22-ubuntu.KIwEKEsRzCKFABch"

too long for Unix domain socket

Это обычное дело при подключении к экземплярам Amazon ЕС2, которым назначаются длинные имена хостов. Решить проблему можно настройкой использования более коротких строк в ControlPath. Официальная документация рекомендует так определять этот параметр в файле ansible.cfg:

[ssh_connection]

control_path = %(directory)s/%%h-%%r

Ansible заменит %(directory)s на $НОМЕ/.ansible.cp (двойной знак процента (%%) необходим для экранирования, потому что знак процента в файлах .ini является специальным символом). При изменении конфигурации SSH-соединения, например параметра ssh_args, когда мультиплексирование уже включено, такое изменение не вступит в силу, пока управляющий сокет остается открытым с прошлого подключения.

Продолжение следует.

No comments:

Post a Comment

А что вы думаете по этому поводу?

Версия на печать

Популярное