Bermigrasi dari Nagios ke Icinga2 di Australia

Halo semuanya.


Saya adalah sysadmin linux, saya pindah dari Rusia ke Australia dengan visa profesional independen pada tahun 2015, tetapi artikelnya tidak akan mengenai cara mendapatkan anak babi traktor. Artikel-artikel seperti itu sudah cukup (namun, jika ada minat, saya akan menulis tentang itu juga), jadi saya ingin berbicara tentang bagaimana, di tempat kerja saya di Australia sebagai insinyur linux-ops, saya memulai migrasi dari satu sistem pemantauan ke yang lain. Khususnya - Nagios => Icinga2.


Artikel ini sebagian teknis dan sebagian tentang komunikasi dengan orang-orang dan masalah yang terkait dengan perbedaan budaya dan metode kerja.


Sayangnya, tag "code" tidak menyoroti kode boneka dan yaml, jadi saya harus menggunakan "plaintext".


Tidak ada yang sakit pada pagi hari 21 Desember 2016. Saya, seperti biasa, membaca Habr dengan anonimus yang tidak terdaftar pada setengah jam pertama hari kerja, menyerap kopi dan menemukan artikel ini .


Karena Nagios digunakan di perusahaan saya, tanpa berpikir dua kali, saya membuat tiket di Redmine dan melemparkan tautan ke dalam obrolan umum, karena saya pikir itu penting. Inisiatif ini dapat dihukum bahkan di Australia, jadi insinyur utama menggantung masalah ini pada saya, karena saya menemukannya.


Layar dari Redmine

Di departemen kami, sebelum menetapkan pendapat kami, sudah lazim untuk menawarkan setidaknya satu alternatif, bahkan jika pilihannya sudah jelas, jadi saya mulai dengan googling yang sistem pemantauannya secara umum relevan, karena di Rusia di tempat terakhir saya bekerja, saya memiliki sistem rekaman pribadi saya sendiri, sangat primitif, tapi tetap saja cukup bekerja dan memenuhi semua tugas yang diberikan padanya. Python, Politeknik St. Petersburg dan aturan metro. Tidak, kereta bawah tanah itu payah. Ini bersifat pribadi (11 tahun bekerja) dan layak untuk artikel yang terpisah, tetapi tidak sekarang.


Sedikit tentang aturan untuk membuat perubahan pada konfigurasi infrastruktur di lokasi saya saat ini. Kami menggunakan Wayang, Gitlab dan prinsip Infrastruktur sebagai Kode, sehingga:


  • Tidak ada perubahan manual melalui SSH dengan memodifikasi secara manual file apa pun di mesin virtual. Selama tiga tahun bekerja, saya menerima topi untuk ini berkali-kali, yang terakhir seminggu yang lalu dan saya pikir itu bukan yang terakhir. Sebenarnya, perbaiki satu baris di konfigurasi, restart layanan dan lihat apakah masalahnya telah diselesaikan - 10 detik. Buat cabang baru di Gitlab, dorong perubahan, tunggu r10k bekerja di Puppetmaster, jalankan Puppet --environment = mybranch dan tunggu beberapa menit lagi sampai semua ini berfungsi - minimum 5 menit.
  • Setiap perubahan dilakukan dengan membuat Permintaan Gabung di Gitlab dan Anda harus mendapatkan persetujuan dari setidaknya satu anggota tim. Perubahan besar pada pemimpin tim membutuhkan dua atau tiga persetujuan.
  • Semua perubahan bersifat tekstual dalam satu atau lain cara (karena Puppet memanifestasikan, skrip Hiera dan data adalah teks), biner sangat tidak disarankan, dan diperlukan alasan yang baik untuk menyetujuinya.

