Глава 5. Применение Ansible для создания шаблонов виртуальных машин развёртывания

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

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

В этой главе будут рассмотрены следующие вопросы:

  • Выполнение первоначальной сборки

  • Применение Ansible для сборки и стандартизации основного шаблона

  • Очистка получаемой сборки с помощью Ansible

Технические требования

Данная глава предполагает что у вас имеется доступ к среде с возможностями виртуализации, запущенной под Ubuntu 18.04 LTS. Некоторые примеры также выполняются в CentOS 7. В любом из этих случаев все примеры могут выполняться либо в некой физической машине (или ноутбуке) с запущенной одной из упомянутых выше операционных систем, процедурой, которая обладает включёнными расширения виртуализации, либо в некой виртуальной машине с включённой встроенной виртуализацией.

Позднее в этой главе также применяется Ansible 2.8 и предполагается что вы уже имеете его установленным на применявшемся нами хосте.

Все обсуждаемые в этой книге примеры доступны в GitHub.

Выполнение первоначального построения

Как уже обсуждалось в Главе 4, Методологии развёртывания, будете ли вы применять традиционные платформы виртуализации, такие как Virt или VMware, либо основанный на таких облачных решениях как OpenStack или EC2 Amazon, вашей отправной точкой для любых развёртываний Linux (а следовательно и последующей автоматизации) будет некий образ шаблона.

В определённых нами в Главе 1, Построение стандартной среды работы в Linux терминах SOE, такой образ шаблона является достаточно действенным её проявлением. Обычно это некий небольшой образ виртуальной машины с программным обеспечением достаточным только для установки и выполнения настройки, который полезен почти во всех случаях развёртывания в рамках определённого предприятия. При условии что такой образ загружается чистым с неким уникальным именем хоста, ключи SSH хоста и тому подобное могут быть настроены почти сразу же с применением последующей автоматизации, как мы узнаем это из Главы 7, Управление настройками при помощи Ansible позднее в этой книге. Давайте окунёмся в сам процесс сборки, взяв за основу в качестве своей отправной точки готовый образ шаблона (предоставляемый сторонним разработчиком).

Применение готовых шаблонов образов

Для большинства платформ имеются готовыми большое число доступных для выгруки вами образов, и опять же, некоторые из них мы обсуждали в своих предыдущих главах. Для многих предприятий таких образов может быть достаточно. Тем не менее, что если вам требуется абсолютно полный контроль над определяемыми вами образами? Возможно, вы уже приспособились к новому стандарту (на момент написания этих строк бы выпущен Red Hat Enterprise Linux 8 и несомненно вскорости последует CentOS 8), и вы желаете реализовать его на ранней стадии чтобы получить опыт и проверить на рабочих нагрузках. Что если вы работаете в защищённой среде (возможно, отвечающей требованиям отрасли платёжных карт) и вам абсолютно необходимо обладать уверенностью в том как был собран ваш образ и не может быть никакого риска его компрометации?

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

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

Давайте рассмотрим некий практический пример: допустим, что для некого нового набора подразделений мы приняли решение создать некую новую SOE на основании образа сервера Fedora 30 и будем запускать его в некой инфраструктуре OpenStack:

  1. Мы бы выгрузили необходимый образ облачного решения с официального веб сайта проекта Fedora - подробности можно найти тут, хотя сам номер версии мог измениться со временем, поскольку появился новый выпуск Fedora https://alt.fedoraproject.org/cloud//

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

    
    $ wget https://download.fedoraproject.org/pub/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2
    		
  2. Достаточно просто - теперь давайте проверим его. Инструкции для проверки обычно предоставляются всеми основными выпусками Linux, как для ISO, так и для полных образов, а для выгруженного нами образа Fedora их можно найти на https://alt.fedoraproject.org/en/verify.html.

    Давайте осуществим этот процесс и подтвердим свой образ. Прежде всего мы импортируем сам официальный ключ GPG Fedora для подтверждения доступной контрольной суммы файлы чтобы убедиться что он не был подделан:

    
    $ curl https://getfedora.org/static/fedora.gpg | gpg --import
    		
  3. Теперь мы выгрузим сам файл контрольной суммы для своих облачных образов и проверим его:

    
    $ wget https://alt.fedoraproject.org/en/static/checksums/Fedora-Cloud-30-1.2-x86_64-CHECKSUM
    $ gpg --verify-files *-CHECKSUM
    		
  4. Хотя вы можете получить предупредительное сообщение что данный ключ не был сертифицирован некой доверенной подписью (это одна из сторон того как устанавливается доверенный ключ GPG), самое существенное здесь то, что подпись данного файла проверена как хорошая - обратите внимание на следующий снимок экрана в качестве образца такого вывода:

     

    Рисунок 5-1



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

    
    $ sha256sum -c *-CHECKSUM
    		

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

     

    Рисунок 5-2



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

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

