Child pages
  • Автоматизация системы мониторинга на базе Icinga2 и Puppet
Skip to end of metadata
Go to start of metadata

Поговорим немного о... Infrastructure as code (IaC).



На Хабре есть несколько очень хороших статей про Icinga2, есть также отличные статьи про Puppet:

https://habr.com/post/326450/
https://habr.com/post/307358/
https://habr.com/post/229867/

 Однако, тема автоматизации и интеграции этих двух потрясающих систем совсем не раскрыта.

В данном руководстве, я покажу на «живом» примере, как можно, объединив эти две системы, получить мощный инструмент мониторинга вашей инфраструктуры со всем набором необходимых функций. Статья является своего рода руководством к действию по установке пакета «все в одном флаконе». После выполнения этого руководства у вас в наличии будет полностью рабочее решение мониторинга, которое в дальнейшем можно будет «допиливать» под себя. Давайте попробуем!

Итак:

Мы подняли новый хост. И нам нужно:

1. Чтобы его мониторинг автоматически появился в Icinga2, и создались базовые проверки:
ПроверкиСнимкиПояснения

Host

С заданной периодичностью проверяем командой ping, что хост «живой».

Disk usage

Проверяем, что у нас достаточно свободного места на дисках.

Load average

Мониторим нагрузку на сервере динамически. Учитывается количество  процессоров на нём.

Free memory

Проверяем, что у нас достаточно свободной памяти на сервере.

Open ports



Сканируем порты на сервере и создаём карту открытых портов. Мониторим, что у нас не появились новые открытые или закрытые порты.

Critical updates

Мониторим наличие критических обновлений на сервере.


2. Добавлять кастомные проверки на различные сервисы в удобном и понятном виде. Что бы потом директору показать какие мы молодцы и премию получить!
Некоторые примеры:
СервисСнимкиYAML код проверкиПояснения

Virtual host

    '%{::fqdn} virtual host' :
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: '%{::fqdn} virtualhost'
        check_command: 'http'
        vars:
            http_uri: /
            http_ssl: true
            http_vhost: 'hostname'
            http_address: "%{lookup('host_address')}"
Проверяем «живой» хост или нет.

PostgreSQL

    '%{::fqdn} PostgreSQL':
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: 'PostgreSQL'
        command_endpoint: '%{::fqdn}'
        check_command: "postgres"
        vars:
            postgres_host: "localhost"
            postgres_action: "connection"
            phone_notifications: true


Проверяем, что мы можем соединиться с БД PostgreSQL.

Nginx Status

    '%{::fqdn} nginx status' :
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        command_endpoint: '%{::fqdn}'
        display_name: 'nginx status'
        check_command: 'nginx_status'
        vars:
            nginx_status_host_address: localhost
            nginx_status_servername: server.com
            nginx_status_critical: '1600,60,30'
            nginx_status_warn: '1500,55,25'
Мониторим статус Nginx через stub_status.

3. Чтобы всё было аккуратно, надёжно и красиво. И главное, потратить не более 30 минут на возню с первоначальной настройкой.

У вас должен быть опыт работы с Docker'ом, а значит и с Linux — само собой.

Данный сетап описан под Debian/Ubuntu. И, хотя я не вижу причин ему не работать на других Unix-подобных системах, сам я таких гарантий дать не могу. У меня есть пара машин с CentOS, там это работает, но большинство, всё же — это Debian/Ubuntu.


Начнём

Скажу сразу, мне удобно, когда вся конфигурация хоста — сервисы, конфиги, софт, аккаунты и т.п. — описываются одним yaml-файлом, это фактически позволяет избежать документирования инфраструктуры и даёт наглядность конфигурации. Открыл соответствующий проект в git-репозитории, где имена файлов соответствуют имени хоста, затем открыл конфиг нужного хоста. И сразу видно, какие сервисы есть на хосте, что из этого бэкапится, что мониторится и т.д.

Вот так выглядит структура проекта в репозитории:
project_1/hostname1.com.yaml
project_2/hostname2.com.yaml
project_3/hostname3.com.yaml
У себя я использую вот такой шаблон, в котором описывается конфигурация любого из наших серверов:
 Полный шаблон...
#============================|INPUT DATA|======================================================================================================================#
#---------------------------------------|VARS|-----------------------------------------------------------------------------------------------------------------#
#---//Information about variables, keys & contacts//-----------------------------------------------------------------------------------------------------------#

host_address: x.x.x.x
my_company: 
my_mail_domain: 
my_ssh_port: 



#---------------------------------------|CLASSES|--------------------------------------------------------------------------------------------------------------#
#---//Classes are modules installed on the server. These modules process the arguments typed below.//----------------------------------------------------------#
#---//Without classes nothing will work.//---------------------------------------------------------------------------------------------------------------------#
#---//Class default_role is mandatory. This class will install etckeeper, some required perl modules and manages all the logics.//-----------------------------#

classes:
  - default_role

#---------------------------------------|TIMEZONE|-------------------------------------------------------------------------------------------------------------#
#---//Set timezone, which will be used on the host.//----------------------------------------------------------------------------------------------------------#

timezone::timezone: Europe/Moscow

#---------------------------------------|FACTS|----------------------------------------------------------------------------------------------------------------#
#---//Facts are variables which puppet agent uses.//-----------------------------------------------------------------------------------------------------------#

facter::facts_hash:
 role:
   value: 'name'
 company:
   value: 'name of company'
   file: 'location.txt'