Jadi, opsi yang saya lihat adalah:


  • Munin - jika ada lebih dari 10 server di infrastruktur, administrasi berubah menjadi neraka (dari artikel ini . Saya tidak punya banyak keinginan untuk memeriksa ini, jadi saya mengambil kata-kata saya untuk itu).
  • Zabbix - sudah lama mengincar, kembali ke Rusia, tapi kemudian sudah berlebihan untuk tugas saya. Di sini - harus dihapus karena penggunaan Wayang sebagai manajer konfigurasi dan Gitlab sebagai sistem kontrol versi. Pada saat itu, seperti yang saya pahami, Zabbix menyimpan seluruh konfigurasi dalam database, dan karena itu tidak jelas bagaimana mengelola konfigurasi dalam kondisi saat ini dan bagaimana melacak perubahan.
  • Prometheus adalah apa yang akan kita bahas pada akhirnya, menilai dari mood di departemen, tetapi pada saat itu saya tidak bisa menguasainya dan tidak dapat menunjukkan sampel yang benar-benar berfungsi (Bukti Konsep), jadi saya harus menolak.
  • Ada beberapa opsi lain yang membutuhkan perancangan ulang sistem yang lengkap, atau masih dalam masa pertumbuhan / ditinggalkan dan karena alasan yang sama ditolak.

Pada akhirnya, saya memilih Icinga2 karena tiga alasan:


1 - kompatibilitas dengan Nrpe (layanan klien yang menjalankan pemeriksaan perintah dari Nagios). Ini sangat penting, karena pada saat itu kami memiliki 135 (sekarang ada 165 di antaranya pada tahun 2019) mesin virtual dengan banyak layanan / cek yang ditulis sendiri dan mengulang semua ini akan menjadi wasir yang mengerikan.
2 - semua file konfigurasi adalah teks, yang memudahkan untuk mengedit masalah ini, membuat permintaan gabungan dengan kemampuan untuk melihat apa yang telah ditambahkan atau dihapus.
3 adalah proyek OpenSource yang ramai dan terus berkembang. Kami sangat menyukai OpenSource dan memberikan kontribusi yang layak untuk itu dengan membuat Permintaan Tarik dan Masalah untuk menyelesaikan masalah.


Jadi ayo pergi, Icinga2.


Hal pertama yang harus saya hadapi adalah kelembaman rekan-rekan saya. Semua orang terbiasa dengan Nagios / Najios (meskipun bahkan di sini mereka tidak bisa berkompromi tentang cara mengucapkan ini) dan antarmuka CheckMK. Antarmuka icinga terlihat sangat berbeda (itu minus), tetapi dimungkinkan untuk mengkonfigurasi secara fleksibel apa yang perlu Anda lihat dengan filter secara harfiah berdasarkan parameter apa pun (itu adalah nilai tambah, tapi saya memperjuangkannya secara khusus).


Filter

Perkirakan rasio ukuran bilah gulir dengan ukuran bidang gulir.


Kedua, semua orang terbiasa melihat seluruh infrastruktur pada satu monitor, karena CheckMk memungkinkan Anda untuk bekerja dengan beberapa host Nagios, tetapi Icinga tidak tahu bagaimana melakukannya (pada kenyataannya, memang, tetapi lebih pada yang di bawah). Alternatif adalah sesuatu yang disebut Thruk, tetapi desainnya menyebabkan muntah untuk semua anggota tim, kecuali satu - orang yang menyarankannya (bukan saya).


Thruk Firebox - Keputusan Tim dengan suara bulat

Setelah beberapa hari badai otak, saya mengusulkan ide pemantauan cluster, ketika ada satu tuan rumah tuan di zona produksi dan dua bawahan - satu di dev / tes dan satu tuan rumah eksternal yang terletak di penyedia lain untuk memantau layanan kami dari sudut pandang klien atau orang luar pengamat. Konfigurasi ini memungkinkan saya untuk melihat semua masalah dalam satu antarmuka berbasis web dan itu bekerja untuk saya sendiri, tetapi Wayang ... Masalah dengan Wayang adalah bahwa tuan rumah tuan sekarang harus tahu tentang semua host dan layanan / pemeriksaan dalam sistem dan harus mendistribusikannya di antara zona (dev-test, staging-prod, ext), tetapi mengirimkan perubahan melalui API Icinga membutuhkan beberapa detik, tetapi mengkompilasi direktori Wayang dari semua layanan untuk semua host membutuhkan beberapa menit. Ini masih menyalahkan saya, meskipun saya sudah menjelaskan beberapa kali bagaimana semuanya bekerja dan mengapa semuanya begitu lama.