Что если вам абсолютно необходимо создать собственный образ? Мы рассмотрим это в следующем разделе данной главы.

Создание ваших собственных образов виртуальных машин

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

Давайте рассмотрим сборку образа виртуальной машины CentOS 7.6 при помощи хоста сервера Ubuntu 18.04:

  1. Самый первый шаг, прежде чем мы приступим, состоит в том чтобы убедиться что узел сборки способен работать с виртуальными машинами - обычно это некий набор расширений ЦПУ, которые содержатся в большинстве современных систем x86. Также имеется возможность сборки виртуальных машин при помощи вложенной виртуализации, то есть создавать виртуальные машины внутри других виртуальных машин. Однако для этого вам требуется включить сопровождение виртуализации в своей виртуальной машине сборки. Процесс этого меняется от одного гипервизора к другому, а поэтому мы не будем приводить здесь подробности.

    [Совет]Совет

    Когда для осуществления вложенной виртуализации вы пользуетесь гипервизором Vmware, вам потребуется включить поддержку code profiling (профилирования кода) для своего ЦПУ, а также включить hypervisor applications (приложения гипервизора) - иначе в этом процессе некоторые шаги могут завершиться отказом.

  2. После того как вы собрали свой хост поднятым и работающим, вам потребуется установить набор инструментария KVM (Kernel-based Virtual Machine) - необходимые для этого команды будут отличаться в зависимости от версии Linux хоста сборки, но в хосте Ubuntu нам потребуется выполнить такие команды:

    
    $ sudo apt-get install libvirt-bin libvirt-doc libvirt-clients virtinst libguestfs-tools libosinfo-bin
    $ sudo gpasswd -a <your account> libvirt
    $ sudo gpasswd -a <your account> kvm
    $ logout
    		
  3. Code

    
    > 
    		

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

  4. Когда это выполнено, вам также потребуется выгрузить локальную копию образа ISO для выбранного вами образа Linux. Для выгрузки образа ISO, достаточного для SOE образа CentOS 7.6, которую я намерен создать, я воспользовался такой командой:

    
    $ wget http://vault.centos.org/7.6.1810/isos/x86_64/CentOS-7-x86_64-Minimal-1810.iso
    		

Разложив это всё по своим местам, вы теперь создадите пустой дисковый образ виртуальной машины. Наилучшим форматом для этого является QCOW2 ( Quick Copy On Write), совместимый с OpenStack и большинством облачных платформ. тем самым мы сделаем этот образ как можно более универсальным чтобы обеспечить максимально допустимую поддержку.

Для создания некого чистого образа QCOW2 с 20ГБ в своём текущем каталоге нам придётся выполнить такую команду:


$ qemu-img create -f qcow2 centos76-soe.qcow2 20G
		

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


$ qemu-img create -f vmdk centos76-soe.vmdk 20G
		

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

 

Рисунок 5-3



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

  1. Для достижения этого мы воспользуемся командой virt-install, которая в целом запускает некую временную ВМ для установки ОС. Не беспокойтесь о таких параметрах как ЦПУ и память - раз их достаточно для запуска и установки ОС, всё будет нормально - они не имеют никакого отношенря к развёрнутой виртуальной машине.

    [Совет]Совет

    Обратите внимание на параметр VNC --graphics vnc,listen=0.0.0.0 - мы будем применять его для удалённого управления своей виртуальной машиной и завершения своей установки. Вы можете выбрать и другой вариант графики, например, если вы его предпочитаете, SPICE.

  2. Наша следующая команда является образцом того как пользоваться virt-install для создания образа CentOS 7 из выгруженного нами ранее ISO применяя созданный нами предыдущий 20 ГБ образ диска QCOW2:

    
    $ virt-install --virt-type kvm \
    --name centos-76-soe \
    --ram 1024 \
    --cdrom=CentOS-7-x86_64-Minimal-1810.iso \
    --disk path=/home/james/centos76-soe.qcow2,size=20,format=qcow2 \
    --network network=default \
    --graphics vnc,listen=0.0.0.0 \
    --noautoconsole \
    --os-type=linux \
    --os-variant=centos7.0 \
    --wait=-1
    		

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

    [Совет]Совет

    Чтобы просмотреть полный перечень поддерживаемых параметров --os-variant запустите команду os-infoquery os.

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

  3. Теперь давайте исполним эту команду - в случае успеха она должна проинформировать что вы можете подключиться к консоли своей виртуальной машины для продолжения:

     

    Рисунок 5-4



  4. Теперь мы подключимся к ней из другой оболочки при помощи утилиты virt-viewer:

    
    $ virt-viewer centos-76-soe
    		