#==============================================================================================================================================================#
 

#============================|PUPPET|==========================================================================================================================#
#---//Settings for puppet agent.//-----------------------------------------------------------------------------------------------------------------------------#

puppet::runmode: cron
puppet::ca_server: "%{lookup('puppet_ca')}"
puppet::puppetmaster: "%{lookup('puppet_master')}"

#==============================================================================================================================================================#
 
#============================|CRON TASKS|======================================================================================================================#

cron_tasks:
    Name:
        command: ""
        user: 
        minute: ''
        hour: ''   

#==============================================================================================================================================================#

#============================|SUPERVISOR|======================================================================================================================#
#---//Supervisor is a process manager//------------------------------------------------------------------------------------------------------------------------#

supervisord::install_pip: false
supervisord::install_init: false
supervisord::service_name: supervisor
supervisord::package_provider: apt
supervisord::executable: /usr/bin/supervisord
supervisord::executable_ctl: /usr/bin/supervisorctl
supervisord::config_file: /etc/supervisor/supervisord.conf
supervisord::programs:
  'name':
    ensure: present
    command: 'su - rails -c "/home/name/s2"'
    autostart: no
    autorestart: 'false'
    directory: /home/name/domainName/current

#==============================================================================================================================================================#
 
 
#============================|SECURITY|========================================================================================================================#
#-------------------------------------|FIREWALL|---------------------------------------------------------------------------------------------------------------#
#---//Iptables rules//-----------------------------------------------------------------------------------------------------------------------------------------#

firewall:
    096 Allow inbound SSH:
      dport: "%{lookup('my_ssh_port')}"
      proto: tcp
      action: accept

#-------------------------------------|FAIL2BAN|---------------------------------------------------------------------------------------------------------------#


#-------------------------------------|ACCESS|-----------------------------------------------------------------------------------------------------------------#
#--------------------------------------------|ACCOUNTS|--------------------------------------------------------------------------------------------------------#
#---//Discription of accounts which will be created on server.//-----------------------------------------------------------------------------------------------#

accounts:
    user:
        shell: '/bin/bash'
        password: ''
        locked: false
        purge_sshkeys: true
         groups:
            - docker
        sshkeys:
            - "%{alias('admins_ssh_keys')}"

   
#--------------------------------------------|SUDO|------------------------------------------------------------------------------------------------------------#
#---//Appointment permissions for users.//---------------------------------------------------------------------------------------------------------------------#

sudo::config_file_replace: false
sudo::configs:
    user:
        content: "user ALL=(ALL) NOPASSWD: ALL"
    
#--------------------------------------------|SSH|-------------------------------------------------------------------------------------------------------------#
#--------//Settings for ssh server.//--------------------------------------------------------------------------------------------------------------------------#

ssh::storeconfigs_enabled: true
ssh::server_options:
    Protocol: '2'
    Port: "%{lookup('my_ssh_port')}"
    PasswordAuthentication: 'yes'
    PermitRootLogin: 'without-password'
    SyslogFacility: 'AUTHPRIV'
    UsePAM: 'yes'
    X11Forwarding: 'no'
 
#--------------------------------------------|VPN|-------------------------------------------------------------------------------------------------------------#
#---//Settings for vpn server.//-------------------------------------------------------------------------------------------------------------------------------#

openvpn::servers:
  'namehost':
    country: ''
    province: ''
    city: ''
    organization: ''
    email: ''
    server: 'x.x.x.x 255.255.255.0'
    dev: tun
    local: "%{lookup('host_address')}"

openvpn::client_defaults:
  server: 'namehost'

openvpn::clients:
  # Firstname Lastname
  'user': {}

openvpn::client_specific_configs:
  'user':
    server: 'namehost'
    redirect_gateway: true
    route:
    - x.x.x.x 255.255.255.255

#==============================================================================================================================================================#
 
#============================|OPERATING SYSTEM|================================================================================================================#
#---------------------------------------------|SYSCTL|---------------------------------------------------------------------------------------------------------#
#---//Set sysctl parameters//----------------------------------------------------------------------------------------------------------------------------------#

sysctl::base::values:
  fs.file-max:
    value: '2097152000'
  net.netfilter.nf_conntrack_max:
    value: '1048576'
  net.nf_conntrack_max:
    value: '1048576'
  net.ipv6.conf.all.disable_ipv6:
    value: '1'
  vm.oom_kill_allocating_task:
    value: '1'    
  net.ipv4.ip_forward:
    value: '0'
  net.ipv4.tcp_keepalive_time:
     value: '3'
  net.ipv4.tcp_keepalive_intvl:
    value: '60'
  net.ipv4.tcp_keepalive_probes:
    value: '9'
    
    
#---------------------------------------------|RCS|------------------------------------------------------------------------------------------------------------#
#---//Managment of RC scenario//-------------------------------------------------------------------------------------------------------------------------------#

rcs::tmptime: '-1'

#---------------------------------------------|WEB SERVERS|----------------------------------------------------------------------------------------------------#
#---------------------------------------------------------|HAPROXY|--------------------------------------------------------------------------------------------#
#---//HAProxy is software that provides a high availability load balancer and proxy server for TCP and HTTP-based applications that spreads//------------------# 
#---//requests across multiple servers.//----------------------------------------------------------------------------------------------------------------------#