Ketiga - sekelompok SnowFlakes (kepingan salju) - hal-hal yang tersingkir dari sistem umum, karena mereka memiliki sesuatu yang istimewa, sehingga aturan umum tidak berlaku untuk mereka. Itu diputuskan oleh serangan frontal - jika ada alarm, tetapi sebenarnya semuanya beres, maka di sini Anda perlu menggali lebih dalam dan memahami mengapa itu mengingatkan saya, meskipun seharusnya tidak. Atau sebaliknya - mengapa Nagios panik, tetapi Icinga tidak.


Keempat - Nagios bekerja di sini untuk saya selama tiga tahun dan awalnya ada lebih banyak kepercayaan padanya daripada pada sistem hipster bermodel baru saya, jadi setiap kali Icinga menimbulkan kepanikan - tidak ada yang melakukan apa-apa sampai Nagios bersemangat dengan masalah yang sama. Tapi sangat jarang Icinga mengeluarkan alarm nyata lebih awal dari Nagios dan saya menganggap ini sebagai kusen yang serius, yang akan saya bahas di bagian "Kesimpulan".


Akibatnya, komisioning tertunda selama lebih dari 5 bulan (direncanakan pada 28 Juni 2018, pada kenyataannya - 3 Desember 2018), terutama karena "pemeriksaan paritas" - yang omong kosong ketika ada beberapa layanan di Nagios yang tidak ada yang berbicara tentang Saya belum pernah mendengar apa pun selama beberapa tahun terakhir, tetapi SEKARANG mereka tidak mengeluarkan kritikan tanpa alasan dan saya harus menjelaskan mengapa mereka tidak ada di panel saya dan harus menambahkannya ke Icinga ke β€œcek paritas selesai” (Semua layanan / pemeriksaan dalam Nagios sesuai dengan layanan / cek di Icinga)


Implementasi:
Yang pertama adalah perang Kode vs Data, seperti Gaya Wayang. Semua data, di sini semuanya secara umum, harus di Hiera dan tidak ada yang lain. Semua kode dalam file .pp. Variabel, abstraksi, fungsi - semuanya berjalan di hlm.
Akibatnya, kami memiliki banyak mesin virtual (165 pada saat penulisan) dan 68 aplikasi web yang perlu dipantau untuk kesehatan dan validitas sertifikat SSL. Tetapi karena wasir historis, informasi untuk aplikasi pemantauan diambil dari repositori gitlab yang terpisah dan format data tidak berubah sejak Puppet 3, yang menciptakan kesulitan konfigurasi tambahan.


