Merge pull request #117379 from hercules-ci/nixos-metricbeat
nixos/metricbeat: init
This commit is contained in:
commit
843248d39f
|
@ -594,6 +594,7 @@
|
||||||
./services/monitoring/loki.nix
|
./services/monitoring/loki.nix
|
||||||
./services/monitoring/longview.nix
|
./services/monitoring/longview.nix
|
||||||
./services/monitoring/mackerel-agent.nix
|
./services/monitoring/mackerel-agent.nix
|
||||||
|
./services/monitoring/metricbeat.nix
|
||||||
./services/monitoring/monit.nix
|
./services/monitoring/monit.nix
|
||||||
./services/monitoring/munin.nix
|
./services/monitoring/munin.nix
|
||||||
./services/monitoring/nagios.nix
|
./services/monitoring/nagios.nix
|
||||||
|
|
152
nixos/modules/services/monitoring/metricbeat.nix
Normal file
152
nixos/modules/services/monitoring/metricbeat.nix
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (lib)
|
||||||
|
attrValues
|
||||||
|
literalExample
|
||||||
|
mkEnableOption
|
||||||
|
mkIf
|
||||||
|
mkOption
|
||||||
|
types
|
||||||
|
;
|
||||||
|
cfg = config.services.metricbeat;
|
||||||
|
|
||||||
|
settingsFormat = pkgs.formats.yaml {};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
|
||||||
|
services.metricbeat = {
|
||||||
|
|
||||||
|
enable = mkEnableOption "metricbeat";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.metricbeat;
|
||||||
|
defaultText = literalExample "pkgs.metricbeat";
|
||||||
|
example = literalExample "pkgs.metricbeat7";
|
||||||
|
description = ''
|
||||||
|
The metricbeat package to use
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
modules = mkOption {
|
||||||
|
description = ''
|
||||||
|
Metricbeat modules are responsible for reading metrics from the various sources.
|
||||||
|
|
||||||
|
This is like <literal>services.metricbeat.settings.metricbeat.modules</literal>,
|
||||||
|
but structured as an attribute set. This has the benefit that multiple
|
||||||
|
NixOS modules can contribute settings to a single metricbeat module.
|
||||||
|
|
||||||
|
A module can be specified multiple times by choosing a different <literal><name></literal>
|
||||||
|
for each, but setting <xref linkend="opt-services.metricbeat.modules._name_.module"/> to the same value.
|
||||||
|
|
||||||
|
See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>.
|
||||||
|
'';
|
||||||
|
default = {};
|
||||||
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
|
freeformType = settingsFormat.type;
|
||||||
|
options = {
|
||||||
|
module = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = name;
|
||||||
|
defaultText = literalExample ''<name>'';
|
||||||
|
description = ''
|
||||||
|
The name of the module.
|
||||||
|
|
||||||
|
Look for the value after <literal>module:</literal> on the individual
|
||||||
|
module pages linked from <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
example = {
|
||||||
|
system = {
|
||||||
|
metricsets = ["cpu" "load" "memory" "network" "process" "process_summary" "uptime" "socket_summary"];
|
||||||
|
enabled = true;
|
||||||
|
period = "10s";
|
||||||
|
processes = [".*"];
|
||||||
|
cpu.metrics = ["percentages" "normalized_percentages"];
|
||||||
|
core.metrics = ["percentages"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
freeformType = settingsFormat.type;
|
||||||
|
options = {
|
||||||
|
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
Name of the beat. Defaults to the hostname.
|
||||||
|
See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/configuration-general-options.html#_name"/>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
tags = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Tags to place on the shipped metrics.
|
||||||
|
See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/configuration-general-options.html#_tags_2"/>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
metricbeat.modules = mkOption {
|
||||||
|
type = types.listOf settingsFormat.type;
|
||||||
|
default = [];
|
||||||
|
internal = true;
|
||||||
|
description = ''
|
||||||
|
The metric collecting modules. Use <xref linkend="opt-services.metricbeat.modules"/> instead.
|
||||||
|
|
||||||
|
See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-modules.html"/>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Configuration for metricbeat. See <link xlink:href="https://www.elastic.co/guide/en/beats/metricbeat/current/configuring-howto-metricbeat.html"/> for supported values.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
# empty modules would cause a failure at runtime
|
||||||
|
assertion = cfg.settings.metricbeat.modules != [];
|
||||||
|
message = "services.metricbeat: You must configure one or more modules.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services.metricbeat.settings.metricbeat.modules = attrValues cfg.modules;
|
||||||
|
|
||||||
|
systemd.services.metricbeat = {
|
||||||
|
description = "metricbeat metrics shipper";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = ''
|
||||||
|
${cfg.package}/bin/metricbeat \
|
||||||
|
-c ${settingsFormat.generate "metricbeat.yml" cfg.settings} \
|
||||||
|
--path.data $STATE_DIRECTORY \
|
||||||
|
--path.logs $LOGS_DIRECTORY \
|
||||||
|
;
|
||||||
|
'';
|
||||||
|
Restart = "always";
|
||||||
|
DynamicUser = true;
|
||||||
|
ProtectSystem = "strict";
|
||||||
|
ProtectHome = "tmpfs";
|
||||||
|
StateDirectory = "metricbeat";
|
||||||
|
LogsDirectory = "metricbeat";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -56,6 +56,24 @@ let
|
||||||
'');
|
'');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
metricbeat = {
|
||||||
|
enable = true;
|
||||||
|
package = elk.metricbeat;
|
||||||
|
modules.system = {
|
||||||
|
metricsets = ["cpu" "load" "memory" "network" "process" "process_summary" "uptime" "socket_summary"];
|
||||||
|
enabled = true;
|
||||||
|
period = "5s";
|
||||||
|
processes = [".*"];
|
||||||
|
cpu.metrics = ["percentages" "normalized_percentages"];
|
||||||
|
core.metrics = ["percentages"];
|
||||||
|
};
|
||||||
|
settings = {
|
||||||
|
output.elasticsearch = {
|
||||||
|
hosts = ["127.0.0.1:9200"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
logstash = {
|
logstash = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = elk.logstash;
|
package = elk.logstash;
|
||||||
|
@ -135,6 +153,16 @@ let
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def has_metricbeat():
|
||||||
|
dictionary = {"query": {"match": {"event.dataset": {"query": "system.cpu"}}}}
|
||||||
|
return (
|
||||||
|
"curl --silent --show-error '${esUrl}/_search' "
|
||||||
|
+ "-H 'Content-Type: application/json' "
|
||||||
|
+ "-d '{}' ".format(json.dumps(dictionary))
|
||||||
|
+ "| jq '.hits.total > 0'"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
start_all()
|
start_all()
|
||||||
|
|
||||||
one.wait_for_unit("elasticsearch.service")
|
one.wait_for_unit("elasticsearch.service")
|
||||||
|
@ -161,6 +189,12 @@ let
|
||||||
"curl --silent --show-error 'http://localhost:5601/api/status' | jq .status.overall.state | grep green"
|
"curl --silent --show-error 'http://localhost:5601/api/status' | jq .status.overall.state | grep green"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with subtest("Metricbeat is running"):
|
||||||
|
one.wait_for_unit("metricbeat.service")
|
||||||
|
|
||||||
|
with subtest("Metricbeat metrics arrive in elasticsearch"):
|
||||||
|
one.wait_until_succeeds(has_metricbeat() + " | tee /dev/console | grep 'true'")
|
||||||
|
|
||||||
with subtest("Logstash messages arive in elasticsearch"):
|
with subtest("Logstash messages arive in elasticsearch"):
|
||||||
one.wait_until_succeeds(total_hits("flowers") + " | grep -v 0")
|
one.wait_until_succeeds(total_hits("flowers") + " | grep -v 0")
|
||||||
one.wait_until_succeeds(total_hits("dragons") + " | grep 0")
|
one.wait_until_succeeds(total_hits("dragons") + " | grep 0")
|
||||||
|
@ -190,12 +224,14 @@ in pkgs.lib.mapAttrs mkElkTest {
|
||||||
logstash = pkgs.logstash6;
|
logstash = pkgs.logstash6;
|
||||||
kibana = pkgs.kibana6;
|
kibana = pkgs.kibana6;
|
||||||
journalbeat = pkgs.journalbeat6;
|
journalbeat = pkgs.journalbeat6;
|
||||||
|
metricbeat = pkgs.metricbeat6;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
elasticsearch = pkgs.elasticsearch6-oss;
|
elasticsearch = pkgs.elasticsearch6-oss;
|
||||||
logstash = pkgs.logstash6-oss;
|
logstash = pkgs.logstash6-oss;
|
||||||
kibana = pkgs.kibana6-oss;
|
kibana = pkgs.kibana6-oss;
|
||||||
journalbeat = pkgs.journalbeat6;
|
journalbeat = pkgs.journalbeat6;
|
||||||
|
metricbeat = pkgs.metricbeat6;
|
||||||
};
|
};
|
||||||
ELK-7 =
|
ELK-7 =
|
||||||
if enableUnfree
|
if enableUnfree
|
||||||
|
@ -204,11 +240,13 @@ in pkgs.lib.mapAttrs mkElkTest {
|
||||||
logstash = pkgs.logstash7;
|
logstash = pkgs.logstash7;
|
||||||
kibana = pkgs.kibana7;
|
kibana = pkgs.kibana7;
|
||||||
journalbeat = pkgs.journalbeat7;
|
journalbeat = pkgs.journalbeat7;
|
||||||
|
metricbeat = pkgs.metricbeat7;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
elasticsearch = pkgs.elasticsearch7-oss;
|
elasticsearch = pkgs.elasticsearch7-oss;
|
||||||
logstash = pkgs.logstash7-oss;
|
logstash = pkgs.logstash7-oss;
|
||||||
kibana = pkgs.kibana7-oss;
|
kibana = pkgs.kibana7-oss;
|
||||||
journalbeat = pkgs.journalbeat7;
|
journalbeat = pkgs.journalbeat7;
|
||||||
|
metricbeat = pkgs.metricbeat7;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, fetchFromGitHub, elk6Version, buildGoPackage, libpcap, systemd }:
|
{ lib, fetchFromGitHub, elk6Version, buildGoPackage, libpcap, nixosTests, systemd }:
|
||||||
|
|
||||||
let beat = package : extraArgs : buildGoPackage (rec {
|
let beat = package : extraArgs : buildGoPackage (rec {
|
||||||
name = "${package}-${version}";
|
name = "${package}-${version}";
|
||||||
|
@ -22,10 +22,17 @@ let beat = package : extraArgs : buildGoPackage (rec {
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
};
|
};
|
||||||
} // extraArgs);
|
} // extraArgs);
|
||||||
in {
|
in rec {
|
||||||
filebeat6 = beat "filebeat" {meta.description = "Lightweight shipper for logfiles";};
|
filebeat6 = beat "filebeat" {meta.description = "Lightweight shipper for logfiles";};
|
||||||
heartbeat6 = beat "heartbeat" {meta.description = "Lightweight shipper for uptime monitoring";};
|
heartbeat6 = beat "heartbeat" {meta.description = "Lightweight shipper for uptime monitoring";};
|
||||||
metricbeat6 = beat "metricbeat" {meta.description = "Lightweight shipper for metrics";};
|
metricbeat6 = beat "metricbeat" {
|
||||||
|
meta.description = "Lightweight shipper for metrics";
|
||||||
|
passthru.tests =
|
||||||
|
assert metricbeat6.drvPath == nixosTests.elk.ELK-6.elkPackages.metricbeat.drvPath;
|
||||||
|
{
|
||||||
|
elk = nixosTests.elk.ELK-6;
|
||||||
|
};
|
||||||
|
};
|
||||||
packetbeat6 = beat "packetbeat" {
|
packetbeat6 = beat "packetbeat" {
|
||||||
buildInputs = [ libpcap ];
|
buildInputs = [ libpcap ];
|
||||||
meta.broken = true;
|
meta.broken = true;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, fetchFromGitHub, elk7Version, buildGoPackage, libpcap, systemd }:
|
{ lib, fetchFromGitHub, elk7Version, buildGoPackage, libpcap, nixosTests, systemd }:
|
||||||
|
|
||||||
let beat = package : extraArgs : buildGoPackage (rec {
|
let beat = package : extraArgs : buildGoPackage (rec {
|
||||||
name = "${package}-${version}";
|
name = "${package}-${version}";
|
||||||
|
@ -22,10 +22,17 @@ let beat = package : extraArgs : buildGoPackage (rec {
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
};
|
};
|
||||||
} // extraArgs);
|
} // extraArgs);
|
||||||
in {
|
in rec {
|
||||||
filebeat7 = beat "filebeat" {meta.description = "Lightweight shipper for logfiles";};
|
filebeat7 = beat "filebeat" {meta.description = "Lightweight shipper for logfiles";};
|
||||||
heartbeat7 = beat "heartbeat" {meta.description = "Lightweight shipper for uptime monitoring";};
|
heartbeat7 = beat "heartbeat" {meta.description = "Lightweight shipper for uptime monitoring";};
|
||||||
metricbeat7 = beat "metricbeat" {meta.description = "Lightweight shipper for metrics";};
|
metricbeat7 = beat "metricbeat" {
|
||||||
|
meta.description = "Lightweight shipper for metrics";
|
||||||
|
passthru.tests =
|
||||||
|
assert metricbeat7.drvPath == nixosTests.elk.ELK-7.elkPackages.metricbeat.drvPath;
|
||||||
|
{
|
||||||
|
elk = nixosTests.elk.ELK-7;
|
||||||
|
};
|
||||||
|
};
|
||||||
packetbeat7 = beat "packetbeat" {
|
packetbeat7 = beat "packetbeat" {
|
||||||
buildInputs = [ libpcap ];
|
buildInputs = [ libpcap ];
|
||||||
meta.description = "Network packet analyzer that ships data to Elasticsearch";
|
meta.description = "Network packet analyzer that ships data to Elasticsearch";
|
||||||
|
|
Loading…
Reference in a new issue