С этого момента вы устанавливаете свою операционную систему обычным способом. Как мы уже обсуждали в Главе 4, Методологии развёртывания, попытайтесь проследовать наиболее минимальную установку, какую только сможете выполнить. Не беспокойтесь слишком сильно об имене хоста по сути, так как это будет позднее частью самого процесса развёртывания; определите следующее:

  1. Выберите наиболее подходящие для вашего местоположения KEYBOARD и LANGUAGE SUPPORT.

  2. Выберите настройки DATE & TIME для своей страны.

  3. Убедитесь что SOFTWARE SELECTION установлены в Minimal Install (это настройка по умолчанию).

  4. Установите INSTALLATION DESTINATION - бедет иметься подключённым к данной ВМ лишь один виртуальный жёсткий диск при использовании нашей предыдущей команды virt-install, поэтому это просто средство его выбора.

  5. Включите или отключите KDUMP в зависимости от ситуации.

  6. Убедитесь что сетевая среда включена в NETWORK & HOST NAME.

Получаемый в результате экран настроек установки CentOS 7 должен выглядеть похожим на приводимый ниже снимок экрана:

 

Рисунок 5-5



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

Когда ваша ВМ перезагрузится после своей первоначальной установки, вы сможете обнаружить что она остановлена. Если это так, вам придётся отменить её определение при помощи утилиты virsh, а затем запустить его снова слегка изменив свою предыдущую команду virt-install, сообщая virt-install о необходимости загрузки на этот раз с имеющегося образа жёсткого диска вместо CD:


$ virsh undefine centos-76-soe
$ virt-install --virt-type kvm \
--name centos-76-soe \
--ram 1024 \
--disk path=/home/james/centos76-soe.qcow2,size=20,format=qcow2 \
--network network=default \
--graphics vnc,listen=0.0.0.0 \
--noautoconsole \
--os-type=linux \
--os-variant=centos7.0 \
--boot=hd
		

На данном этапе следует заметить, что большинство облачных платформ, будь то OpenStack, AWS (Amazon Web Services) или нечто иное, все они пользуются утилитой virt-install для осуществления начальных настроек создаваемого образа виртуальной машины прежде чем мы остановим её. Ниже перечисляются команды, необходимые для установки вручную и в своём следующем разделе мы превратим их в некую роль Ansible для установки:


$ yum -y install epel-release
$ yum -y install cloud-init cloud-utils-growpart dracut-modules-growroot
		

После того как вы успешно выполнили эти команды, вам по всей видимости придётся персонализировать /etc/cloud/cloud.cfg для настройки cloud-init под ту среду, в которой вы её применяете, хотя устанавливаемые по умолчанию настройки являются достойным отправным пунктом для многих сред.

[Замечание]Замечание

Настройка cloud-init оставлена вам в качестве вашего самостоятельного упражнения, принимая во внимание широкое разнообразие платформ..

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

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

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

  • Ключи хоста SSH

  • Файлы истории

  • Настройки локального сеанса

  • Файлы журналов

  • Ссылки на MAC адреса в сетевых настройках

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


$ sudo virt-sysprep -a centos76-soe.qcow2
$ sudo virt-sparsify --compress centos76-soe.qcow2 centos76-soe-final.qcow2
		

Хотя вывод первой из приведённых команд слишком длинный чтобы уместиться в одном снимке экрана, он отображает широкий спектр задач, которые считаются необходимыми в рамках sysprep и когда вы выполняете это вручную или при помощи Ansible, данная утилита virt-sysprep снабдит вас хорошим пособием относительно задач, которые вам следует осуществлять:

 

Рисунок 5-6



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

 

Рисунок 5-7



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

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

Применение Ansible для построения и стандартизации конкретного шаблона

На данный момент вы должны обладать базовым образом Linux для развёртывания в своём предприятии. Если вы выбрали выгрузку готового к применению шаблона (или, на самом деле, остановились на применении предоставляемого поставщиком общедоступного облака), тогда ваш образ будет очень пустым шаблоном, готовым для индивидуальных настроек. Если вы решили создать свой собственный, то, вероятно, вы уже выбрали выполнение небольшого числа персональных настроек, как выполненная нами ранее настройка cloud-init. Вы заметили, тем не менее, что мы сделали это вручную, что едва ли соответствует линии масштабируемых, повторяемых процессов, которые мы нахваливали в своих более ранних частях этой книги. Проходя данный раздел этой главы мы рассмотрим как при помощи Ansible выполнить индивидуальные настройки базового шаблона, причём вне зависимости от его происхождения.

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

  • Перемещение файлов в соответствующий образ

  • Установка пакетов

  • Изменение файлов настройки

  • Проверка полученного образа

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

