Centos 7 + Puppet master 4.* (Puppet server 2.*) + PuppetDB/PostgreSQL [Best Practice]

Пытаемся воспроизвести best practice разработчиков puppet. Всё ставится просто и по шагам. Только учитываем, что в самом лучшем случае, если в вашей компании нормальное руководство и им не жалко денег на нужды оркестровки, администрирования и экономию времени своих администраторов, то вам понадобится 3 сервера: 1 – puppetmaster, 2 – postgresql, 3 – puppetdb. Так же такая схема в будущем поможет вам при росте вашей инфраструктуры в кластеризации puppet сервиса. В моём случае, увы, я буду использовать 2 физических сервера: 1 – puppetmaster, 2 – postgresql/puppetdb.


Centos 7

    • Берём образ centos 7 netinstall либо minimal из официальных реп либо зеркал. Расписывать подробный процесс установки centos в рамках этой статьи не буду.
    • После установки centos добавляем необходимые нам репозитарии:
      yum -y install epel-release
      rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm
      
    • Устанавливаем набор необходимых утилит:
      yum install vim-enhanced htop mc screen tcpdump wget ethtool traceroute bind-utils dmidecode iptables ntp bash-completion iptables-services pciutils telnet sudo puppet
      
    • [Необязательно] Изменяем названия интерфейсов с enp на привычное eth. Для этого редактируем /etc/default/grub и добавляем в GRUB_CMDLINE_LINUX параметр net.ifnames=0 . В итоге получится что-то типа:
      GRUB_TIMEOUT=5
      GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
      GRUB_DEFAULT=saved
      GRUB_DISABLE_SUBMENU=true
      GRUB_TERMINAL_OUTPUT="console"
      GRUB_CMDLINE_LINUX="crashkernel=auto rhgb net.ifnames=0 quiet"
      GRUB_DISABLE_RECOVERY="true"

      Переписываем конфиг загрузчика:

      grub2-mkconfig -o /boot/grub2/grub.cfg
    • Разбираемся с Selinux. Отключать совсем не будем, но изменим дефолтную политику на “разрешить всё” и используем только DAC (избирательное управление доступом). Для этого приводим /etc/selinux/config к виду:
      # This file controls the state of SELinux on the system.
      # SELINUX= can take one of these three values:
      # enforcing - SELinux security policy is enforced.
      # permissive - SELinux prints warnings instead of enforcing.
      # disabled - No SELinux policy is loaded.
      SELINUX=permissive
      # SELINUXTYPE= can take one of three two values:
      # targeted - Targeted processes are protected,
      # minimum - Modification of targeted policy. Only selected processes are protected..
      # mls - Multi Level Security protection.
      SELINUXTYPE=targeted
      

      Выполняем:

      /usr/sbin/setenforce 0
    • Добавляем нового пользователя в систему под которым будем производить все дальнейшие изменения, потому что под пользователем root это делать небезопасно.
      useradd -m -G wheel vasya
      

      Приводим /etc/sudoers к виду:

      Defaults    requiretty
      Defaults   !visiblepw
      Defaults    always_set_home
      
      Defaults    env_reset
      Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
      Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
      Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
      Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
      Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
      
      Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
      
      root	ALL=(ALL) 	ALL
      %wheel	ALL=(ALL)	ALL
      
    • Апдейтим систему если это необходимо и перезагружаемся:
      yum update
      /sbin/reboot
      
    • Заходим в систему под нашим пользователем vasya , получаем привилегии root командой sudo -s и далее все изменения в системе производим из под него.
    • Выключаем firewalld и включаем iptables:
      systemctl stop firewalld
      systemctl disable firewalld
      systemctl enable iptables.service
      systemctl start iptables.service
      

      Разрешаем всё, что необходимо для работы puppetmaster и puppetdb приведя файл /etc/sysconfig/iptables к виду:

      # sample configuration for iptables service
      # you can edit this manually or use system-config-firewall
      # please do not ask us to add additional ports/services to this default configuration
      *filter
      :INPUT ACCEPT [0:0]
      :FORWARD ACCEPT [0:0]
      :OUTPUT ACCEPT [0:0]
      -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
      -A INPUT -p icmp -j ACCEPT
      -A INPUT -i lo -j ACCEPT
      -A INPUT -p tcp -m tcp -m multiport --dports 8140,8081 -j ACCEPT
      -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
      -A INPUT -j REJECT --reject-with icmp-host-prohibited
      -A FORWARD -j REJECT --reject-with icmp-host-prohibited
      COMMIT
      

      Перезагружаем правила сетевого фильтра:

      iptables-restore < /etc/sysconfig/iptables &#91;/sourcecode&#93;</li>
       	<li>Правим часовую зону и время наших серверов. Это очень важно при подписывании сертификатов <em>timedatectl set-timezone Russia/Moscow </em>и синхронизируем время <em>ntpdate ntp4.stratum2.ru </em>либо с любым сервером из <a href="https://www.ntp-servers.net/servers.html">списка</a>.</li>
       	<li>Тюним ядро. Можно использовать мой <a href="https://avalon.land/blog/?p=253">strong optimization</a> из предыдущей статьи.</li>
      </ul>
      </ul>
      Готово! Настройка серверов завершена. Если вы используете виртуальные машины, то с этой точки можно сделать <em>snapshot</em>.
      
      <hr />
      
      <h1 style="text-align: center;"><span style="color: #808080;">Puppet Server</span></h1>
      <strong>Puppet Server</strong> он же <em>puppet master</em> в нашей схеме будет отвечать за хранение и раздачу конфигурации для нод клиентов и хранение сертификатов. Вообще, хранить конфигурации правильнее в git с помощью модуля <strong>r10k</strong> , а сертификаты нод на отдельном сервере при кластеризации puppet-сервиса, но в этой статье мы всего этого использовать не будем.
      <ul>
       	<li>Переименуем наш puppet server в <em>puppet</em> как рекомендуют нам разработчики. Для этого внесём изменения в <em>/etc/hostname</em> :
      
      puppet.my.domain
      

      так же нам понадобится внести изменения в нашу dns-зону my.domain (если она у нас есть) добавив туда соответствующую символьную A-запись. В противном случае на всех наших серверах правим /etc/hosts приводя его к виду:

      127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
      ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
      192.168.0.1 puppet puppet.my.domain
      192.168.0.2 puppetdb puppetdb.my.domain
      
    • Наконец делаем то, ради чего написана вся эта статья – ставим пакет puppetserver: 
      yum install puppetserver
    • Так как всё это дело написано на ruby/java , оно очень прожорливо в плане системных ресурсов, значит сходу правим /etc/sysconfig/puppetserver увеличив минимальные значения:
      ###########################################
      # Init settings for puppetserver
      ###########################################
      
      # Location of your Java binary (version 7 or higher)
      JAVA_BIN="/usr/bin/java"
      
      # Modify this if you'd like to change the memory allocation, enable JMX, etc
      JAVA_ARGS="-Xms4g -Xmx4g -XX:MaxPermSize=1g"
      
      # These normally shouldn't need to be edited if using OS packages
      USER="puppet"
      GROUP="puppet"
      INSTALL_DIR="/opt/puppetlabs/server/apps/puppetserver"
      CONFIG="/etc/puppetlabs/puppetserver/conf.d"
      BOOTSTRAP_CONFIG="/etc/puppetlabs/puppetserver/bootstrap.cfg"
      SERVICE_STOP_RETRIES=60
      
      # START_TIMEOUT can be set here to alter the default startup timeout in
      # seconds.  This is used in System-V style init scripts only, and will have no
      # effect in systemd.
      # START_TIMEOUT=120
      

      Тут нас интересует пока только JAVA_ARGS указывающий объём памяти отдаваемый демону и максимальное кол-во памяти потребляемое каждым тредом.

    • Добавляем нашему серверу возможность автоподписи сертификатов. Все ноды, попавшие под определённую маску, будут автоматически признаны мастером своими клиентами и начнут попадать под манифесты написанные для них, если такие конечно же будут. Для этого создаём файл /etc/puppetlabs/puppet/autosign.conf с содержимым:
      *.my.domain
      

      То есть все сервера чей FQDN попадает под данную маску – будут нашими клиентами.

    • Запускаем наш puppetmaster:
      systemctl enable puppetserver.service
      systemctl start puppetserver.service
    • В принципе, минимальный набор действий для работы master’а мы совершили. Можно убедиться что всё впорядке прочитав логи: /var/log/puppetlabs/puppetserver/

    PostgreSQL/PuppetDB

    Есть несколько способов установки postrgesql и puppetdb. По какой-то непонятной для меня причине, производитель рекомендует новичкам установку из пакетов. То есть нам сначала предлагают поставить postgresql и настроить его, что, я вам скажу, ни разу не просто, затем поставить пакетом puppetdb и так же его настраивать на работу с нашей БД. Второй способ – установка модулем puppetmaster’а и настройка puppet client’ом – это наш способ! Иначе, на кой ляд бы мы вообще ставили этот puppet, если собираемся делать его работу за него?

    • На puppetserver’е установим необходимые модули для работы puppetdb. Вся прелесть этого способа в том, что нам даже не надо ставить каждый модуль отдельно, так как в puppet’е предусмотрена система зависимостей, а значит он самостоятельно удовлетворит все необходимые зависимости:
      puppet module install puppetlabs-puppetdb
      

      Смотрим что у нас получилось командой puppet module list:

      /etc/puppetlabs/code/environments/production/modules
      +-- puppetlabs-apt (v2.2.2)
      +-- puppetlabs-concat (v2.1.0)
      +-- puppetlabs-firewall (v1.8.0)
      +-- puppetlabs-inifile (v1.5.0)
      +-- puppetlabs-postgresql (v4.7.1)
      +-- puppetlabs-puppetdb (v5.1.2)
      L-- puppetlabs-stdlib (v4.11.0)
      /etc/puppetlabs/code/modules (no modules installed)
      /opt/puppetlabs/puppet/modules (no modules installed)
      
    • Теперь нам следует написать манифест, который установит и настроит всё это на нашем puppetdb сервере. Для этого создаём файл /etc/puppetlabs/code/environments/production/manifests/pmdb.pp следующего содержания:
      $master_host = 'puppet.my.domain'
      $puppetdb_host = 'puppetdb.my.domain'
      
      node puppet.my.domain {
        # Here we configure the Puppet master to use PuppetDB,
        # telling it the hostname of the PuppetDB node
        class { 'puppetdb::master::config':
          puppetdb_server => $puppetdb_host,
        }
      }
      node puppetdb.my.domain {
        # Here we install and configure PostgreSQL and the PuppetDB
        # database instance, and tell PostgreSQL that it should
        # listen for connections to the `$postgres_host`
        class { 'puppetdb::database::postgresql':
          listen_addresses => $puppetdb_host,
        }
        class { 'puppetdb::server':
          database_host => $puppetdb_host,
        }
      }

      Данный манифест содержит инструкции для двух нод: первая нода это наш puppetmaster которому мы говорим отсылать все данные facter’a нашей puppetdb и наоборот брать их оттуда при необходимости. Второй ноде puppetdb мы говорим установить postgresql и настроить его на работу с адресом puppetdb , так как у нас postgresql и puppetdb на одном хосте, затем установить и настроить аналогично puppetdb.

    • Наконец-то на нашем puppetdb-сервере устанавливаем и настраиваем с помощью puppet’a всё необходимое одной командой:
      puppet agent --debug --no-daemonize --onetime
    • Подтюним немного настройки puppetdb отдав ему большую часть нашей ОЗУ приведя /etc/sysconfig/puppetdb к виду:
      ###########################################
      # Init settings for puppetdb
      ###########################################
      
      # Location of your Java binary (version 7 or higher)
      JAVA_BIN="/usr/bin/java"
      
      # Modify this if you'd like to change the memory allocation, enable JMX, etc
      JAVA_ARGS="-Xmx14g"
      
      # These normally shouldn't need to be edited if using OS packages
      USER="puppetdb"
      GROUP="puppetdb"
      INSTALL_DIR="/opt/puppetlabs/server/apps/puppetdb"
      CONFIG="/etc/puppetlabs/puppetdb/conf.d"
      BOOTSTRAP_CONFIG="/etc/puppetlabs/puppetdb/bootstrap.cfg"
      SERVICE_STOP_RETRIES=60
      
      # START_TIMEOUT can be set here to alter the default startup timeout in
      # seconds.  This is used in System-V style init scripts only, and will have no
      # effect in systemd.
      # START_TIMEOUT=300
      
    • Теперь пришло время сказать нашему puppetserver’у настроиться на работу с puppetdb.
      Для этого запустим агента: puppet agent --debug --no-daemonize --onetime

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

    В следующих статьях постараемся завести hiera вместо дефолтных манифестов puppet’a и возможно, если нам очень сильно повезёт, r10k для хранения конфигураций на git’е.

    Всю прочую инфу можно найти на официальном сайте продукта.

2 thoughts on “Centos 7 + Puppet master 4.* (Puppet server 2.*) + PuppetDB/PostgreSQL [Best Practice]

Leave a Reply

Your email address will not be published. Required fields are marked *