haproxy::merge_options: true
haproxy::defaults_options:
    log: global
    maxconn: 20000
    option: [
        'tcplog',
        'redispatch',
        'dontlognull'
    ]
    retries: 3
    stats: enable
    timeout: [
        'http-request 10s',
        'queue 1m',
        'check 10s',
        'connect 300000000ms',
        'client 300000000ms',
        'server 300000000ms'
    ]

haproxy_server:
  stats:
    ipaddress: "%{lookup('host_address')}"
    ports: '9090' 
    options:
      mode: 'http'
      stats: [ 'uri /', 'auth puppet:123123123' ] 
  postgres:
    collect_exported: false
    ipaddress: '0.0.0.0'
    ports: '5432' 
    options:
        option:
            - tcplog
        balance: roundrobin
haproxy_balancemember:
  hostname1:
    listening_service: postgres
    server_names: hostname1
    ipaddresses: "%{lookup('host1_ip')}"
    ports: 6432
    options: check
  hostname2:
    listening_service: postgres
    server_names: hostname2
    ipaddresses: "%{lookup('host2_ip')}"
    ports: 6432
    options:
        - check
        - backup

#---------------------------------------------|NGINX|----------------------------------------------------------------------------------------------------------#
#---//Nginx is a web server which can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache//----------------------------------------------# 

nginx::nginx_cfg_prepend:
  'load_module':
      - modules/ngx_http_geoip_module.so
nginx::http_raw_append:
  - 'real_ip_header X-Forwarded-For;'
  - 'geoip_country /usr/share/GeoIP/GeoIP.dat;'
  - 'set_real_ip_from 0.0.0.0/0;'
nginx::worker_rlimit_nofile: 16384
nginx::confd: true
nginx::server_purrge: true
nginx::server::maintenance: true  

#---------------------------------------------nginx-|MAPS|-----------------------------------------------------------------------------------------------------#

nginx::string_mappings:
  allowed_country:
    ensure: present
    string: '$geoip_country_code'
    mappings:
      - key: 'default'
        value: 'yes'
      - key: 'US'
        value: 'no'

#---------------------------------------------nginx-|UPSTREAMS|------------------------------------------------------------------------------------------------#

nginx::nginx_upstreams:
  "upstreamName":
    ensure: present
    members:
      - "localhost:9999"

#---------------------------------------------nginx-|VHOSTS|---------------------------------------------------------------------------------------------------#

nginx::nginx_servers:

  'hostname':
    proxy: 'http://'
    location_raw_append:
        - 'if ($allowed_country = no) {return 403;}'
    try_files:
    - ''
    - /index.html
    - =404
    ssl: true
    ssl_cert: "/etc/letsencrypt/live/hostname/fullchain.pem"
    ssl_key: "/etc/letsencrypt/live/hostname/privkey.pem"
    ssl_trusted_cert: "/etc/letsencrypt/live/hostname/chain.pem"
    ssl_redirect: false
    ssl_port: 443
    error_pages:
      '403': /usa-restrict.html

#---------------------------------------------nginx-|HTTPAUTH|-------------------------------------------------------------------------------------------------#

httpauth:
  'admin':
    file: "/etc/nginx/htaccess"
    password: ''
    realm: realm
    mechanism: basic
    ensure: present

#---------------------------------------------nginx-|LOCATIONS|------------------------------------------------------------------------------------------------#

nginx::nginx_locations:
  'domain1.com/usa-restricted':
    location: /usa-restrict.html
    www_root: /home/clientName1/clientName1-client-release/current/dist
    server: domain1.com
    ssl: true
  '^~ domain2.com/resources/upload/':
    location: '^~ /resources/upload/'
    server: domain2.com
    location_alias: '/home/clientName2/upload/'
    raw_append:
        - 'if ($allowed_country = no) {return 403;}'
  '/nginx_status-domain3.com':
    location: /nginx_status
    stub_status: on
    raw_append:
        - access_log off;
        - allow 127.0.0.1;
        - deny all;    

#---------------------------------------------nginx-|WELL-KNOWN|-----------------------------------------------------------------------------------------------#
#---//These locations are needed for SSL certificates generating with Letsencrypt.//---------------------------------------------------------------------------#

  'x.hostname.zz/.well-known':
    location: '/.well-known'
    server: x.hostname.zz
    proxy: 'http://kibana' 
    auth_basic: "ciao"
    auth_basic_user_file: "/etc/nginx/htaccess
    www_root: /var/www/html
    ssl: true
  'hostname.zz/~* \.(?:ico|css|js|html|map|gif|jpg|png|svg|ttf|woff|appcache|pdf)$':
    location: '~* \.(?:ico|css|js|html|map|gif|jpg|png|svg|ttf|woff|appcache|pdf)$'
    www_root: '/home/hostname/hostname-client-release/current/dist'
    expires: max
    raw_append:
    - "add_header Pragma public;"
    - 'add_header Cache-Control "public, must-revalidate, proxy-revalidate";'    

#---------------------------------------------------|NGINS STATUS|---------------------------------------------------------------------------------------------#

#----------------------------|LETSENCRYPT|---------------------------------------------------------------------------------------------------------------------#
#---//Let's Encrypt is a certificate authority that provides free X.509 certificates//---#
#---//for Transport Layer Security (TLS) encryption via an automated process//---#
#---//designed to eliminate the hitherto complex process of manual creation,//---#
#---//validation, signing, installation, and renewal of certificates for secure websites.//---#

letsencrypt::email: client@mail.com
letsencrypt_certonly:
    hostname:
        manage_cron: true
        domains:
            - hostname
        plugin: webroot
        webroot_paths:
            - '/var/www/html'