Передача файлов в заданный образ

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

  • Мы уже обладаем своим выгруженным/ собранным шаблоном Linux, как это было выведено в нашем предыдущем разделе данной главы.

  • Мы запускаем этот голый шаблон в некой виртуальной машине.

  • IP адресом этой виртуальной машины выступает 192.168.81.141.

  • Наша виртуальная машина имеет уже настроенную учётную запись пользователя со следующими учётными сведениями:

    • Имя пользователя: imagebuild.

    • Пароль: password.

    • В этой учётной записи включена возможность sudo.

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

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

    
    [imagesetup]
    192.168.81.141
    
    [imagesetup:vars]
    ansible_user=imagebuild
    ansible_password=password
    ansible_sudo_pass=password
    		

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

    [Совет]Совет

    Хотя данный файл описи и носит по своей природе временный характер, всё же рекомендуется пользоваться для хранения паролей ansible-vault и это же рекомендуется и далее. С целью упрощения данной главы и снижения общего числа необходимых для выполнения вами шагов, мы оставим данные пароли не зашифрованными (в открытом тексте).

  2. Затем мы создаём структуру базового каталога для своей роли:

    
    $ mkdir -p roles/filecopyexample/tasks
    $ mkdir -p roles/filecopyexample/files
    		
  3. Теперь давайте создадим несколько образцов файлов для их повсеместного копирования. Прежде всего, создайте некое персональное сообщение для его добавления в конец своего сообщения дня в roles/filecopyexample/files/motd:

    
    ------------------------
    Enteprise Linux Template
    Created with Ansible
    ------------------------
    		
  4. Давайте также создадим некий новый файл настроек для службы chrony чтобы выполнять синхронизацию времени со своими корпоративными серверами времени в roles/filecopyexample/files/chrony.conf:

    
    pool ntp.example.com iburst maxsources 4
    
    keyfile /etc/chrony/chrony.keys
    
    driftfile /var/lib/chrony/chrony.drift
    
    logdir /var/log/chrony
    
    maxupdateskew 100.0
    
    rtcsync
    
    makestep 1 3
    		

Мы намерены повсеместно копировать эти два файла на все свои удалённые серверы. Тем не менее Ansible не ограничен копирование файлов с определённого хоста Ansible - он также способен выгружать файлы с удалённого сервера напрямую в свой целевой хост:

  1. Давайте предположим, что вашей сборке потребуется docker-compose - мы можем выгрузите его с некого внутреннего сервера или даже напрямую через Интернет когда ваша машина образа обладает таким доступом в Интернет. Допустим, мы желаем установить в свои образы docker-compose 1.18.0, тогда мы можем выдать Ansible инструкции для его выгрузки напрямую с https:/​/​github.​com/​docker/​compose/​releases/​download/​1.​18.0/​docker-​compose-​Linux-​x86_​64.

  2. Теперь давайте соберём свою роль для повсеместного копирования двух файлов и выгрузки в свой образ docker-compose - её следует записать в roles/filecopyexample/tasks/main.yml. Самая первая часть данной роли показана в приводимом далее коде, и он служит обсуждавшееся ранее повсеместное копирование двух файлов настройки:

    
    ---
    - name: Copy new MOTD file, and backup any existing file if it             exists
      copy:
        src: files/motd
        dest: /etc/motd
        owner: root
        group: root
        mode: '0644'
        backup: yes
    - name: Copy across new chrony configuration, and backup any existing file if it exists
      copy:
        src: files/chrony.conf
        dest: /etc/chrony.conf
        owner: root
        group: root
        mode: '0644'
        backup: yes
    		

    Эта роль далее продолжается задачей установки docker-compose в соответствующем образе ВМ:

    
    - name: Install docker-compose 1.18.0
      get_url:
        url: https://github.com/docker/compose/releases/download/1.18.0/docker-compose-Linux-x86_64
        dest: /usr/local/bin/docker-compose
        mode: 0755
        owner: root
        group: root
    		

    Итак, наша роль теперь закончена, однако убедитесь что вы верно выполнили персональные настройки для своей среды. Например, скорее всего может быть доступной более новая версия docker-compose, а это означает изменение установленного параметра url нашего предыдущего модуля get_url.

    [Совет]Совет

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

  3. Наконец, мы создадим некий файл в каталоге самого верхнего уровня (в котором был создан каталог roles/) с наименованием site.yml для вызова и запуска данной роли. Он должен содержать следующее:

    
    ---
    - name: Run example roles
      hosts: all
      become: yes
    
      roles:
        - filecopyexample
    		
  4. Окончательно, давайте выполним свой примерпри помощи команды ansible-playbook -i hosts site.yml и посмотрим что произойдёт:

     

    Рисунок 5-8



Как мы можем увидеть, значение changed состояний сообщает нам что все наши три файла были переданы или выгружены успешно и посредством данного примера мы можем видеть что теперь имеется возможность запуска docker-compose, который был установлен в ходе исполнения этого плейбука (хотя для этого и потребуется корректная работа Docker, который мы не установили в качестве части данного примера).

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

Установка пакетов