Kode boneka untuk aplikasi, berhati-hatilah
define profiles::services::monitoring::docker_apps( Hash $app_list, Hash $apps_accessible_from, Hash $apps_access_list, Hash $webhost_defaults, Hash $webcheck_defaults, Hash $service_overrides, Hash $targets, Hash $app_checks, ) { #### APPS #### $zone = $name $app_list.each | String $app_name, Hash $app_data | { $notify_group = { 'notify_group' => ($webcheck_defaults[$zone]['notify_group'] + pick($app_data['notify_group'], {} )) } # adds notifications for default group (systems) + any group defined in int/pm_docker_apps.eyaml $data = merge($webhost_defaults, $apps_accessible_from, $app_data) $site_domain = $app_data['site_domain'] $regexp = pick($app_data['check_regex'], 'html') # Pick a regex to check $check_url = $app_data['check_url'] ? { undef => { 'http_uri' => '/' }, default => { 'http_uri' => $app_data['check_url'] } } $check_regex = $regexp ?{ 'absent' => {}, default => {'http_expect_body_regex' => $regexp} } $site_domain.each | String $vhost, Hash $vdata | { # Split an app by domains if there are two or more $vhost_name = {'http_vhost' => $vhost} $vars = $data['vars'] + $vhost_name + $check_regex + $check_url $web_ipaddress = is_array($vdata['web_ipaddress']) ? { # Make IP-address an array if it's not, because askizzy has 2 ips and it's an array true => $vdata['web_ipaddress'], false => [$vdata['web_ipaddress']], } $access_from_zones = [$zone] + $apps_access_list[$data['accessible_from']] # Merge default zone (where the app is defined) and extra zones if they exist $web_ipaddress.each | String $ip_address | { # For each IP (if we have multiple) $suffix = length($web_ipaddress) ? { # If we have more than one - add IP as a suffix to this hostname to avoid duplicating resources 1 => '', default => "_${ip_address}" } $octets = split($ip_address, '\.') $ip_tag = "${octets[2]}.${octets[3]}" # Using last octet only causes a collision between nginx-vip 203.15.70.94 and ext. ip 49.255.194.94 $access_from_zones.each | $zone_prefix |{ $zone_target = $targets[$zone_prefix] $nginx_vip_name = "${zone_prefix}_nginx-vip-${ip_tag}" # If it's a host for ext - prefix becomes 'ext_' (ext_nginx-vip...) $nginx_host_vip = { $nginx_vip_name => { ensure => present, target => $zone_target, address => $ip_address, check_command => 'hostalive', groups => ['nginx_vip',], } } $ssl_vars = $app_checks['ssl'] $regex_vars = $app_checks['http'] + $vars + $webcheck_defaults[$zone] + $notify_group if !defined( Profiles::Services::Monitoring::Host[$nginx_vip_name] ) { ensure_resources('profiles::services::monitoring::host', $nginx_host_vip) } if !defined( Icinga2::Object::Service["${nginx_vip_name}_ssl"] ) { icinga2::object::service {"${nginx_vip_name}_ssl": ensure => $data['ensure'], assign => ["host.name == $nginx_vip_name",], groups => ['webchecks',], check_command => 'ssl', check_interval => $service_overrides['ssl']['check_interval'], target => $targets['services'], apply => true, vars => $ssl_vars } } if $regexp != 'absent'{ if !defined(Icinga2::Object::Service["${vhost}${$suffix} regex"]){ icinga2::object::service {"${vhost}${$suffix} regex": ensure => $data['ensure'], assign => ["match(*_nginx-vip-${ip_tag}, host.name)",], groups => ['webchecks',], check_command => 'http', check_interval => $service_overrides['regex']['check_interval'], target => $targets['services'], enable_flapping => true, apply => true, vars => $regex_vars } } } } } } } } 

Kode konfigurasi host dan layanan juga tampak mengerikan:


pemantauan / config.pp
 class profiles::services::monitoring::config( Array $default_config, Array $hostgroups, Hash $hosts = {}, Hash $host_defaults, Hash $services, Hash $service_defaults, Hash $service_overrides, Hash $webcheck_defaults, Hash $servicegroups, String $servicegroup_target, Hash $user_defaults, Hash $users, Hash $oncall, Hash $usergroup_defaults, Hash $usergroups, Hash $notifications, Hash $notification_defaults, Hash $notification_commands, Hash $timeperiods, Hash $webhost_defaults, Hash $apps_access_list, Hash $check_commands, Hash $hosts_api = {}, Hash $targets = {}, Hash $host_api_defaults = {}, ) { # Profiles::Services::Monitoring::Hostgroup <<| |>> # will be enabled when we move to icinga completely #### APPS #### case $location { 'int', 'ext': { $apps_by_zone = {} } 'pm': { $int_apps = hiera('int_docker_apps') $int_app_defaults = hiera('int_docker_app_common') $st_apps = hiera('staging_docker_apps') $srs_apps = hiera('pm_docker_apps_srs') $pm_apps = hiera('pm_docker_apps') + $st_apps + $srs_apps $pm_app_defaults = hiera('pm_docker_app_common') $apps_by_zone = { 'int' => $int_apps, 'pm' => $pm_apps, } $app_access_by_zone = { 'int' => {'accessible_from' => $int_app_defaults['accessible_from']}, 'pm' => {'accessible_from' => $pm_app_defaults['accessible_from']}, } } default: { fail('Please ensure the node has $location fact set (int, pm, ext)') } } file { '/etc/icinga2/conf.d/': ensure => directory, recurse => true, purge => true, owner => 'icinga', group => 'icinga', mode => '0750', notify => Service['icinga2'], } $default_config.each | String $file_name |{ file {"/etc/icinga2/conf.d/${file_name}": ensure => present, source => "puppet:///modules/profiles/services/monitoring/default_config/${file_name}", owner => 'icinga', group => 'icinga', mode => '0640', } } $app_checks = { 'ssl' => $services['webchecks']['checks']['ssl']['vars'], 'http' => $services['webchecks']['checks']['http_regexp']['vars'] } $apps_by_zone.each | String $zone, Hash $app_list | { profiles::services::monitoring::docker_apps{$zone: app_list => $app_list, apps_accessible_from => $app_access_by_zone[$zone], apps_access_list => $apps_access_list, webhost_defaults => $webhost_defaults, webcheck_defaults => $webcheck_defaults, service_overrides => $service_overrides, targets => $targets, app_checks => $app_checks, } } #### HOSTS #### # Profiles::Services::Monitoring::Host <<| |>> # This is for spaceship invasion when it's ready. $hosts_has_large_disks = query_nodes('mountpoints.*.size_bytes >= 1099511627776') $hosts.each | String $hostgroup, Hash $list_of_hosts_with_settings | { # Splitting site lists by hostgroups - docker_host/gluster_host/etc $list_of_hosts_in_group = $list_of_hosts_with_settings['hosts'] $hostgroup_settings = $list_of_hosts_with_settings['settings'] $merged_hostgroup_settings = deep_merge($host_defaults, $list_of_hosts_with_settings['settings']) $list_of_hosts_in_group.each | String $host_name, Hash $host_settings |{ # Splitting grouplists by hosts # Is this host in the array $hosts_has_large_disks ? If so set host.vars.has_large_disks if ( $hosts_has_large_disks.reduce(false) | $found, $value| { ( $value =~ "^${host_name}" ) or $found } ) { $vars_has_large_disks = { 'has_large_disks' => true } } else { $vars_has_large_disks = {} } $host_data = deep_merge($merged_hostgroup_settings, $host_settings) $hostgroup_settings_vars = pick($hostgroup_settings['vars'], {}) $host_settings_vars = pick($host_settings['vars'], {}) $host_notify_group = delete_undef_values($host_defaults['vars']['notify_group'] + $hostgroup_settings_vars['notify_group'] + $host_settings_vars['notify_group']) $host_data_vars = delete_undef_values(deep_merge($host_data['vars'] , {'notify_group' => $host_notify_group}, $vars_has_large_disks)) # Merging vars separately $hostgroups = delete_undef_values([$hostgroup] + $host_data['groups']) profiles::services::monitoring::host{$host_name: ensure => $host_data['ensure'], display_name => $host_data['display_name'], address => $host_data['address'], groups => $hostgroups, target => $host_data['target'], check_command => $host_data['check_command'], check_interval => $host_data['check_interval'], max_check_attempts => $host_data['max_check_attempts'], vars => $host_data_vars, template => $host_data['template'], } } } if !empty($hosts_api){ # All hosts managed by API $hosts_api.each | String $zone, Hash $hosts_api_zone | { # Split api hosts by zones $hosts_api_zone.each | String $hostgroup, Hash $list_of_hosts_with_settings | { # Splitting site lists by hostgroups - docker_host/gluster_host/etc $list_of_hosts_in_group = $list_of_hosts_with_settings['hosts'] $hostgroup_settings = $list_of_hosts_with_settings['settings'] $merged_hostgroup_settings = deep_merge($host_api_defaults, $list_of_hosts_with_settings['settings']) $list_of_hosts_in_group.each | String $host_name, Hash $host_settings |{ # Splitting grouplists by hosts # Is this host in the array $hosts_has_large_disks ? If so set host.vars.has_large_disks if ( $hosts_has_large_disks.reduce(false) | $found, $value| { ( $value =~ "^${host_name}" ) or $found } ) { $vars_has_large_disks = { 'has_large_disks' => true } } else { $vars_has_large_disks = {} } $host_data = deep_merge($merged_hostgroup_settings, $host_settings) $hostgroup_settings_vars = pick($hostgroup_settings['vars'], {}) $host_settings_vars = pick($host_settings['vars'], {}) $host_api_notify_group = delete_undef_values($host_defaults['vars']['notify_group'] + $hostgroup_settings_vars['notify_group'] + $host_settings_vars['notify_group']) $host_data_vars = delete_undef_values(deep_merge($host_data['vars'] , {'notify_group' => $host_api_notify_group}, $vars_has_large_disks)) $hostgroups = delete_undef_values([$hostgroup] + $host_data['groups']) if defined(Profiles::Services::Monitoring::Host[$host_name]){ $hostname = "${host_name}_from_${zone}" } else { $hostname = $host_name } profiles::services::monitoring::host{$hostname: ensure => $host_data['ensure'], display_name => $host_data['display_name'], address => $host_data['address'], groups => $hostgroups, target => "${host_data['target_base']}/${zone}/hosts.conf", check_command => $host_data['check_command'], check_interval => $host_data['check_interval'], max_check_attempts => $host_data['max_check_attempts'], vars => $host_data_vars, template => $host_data['template'], } } } } } #### END OF HOSTS #### #### SERVICES #### $services.each | String $service_group, Hash $s_list |{ # Service_group and list of services in that group $service_list = $s_list['checks'] # List of actual checks, separately from SG settings $service_list.each | String $service_name, Hash $data |{ $merged_defaults = merge($service_defaults, $s_list['settings']) # global service defaults + service group defaults $merged_data = merge($merged_defaults, $data) $settings_vars = pick($s_list['settings']['vars'], {}) $this_service_vars = pick($data['vars'], {}) $all_service_vars = delete_undef_values($service_defaults['vars'] + $settings_vars + $this_service_vars) # If we override default check_timeout, but not nrpe_timeout, make nrpe_timeout the same as check_timeout if ( $merged_data['check_timeout'] and ! $this_service_vars['nrpe_timeout'] ) { # NB: Icinga will convert 1m to 60 automatically! $nrpe = { 'nrpe_timeout' => $merged_data['check_timeout'] } } else { $nrpe = {} } # By default we use nrpe and all commands are run via nrpe. So vars.nrpe_command = $service_name is a default value # If it's server-side Icinga command - we don't need 'nrpe_command' # but there is no harm to have that var and the code is shorter if $merged_data['check_command'] == 'nrpe'{ $check_command = $merged_data['vars']['nrpe_command'] ? { undef => { 'nrpe_command' => $service_name }, default => { 'nrpe_command' => $merged_data['vars']['nrpe_command'] } } }else{ $check_command = {} } # Assembling $vars from Global Default service settings, servicegroup settings, this particular check settings and let's not forget nrpe settings. if $all_service_vars['graphite_template'] { $graphite_template = {'check_command' => $all_service_vars['graphite_template']} }else{ $graphite_template = {'check_command' => $service_name} } $service_notify = [] + pick($settings_vars['notify_group'], []) + pick($this_service_vars['notify_group'], []) # pick is required everywhere, otherwise becomes "The value '' cannot be converted to Numeric" $service_notify_group = $service_notify ? { [] => $service_defaults['vars']['notify_group'], default => $service_notify } # Assing default group (systems) if no other groups are defined $vars = $all_service_vars + $nrpe + $check_command + $graphite_template + {'notify_group' => $service_notify_group} # This needs to be merged separately, because merging it as part of MERGED_DATA overwrites arrays instead of merging them, so we lose some "assign" and "ignore" values $assign = delete_undef_values($service_defaults['assign'] + $s_list['settings']['assign'] + $data['assign']) $ignore = delete_undef_values($service_defaults['ignore'] + $s_list['settings']['ignore'] + $data['ignore']) icinga2::object::service {$service_name: ensure => $merged_data['ensure'], apply => $merged_data['apply'], enable_flapping => $merged_data['enable_flapping'], assign => $assign, ignore => $ignore, groups => [$service_group], check_command => $merged_data['check_command'], check_interval => $merged_data['check_interval'], check_timeout => $merged_data['check_timeout'], check_period => $merged_data['check_period'], display_name => $merged_data['display_name'], event_command => $merged_data['event_command'], retry_interval => $merged_data['retry_interval'], max_check_attempts => $merged_data['max_check_attempts'], target => $merged_data['target'], vars => $vars, template => $merged_data['template'], } } } #### END OF SERVICES #### #### OTHER BORING STUFF #### $servicegroups.each | $servicegroup, $description |{ icinga2::object::servicegroup{ $servicegroup: target => $servicegroup_target, display_name => $description } } $hostgroups.each| String $hostgroup |{ profiles::services::monitoring::hostgroup { $hostgroup:} } $notifications.each | String $name, Hash $settings |{ $assign = pick($notification_defaults['assign'], []) + $settings['assign'] $ignore = pick($notification_defaults['ignore'], []) + $settings['ignore'] $merged_settings = $settings + $notification_defaults icinga2::object::notification{$name: target => $merged_settings['target'], apply => $merged_settings['apply'], apply_target => $merged_settings['apply_target'], command => $merged_settings['command'], interval => $merged_settings['interval'], states => $merged_settings['states'], types => $merged_settings['types'], assign => delete_undef_values($assign), ignore => delete_undef_values($ignore), user_groups => $merged_settings['user_groups'], period => $merged_settings['period'], vars => $merged_settings['vars'], } } # Merging notification settings for users with other settings $users_oncall = deep_merge($users, $oncall) # Magic. Do not touch. create_resources('icinga2::object::user', $users_oncall, $user_defaults) create_resources('icinga2::object::usergroup', $usergroups, $usergroup_defaults) create_resources('icinga2::object::timeperiod',$timeperiods) create_resources('icinga2::object::checkcommand', $check_commands) create_resources('icinga2::object::notificationcommand', $notification_commands) profiles::services::sudoers { 'icinga_runs_ping_l2': ensure => present, sudoersd_template => 'profiles/os/redhat/centos7/sudoers/icinga.erb', } } 

Saya masih mengerjakan mie ini dan memperbaikinya sedapat mungkin. Namun, kode inilah yang memungkinkan untuk menggunakan sintaksis sederhana dan jelas di Hiera:


Data
 profiles::services::monitoring::config::services: perf_checks: settings: check_interval: '2m' assign: - 'host.vars.type == linux' checks: procs: {} load: {} memory: {} disk: check_interval: '5m' vars: notification_period: '24x7' disk_iops: vars: notifications: - 'silent' cpu: vars: notifications: - 'silent' dns_fqdn: check_interval: '15m' ignore: - 'xenserver in host.groups' vars: notifications: - 'silent' iftraffic_nrpe: vars: notifications: - 'silent' logging: settings: assign: - 'logserver in host.groups' checks: rsyslog: {} nginx_limit_req_other: {} nginx_limit_req_s2s: {} nginx_limit_req_s2x: {} nginx_limit_req_srs: {} logstash: {} logstash_api: vars: notifications: - 'silent' 

Semua cek dibagi menjadi beberapa grup, setiap grup memiliki pengaturan default seperti di mana dan seberapa sering menjalankan cek ini, pemberitahuan yang dikirim dan kepada siapa.


Dalam setiap pemeriksaan, Anda dapat mengganti opsi apa pun, dan semua ini pada akhirnya menambahkan hingga pengaturan default semua cek secara keseluruhan. Oleh karena itu, mie tersebut ditulis dalam config.pp - ada penggabungan semua pengaturan default dengan pengaturan grup dan kemudian dengan masing-masing individu memeriksa.


Juga, perubahan yang sangat penting adalah kemampuan untuk menggunakan fungsi dalam pengaturan, misalnya, fungsi mengubah port, alamat dan url untuk memeriksa http_regex.


 http_regexp: assign: - 'host.vars.http_regex' - 'static_sites in host.groups' check_command: 'http' check_interval: '1m' retry_interval: '20s' max_check_attempts: 6 http_port: '{{ if(host.vars.http_port) { return host.vars.http_port } else { return 443 } }}' vars: notification_period: 'host.vars.notification_period' http_vhost: '{{ if(host.vars.http_vhost) { return host.vars.http_vhost } else { return host.name } }}' http_ssl: '{{ if(host.vars.http_ssl) { return false } else { return true } }}' http_expect_body_regex: 'host.vars.http_regex' http_uri: '{{ if(host.vars.http_uri) { return host.vars.http_uri } else { return "/" } }}' http_onredirect: 'follow' http_warn_time: 8 http_critical_time: 15 http_timeout: 30 http_sni: true 

Ini berarti - jika ada variabel http_port dalam definisi host - gunakan, jika tidak 443. Misalnya, antarmuka web jabber hang pada 9090, dan Unifi pada 7443.
http_vhost berarti mengabaikan DNS dan mengambil alamat ini.
Jika uri ditentukan di host, maka ikutilah, jika tidak ambil "/".


Sebuah cerita lucu keluar dengan http_ssl - infeksi ini tidak ingin terputus saat diminta. Saya bodoh tersandung pada baris ini untuk waktu yang lama, sampai saya sadar bahwa variabel dalam definisi host:


 http_ssl: false 

Mengganti menjadi ekspresi


 if(host.vars.http_ssl) { return false } else { return true } 

sebagai salah dan pada akhirnya ternyata


 if(false) { return false } else { return true } 

yaitu, pemeriksaan ssl selalu aktif. Diputuskan dengan mengganti sintaks:


 http_ssl: no 

Kesimpulan :


Pro:


  • Kami sekarang memiliki satu sistem pemantauan, dan bukan dua, seperti 7-8 bulan terakhir, atau satu, ketinggalan jaman dan rentan.
  • Struktur data host / layanan (cek) sekarang (menurut saya) jauh lebih mudah dibaca dan dimengerti. Bagi yang lain, ini tidak begitu jelas, jadi saya harus memotong beberapa halaman di wiki lokal untuk menjelaskan cara kerjanya dan di mana untuk mengeditnya.
  • Dimungkinkan untuk mengkonfigurasi pemeriksaan secara fleksibel menggunakan variabel dan fungsi, misalnya, untuk memeriksa http_regexp, pola yang diinginkan, kode pengembalian, url, dan port dapat diatur dalam pengaturan host.
  • Ada beberapa dasbor, untuk masing-masing Anda dapat menentukan daftar alarm yang ditampilkan sendiri dan mengelola semua ini melalui permintaan Wayang dan menggabungkan.

Cons:


  • Kelambanan anggota tim - Nagios bekerja, bekerja, dan bekerja, dan ini Isinga Anda terus-menerus mengganggu dan melambat. Dan bagaimana saya bisa melihat ceritanya? Dan, sialnya, itu tidak diperbarui ... (Masalah sebenarnya adalah riwayat alarm tidak diperbarui secara otomatis, hanya oleh F5)
  • Kelambanan sistem - ketika saya mengklik "periksa sekarang" di antarmuka web - hasil eksekusi tergantung pada cuaca di Mars, terutama pada layanan kompleks yang membutuhkan waktu puluhan detik untuk menyelesaikannya. Hasil serupa adalah hal yang normal.
  • Secara umum, menurut statistik semi-tahunan dari kedua sistem yang bekerja berdampingan, Nagios selalu bekerja lebih cepat daripada Icinga dan itu benar-benar membuatku jengkel. Bagiku ada sesuatu yang dibodohi dengan penghitung waktu dan lima menit pemeriksaan fakta berjalan setiap 5:30 atau sekitar itu.
  • Jika Anda me-restart layanan kapan saja (systemctl restart icinga2) - semua pemeriksaan yang sedang berlangsung pada saat itu akan memicu alarm kritis <diakhiri oleh sinyal 15> di layar dan dari samping itu akan terlihat seolah-olah semuanya telah jatuh ( bug dikonfirmasi) )

Tetapi secara umum - itu berhasil.

Source: https://habr.com/ru/post/id444060/


All Articles