#----------------------------|FILE SERVERS|--------------------------------------------------------------------------------------------------------------------#
#-----------------------------------------|FILES|--------------------------------------------------------------------------------------------------------------#
#---//Creating files & folders on the server.//----------------------------------------------------------------------------------------------------------------#

file:
    "/home/hostname/hostname-release/shared/ecosystem.config.js":
        ensure: present
        owner: hostname
        content: |
            module.exports = {
              /**
               * Application configuration section
               * http://pm2.keymetrics.io/docs/usage/application-declaration/
               */
              apps : [
                // First application
                {
                  name      : 'api',
                  script    : '/home/hostname/hostname-release/current/dist/index.js',
                  cwd       : '/home/hostname/hostname-release/current/dist/',
                  watch     : false,
                  ignore_watch : ["logs"],
                  "log_type": "format",
                  env: {
                    COMMON_VARIABLE: 'true'
                  },
                  env_production : {
                    NODE_ENV: 'production',
                    PORT: 9999,
                    DEBUG   : '*'
                  },
                  env_development : {
                    NODE_ENV: 'development',
                    PORT: 9999,
                    DEBUG   : '*'
                  }
                },
                // Second application
                {
                  name      : 'WEB',
                  script    : 'web.js'
                }
              ],
              /**
               * Deployment section
               * http://pm2.keymetrics.io/docs/usage/deployment/
               */
              deploy : {
                production : {
                  user : 'node',
                  host : '0.0.0.0',
                  ref  : 'origin/master',
                  repo : 'name@name.com:repo.git',
                  path : '/var/www/production',
                  'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production'
                },
                dev : {
                  user : 'node',
                  host : '0.0.0.0',
                  ref  : 'origin/master',
                  repo : 'name@name.com:repo.git',
                  path : '/var/www/development',
                  'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env dev',
                  env  : {
                    NODE_ENV: 'dev'
                  }
                }
              }
            };

#-----------------------------------------|FTP|----------------------------------------------------------------------------------------------------------------#
#---//Very Secure FTP Daemon is an FTP server for Unix-like systems.//-----------------------------------------------------------------------------------------#

vsftpd::ftpd_banner: 'ASCII FTP Server'
vsftpd::anonymous_enable: 'NO'
vsftpd::write_enable: 'YES'
#vsftpd::chroot_local_user: 'YES'
vsftpd::allow_writeable_chroot: 'YES'
vsftpd::userlist_enable: 'YES'
vsftpd::userlist_deny: 'NO'

#-----------------------------------------|NFS|----------------------------------------------------------------------------------------------------------------#
#---//Network File System is a distributed file system protocol, allowing a user on a client computer to access files over a computer//------------------------# 
#---//network much like local storage is accessed.//-----------------------------------------------------------------------------------------------------------#

nfs::server_enabled: true
nfs::client_enabled :  false
nfs::nfs_v4:  true
nfs::nfs_v4_idmap_domain:  "%{::domain}"
nfs::nfs_v4_export_root:  '/share'
nfs::nfs_v4_export_root_clients:  "%{lookup('host_address')}/32(rw,fsid=root,insecure,no_subtree_check,async,no_root_squash)"
nfs::nfs_exports_global:
  /var/www: {}
  /var/smb: {}

#----------------------------|PACKAGES|------------------------------------------------------------------------------------------------------------------------#
#---//Install of packages to server.//-------------------------------------------------------------------------------------------------------------------------#

packages:
    namePackage:
        ensure: installed

#-------------------------------------|APT|--------------------------------------------------------------------------------------------------------------------#
#---//Management of repository of packages.//---#

apt::sources:
  'debian_unstable':
    comment: 'This is the iWeb Debian unstable mirror'
    location: 'http://debian.mirror.iweb.ca/debian/'
    release: 'unstable'
    repos: 'main contrib non-free'
    pin: '-10'
    key:
      id: 'IDIDIDIDIDIDIDIDIDIDIDIDIDIDIDID'
      server: 'subkeys.pgp.net'
    include:
      src: true
      deb: true
  'puppetlabs':
    location: 'http://apt.puppetlabs.com'
    repos: 'main'
    key:
      id: 'IDIDIDIDIDIDIDIDIDIDIDIDIDIDIDID'
      server: 'pgp.mit.edu'


#-------------------------------------|PHP|--------------------------------------------------------------------------------------------------------------------#

php_pool:
  myadmin:
   listen: 'x.x.x.x:x'

#-------------------------------------|RVM|--------------------------------------------------------------------------------------------------------------------#
#---//Ruby Version Manager  is a unix-like software platform designed to manage multiple installations of Ruby on the same device.//---------------------------#

rvm_ruby:
  user1_rvm:
    user: user1
    version: ruby-2.5.1
white_label_platform: default

#-------------------------------------|PYTHON|-----------------------------------------------------------------------------------------------------------------#

python::version: system
python::dev: present
python::virtualenv: true

#----------------------------|NODEJS|--------------------------------------------------------------------------------------------------------------------------#
#-----------------------------------|NVM|----------------------------------------------------------------------------------------------------------------------#
#---//Node Version Manager for Node.js---//
#---//Node.js lets developers use JavaScript to write Command Line tools and for server-side scripting—running scripts server-side//---------------------------#
#---//to produce dynamic web page content before the page is sent to the user's web browser.//-----------------------------------------------------------------#