В своём предыдущем разделе мы рассмотрели ка установить обособленные исполняемые файлы подобные docker-compose - но что если нам требуется на практике установить некие дополнительные пакеты операционной системы, которые не были установлены в нашем базовом образе? К примеру, в большинстве облачных сред невероятно полезен cloud-init, однако он не содержится в нашей минимальной установке CentOS, который мы выполнили ранее.

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

  1. Теперь наш предыдущий образец копирования файлов будет работать во всех дистрибутивах Linux - единственное о чём нам следует помнить, это где могут обитать целевые файлы. Например, наш образ ВМ CentOS 7 будет обладать файлом настроек, chrony, установленным в /etc/chrony.conf, в то время как сервер Ubuntu 18.04 LTS будет иметь его в /etc/chrony/chrony.conf. Помимо этого небольшого изменения для значения параметра dest: в нашем модуле copy, весь код останется прежним.

    К сожалению, это делает установку пакета несколько более сложной.

  2. Давайте допустим что мы хотим установить cloud-init и docker своём примере образа CentOS 7 - необходимая для этого роль может выглядеть следующим образом:

    
    ---
    - name: Install the epel-release package
      yum:
        name: epel-release
        state: present
    
    - name: Install cloud-init and docker
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - cloud-init
        - docker
    		
  3. Вначале нам требуется установить репозиторий EPEL, а затем мы можем установить все необходимые пакеты. После его запуска получаемый вывод должен выглядеть как- то так:

     

    Рисунок 5-9



Если вы пользуетесь другим дистрибутивом Linux, тогда вам необходимо изменять надлежащим образом и применяемый диспетчер пакетов. Например, в таких дистрибутивах как Debian или Ubuntu, которые пользуются диспетчером пакетов apt, аналогичная роль Ansible выглядела бы подобно следующему блоку кода:


---
- name: Install cloud-init and docker
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - cloud-init
    - docker.io
		

Обратите внимание на замену с yum на apt и различные названия пакетов для службы контейнеров Docker. Во всём кроме этого данный плейбук почти идентичен.

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

Мы видоизменим свой код более ранних примеров чтобы соединить обе эти установки в одной роли Ansible:

  1. Самая первая часть нашего кода почти идентична нашему предыдущему примеру, за исключением того что нам придётся задать соответствующий оператор when для того чтобы убедиться что мы выполняем запуск лишь дистрибутивах Linux на основании Debian или Ubuntu:

    
    ---
    - name: Install cloud-init and docker
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - cloud-init
        - docker.io
      when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
    		
  2. Далее мы добавим две следующие задачи, которые выполняют необходимые шаги установки Docker в CentOS или Red Hat Enterprise Linux:

    
    - name: Install the epel-release package
      yum:
        name: epel-release
        state: present
      when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat enterprise Linux'
    
    - name: Install cloud-init and docker
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - cloud-init
        - docker
      when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat enterprise Linux'
    		

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

     

    Рисунок 5-10



  3. Как вы можете видеть, была выполнена наша самая первая задача, относящаяся к apt, а две следующие, основанные yum были пропущены по причине не соответствия в значении оператора when. Теперь, если мы запустим его имея вместо этого своей целью CentOS 7, мы обнаружим такое:

     

    Рисунок 5-11



    Теперь верно обратное: задача apt пропущена, но две относящиеся к yum задачи были исполнены. Тем самым становится возможной поддержка одной ролью установки общего набора необходимых пакетов даже когда мы имеем дело с несколькими различными базовыми операционными системами. Сочетание операторов when с фактами Ansible является очень мощным способом, который обеспечивает правильное поведение отдельного базового кода по разнообразным системам, а следовательно когда ваша SOE расширена на обе базовые системы, Debian и Red Hat, вы всё ещё способны запросто с лёгкостью сопровождать код.

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

Изменение файлов настройки

До сих пор вся выполнявшаяся нами работа по настройке была слишком чёрно- белой - мы либо устанавливали нечто (будь то пакет или файл) , либо мы могли в равной степени просто удалять их (об этом больше в разделе, посвящённом очистке). Тем не менее, что если требуется нечто более тонкое? Ранее в этой главе, в разделе, озаглавленном Передача файлов в заданный образ, мы заменяли свой файл chrony.conf целиком на нашу собственную версию. Это, однако, может оказаться слишком брутальным - например, нам может потребоваться изменить всего одну строку в файле, а замена всего файла целиком для замены лишь одной строки - это достаточно сложно, в особенности если учесть, что данный файл настроек может быть обновлён в последующей версии пакета.

Давайте обратимся к другому распространённому требованию настройки образа операционной системы: безопасности демона SSH. По умолчанию, подобные созданной нами ранее установки CentOS 7 допускают удалённый вход в систему от имени учётной записи root. По причинам безопасности это нежелательно, а потому вопрос состоит в том, как нам обновлять соответствующую настройку демона SSH без необходимости замены её файла целиком? К счастью, Ansible обладает модулями именно для такой задачи.

