Helo semua.
Saya seorang pentadbir sistem Linux, saya berpindah dari Rusia ke Australia dengan visa profesional bebas pada tahun 2015, tetapi artikel itu tidak akan mengenai cara memulakan traktor untuk babi. Artikel sedemikian sudah cukup (namun, jika ada minat, saya akan menulis tentang ini juga), jadi saya ingin bercakap tentang bagaimana, di tempat kerja saya di Australia sebagai jurutera linux-ops, saya memulakan penghijrahan dari satu pemantauan sistem kepada yang lain. Khususnya - Nagios => Icinga2.
Artikel ini sebahagiannya teknikal dan sebahagian lagi mengenai komunikasi dengan orang ramai dan masalah yang berkaitan dengan perbezaan dalam budaya dan kaedah kerja.
Malangnya, teg "kod" tidak menyerlahkan kod Boneka dan yaml, jadi saya terpaksa menggunakan "teks biasa".
Tiada tanda-tanda masalah pada pagi 21 Disember 2016. Seperti biasa, saya membaca Habr oleh pengguna tanpa nama yang tidak berdaftar pada setengah jam pertama hari bekerja, sambil minum kopi, dan terjumpa .
Memandangkan syarikat saya menggunakan Nagios, tanpa berfikir dua kali, saya mencipta tiket di Redmine dan menghantar pautan ke sembang umum, kerana saya menganggapnya penting. Inisiatif ini boleh dihukum walaupun di Australia, jadi jurutera utama meletakkan masalah itu pada saya sejak saya menemuinya.
Tangkapan skrin daripada Redmine
Di jabatan kami, sebelum menyatakan pendapat anda, adalah kebiasaan untuk menawarkan sekurang-kurangnya satu alternatif, walaupun pilihannya jelas, jadi saya mulakan dengan mencari jenis sistem pemantauan yang relevan pada masa ini, kerana di Rusia di tempat kerja terakhir saya, saya mempunyai sistem tulisan sendiri saya sendiri, sangat primitif, tetapi cukup berfungsi dan melaksanakan semua tugas yang diberikan kepadanya. Python, Politeknik St. Petersburg dan peraturan metro. Tidak, kereta bawah tanah menyebalkan. Ini adalah peribadi (11 tahun bekerja) dan layak untuk artikel berasingan, tetapi bukan sekarang.
Sedikit tentang peraturan untuk membuat perubahan pada konfigurasi infrastruktur di tempat saya sekarang. Kami menggunakan Puppet, Gitlab dan Infrastruktur sebagai prinsip Kod, jadi:
- Tiada perubahan manual melalui SSH dengan menukar mana-mana fail secara manual pada mesin maya. Selama tiga tahun bekerja, saya dipukul dengan topi untuk ini berkali-kali, kali terakhir adalah seminggu yang lalu dan saya tidak fikir itu adalah kali terakhir. Nah, benar - betulkan satu baris dalam konfigurasi, mulakan semula perkhidmatan dan lihat jika masalah itu diselesaikan - 10 saat. Buat cawangan baharu dalam Gitlab, tolak perubahan, tunggu r10k berfungsi pada Puppetmaster, jalankan Puppet -environment=mybranch dan tunggu beberapa minit lagi sehingga semuanya berfungsi - minimum 5 minit.
- Sebarang perubahan dibuat dengan membuat Permintaan Gabungan dalam Gitlab dan mesti diluluskan oleh sekurang-kurangnya seorang ahli pasukan. Perubahan besar yang diputuskan oleh ketua pasukan memerlukan dua atau tiga kelulusan.
- Semua perubahan adalah teks dalam satu cara atau yang lain (memandangkan manifes Boneka, skrip dan data Hiera adalah teks), perduaan amat tidak digalakkan dan perlu ada sebab yang kukuh untuk meluluskan fail tersebut.
Jadi, pilihan yang saya pertimbangkan:
- Munin - jika terdapat lebih daripada 10 pelayan dalam infrastruktur, pentadbiran berubah menjadi neraka (dari . Saya tidak mempunyai keinginan khusus untuk menyemak ini, jadi saya mengambil kata-katanya untuk itu).
- Zabbix - Saya telah melihatnya untuk masa yang lama, di Rusia, tetapi kemudian ia berlebihan untuk tugas saya. Di sini - terpaksa dibuang kerana penggunaan Puppet sebagai pengurus konfigurasi dan Gitlab sebagai sistem kawalan versi. Pada masa itu, setakat yang saya faham, Zabbix menyimpan keseluruhan konfigurasi dalam pangkalan data, dan oleh itu tidak jelas cara mengurus konfigurasi di bawah keadaan semasa dan cara menjejaki perubahan.
- Prometheus adalah apa yang kita akan datang pada akhirnya, berdasarkan mood di jabatan, tetapi pada masa itu saya tidak menguasainya dan tidak dapat menunjukkan sampel yang benar-benar berfungsi (Bukti Konsep), jadi saya terpaksa menolak.
- Terdapat juga beberapa pilihan lain yang sama ada memerlukan kerja semula sistem yang lengkap, atau berada di peringkat awal / ditinggalkan dan ditolak atas sebab yang sama.
Pada akhirnya, saya menetap di Icinga2 kerana tiga sebab:
1 - keserasian dengan Nrpe (perkhidmatan pelanggan yang menjalankan pemeriksaan arahan dari Nagios). Ini sangat penting, kerana pada masa itu kami mempunyai 135 (kini terdapat 2019 pada tahun 165) mesin maya dengan sekumpulan perkhidmatan/semakan bertulis tersuai, dan membuat semula semuanya akan menjadi satu kesakitan yang nyata.
2 - semua fail konfigurasi adalah teks, yang memudahkan untuk mengedit perkara ini, membuat permintaan gabungan dengan keupayaan untuk melihat apa yang telah ditambah atau dipadamkan.
3 ialah projek OpenSource yang masih hidup dan sedang dibangunkan. Kami sangat menyukai OpenSource dan membuat setiap sumbangan yang mungkin kepadanya dengan mencipta Permintaan Tarik dan Isu untuk menyelesaikan masalah.
Jadi, mari kita pergi, Icinga2.
Perkara pertama yang perlu saya hadapi ialah inersia rakan sekerja saya. Semua orang sudah biasa dengan Nagios/Naggios (walaupun di sini mereka tidak dapat berkompromi tentang cara menyebutnya) dan antara muka CheckMK. Antara muka icinga kelihatan berbeza sama sekali (ini adalah tolak), tetapi adalah mungkin untuk menyesuaikan secara fleksibel apa yang anda perlukan untuk melihat menggunakan penapis untuk mana-mana parameter secara literal (ini adalah tambahan, tetapi saya banyak berjuang untuk itu).
Penapis
Anggarkan nisbah saiz bar skrol kepada saiz medan skrol.
Kedua, semua orang biasa melihat keseluruhan infrastruktur pada satu monitor, kerana CheckMk membolehkan anda bekerja dengan beberapa hos Nagios, tetapi antara muka Icinga tidak dapat melakukan ini (sebenarnya, ia boleh, tetapi lebih banyak lagi di bawah). Alternatifnya ialah sesuatu yang dipanggil Thruk, tetapi reka bentuknya membuatkan semua orang di dalam pasukan terkedu kecuali seorang—orang yang mencadangkannya (bukan saya).
Ke dalam relau Thruk - keputusan sebulat suara pasukan
Selepas beberapa hari sumbang saran, saya mencadangkan idea pemantauan kluster, apabila terdapat satu hos induk dalam zon pengeluaran dan dua hamba - satu dalam dev/test dan satu hos luaran terletak di penyedia lain untuk memantau kami perkhidmatan dari sudut pandangan pelanggan atau pemerhati luar. Konfigurasi ini memungkinkan untuk melihat semua masalah dalam satu antara muka web dan berfungsi dengan baik, tetapi Puppet... Masalah dengan Puppet ialah hos induk kini perlu mengetahui tentang semua hos dan perkhidmatan/semakan dalam sistem dan mempunyai untuk mengedarkannya antara zon (ujian dev, prod pementasan, ext), tetapi menghantar perubahan melalui API Icinga mengambil masa beberapa saat, tetapi menyusun direktori Boneka semua perkhidmatan untuk semua hos mengambil masa beberapa minit. Ini masih dipersalahkan kepada saya, walaupun saya telah menjelaskan beberapa kali bagaimana semuanya berfungsi dan mengapa semuanya mengambil masa yang lama.
Ketiga, terdapat sekumpulan SnowFlakes - perkara yang menonjol daripada sistem umum kerana ia mempunyai sesuatu yang istimewa, jadi peraturan am tidak terpakai kepada mereka. Ia telah diselesaikan dengan serangan hadapan - jika terdapat penggera, tetapi sebenarnya semuanya teratur, maka saya perlu menggali lebih dalam dan memikirkan mengapa ia memberi amaran kepada saya, walaupun tidak sepatutnya. Atau sebaliknya - mengapa Nagios panik, tetapi Icinga tidak.
Keempat, Nagios bekerja di sini sebelum saya selama tiga tahun dan pada mulanya terdapat lebih banyak kepercayaan kepadanya berbanding sistem hipster baharu saya, jadi setiap kali Icinga menimbulkan panik, tiada siapa yang melakukan apa-apa sehingga Nagios teruja dengan isu yang sama. Tetapi sangat jarang Icinga menghasilkan penggera sebenar lebih awal daripada Nagios dan saya menganggap ini sebagai masalah serius, yang akan saya bincangkan dalam bahagian "Kesimpulan".
Akibatnya, pentauliahan telah ditangguhkan selama lebih daripada 5 bulan (dirancang pada 28 Jun 2018, sebenarnya - 3 Disember 2018), terutamanya disebabkan oleh "semakan pariti" - omong kosong itu apabila terdapat beberapa perkhidmatan di Nagios yang tiada siapa tahu kira-kira tidak mendengar apa-apa selama beberapa tahun kebelakangan ini, tetapi SEKARANG mereka mengkritik tanpa sebab dan saya terpaksa menjelaskan mengapa mereka tidak berada dalam panel saya dan terpaksa menambahkannya ke Icinga supaya "semakan pariti adalah lengkap" (Semua perkhidmatan/cek di Nagios sepadan dengan perkhidmatan/cek di Icinga)
Pelaksanaan:
Yang pertama ialah perang Kod vs Data, seperti Gaya Boneka. Semua data, semuanya, mesti ada dalam Hiera dan tiada yang lain. Semua kod ada dalam fail .pp. Pembolehubah, abstraksi, fungsi - semuanya berlaku dalam ms.
Akibatnya, kami mempunyai sekumpulan mesin maya (165 pada masa penulisan) dan 68 aplikasi web yang perlu dipantau untuk prestasi dan kesahihan sijil SSL. Tetapi disebabkan oleh buasir sejarah, maklumat untuk aplikasi pemantauan diambil daripada repositori gitlab yang berasingan dan format data tidak berubah sejak Boneka 3, yang mewujudkan kerumitan tambahan dalam konfigurasi.
Kod boneka untuk aplikasi, lindungi mata anda
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
}
}
}
}
}
}
}
}Kod konfigurasi untuk hos dan perkhidmatan juga kelihatan 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 mengusahakan mi ini dan menambah baiknya sebaik mungkin. Walau bagaimanapun, kod inilah yang membolehkan kami menggunakan sintaks yang mudah dan mudah difahami dalam 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 semakan dibahagikan kepada kumpulan, setiap kumpulan mempunyai tetapan lalai seperti di mana dan berapa kerap untuk menjalankan semakan ini, pemberitahuan apa yang perlu dihantar dan kepada siapa.
Dalam setiap semakan, anda boleh mengatasi sebarang pilihan, dan semua ini akhirnya menambah tetapan lalai semua semakan secara keseluruhan. Itulah sebabnya karut seperti itu ditulis dalam config.pp - ia menggabungkan semua tetapan lalai dengan tetapan kumpulan dan kemudian dengan setiap semakan individu.
Satu lagi perubahan yang sangat penting ialah keupayaan untuk menggunakan fungsi dalam tetapan, contohnya, fungsi menggantikan port, alamat dan url untuk menyemak 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: trueIni bermakna - jika terdapat pembolehubah dalam definisi hos http_port — gunakannya, jika tidak 443. Contohnya, antara muka web jabber digantung pada 9090, dan Unifi digantung pada 7443.
http_vhost bermakna abaikan DNS dan ambil alamat ini.
Jika uri dinyatakan dalam hos, kemudian ikuti, jika tidak, ambil "/".
Satu cerita lucu keluar dengan http_ssl - jangkitan ini tidak mahu memutuskan sambungan atas permintaan. Saya keliru tentang baris ini untuk masa yang lama sehingga saya sedar bahawa pembolehubah dalam definisi hos ialah:
http_ssl: falseDigantikan kepada ekspresi
if(host.vars.http_ssl) { return false } else { return true }sebagai palsu dan akhirnya ternyata
if(false) { return false } else { return true }iaitu semakan ssl sentiasa aktif. Saya menyelesaikannya dengan menggantikan sintaks:
http_ssl: noPenemuan:
Kelebihan:
- Kami kini mempunyai satu sistem pemantauan, dan bukan dua, seperti yang kami ada selama 7-8 bulan yang lalu, atau sistem yang sudah lapuk dan terdedah.
- Struktur data hos/perkhidmatan(menyemak) kini (pada pendapat saya) lebih mudah dibaca dan difahami. Bagi yang lain, ini ternyata tidak begitu jelas, jadi saya terpaksa menyiarkan beberapa halaman di wiki tempatan untuk menerangkan cara semuanya berfungsi dan perkara yang perlu diedit di mana.
- Adalah mungkin untuk mengkonfigurasi semakan secara fleksibel menggunakan pembolehubah dan fungsi, sebagai contoh, untuk menyemak http_regexp, corak yang dikehendaki, kod pulangan, url dan port boleh ditetapkan dalam tetapan hos.
- Terdapat beberapa papan pemuka, untuk setiap satunya anda boleh menentukan senarai penggera anda sendiri yang dipaparkan dan mengurus semua ini melalui Boneka dan permintaan gabungan.
Cons:
- Inersia ahli pasukan - Nagios bekerja, bekerja dan bekerja, dan Isinga anda ini sentiasa buggy dan lambat. Bagaimana anda boleh melihat sejarah di sini? Oh, sial, ia tidak dikemas kini... (Masalah sebenar ialah sejarah penggera tidak dikemas kini secara automatik, hanya oleh F5)
- Inersia sistem - apabila saya mengklik pada "kemas kini" (semak sekarang) dalam antara muka web - hasil pelaksanaan bergantung pada cuaca di Marikh, terutamanya pada perkhidmatan kompleks yang memerlukan berpuluh-puluh saat untuk dilaksanakan. Keputusan sedemikian adalah normal.

- Secara umum, mengikut statistik enam bulan operasi kedua-dua sistem secara bersebelahan, Nagios sentiasa bekerja lebih cepat daripada Icinga dan ini benar-benar menjengkelkan saya. Nampaknya saya telah mengacaukan sesuatu dengan pemasa dan pemeriksaan dilakukan setiap lima minit, malah ia berlaku setiap 5:30 atau sesuatu seperti itu.
- Jika anda memulakan semula perkhidmatan pada bila-bila masa (systemctl restart icinga2) - semua pemeriksaan yang sedang dijalankan pada masa itu akan menjana penggera kritikal pada skrin dan dari luar ia kelihatan seolah-olah semuanya telah jatuh ().
Tetapi secara keseluruhan, ia berfungsi.
Sumber: www.habr.com