nodejs::repo_url_suffix: '8.x'
nvm::user: name
nvm::install_node: 8.10.0

#----------------------------|DOCKER|--------------------------------------------------------------------------------------------------------------------------#
#---//Docker's management//------------------------------------------------------------------------------------------------------------------------------------# 

docker::run_instance::instance:
  nats:
    image: 'nats'
    extra_parameters: '-p 8222:8222 -p 4222:4222 -p 6222:6222 --name nats --network admin_default'
docker::compose::ensure: present
docker_compose:
    /etc/admin/gitlab/docker-compose.yaml:
        ensure: present
docker::iptables: false
docker::tcp_bind: tcp://0.0.0.0:2375  
docker::compose::ensure: present
docker_swarm:
    'agent':
        ensure: present
        join: true
        advertise_addr: '%{::ipaddress_enp2s0}'
        listen_addr: '%{::ipaddress_enp2s0}'
        manager_ip: '%{lookup("host_address")}'
        token: ''  
docker_registry:
    'host.com:5000': 
      username: ''
      password: ''
      email: 'mail@mail.com'

#==============================================================================================================================================================#
 
#============================|BACKUPS UPDATES|=================================================================================================================#
#--------------------------------------------|UPDATES|---------------------------------------------------------------------------------------------------------#
#---//Unattended upgrades is the linux-like mechanism automatic updates.//-------------------------------------------------------------------------------------#

unattended_upgrades::origins:
    - "o=Debian,n=${distro_codename}"
    - "o=Debian,n=${distro_codename}-security"
    - "o=Debian,n=${distro_codename}-updates"
    - "o=Debian,n=${distro_codename}-proposed"
    - "o=Debian,n=${distro_codename}-backports"
    - "o=debian icinga,n=icinga-${distro_codename}"
    - "o=Zabbix,n=${distro_codename}"

#--------------------------------------------|BACKUPS|---------------------------------------------------------------------------------------------------------#
#---//The backups are processed by gembackup.//----------------------------------------------------------------------------------------------------------------#
backup_jobs:
    #Creates full backup
    type_files:
        types: ['archive']
        add:
            - '/path'
        storage_type: 'ftp'
        storage_host: "%{lookup('my_ftp_hostname')}"
        path: '/files/'
        storage_username: "%{lookup('my_backup_ftp_username')}"
        storage_password: "%{lookup('my_backup_ftp_password')}"
        compressor: "%{lookup('my_backup_compressor')}"
        keep: 7
        weekday: [1-7]
        hour: 0
        minute: 0

#--------------------------------------------|MOUNT|-----------------------------------------------------------------------------------------------------------#
#---//Сontrol the mounting of remote & local mount points.//---------------------------------------------------------------------------------------------------#
mount:
    #Mount folder from other server to keep backups
    "/tmp/mediastagetv_netbynet":
        device: "%{lookup('host_address')}:/"
        ensure: mounted
        fstype: nfs4
        options: defaults
        atboot: false

#--------------------------------------------|S3 AMAZON|-------------------------------------------------------------------------------------------------------#
#---//Simple Storage Service is a cloud computing web service.//-----------------------------------------------------------------------------------------------#

hostname1-archives: '/home/hostname1/hostname1/shared/log_amazon'
hostname2-archives: '/home/hostname2/hostname2/shared/log_amazon'
yas3fs::mounts:


#==============================================================================================================================================================#
 
#============================|MONITORING|======================================================================================================================#
#---------------------------------------|ICINGA SERVICES|------------------------------------------------------------------------------------------------------#
#---//Managment of monitoring system.//------------------------------------------------------------------------------------------------------------------------#

icinga2_service:    
    '%{::fqdn} virtual host' :
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: '%{::fqdn} virtualhost'
        check_command: 'http'
        vars:
            http_uri: /
            http_ssl: true
            http_vhost: 'hostname'
            http_address: "%{lookup('host_address')}"
    
    '%{::fqdn} nginx status' :
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        command_endpoint: '%{::fqdn}'
        display_name: 'nginx status'
        check_command: 'nginx_status'
        vars:
            nginx_status_host_address: localhost
            nginx_status_servername: server.com
            nginx_status_critical: '1600,60,30'
            nginx_status_warn: '1500,55,25'
    '%{::fqdn} redis':
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: 'Redis'
        command_endpoint: '%{::fqdn}'
        check_command: "redis"
        vars:
            redis_hostname: localhost
            redis_port: 6379
            redis_perfvars: '*'

#==============================================================================================================================================================#
 
#============================|MAIL & LOGS|=====================================================================================================================#
#----------------------------------------|MAIL|----------------------------------------------------------------------------------------------------------------#
#---------------------------------------------|POSTFIX|--------------------------------------------------------------------------------------------------------#
#---//Management of mail-server Postfix.//---------------------------------------------------------------------------------------------------------------------#

#postfix::manage_conffiles: false
postfix_config:
    relayhost:
        ensure: present
        value: "%{lookup('host_address')}"
    virtual_maps:
        value: hash:/etc/postfix/virtual
        ensure: present
    sender_canonical_map:
        value: hash:/etc/postfix/canonical_sender
        ensure: present
postfix_hash:
    '/etc/postfix/virtual':
        ensure: present
        content: |
          root %{lookup('hostname_admin_emails')}
          rails %{lookup('hostname_emails')}
    '/etc/postfix/canonical_sender':
        ensure: present
        content: |
            name@%{lookup('my_domain')} name@my_domain.com
            root@%{lookup('my_domain')} root@my_domain.com