Для выполнения данной задачи на подмогу нам приходит модуль lineinfile. Рассмотрим следующую роль, которую мы назовём securesshd:


---
- name: Disable root logins over SSH
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: "^PermitRootLogin"
    line: "PermitRootLogin no"
    state: present
 	   

Здесь для обработки своего файла /etc/ssh/sshd_config мы применяем модуль lineinfile. Мы запрашиваем поиск строк, начинающихся с PermitRootLogin (это избавляет нас от непредумышденного изменения строк, скрытых комментарием), а затем заменяем эту строку на PermitRootLogin no.

Давайте испробуем это для своей проверочной системы CentOS 7:

 

Рисунок 5-12



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

[Совет]Совет

Обратите внимание, что в запущенной системе вам также потребуется перезапуск такой службы SSH чтобы ввести в действие применённые изменения; однако когда мы очистили и остановили некий образ для его последующего развёртывания, в этом нет нужды.

Средним путём между загрузкой некого файла целиком и изменением некого имеющегося является применение шаблонов. Шаблоны Jinja2 Ansible невероятно мощны и полезны когда файлы могут обладать зависящее от некого параметра переменной содержимое.

Рассмотрим снова пример более ранней настройки chrony - в данном случае мы передавали некий статический файл с жёстко закодированным адресом NTP. Это отлично когда ваше предприятие полагается на некий статичный сервер NTP (или их набор), но некоторые будут полагаться на различные серверы в зависимости от того где надлежит развернуть данный образ.

Давайте продемонстрируем это новой ролью с названием templatentp. Для этого мы определим некий каталог шаблонов в roles/templatentp/templates и поместим в него файл с нназванием chrony.conf.j2 и следующим содержимым:


pool {{ ntpserver }} iburst maxsources 4

keyfile /etc/chrony/chrony.keys

driftfile /var/lib/chrony/chrony.drift

logdir /var/log/chrony

maxupdateskew 100.0

rtcsync

makestep 1 3
 	   

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

Давайте создадим соответствующий файл роли main.yml таким образом:


---
- name: Deploy chrony configuration template
  template:
    src: templates/chrony.conf.j2
    dest: /etc/chrony.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes
 	   

Заметьте насколько он похож на наш пример с copy. Наш site.yml тоже отличается лишь слегка - в нём ма задаём значение переменной с названием хоста сервера NTP. В Ansible существует множество мест в котором можно задать эту переменную и определить наилучшее место для её размещения оставлено на усмотрение самого пользователя:


---
- name: Run example roles
  hosts: all
  become: yes

  vars:
    ntpserver: time.example.com

  roles:
    - templatentp
 	   

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

 

Рисунок 5-13



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

Проверка правильности построения образа

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

Существует множество варианты выполнения этой задачи в Ansible - давайте рассмотрим некий простейший пример. Допустим, у вас имеется некий сценарий архивирования, который применяет утилиту сжатия bzip2 для упаковки файлов. Это всего лишь небольшой инструмент, но если вы полагаетесь на него для определённых целей, ваш сценарий будет прерван в случае его отсутствия. Это к тому же и уместный пример, ибо собственно минимальная установка CentOS 7 (как мы столкнулись с этим ранее) в действиельности не обладает им.

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

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


---
- name: Ensure bzip2 is installed
  yum:
    name: bzip2
    state: present
   	   

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

Если бы вы применяли некие команды оболочки, вы бы проверили присутствие bzip2 одним из двух способов, коими являются запрос имеющейся базы данных RPM на предмет того, установлен ли такой пакет bzip2 или проверите наличие /bin/bzip2 в рассматриваемой файловой системе.

  1. Давайте взглянем на свой самый последний пример Ansible. Модуль stat Ansible может применяться для проверки присутствия некого файла. Рассмотрим приводимый ниже код, который мы создали обычным образом в роли с названием checkbzip2:

    
    ---
    - name: Check for the existence of bzip2
      stat:
        path: /bin/bzip2
      register: bzip2result
      failed_when: bzip2result.stat.exists == false
    
    - name: Display a message if bzip2 exists
      debug:
        msg: bzip2 installed.
    		

    Здесь мы применяем модуль stat чтобы сообщить нам о конкретном файле /bin/bzip2 (если он имеется). Мы register полученный результат исполнения данного модуля в переменной с названием bzip2result, а затем мы определяем некое индивидуальное условие отказа данной задачи, которое вызовет его отказ (а тем самым и отказ в исполнении данного плейбука целиком) когда данный файл отсутствует. Обратите внимание, что когда встречается условие отказа, Ansible останавливает исполнение всего плейбука, заставляя вас разрешать возникшую проблему прежде чем продолжать. Очевидно, это может быть, а может и нет желательным для вас поведением, но будет проще видоизменять надлежащим образом само условие отказа.

  2. Давайте снова взглянем на это действие:

     

    Рисунок 5-14



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

  3. Когда bzip2 установлен, выполнение выглядит несколько иначе:

     

    Рисунок 5-15



