Баарына салам.
Мен Linux тутумунун администраторумун, мен 2015-жылы Россиядан Австралияга көз карандысыз профессионалдык виза менен көчүп келдим, бирок макала чочко үчүн тракторду кантип баштоо керектиги жөнүндө болбойт. Мындай макалалар буга чейин эле жетиштүү (бирок, кызыкчылык болсо, мен бул жөнүндө да жазам), ошондуктан мен Австралияда Linux-ops инженери катары иштегенимде бир системанын мониторингинен миграцияны кантип демилгелегеним жөнүндө айткым келет. башкага. Тактап айтканда - Nagios => Icinga2.
Макала жарым-жартылай техникалык жана жарым-жартылай адамдар менен баарлашуу жана маданият жана иштөө ыкмаларындагы айырмачылыктарга байланыштуу көйгөйлөр жөнүндө.
Тилекке каршы, "код" теги куурчак жана ямл кодун баса албайт, ошондуктан мен "ачык текстти" колдонууга туура келди.
21-жылдын 2016-декабрында эртең менен кырсыктын белгилери болгон эмес. Адаттагыдай эле, мен Хабрды катталбаган анонимдүү колдонуучудан жумуш күнүнүн биринчи жарым саатында кофе ичип жатып окуп жатып, анан көрдүм. .
Менин компаниям Нагиосту колдонгондуктан, эки жолу ойлонбой туруп, Redmineде билет түзүп, шилтемени жалпы чатка жөнөттү, анткени мен аны маанилүү деп эсептедим. Демилге Австралияда да жазаланат, ошондуктан мен аны тапкандан бери башкы инженер көйгөйдү мага кадап койду.
Redmineден скриншот
Биздин бөлүмдө, өз оюңузду айтуудан мурун, тандоо ачык болсо да, жок дегенде бир альтернатива сунуштоо адатка айланган, ошондуктан мен азыр кандай мониторинг системалары актуалдуу экенин гуглдан баштадым, анткени мен Россияда акыркы иштеген жеримде элем. менин өзүмдүн өзүм жазган системасы бар болчу, абдан примитивдүү, бирок ошого карабастан толук иштеп, ага жүктөлгөн бардык милдеттерди аткарып жатты. Python, Санкт-Петербург политехникалык жана метро эрежеси. Жок, метро жаман. Бул жеке (11 жыл иштеген) жана өзүнчө макалага татыктуу, бирок азыр эмес.
Менин азыркы жеримде инфраструктуранын конфигурациясына өзгөртүүлөрдү киргизүү эрежелери жөнүндө бир аз. Биз Куурчак, Гитлаб жана Инфраструктураны Кодекстин принциби катары колдонобуз, ошондуктан:
- Виртуалдык машиналардагы файлдарды кол менен өзгөртүү менен SSH аркылуу кол менен өзгөртүүлөр болбойт. Үч жылдын ичинде мен бул үчүн көп жолу шляпа менен уруп алдым, акыркы жолу бир жума мурун болгон жана бул акыркы жолу болгон жок деп ойлойм. Ооба, чындап эле - конфигурациядагы бир сапты оңдоп, кызматты кайра күйгүзүп, маселе чечилгенин көрүңүз - 10 секунд. Gitlab'те жаңы филиал түзүп, өзгөртүүлөрдү түртүп, r10k Puppetmasterде иштешин күтүңүз, Puppet -environment=mybranch иштетиңиз жана баары иштегенге чейин дагы бир нече мүнөт күтүңүз - эң аз дегенде 5 мүнөт.
- Бардык өзгөртүүлөр Gitlab'те бириктирүү өтүнүчүн түзүү аркылуу жүргүзүлөт жана жок дегенде бир команда мүчөсү тарабынан бекитилиши керек. Команда лидери чечкен негизги өзгөртүүлөр эки же үч жактырууну талап кылат.
- Бардык өзгөртүүлөр тигил же бул жол менен текст болуп саналат (Куурчак манифесттери, скрипттер жана Hiera маалыматтары текст болгондуктан), бинардык форматтар абдан көңүл бурулбайт жана мындай файлдарды бекитүүгө орчундуу себеп болушу керек.
Ошентип, мен карап чыккан варианттар:
- Мунин - эгерде инфраструктурада 10дон ашык сервер болсо, администрация тозокко айланат (ден . Мен муну текшерүүгө эч кандай каалоом жок болчу, ошондуктан мен анын сөзүн кабыл алдым).
- Zabbix - Мен аны Россияда көптөн бери карап жүрдүм, бирок кийин менин тапшырмаларым үчүн ашыкча болду. Бул жерде - куурчакты конфигурация менеджери жана Gitlab версиясын башкаруу системасы катары колдонуудан улам жокко чыгарууга туура келди. Ошол учурда, менин түшүнгөнүм боюнча, Zabbix бардык конфигурацияны маалымат базасында сактайт, ошондуктан азыркы шарттарда конфигурацияны кантип башкаруу жана өзгөрүүлөрдү кантип көзөмөлдөө керектиги түшүнүксүз болчу.
- Кафедрадагы маанайга карап, акырында Прометейге жетебиз, бирок ал кезде мен аны өздөштүргөн эмесмин жана чындап иштеген үлгүнү (Proof of Concept) көрсөтө алган жокмун, ошондуктан мен баш тартууга туура келди.
- Ошондой эле системаны толук кайра иштеп чыгууну талап кылган, же ымыркай кезинде болгон/ташталган жана ошол эле себептен улам четке кагылган дагы бир нече варианттар бар.
Акыр-аягы, мен Icinga2ге үч себеп менен отурдум:
1 - Nrpe менен шайкештик (Нагиостун буйрук текшерүүлөрүн жүргүзгөн кардар кызматы). Бул абдан маанилүү болчу, анткени ал убакта бизде 135 (азыр 2019-жылы 165) виртуалдык машиналары бар, бир топ жазма кызматтар/чектер бар болчу жана мунун баарын кайра жасоо чыныгы азап болмок.
2 - бардык конфигурация файлдары текст болуп саналат, бул маселени оңдоону жеңилдетет, эмне кошулганын же жок кылынганын көрүү мүмкүнчүлүгү менен бириктирүү өтүнүчтөрүн түзөт.
3 тирүү жана өнүгүп келе жаткан OpenSource долбоору. Биз OpenSource'ду чындап жакшы көрөбүз жана көйгөйлөрдү чечүү үчүн Тартуу өтүнүчтөрүн жана Маселелерин түзүү менен ага бардык мүмкүн болгон салымыбызды кошобуз.
Ошентип, кетели, Icinga2.
Мен биринчи жолу кесиптештеримдин инерциясына туш болушум керек болчу. Нагиос/Наггиоско бардыгы көнүп калышкан (бирок бул жерде алар аны кантип айтуу керектиги боюнча мунасага келе алышкан жок) жана 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) жана 68 веб-тиркемелер бар, алар SSL сертификаттарынын иштеши жана жарактуулугу үчүн көзөмөлдөнүшү керек. Бирок тарыхый геморройдон улам мониторинг колдонмолору үчүн маалымат өзүнчө 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',
}
}Мен дагы эле ушул кесмелердин үстүндө иштеп жатам жана мүмкүн болушунча аларды өркүндөтүп жатам. Бирок, дал ушул код Хиерада жөнөкөй жана түшүнүктүү синтаксисти колдонууга мүмкүндүк берген:
маалымат
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 менен гана)
- Системанын инерциясы - мен веб-интерфейстеги "жаңыртуу" баскычын чыкылдатканда (азыр текшерүү) - аткаруунун натыйжасы Марстагы аба ырайынан көз каранды, айрыкча он секунданы талап кылган татаал кызматтардан. Мындай натыйжа кадыресе көрүнүш.

- Жалпысынан алганда, эки системанын жанаша иштешинин алты айлык статистикасына ылайык, Нагиос ар дайым Icinga караганда тезирээк иштеген жана бул мени чындап кыжырдантты. Менин оюмча, алар таймерлер менен бир нерсени бузуп алышкан жана текшерүү ар бир беш мүнөттө жүргүзүлөт, чындыгында бул ар бир 5:30 же ушуга окшош.
- Эгер сиз кызматты каалаган убакта өчүрүп күйгүзсөңүз (systemctl restart icinga2) - ошол убакта аткарылып жаткан бардык текшерүүлөр критикалык ойготкучту жаратат экранда жана сыртынан баары кулап кеткендей көрүнөт ().
Бирок, жалпысынан, ал иштейт.
Source: www.habr.com