#----------------------------------------|LOGS|----------------------------------------------------------------------------------------------------------------#
#---------------------------------------------|RSYSLOG|--------------------------------------------------------------------------------------------------------#
#---//Rsyslog is a software utility for forwarding log messages in an IP network. It implements the basic syslog protocol, extends it with//-------------------#
#---//content-based filtering, rich filtering capabilities, flexible configuration options and adds features such as using TCP for transport.//----------------#

rsyslog::client:
  log_local: true

my_rsyslog_snippet:
  99_everything:
    content: "*.*;auth,authpriv.none /var/log/syslog\n"
  01_mail:
    content: "mail.*  -/var/log/mail.log\n& stop"
  02_auth:
    content: "auth,authpriv.* /var/log/auth\n& stop"
  03_puppetagent:
    content: ":programname,contains,\"puppet-agent\" /var/log/puppetlabs/puppet/puppet-agent.log\n& stop"
  04_iptables:
    content: ":msg,contains,\"IPTABLES INPUT\" /var/log/iptables/iptables.log\n& stop"
  05_pam_unix:
    content: ":msg,regex,\".*session opened for.*(uid=0)\" /var/log/admin/auth.log\n& stop"
  06_sshd:
    content: ":msg,regex,\".*publickey for username.*0.0.0.0\" /var/log/admin/auth.log\n& stop

#---------------------------------------------|LOGWATCH|-------------------------------------------------------------------------------------------------------#
#---//Logwatch is a log-analysator for create short reports.//-------------------------------------------------------------------------------------------------#

logwatch::format: text
logwatch::service:
    # Ignore this servie
    - -http
    - -iptables

#---------------------------------------------|LOGROTATE|------------------------------------------------------------------------------------------------------#
#---//Management of rotation of log files.//-------------------------------------------------------------------------------------------------------------------#

my_rclogs_path: '/home/hostname/hostname/shared/log'
my_rclogs_amazon_path: '/home/hostname1/hostname1/shared/log_amazon'
my_ttlogs_path: '/home/hostname2/hostname2/shared/log'
my_ttlogs_amazon_path: '/home/hostname/hostname/shared/log_amazon'
logrotate::ensure: latest
logrotate::config:
  dateext: true
  compress: true
logrotate::rules:
  booking-logs:
    path: '%{lookup("my_rclogs_path")}/booking_com.log'
    size: 2500M
    rotate: 20
    copytruncate: true
    delaycompress: true
    dateext: true
    dateformat: -%Y%m%d-%s
    compress: true
    postrotate: mv %{lookup('my_rclogs_path')}/booking_com.log*.gz %{lookup('my_rclogs_amazon_path')}/




#---------------------------------------------|ATOP|-----------------------------------------------------------------------------------------------------------#
#---//ATOP service displays a new information about CPU and memory utilization.//------------------------------------------------------------------------------#
atop::service: true
atop::interval: 30

#----------------------------------------|DNS|-----------------------------------------------------------------------------------------------------------------#
#---//Management of file /etc/resolv.conf//--------------------------------------------------------------------------------------------------------------------#

resolv_conf::nameservers:
    - 0.0.0.0
    - 0.0.0.0

#==============================================================================================================================================================#
 
#============================|DATABASES|=======================================================================================================================#
#--------------------------------------|MYSQL|-----------------------------------------------------------------------------------------------------------------#
#---//MySQL is a relational database management system.//------------------------------------------------------------------------------------------------------#

mysql::server::package_ensure: 'installed' #·
mysql::server::root_password: "ooy5ieneePahnei"
mysql::server::manage_config_file: true
mysql::server::service_name: 'mysql' # required for puppet module
mysql::server::override_options:
  'mysqld':
    'bind-address': '*'

        "userName": "",
        "password": "",
        "databaseName": "",

mysql::server::db:
  "hostname":
    user: ""
    password: ""
    host: "%"
    grant:
      - "ALL"

#-------------------------------------|ELASTICSEARCH|----------------------------------------------------------------------------------------------------------#
#---//Elasticsearch is a search engine based on Lucene. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface //---#
#---//and schema-free JSON documents.//------------------------------------------------------------------------------------------------------------------------# 

elasticsearch::version: 5.5.1
elasticsearch::manage_repo: true
elasticsearch::repo_version: 5.x
elasticsearch::java_install: false
elasticsearch::restart_on_change: true
elasticsearch_instance:
    'es-01':
      ensure:  'present'

#-------------------------------------|REDIS|------------------------------------------------------------------------------------------------------------------#
#---//Redis is an in-memory database project implementing a distributed, in-memory key-value store with optional durability.//---------------------------------#

redis::bind: 0.0.0.0

#-------------------------------------|ZOOKEPER|---------------------------------------------------------------------------------------------------------------#
#---//Zooker is a centralized service for distributed systems to a hierarchical key-value store, which is used to provide a distributed configuration//--------#
#---//service, synchronization service, and naming registry for large distributed systems.//-------------------------------------------------------------------#

zookeeper::init_limit: '1000'
zookeeper::id: '1'
zookeeper::purge_interval: '1'
zookeeper::servers:
  - "%{lookup('host')}"

#-------------------------------------|POSTGRES|---------------------------------------------------------------------------------------------------------------#
#---//Postgres, is an object-relational database management system  with an emphasis on extensibility and standards compliance. As a database server,//--------#
#---//its primary functions are to store data securely and return that data in response to requests from other software applications.//------------------------#