Это вполне точное поведение и в точности то, которое мы пожелали. Ansible не просто ограничивается проверкой файлов - мы к тому же можем убедиться что в нашем файле sshd_config отсутствует рассматривавшаяся нами ранее строка PermitRootLogin no:

  1. Мы можем осуществить это с помощью такой роли:

    
    ---
    - name: Check root login setting in sshd_config
      command: grep -e "^PermitRootLogin no" /etc/ssh/sshd_config
      register: grepresult
      failed_when: grepresult.rc != 0
    
    - name: Display a message if root login is disabled
      debug:
        msg: root login disabled for SSH
    		
  2. Теперь её выполнение при условии отсутствия данной установки даёт нам некий отказ:

     

    Рисунок 5-16



  3. Когда эта настройка на месте, мы обнаружим следующее:

     

    Рисунок 5-17



И снова всё определённо. В предыдущем выводе нет никакого состояния changed - это именно так по причине применения нами модуля command, который успешно выполнил command - следовательно, всегда возвращается changed. Мы можем изменить такое поведение данной задачи при помощи условия changed_when, если вы пожелаете.

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

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

Собирая всё воедино

На протяжении данного раздела этой главы вы обратили внимание на то, что во всех своих примерах мы пользовались ролями. Естественно, когда дело доходит до сборки вашего окончательного образа, вы не желаете закончить всё запуском множества плейбуков по отдельности, как мы это делали здесь. К счастью, если бы мы соединили их все, всё что потребовалось бы для этого, так это поместить все эти роли в соответствующий подкаталог roles/, а далее сослаться на них всех в своём плейбуке site.yml. Такой каталог roles должен бы выглядеть как- то так:


~/hands-on-automation/chapter05/example09/roles> tree -d
.
├── checkbzip2
│   └── tasks
├── checksshdroot
│   └── tasks
├── filecopyexample
│   ├── files
│   └── tasks
├── installbzip2
│   └── tasks
├── packageinstall
│   └── tasks
├── securesshd
│   └── tasks
└── templatentp
    ├── tasks
    └── templates
 	   

После этого наш файл site.yml будет смотреться подобно следующему:


---
- name: Run example roles
  hosts: all
  become: yes

  roles:
    - filecopyexample
    - packageinstall
    - templatentp
    - installbzip2
    - securesshd
    - checkbzip2
    - checksshdroot
 	   

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

Когда вы пройдёте описанный в данной главе процесс сборки, скорее всего, полученный образ потребуется очистить повторно. Мы могли бы снова обратиться к команде virt-sysprep, однако и тут приходит на помощь Ansible. В своём следующем разделе мы изучим применение Ansible для очистки образов при крупномасштабном развёртывании.

Очистка построения при помощи Ansible

На данный момент вы должны обладать достаточно хорошим пониманием сборки или валидации некого базового образа и последующей его персонализации при помощи Ansible. Прежде чем мы закроем данную главу, неплохо повторить свою задачу очистки вашего готового к развёртыванию образа. Собрали ли вы некий образ с нуля, либо выгрузили уже подготовленный, когда вы его запускаете и выполняете в нём команды, будь то вручную или через Ansible, вам скорее всего пришлось загружать элементы, которые на практике нежелательно представлять при каждом развёртывании данного образа. Например, на самом ли деле вы хотите чтобы все файлы системных журналов от всех задач выполненных вами настроек и всех первичных загрузок присутствовали во всех развёртываемых отдельных виртуальных машинах? Когда вам приходится запускать все команды вручную (даже когда это была установка аутентификации при запуске Ansible), хотите ли вы чтобы эти команды присутствовали во всех развёртывания в соответствующем файле .bash_history той учётной записи, которая запускала их?

Ответом на это будет, естественно, нет. Кроме того, имеются такие файлы, которые способны вызывать проблемы при клонировании - например, дубликаты ключей SSH или особые для MAC- адреса настройки, такие как данные настроек udev. Всё это следует вычистить до того как вы будете полагать что ваш образ готов к развёртыванию.

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

Ниже приводится некий образец роли, которая полагается на сырые команды оболочки для очистки образа при его подготовке к развёртыванию. Он не настолько полный как то задание, которые осуществляет virt-sysprep, но служит достойным примером того как это можно выполнять с помощью Ansible. Обратите внимание, что данный образец специфичен именно для CentOS 7 - когда применяется иная операционная система, тогда понадобится поменять пути, команды очистки базы данных пакетов и тому подобное. Следовательно, этот плейбук предоставляется пользователю во многом как некий практический пример того как следует выполнять очистку через Ansible, хотя и предполагается, что читатель двинется дальше в зависимости от своих собственных требований. Прежде всего, мы очищаем имеющуюся базу данных пакетов, так как эти сведения не следует реплицировать во все развёртывания:


