Всем привет.
Мен Linux жүйесінің әкімшісімін, мен Ресейден Австралияға тәуелсіз кәсіби визамен 2015 жылы көшіп келдім, бірақ мақала шошқаға арналған тракторды қалай іске қосу туралы болмайды. Мұндай мақалалар қазірдің өзінде жеткілікті (дегенмен, қызығушылық болса, мен бұл туралы да жазамын), сондықтан мен Австралияда Linux-ops инженері ретінде жұмыс істеген кезде бір жүйе мониторингінен көшуді қалай бастағаным туралы айтқым келеді басқасына. Атап айтқанда - Nagios => Icinga2.
Мақала ішінара техникалық және ішінара адамдармен қарым-қатынас және мәдениет пен жұмыс әдістерінің айырмашылығына байланысты мәселелер туралы.
Өкінішке орай, «код» тегі Қуыршақ және ямл кодын бөлектемейді, сондықтан мен «ашық мәтінді» қолдануға тура келді.
21 жылдың 2016 желтоқсанында таңертең ешқандай қиындық белгілері байқалмады. Әдеттегідей, мен Хабрды тіркелмеген анонимді қолданушының жұмыс күнінің бірінші жарты сағатында кофе ішіп отырып оқып жатқанда, мен кездестім. .
Менің компаниям Nagios-ты пайдаланғандықтан, екі рет ойланбастан, мен Redmine-де билет жасап, сілтемені жалпы чатқа жібердім, өйткені мен оны маңызды деп санадым. Бұл бастама тіпті Австралияда да жазаланады, сондықтан мен оны ашқаннан бері жетекші инженер бұл мәселені маған жүктеді.
Redmine ұсынған скриншот
Біздің бөлімде өз пікіріңізді білдірмес бұрын, таңдау анық болса да, кем дегенде бір балама ұсыну әдетке айналған, сондықтан мен қазіргі уақытта қандай мониторинг жүйелері өзекті екенін Google іздеуден бастадым, өйткені мен Ресейде соңғы жұмыс орнымда болдым. Менің жеке жазған жүйесім болды, өте қарапайым, бірақ соған қарамастан толық жұмыс істеп, оған жүктелген барлық тапсырмаларды орындайды. Python, Санкт-Петербург политехникалық және метро ережесі. Жоқ, метро жаман. Бұл жеке (11 жыл жұмыс) және жеке мақалаға лайық, бірақ қазір емес.
Менің қазіргі орнымдағы инфрақұрылым конфигурациясына өзгерістер енгізу ережелері туралы аздап. Біз Puppet, Gitlab және инфрақұрылымды код принципі ретінде пайдаланамыз, сондықтан:
- Виртуалды машиналардағы кез келген файлдарды қолмен өзгерту арқылы SSH арқылы қолмен өзгертулер болмайды. Үш жыл жұмыс істеген кезде мен бұл үшін шляпамен бірнеше рет соққыға түстім, соңғы рет бір апта бұрын болды және бұл соңғы рет емес деп ойлаймын. Ал, шынымен - конфигурациядағы бір жолды түзетіңіз, қызметті қайта іске қосыңыз және мәселенің шешілгенін көріңіз - 10 секунд. Gitlab-те жаңа филиал жасаңыз, өзгертулерді итеріңіз, r10k Puppetmaster-де жұмыс істеуін күтіңіз, Puppet -environment=mybranch іске қосыңыз және бәрі жұмыс істегенше тағы бірнеше минут күтіңіз - кемінде 5 минут.
- Кез келген өзгертулер Gitlab жүйесінде біріктіру сұрауын жасау арқылы жасалады және кем дегенде бір топ мүшесінің мақұлдауын алуы керек. Топ басшысы шешкен негізгі өзгерістер екі немесе үш мақұлдауды қажет етеді.
- Барлық өзгерістер қандай да бір түрде мәтін болып табылады (өйткені қуыршақ манифесттері, сценарийлер және Hiera деректері мәтін болып табылады), екілік файлдар өте ұнамайды және мұндай файлдарды мақұлдау үшін сенімді себеп болуы керек.
Сонымен, мен қарастырған опциялар:
- Мунин - егер инфрақұрылымда 10-нан астам сервер болса, әкімшілік тозаққа айналады ( . Мен мұны тексергім келмеді, сондықтан мен оның сөзін қабылдадым).
- Заббикс - Мен оны Ресейде бұрыннан қарадым, бірақ ол менің тапсырмаларым үшін артық болды. Мұнда - конфигурация менеджері ретінде Puppet және нұсқаларды басқару жүйесі ретінде Gitlab пайдаланылуына байланысты бас тартуға тура келді. Сол кезде, менің түсінуімше, Zabbix барлық конфигурацияны дерекқорда сақтайды, сондықтан ағымдағы жағдайларда конфигурацияны қалай басқару және өзгерістерді қалай қадағалау керектігі түсініксіз болды.
- Кафедрадағы көңіл-күйге қарап, ақыр соңында біз Прометейге келеміз, бірақ мен оны игермедім және шынымен жұмыс істейтін үлгіні (Тұжырымдаманың дәлелі) көрсете алмадым, сондықтан мен бас тартуға тура келді.
- Сондай-ақ жүйені толығымен қайта өңдеуді қажет ететін немесе олардың бастапқы кезеңінде/тасталған және сол себепті қабылданбаған бірнеше басқа нұсқалар болды.
Ақырында, мен Icinga2-ге үш себеп бойынша қоныстандым:
1 - Nrpe (Nagios пәрмендерін тексеруді іске қосатын клиент қызметі) үйлесімділігі. Бұл өте маңызды болды, өйткені ол кезде бізде тапсырыс бойынша жазылған қызметтері/чектері бар 135 (қазір 2019 жылы 165 бар) виртуалды машиналар болды және оның бәрін қайта жасау нағыз азап болар еді.
2 - барлық конфигурация файлдары мәтін болып табылады, бұл мәселені өңдеуді жеңілдетеді, не қосылғанын немесе жойылғанын көру мүмкіндігімен біріктіру сұрауларын жасайды.
3 - тірі және дамып келе жатқан OpenSource жобасы. Біз OpenSource-ті өте жақсы көреміз және мәселелерді шешу үшін тарту сұраулары мен мәселелерін жасау арқылы оған барлық мүмкін үлесімізді қосамыз.
Ендеше, кеттік, Айсинга2.
Мен бірінші кезекте әріптестерімнің инерциясына тап болдым. Барлығы Nagios/Nagios (бірақ мұнда олар оны қалай айту керектігі туралы ымыраға келе алмағанымен) және CheckMK интерфейсіне үйренген. icinga интерфейсі мүлдем басқаша көрінеді (бұл минус болды), бірақ кез келген параметр үшін сүзгілерді пайдаланып көру керек нәрсені икемді түрде теңшеуге болады (бұл плюс болды, бірақ мен ол үшін көп күрестім).
Сүзгілер
Айналдыру жолағы өлшемі мен айналдыру өрісінің өлшеміне қатынасын бағалаңыз.
Екіншіден, барлығы бір мониторда барлық инфрақұрылымды көруге үйренген, өйткені CheckMk бірнеше Nagios хосттарымен жұмыс істеуге мүмкіндік береді, бірақ Icinga интерфейсі мұны істей алмады (шын мәнінде, мүмкін, бірақ төменде бұл туралы көбірек). Альтернативті нұсқа Thruk деп аталатын нәрсе болды, бірақ оның дизайны командадағылардың барлығын тітіркендірді, біреуінен басқа, оны ұсынған (мен емес).
Thruk пешіне - ұжымның бірауыздан шешімі
Бірнеше күндік миға шабуылдан кейін мен кластерлік мониторинг идеясын ұсындым, бұл кезде өндірістік аймақта бір негізгі хост және екі құл – біреуі әзірлеу/сынақта және бір сыртқы хост басқа провайдерде орналасқан. клиент немесе бөгде бақылаушы көзқарасы бойынша қызметтер. Бұл конфигурация бір веб-интерфейстегі барлық мәселелерді көруге мүмкіндік берді және өте жақсы жұмыс істеді, бірақ Қуыршақ... Қуыршақ проблемасы басты хост енді жүйедегі барлық хосттар мен қызметтер/текстер туралы білуі керек болды. оларды аймақтар арасында тарату үшін (dev-test, staging-prod, ext), бірақ Icinga API арқылы өзгертулерді жіберу бірнеше секундты алады, бірақ барлық хосттар үшін барлық қызметтердің қуыршақ каталогын құрастыру бірнеше минутты алады. Бұл мені әлі күнге дейін кінәлайды, дегенмен мен барлығы қалай жұмыс істейтінін және неге көп уақыт алатынын бірнеше рет түсіндірдім.
Үшіншісі - SnowFlakes шоғыры - жалпы жүйеден ерекшеленетін заттар, өйткені оларда ерекше нәрсе бар, сондықтан жалпы ережелер оларға қолданылмайды. Бұл фронтальды шабуылмен шешілді - егер дабылдар болса, бірақ іс жүзінде бәрі тәртіпте болса, мен тереңірек қазып, неге ол мені ескертетінін түсінуім керек, бірақ олай болмауы керек. Немесе керісінше - неге Нагиос үрейленеді, бірақ Исинга емес.
Төртіншіден, Нагиос менің алдымда үш жыл жұмыс істеді және бастапқыда менің жаңадан шыққан хипстер жүйесіме қарағанда оған көбірек сенім артты, сондықтан Исинга дүрбелең көтерген сайын, Нагиос дәл сол мәселеге толқығанша ешкім ештеңе істемеді. Бірақ Icinga Нагиосқа қарағанда өте сирек нақты дабылдарды жасады және мен бұл туралы «Қорытындылар» бөлімінде айтатын маңызды мәселе деп санаймын.
Нәтижесінде, пайдалануға беру 5 айдан астам уақытқа кешіктірілді (28 жылдың 2018 маусымына жоспарланған, іс жүзінде - 3 жылдың 2018 желтоқсаны), негізінен «паритеттік тексеруге» байланысты - Нагиоста бірнеше қызметтер болған кездегі ақымақтық, олар туралы жоқ. Соңғы екі жыл ішінде ешкім ештеңе естіген жоқ, бірақ ДӘЛ ҚАЗІР олар еш себепсіз сын айтты, мен олардың менің панелімде болмағанын түсіндіруім керек болды және оларды Icinga-ға қосу керек болды, осылайша «паритет тексеру аяқталды» (Нагиостағы барлық қызметтер/чектер Исингадағы қызметтерге/чектерге сәйкес келеді)
Іске асыру:
Біріншісі - қуыршақ стилі сияқты Code vs Data соғысы. Барлық деректер, мүлдем бәрі, Hiera-да болуы керек, басқа ештеңе жоқ. Барлық код .pp файлдарында. Айнымалылар, абстракциялар, функциялар - бәрі pp.
Нәтижесінде бізде көптеген виртуалды машиналар (жазу кезінде 165) және SSL сертификаттарының өнімділігі мен жарамдылығын бақылау қажет 68 веб-қосымшалар бар. Бірақ тарихи геморройға байланысты қолданбаларды бақылауға арналған ақпарат бөлек gitlab репозиторийінен алынады және деректер пішімі Қуыршақ 3-тен бері өзгерген жоқ, бұл конфигурацияда қосымша күрделілікті тудырады.
Қолданбаларға арналған қуыршақ коды, көзіңізді қорғаңыз
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
}
}
}
}
}
}
}
}Хосттар мен қызметтерге арналған конфигурация коды да қорқынышты көрінеді:
monitoring/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',
}
}Мен әлі де осы кеспемен жұмыс істеп жатырмын және оларды мүмкіндігінше жетілдіремін. Дегенмен, дәл осы код бізге Hiera-да қарапайым және түсінікті синтаксисті пайдалануға мүмкіндік берді:
мәліметтер
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'Барлық тексерулер топтарға бөлінген, әр топта бұл тексерулерді қай жерде және қаншалықты жиі орындау, қандай хабарландыруларды жіберу және кімге жіберу сияқты әдепкі параметрлер бар.
Әрбір тексеруде кез келген опцияны қайта анықтауға болады және мұның бәрі сайып келгенде, тұтастай алғанда барлық тексерулердің әдепкі параметрлерін қосады. Сондықтан config.pp файлында мұндай ақымақтық жазылған - ол барлық әдепкі параметрлерді топ параметрлерімен, содан кейін әрбір жеке тексерумен біріктіреді.
Тағы бір өте маңызды өзгеріс параметрлердегі функцияларды пайдалану мүмкіндігі болды, мысалы, http_regex тексеру үшін портты, мекенжайды және URL мекенжайын ауыстыру функциясы.
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Бұл дегеніміз - егер хост анықтамасында айнымалы болса http_port — оны пайдаланыңыз, әйтпесе 443. Мысалы, jabber веб-интерфейсі 9090-да, ал Unifi 7443-те тұрады.
http_vhost DNS-ті елемеу және осы мекенжайды алу дегенді білдіреді.
Егер uri хостта көрсетілсе, оны орындаңыз, әйтпесе «/» таңдаңыз.
http_ssl көмегімен күлкілі оқиға шықты - бұл инфекция сұраныс бойынша ажыратқысы келмеді. Мен хост анықтамасындағы айнымалы мән екенін түсінгенге дейін бұл сызық туралы ұзақ уақыт шатастырдым:
http_ssl: falseӨрнекпен ауыстырылады
if(host.vars.http_ssl) { return false } else { return true }қалай жалған және соңында бұл шығады
if(false) { return false } else { return true }яғни ssl тексеруі әрқашан белсенді. Мен оны синтаксисті ауыстыру арқылы шешдім:
http_ssl: noқорытындылар:
Артықшылықтары:
- Қазір бізде соңғы 7-8 айдағыдай екі емес, бір бақылау жүйесі бар немесе ескірген және осал.
- Хосттар/қызметтер (тексерулер) деректер құрылымы енді (менің ойымша) әлдеқайда оқылатын және түсінікті. Басқалар үшін бұл соншалықты айқын емес болып шықты, сондықтан мен мұның қалай жұмыс істейтінін және қай жерде нені өңдеу керектігін түсіндіру үшін жергілікті викиге бірнеше бет жариялауға тура келді.
- Айнымалылар мен функцияларды пайдаланып тексерулерді икемді конфигурациялауға болады, мысалы, http_regexp тексеру үшін хост параметрлерінде қалаған үлгіні, қайтару кодын, URL мекенжайын және портты орнатуға болады.
- Бірнеше бақылау тақталары бар, олардың әрқайсысы үшін сіз көрсетілген дабылдардың жеке тізімін анықтай аласыз және мұның барлығын Қуыршақ және біріктіру сұраулары арқылы басқара аласыз.
Кемшіліктері:
- Команда мүшелерінің инерциясы - Нагиос жұмыс істеді, жұмыс істеді және жұмыс істеді, ал сіздің бұл Исинга үнемі қате және баяу. Мұндағы тарихты қалай көруге болады? Ой, қарғыс атсын, ол жаңартылмайды... (Нақты мәселе мынада, дабыл тарихы автоматты түрде жаңартылмайды, тек F5 арқылы)
- Жүйенің инерциясы - веб-интерфейстегі «жаңарту» (қазір тексеру) түймесін басқан кезде - орындау нәтижесі Марстағы ауа-райына, әсіресе орындау үшін ондаған секундты қажет ететін күрделі қызметтерге байланысты. Мұндай нәтиже қалыпты жағдай.

- Жалпы, екі жүйенің қатар жұмыс істеуінің алты айлық статистикасына сәйкес, Нагиос әрқашан Исингаға қарағанда жылдам жұмыс істеді және бұл мені қатты тітіркендірді. Менің ойымша, олар таймерлермен және әрбір бес минут сайын тексерулермен бірдеңе шатастырған сияқты, шын мәнінде олар 5:30 немесе сол сияқты бір рет болады.
- Қызметті кез келген уақытта қайта іске қоссаңыз (systemctl restart icinga2) - сол уақытта жүргізіліп жатқан барлық тексерулер маңызды дабылды тудырады. экранда және сырттан бәрі құлап кеткендей көрінеді ().
Бірақ тұтастай алғанда, ол жұмыс істейді.
Ақпарат көзі: www.habr.com