postgresql::server::postgres_password: 
postgresql::server::ip_mask_allow_all_users: '0.0.0.0/0'

postgresql::postgresql::server:
  ip_mask_allow_all_users: '0.0.0.0/32'

postgres_db:
  master:
    user: 
    password: 
  confluence:
    user: 
    password: 
postgres_config:
    'max_connections':
       value: 300

postgres_hba:
    'Allow locals without password':
        order: 1
        description: 'locals postgres no password'
        type: 'host'
        address: '127.0.0.1/32'
        database: 'all'
        user: 'all'
        auth_method: 'trust'  

#----------------------------------------------|PGBOUNCER|-----------------------------------------------------------------------------------------------------#
#---//PgBouncer is a connection pooler for PostgreSQL//--------------------------------------------------------------------------------------------------------#

pgbouncer::group: postgres
pgbouncer::user: postgres
pgbouncer::userlist:
   - user:  
     password: 

pgbouncer::databases:
   - source_db: recommender
     host: "%{lookup('')}"
     dest_db: recommender
     auth_user: recommender
     pool_size: 200
     auth_pass: 
   - source_db: master
     host: "%{lookup('')}"
     dest_db: recommender
     auth_user: recommender
     pool_size: 50
     auth_pass: 
   - source_db: slave
     host: "%{lookup('')}"
     dest_db: recommender
     auth_user: recommender
     pool_size: 200
     auth_pass: 

#==============================================================================================================================================================#

#==============================|APPLICATION SERVICES|==========================================================================================================#
#---------------------------------------------------|CONFLUENCE|-----------------------------------------------------------------------------------------------#
#---------------------------------------------------|JENKINS|--------------------------------------------------------------------------------------------------#

#==============================================================================================================================================================#










Пример секции мониторинга:
#============================|MONITORING|======================================================================================================================#
#---------------------------------------|ICINGA SERVICES|------------------------------------------------------------------------------------------------------#
#---//Managment of monitoring system.//------------------------------------------------------------------------------------------------------------------------#
 
icinga2_service:    
    '%{::fqdn} virtual host' :
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: '%{::fqdn} virtualhost'
        check_command: 'http'
        vars:
            http_uri: /
            http_ssl: true
            http_vhost: 'hostname'
            http_address: "%{lookup('host_address')}"
     
    '%{::fqdn} nginx status' :
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        command_endpoint: '%{::fqdn}'
        display_name: 'nginx status'
        check_command: 'nginx_status'
        vars:
            nginx_status_host_address: localhost
            nginx_status_servername: server.com
            nginx_status_critical: '1600,60,30'
            nginx_status_warn: '1500,55,25'
    
    '%{::fqdn} redis':
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: 'Redis'
        command_endpoint: '%{::fqdn}'
        check_command: "redis"
        vars:
            redis_hostname: localhost
            redis_port: 6379
            redis_perfvars: '*'
 
#==============================================================================================================================================================#
Общая схема работы такой схемы заключается всего лишь в двух простых действиях:

1. Запускаем puppet на хосте — хост видит проверки, которые ему принадлежат и экспортирует их в puppetDB.
2. Запускаем puppet в контейнере icinga2 — проверки из puppetdb превращаются в реальные конфиги Icinga2.


Тут многие скажут: «А зачем мне всё это городить, если я могу поднять обычную icinga2 и добавлять проверки руками или через веб-интерфейс?»

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