---
- name: Clean out yum cache
  shell: yum clean all
 	   

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


- name: Stop syslog
  shell: service rsyslog stop

- name: Force log rotation
  shell: /sbin/logrotate -f /etc/logrotate.conf
  ignore_errors: yes

- name: Clean out logs
  shell: /bin/rm -f /var/log/*-???????? /var/log/*.gz /var/log/*.[0-9] /var/log/**/*.gz /var/log/**/*.[0-9]

- name: Truncate log files
  shell: truncate -s 0 /var/log/*.log

- name: Truncate more logs
  shell: truncate -s 0 /var/log/**/*.log

- name: Clear the audit log
  shell: /bin/cat /dev/null > /var/log/audit/audit.log

- name: Clear wtmp
  shell: /bin/cat /dev/null > /var/log/wtmp
 	   

После этого мы вычищаем свои особенности настроек оборудования и MAC адресов, которые будут неверными при развёртывании образа ВМ:


- name: Remove the udev persistent device rules
  shell: /bin/rm -f /etc/udev/rules.d/70*

- name: Remove network related MAC addresses and UUID's
  shell: /bin/sed -i '/^\(HWADDR\|UUID\)=/d' /etc/sysconfig/network-scripts/ifcfg-*
 	   

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


- name: Clear out /tmp
  shell: /bin/rm -rf /tmp/* /var/tmp/*

- name: Remove user history
  shell: /bin/rm -f ~root/.bash_history /home/**/.bash_history

- name: Remove any viminfo files
  shell: rm -f /root/.viminfo /home/**/.viminfo

- name: Remove .ssh directories
  shell: rm -rf ~root/.ssh m -rf /home/**/.ssh
 	   

Наконец, мы выполняем свою окончательную задачу - в данном случае удаление имеющихся SSH ключей хоста. Обратите внимание, что после этого мы также выключаем свою ВМ - это выполняется как часть данной команды чтобы предотвратить непредумышленное создание каких- либо дополнительных сведений истории или регистрационных записей. Также обратите внимание и на условие ignore_errors, которое препятствует сбою плейбука при выполнении останова и прерывании установленного подключения SSH:


- name: Remove SSH keys and shut down the VM (this kills SSH connection)
  shell: /bin/rm -f /etc/ssh/*key* && shutdown -h now
  ignore_errors: yes
 	   

Выполнение данного кода в некой ВМ CentOS 7 приведёт в результате к достаточно неплохо очищенному образу, однако имеются не охваченные здесь особенности. К примеру, мы выполнили очистку всех историй bash, однако если использовалась иная оболочка, имеются не вычищенными её данные. Аналогично, мы очистили сведения приложения VIM из домашнего каталога root, но не касались всех прочих приложений, которые могли применяться, а могли и нет в процессе создания данного образа. Следовательно, это оставляется вам для расширения данной роли в зависимости от требований вашей среды.

На данном этапе вы выполнили прогон всего процесса, причём повсеместно, в отношении создания, персонализации и очистки операционной системы Linux для целей SOE. Действенное использование Ansible означает, что весь процесс может быть автоматизирован, а следовательно делает для нас возможным выполнение мощного старта в направлении автоматизации на вашем предприятии и начиная с данного момента вы имеете возможность его клонирования и применения там, где только пожелаете.

Выводы

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

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

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

Вопросы

  1. В чём состоит основная цель подготовки системы (sysprep)?

  2. Когда вам может потребоваться применение фактов Ansible в своих ролях?

  3. Как бы вы развёртывали некий новый файл конфигурации некого образа виртуальной машины при помощи Ansible?

  4. Какой модуль Ansible применяется для выгрузки файла из Интернета напрямую в образ некой виртуальной машины?

  5. Как бы вы написали некую отдельную роль Ansible, которая установит пакеты и в Ubuntu, и в CentOS?

  6. Зачем вам желательно проверять выгружаемый вами образ ISO?

  7. Как само применение ролей Ansible на данном этапе даёт преимущества вашей среде при её развёртывании?

Последующее чтение

Для более глубокого понимания Ansible, будьте добры ознакомиться с Mastering Ansible, Third Edition — James Freeman и Jesse Keating {Прим. пер.: рекомендуем также свой перевод этого 3 издания Полного руководства Ansible Джеймса Фримана и Джесса Китинга}.

Для получения дополнительных подробностей о применении KVM при виртуализации Linux, обратитесь, пожалуйста, к Mastering KVM Virtualization, Prasad Mukhedkar, Anil Vettathu и Humble Devassy Chirammal {Прим. пер.: рекомендуем также свой перевод отдельных глав из Виртуализация KVM, Полное руководство этих авторов, Книги рецептов виртуализации KVM Константина Иванова и Основ разработки libvirt Как настраивать и сопровождать виртуальную машину при помощи Python, В. Дэйвида Эшли}.