Обозначим основные плюсы:
Посмотрим на вот такой шаблон:
icinga2_service:
    '%{::fqdn} disk service':
        target: /etc/icinga2/zones.d/master/%{::fqdn}.conf
        apply: true
        assign: [ 'host.name == %{::fqdn}' ]
        display_name: 'Disk usage'
        command_endpoint: '%{::fqdn}'
        check_command: 'disk'
        vars:
          #All disks
          disk_all: true
          disk_exclude_type:
            - aufs
            - tmpfs
          disk_ignore_ereg_path:
            - /run/docker/*
            - /sys/*
            - /var/lib/docker*
            - /var/lib/ureadahead/debugfs/*
            - /run/user/*
+ 1. Этот шаблон встречается в Hiera только один раз и применяется ко всем хостам в таком виде — т.е. он универсальный. Конфиги на сервере Icinga2, для данного сервиса, будут созданы автоматически для каждого хоста в нашей системе. К тому же, произойдёт создание самих конфигов хостов, ключей, зон и прочей радости.
+ 2. Нам не нужно помнить, добавили мы проверки или нет. Если паппет на хосте был запущен — стандартный набор проверок для этого хоста сгененрирован в нашей системе мониторинга.
+ 3. Мы не переживаем о бекапах нашей системы мониторинга, т.к. все проверки у нас генерируются паппет сервером и даже при полной потере всех конфигов на сервере Icinga2 их можно будет легко восстановить, запустив puppet на сервере Icinga2.
+ 4. Так так все проверки у нас храняться в единой базе puppetDB мы можем создавать довольно мощные сценарии для дальнейшей автоматизации, в которых будем эту информацию использовать.

Итак, поехали:

1. Настроим puppet.

Надеюсь у вас есть настроенный docker и docker-compose. Если нет, то их необходимо установить:
Установка Docker...
Установка Docker-compose...

2. Склонируем репозиторий к себе на сервер:

git clone http://git.comgress64.com/external/puppet-icinga2-how-to.git

3. Откроем docker-compose.yaml любимым редактором и посмотрим на него.

Мы видим, что в данной пачке у нас поднимается сразу несколько контейнеров — PuppetServer, PuppetDb, PostgreSQL сервер и PuppetBoard. Так же монтируются volumes из текущей директории. Не для всех эта конфигурация является оптимальной, поэтому учитывайте свою инфраструктуру. У кого-то уже есть PostgreSQL сервер, кто-то хочет хранить код на другом разделе — тут свобода для творчества. На данном этапе я предлагаю оставить шаблон по умолчанию — к нему всегда можно будет вернуться позже. Поднимем нашу пачку контейнеров и посмотрим, что у нас вышло:


4. Запустим контейнер Puppet, Postgres, Puppetdb и Graphite.

#Запустим контейнер Puppet, Postgres, Puppetdb и Graphite
cd puppet-icinga2-how-to
docker-compose up -d puppet puppetdb-postgres puppetdb graphite  && docker-compose logs -f
Сейчас у нас загрузилось несколько образов и запустились контейнеры, создались базы данных в PostgreSQL. Дождемся, пока все серверы будут запущены — ошибки можно игнорировать, т.к. они через какое-то время должны стабилизироваться. Жмём Ctrl+C, чтобы выйти из режима просмотра логов.

5. Проверим работу нашего puppet master:

docker run --hostname test.test --net puppeticinga2howto_default --link puppet:puppet puppet/puppet-agent

6. Если все ок, вы увидите вот такой вывод:

Notice: Applied catalog in 0.03 seconds
Changes:
            Total: 1
Events:
          Success: 1
            Total: 1
Resources:
          Changed: 1
      Out of sync: 1
            Total: 8
Time:
         Schedule: 0.00
             File: 0.00
   Transaction evaluation: 0.01
   Catalog application: 0.03
   Convert catalog: 0.04
   Config retrieval: 0.45
   Node retrieval: 1.38
         Last run: 1532605377
   Fact generation: 2.24
      Plugin sync: 4.50
       Filebucket: 0.00
            Total: 8.65
Version:
           Config: 1532605376
           Puppet: 5.5.1


Настроим cервер Icinga2.

7. Сделаем образ из Dockerfile, выполнив:

docker-compose build icinga

8. Запустим контейнер, в котором у нас будет жить сервер Icinga2.

docker-compose up -d icinga

9. Пока что у нас контейнер пустой. Давайте настроим icinga2 сервер при помощи нашего Puppet сервера, выполнив:

#Сгенерируем модули для puppet запустив librarian-puppet в контейнере puppet
docker-compose exec puppet bash -c 'cd /etc/puppetlabs/code && gem install librarian-puppet && librarian-puppet install --verbose'
#Запускаем Puppet в контейнере Icinga для первичной конфигурации контейнера
docker-compose exec icinga puppet agent --server puppet --waitforcert 60 --test

10. Установится и сконфигурируется Icinga, Icingaweb2 и Apache

Ваш сервер Icinga2 готов!


Icingaweb2

1. Давайте посмотрим, что у нас получилось. Удобно смотреть на состояние системы мониторинга в браузере, выполним:
Откроем в браузере http://ip_адресс_вашего_хоста:8081/icingaweb2 и зайдём в Icinga c дефолтным логином — icingaadmin/icinga

Видим вот такую картинку:

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

Графики тоже работают:

У нас есть рабочая веб-среда для Icinga2, но пока ещё нет ни одного хоста, кроме самого контейнера icinga2, подключённого к Icinga. Давайте подключим наш первый хост.
2. Подключим новый хост в систему мониторинга.
Сейчас у нас к icinga2 подключен только один хост - сама Icinga. Давайте подключим ещё один.
Показываю на примере в докере, но всё тоже самое будет работать и на голом железе:

Для начала нужно подготовить шаблон и дать некоторую информацию о хосте для puppet:

#Переходим в директорию шаблонов
cd puppet-icinga2-how-to/code/environments/production/hieradata/nodes
#Копируем шаблон с новым именем(должен называться именем хоста)
cp template.yaml example.com.yaml
#Открываем новый фаил любимым редактором и меняем переменные:
host_address: 172.18.0.7
my_company: COMGRESS64
my_package_manager: apt
my_ssh_port: 22
#Сохраняем фаил и выходим

Запустим образ докера. Тут самое главное поставить ему hostname такой же как у фаила шаблона, который мы только что создали:

docker run --hostname example.com --rm -t --link puppet:puppet --net puppeticinga2howto_default -i phusion/baseimage:latest /sbin/my_init -- bash -l

Установим puppet на нашем хосте:

apt-get update && apt-get install -y ruby make gcc perl-modules && gem install --no-ri --no-rdoc puppet

Запускаем puppet:

puppet agent --server puppet --waitforcert 60 --test

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

docker-compose exec icinga puppet agent --server puppet --waitforcert 60 --test

Смотрим через браузер, что у нас получилось:

Проверки добавились и ожидают выполнения.

Через 5 минут:

Таким же образом добавляются все остальные хосты в систему. Хочу обратить ваше внимание, что данное руководство является доказательством концепта и не может быть использовано в среде production без доработок.

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

Спасибо за внимание!


Здесь можно задать вопрос: comgress64.com
Ссылки на материал:
https://github.com/Icinga/puppet-icinga2
https://forge.puppet.com/icinga/icingaweb2
https://docs.docker.com/
https://docs.puppet.com/
https://docs.puppet.com/hiera/
  • No labels