nixos/prometheus: remove prometheus1 module, rename prometheus2

Prometheus 1 is no longer supported, instead 'services.prometheus'
now configures the Prometheus 2 service.
This commit is contained in:
WilliButz 2019-09-06 21:40:27 +02:00
parent 283d9a0942
commit bb62066225
No known key found for this signature in database
GPG Key ID: 92582A10F1179CB2
4 changed files with 173 additions and 399 deletions

View File

@ -464,7 +464,14 @@
<literal>packetbeat5</literal>) of the ELK-stack and Elastic beats have been removed. <literal>packetbeat5</literal>) of the ELK-stack and Elastic beats have been removed.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
For NixOS 19.03, both Prometheus 1 and 2 were available to allow for
a seamless transition from version 1 to 2 with existing setups.
Because Prometheus 1 is no longer developed, it was removed.
Prometheus 2 is now configured with <literal>services.prometheus</literal>.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>

View File

@ -52,10 +52,11 @@ with lib;
(mkRemovedOptionModule [ "services" "misc" "nzbget" "openFirewall" ] "The port used by nzbget is managed through the web interface so you should adjust your firewall rules accordingly.") (mkRemovedOptionModule [ "services" "misc" "nzbget" "openFirewall" ] "The port used by nzbget is managed through the web interface so you should adjust your firewall rules accordingly.")
(mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "user" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a user setting.") (mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "user" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a user setting.")
(mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "group" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a group setting.") (mkRemovedOptionModule [ "services" "prometheus" "alertmanager" "group" ] "The alertmanager service is now using systemd's DynamicUser mechanism which obviates a group setting.")
(mkRemovedOptionModule [ "services" "prometheus2" "alertmanagerURL" ] '' (mkRemovedOptionModule [ "services" "prometheus" "alertmanagerURL" ] ''
Due to incompatibility, the alertmanagerURL option has been removed, Due to incompatibility, the alertmanagerURL option has been removed,
please use 'services.prometheus2.alertmanagers' instead. please use 'services.prometheus2.alertmanagers' instead.
'') '')
(mkRenamedOptionModule [ "services" "prometheus2" ] [ "services" "prometheus" ])
(mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ]) (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ])
(mkRenamedOptionModule [ "services" "vmwareGuest" ] [ "virtualisation" "vmware" "guest" ]) (mkRenamedOptionModule [ "services" "vmwareGuest" ] [ "virtualisation" "vmware" "guest" ])
(mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ]) (mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ])

View File

@ -4,37 +4,14 @@ with lib;
let let
cfg = config.services.prometheus; cfg = config.services.prometheus;
cfg2 = config.services.prometheus2;
promUser = "prometheus";
promGroup = "prometheus";
stateDir = workingDir = "/var/lib/" + cfg.stateDir;
if cfg.stateDir != null
then cfg.stateDir
else
if cfg.dataDir != null
then
# This assumes /var/lib/ is a prefix of cfg.dataDir.
# This is checked as an assertion below.
removePrefix stateDirBase cfg.dataDir
else "prometheus";
stateDirBase = "/var/lib/";
workingDir = stateDirBase + stateDir;
workingDir2 = stateDirBase + cfg2.stateDir;
# a wrapper that verifies that the configuration is valid # a wrapper that verifies that the configuration is valid
promtoolCheck = what: name: file: pkgs.runCommand "${name}-${what}-checked" promtoolCheck = what: name: file:
{ buildInputs = [ cfg.package ]; } ''
ln -s ${file} $out
promtool ${what} $out
'';
# a wrapper that verifies that the configuration is valid for
# prometheus 2
prom2toolCheck = what: name: file:
pkgs.runCommand pkgs.runCommand
"${name}-${replaceStrings [" "] [""] what}-checked" "${name}-${replaceStrings [" "] [""] what}-checked"
{ buildInputs = [ cfg2.package ]; } '' { buildInputs = [ cfg.package ]; } ''
ln -s ${file} $out ln -s ${file} $out
promtool ${what} $out promtool ${what} $out
''; '';
@ -45,61 +22,34 @@ let
echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out echo '${builtins.toJSON x}' | ${pkgs.jq}/bin/jq . > $out
''; '';
# This becomes the main config file for Prometheus 1 generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig;
# This becomes the main config file for Prometheus
promConfig = { promConfig = {
global = filterValidPrometheus cfg.globalConfig; global = filterValidPrometheus cfg.globalConfig;
rule_files = map (promtoolCheck "check-rules" "rules") (cfg.ruleFiles ++ [ rule_files = map (promtoolCheck "check rules" "rules") (cfg.ruleFiles ++ [
(pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules)) (pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg.rules))
]); ]);
scrape_configs = filterValidPrometheus cfg.scrapeConfigs; scrape_configs = filterValidPrometheus cfg.scrapeConfigs;
alerting = {
inherit (cfg) alertmanagers;
};
}; };
generatedPrometheusYml = writePrettyJSON "prometheus.yml" promConfig;
prometheusYml = let prometheusYml = let
yml = if cfg.configText != null then yml = if cfg.configText != null then
pkgs.writeText "prometheus.yml" cfg.configText pkgs.writeText "prometheus.yml" cfg.configText
else generatedPrometheusYml; else generatedPrometheusYml;
in promtoolCheck "check-config" "prometheus.yml" yml; in promtoolCheck "check config" "prometheus.yml" yml;
cmdlineArgs = cfg.extraFlags ++ [ cmdlineArgs = cfg.extraFlags ++ [
"-storage.local.path=${workingDir}/metrics" "--storage.tsdb.path=${workingDir}/data/"
"-config.file=${prometheusYml}" "--config.file=${prometheusYml}"
"-web.listen-address=${cfg.listenAddress}" "--web.listen-address=${cfg.listenAddress}"
"-alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" "--alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}"
"-alertmanager.timeout=${toString cfg.alertmanagerTimeout}s" "--alertmanager.timeout=${toString cfg.alertmanagerTimeout}s"
] ++ ] ++
optional (cfg.alertmanagerURL != []) "-alertmanager.url=${concatStringsSep "," cfg.alertmanagerURL}" ++ optional (cfg.webExternalUrl != null) "--web.external-url=${cfg.webExternalUrl}";
optional (cfg.webExternalUrl != null) "-web.external-url=${cfg.webExternalUrl}";
# This becomes the main config file for Prometheus 2
promConfig2 = {
global = filterValidPrometheus cfg2.globalConfig;
rule_files = map (prom2toolCheck "check rules" "rules") (cfg2.ruleFiles ++ [
(pkgs.writeText "prometheus.rules" (concatStringsSep "\n" cfg2.rules))
]);
scrape_configs = filterValidPrometheus cfg2.scrapeConfigs;
alerting = {
inherit (cfg2) alertmanagers;
};
};
generatedPrometheus2Yml = writePrettyJSON "prometheus.yml" promConfig2;
prometheus2Yml = let
yml = if cfg2.configText != null then
pkgs.writeText "prometheus.yml" cfg2.configText
else generatedPrometheus2Yml;
in prom2toolCheck "check config" "prometheus.yml" yml;
cmdlineArgs2 = cfg2.extraFlags ++ [
"--storage.tsdb.path=${workingDir2}/data/"
"--config.file=${prometheus2Yml}"
"--web.listen-address=${cfg2.listenAddress}"
"--alertmanager.notification-queue-capacity=${toString cfg2.alertmanagerNotificationQueueCapacity}"
"--alertmanager.timeout=${toString cfg2.alertmanagerTimeout}s"
] ++
optional (cfg2.webExternalUrl != null) "--web.external-url=${cfg2.webExternalUrl}";
filterValidPrometheus = filterAttrsListRecursive (n: v: !(n == "_module" || v == null)); filterValidPrometheus = filterAttrsListRecursive (n: v: !(n == "_module" || v == null));
filterAttrsListRecursive = pred: x: filterAttrsListRecursive = pred: x:
@ -514,343 +464,159 @@ let
}; };
in { in {
options = { options.services.prometheus = {
services.prometheus = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
description = '' description = ''
Enable the Prometheus monitoring daemon. Enable the Prometheus monitoring daemon.
''; '';
}; };
package = mkOption { package = mkOption {
type = types.package; type = types.package;
default = pkgs.prometheus; default = pkgs.prometheus;
defaultText = "pkgs.prometheus"; defaultText = "pkgs.prometheus";
description = '' description = ''
The prometheus package that should be used. The prometheus package that should be used.
''; '';
}; };
listenAddress = mkOption { listenAddress = mkOption {
type = types.str; type = types.str;
default = "0.0.0.0:9090"; default = "0.0.0.0:9090";
description = '' description = ''
Address to listen on for the web interface, API, and telemetry. Address to listen on for the web interface, API, and telemetry.
''; '';
}; };
dataDir = mkOption { stateDir = mkOption {
type = types.nullOr types.path; type = types.str;
default = null; default = "prometheus2";
description = '' description = ''
Directory to store Prometheus metrics data. Directory below <literal>/var/lib</literal> to store Prometheus metrics data.
This option is deprecated, please use <option>services.prometheus.stateDir</option>. This directory will be created automatically using systemd's StateDirectory mechanism.
''; '';
}; };
stateDir = mkOption { extraFlags = mkOption {
type = types.nullOr types.str; type = types.listOf types.str;
default = null; default = [];
description = '' description = ''
Directory below <literal>${stateDirBase}</literal> to store Prometheus metrics data. Extra commandline options when launching Prometheus.
This directory will be created automatically using systemd's StateDirectory mechanism. '';
Defaults to <literal>prometheus</literal>. };
'';
};
extraFlags = mkOption { configText = mkOption {
type = types.listOf types.str; type = types.nullOr types.lines;
default = []; default = null;
description = '' description = ''
Extra commandline options when launching Prometheus. If non-null, this option defines the text that is written to
''; prometheus.yml. If null, the contents of prometheus.yml is generated
}; from the structured config options.
'';
};
configText = mkOption { globalConfig = mkOption {
type = types.nullOr types.lines; type = promTypes.globalConfig;
default = null; default = {};
description = '' description = ''
If non-null, this option defines the text that is written to Parameters that are valid in all configuration contexts. They
prometheus.yml. If null, the contents of prometheus.yml is generated also serve as defaults for other configuration sections
from the structured config options. '';
''; };
};
globalConfig = mkOption { rules = mkOption {
type = promTypes.globalConfig; type = types.listOf types.str;
default = {}; default = [];
description = '' description = ''
Parameters that are valid in all configuration contexts. They Alerting and/or Recording rules to evaluate at runtime.
also serve as defaults for other configuration sections '';
''; };
};
rules = mkOption { ruleFiles = mkOption {
type = types.listOf types.str; type = types.listOf types.path;
default = []; default = [];
description = '' description = ''
Alerting and/or Recording rules to evaluate at runtime. Any additional rules files to include in this configuration.
''; '';
}; };
ruleFiles = mkOption { scrapeConfigs = mkOption {
type = types.listOf types.path; type = types.listOf promTypes.scrape_config;
default = []; default = [];
description = '' description = ''
Any additional rules files to include in this configuration. A list of scrape configurations.
''; '';
}; };
scrapeConfigs = mkOption { alertmanagers = mkOption {
type = types.listOf promTypes.scrape_config; type = types.listOf types.attrs;
default = []; example = literalExample ''
description = '' [ {
A list of scrape configurations. scheme = "https";
''; path_prefix = "/alertmanager";
}; static_configs = [ {
targets = [
"prometheus.domain.tld"
];
} ];
} ]
'';
default = [];
description = ''
A list of alertmanagers to send alerts to.
See <link xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config">the official documentation</link> for more information.
'';
};
alertmanagerURL = mkOption { alertmanagerNotificationQueueCapacity = mkOption {
type = types.listOf types.str; type = types.int;
default = []; default = 10000;
description = '' description = ''
List of Alertmanager URLs to send notifications to. The capacity of the queue for pending alert manager notifications.
''; '';
}; };
alertmanagerNotificationQueueCapacity = mkOption { alertmanagerTimeout = mkOption {
type = types.int; type = types.int;
default = 10000; default = 10;
description = '' description = ''
The capacity of the queue for pending alert manager notifications. Alert manager HTTP API timeout (in seconds).
''; '';
}; };
alertmanagerTimeout = mkOption { webExternalUrl = mkOption {
type = types.int; type = types.nullOr types.str;
default = 10; default = null;
description = '' example = "https://example.com/";
Alert manager HTTP API timeout (in seconds). description = ''
''; The URL under which Prometheus is externally reachable (for example,
}; if Prometheus is served via a reverse proxy).
'';
};
};
webExternalUrl = mkOption { config = mkIf cfg.enable {
type = types.nullOr types.str; users.groups.prometheus.gid = config.ids.gids.prometheus;
default = null; users.users.prometheus = {
example = "https://example.com/"; description = "Prometheus daemon user";
description = '' uid = config.ids.uids.prometheus;
The URL under which Prometheus is externally reachable (for example, group = "prometheus";
if Prometheus is served via a reverse proxy). };
''; systemd.services.prometheus = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/prometheus" +
optionalString (length cmdlineArgs != 0) (" \\\n " +
concatStringsSep " \\\n " cmdlineArgs);
User = "prometheus";
Restart = "always";
WorkingDirectory = workingDir;
StateDirectory = cfg.stateDir;
}; };
}; };
services.prometheus2 = { };
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable the Prometheus 2 monitoring daemon.
'';
};
package = mkOption {
type = types.package;
default = pkgs.prometheus_2;
defaultText = "pkgs.prometheus_2";
description = ''
The prometheus2 package that should be used.
'';
};
listenAddress = mkOption {
type = types.str;
default = "0.0.0.0:9090";
description = ''
Address to listen on for the web interface, API, and telemetry.
'';
};
stateDir = mkOption {
type = types.str;
default = "prometheus2";
description = ''
Directory below <literal>${stateDirBase}</literal> to store Prometheus metrics data.
This directory will be created automatically using systemd's StateDirectory mechanism.
Defaults to <literal>prometheus2</literal>.
'';
};
extraFlags = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra commandline options when launching Prometheus 2.
'';
};
configText = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
If non-null, this option defines the text that is written to
prometheus.yml. If null, the contents of prometheus.yml is generated
from the structured config options.
'';
};
globalConfig = mkOption {
type = promTypes.globalConfig;
default = {};
description = ''
Parameters that are valid in all configuration contexts. They
also serve as defaults for other configuration sections
'';
};
rules = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Alerting and/or Recording rules to evaluate at runtime.
'';
};
ruleFiles = mkOption {
type = types.listOf types.path;
default = [];
description = ''
Any additional rules files to include in this configuration.
'';
};
scrapeConfigs = mkOption {
type = types.listOf promTypes.scrape_config;
default = [];
description = ''
A list of scrape configurations.
'';
};
alertmanagers = mkOption {
type = types.listOf types.attrs;
example = literalExample ''
[ {
scheme = "https";
path_prefix = "/alertmanager";
static_configs = [ {
targets = [
"prometheus.domain.tld"
];
} ];
} ]
'';
default = [];
description = ''
A list of alertmanagers to send alerts to.
See <link xlink:href="https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alertmanager_config">the official documentation</link> for more information.
'';
};
alertmanagerNotificationQueueCapacity = mkOption {
type = types.int;
default = 10000;
description = ''
The capacity of the queue for pending alert manager notifications.
'';
};
alertmanagerTimeout = mkOption {
type = types.int;
default = 10;
description = ''
Alert manager HTTP API timeout (in seconds).
'';
};
webExternalUrl = mkOption {
type = types.nullOr types.str;
default = null;
example = "https://example.com/";
description = ''
The URL under which Prometheus is externally reachable (for example,
if Prometheus is served via a reverse proxy).
'';
};
};
};
config = mkMerge [
(mkIf (cfg.enable || cfg2.enable) {
users.groups.${promGroup}.gid = config.ids.gids.prometheus;
users.users.${promUser} = {
description = "Prometheus daemon user";
uid = config.ids.uids.prometheus;
group = promGroup;
};
})
(mkIf cfg.enable {
warnings =
optional (cfg.dataDir != null) ''
The option services.prometheus.dataDir is deprecated, please use
services.prometheus.stateDir.
'';
assertions = [
{
assertion = !(cfg.dataDir != null && cfg.stateDir != null);
message =
"The options services.prometheus.dataDir and services.prometheus.stateDir" +
" can't both be set at the same time! It's recommended to only set the latter" +
" since the former is deprecated.";
}
{
assertion = cfg.dataDir != null -> hasPrefix stateDirBase cfg.dataDir;
message =
"The option services.prometheus.dataDir should have ${stateDirBase} as a prefix!";
}
{
assertion = cfg.stateDir != null -> !hasPrefix "/" cfg.stateDir;
message =
"The option services.prometheus.stateDir shouldn't be an absolute directory." +
" It should be a directory relative to ${stateDirBase}.";
}
{
assertion = cfg2.stateDir != null -> !hasPrefix "/" cfg2.stateDir;
message =
"The option services.prometheus2.stateDir shouldn't be an absolute directory." +
" It should be a directory relative to ${stateDirBase}.";
}
];
systemd.services.prometheus = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/prometheus" +
optionalString (length cmdlineArgs != 0) (" \\\n " +
concatStringsSep " \\\n " cmdlineArgs);
User = promUser;
Restart = "always";
WorkingDirectory = workingDir;
StateDirectory = stateDir;
};
};
})
(mkIf cfg2.enable {
systemd.services.prometheus2 = {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${cfg2.package}/bin/prometheus" +
optionalString (length cmdlineArgs2 != 0) (" \\\n " +
concatStringsSep " \\\n " cmdlineArgs2);
User = promUser;
Restart = "always";
WorkingDirectory = workingDir2;
StateDirectory = cfg2.stateDir;
};
};
})
];
} }

View File

@ -218,8 +218,8 @@ let
toArgs = optionToArgs; toArgs = optionToArgs;
option = mkOption { option = mkOption {
type = types.str; type = types.str;
default = "/var/lib/${config.services.prometheus2.stateDir}/data"; default = "/var/lib/${config.services.prometheus.stateDir}/data";
defaultText = "/var/lib/\${config.services.prometheus2.stateDir}/data"; defaultText = "/var/lib/\${config.services.prometheus.stateDir}/data";
description = '' description = ''
Data directory of TSDB. Data directory of TSDB.
''; '';
@ -679,22 +679,22 @@ in {
(mkIf cfg.sidecar.enable { (mkIf cfg.sidecar.enable {
assertions = [ assertions = [
{ {
assertion = config.services.prometheus2.enable; assertion = config.services.prometheus.enable;
message = message =
"Please enable services.prometheus2 when enabling services.thanos.sidecar."; "Please enable services.prometheus when enabling services.thanos.sidecar.";
} }
{ {
assertion = !(config.services.prometheus2.globalConfig.external_labels == null || assertion = !(config.services.prometheus.globalConfig.external_labels == null ||
config.services.prometheus2.globalConfig.external_labels == {}); config.services.prometheus.globalConfig.external_labels == {});
message = message =
"services.thanos.sidecar requires uniquely identifying external labels " + "services.thanos.sidecar requires uniquely identifying external labels " +
"to be configured in the Prometheus server. " + "to be configured in the Prometheus server. " +
"Please set services.prometheus2.globalConfig.external_labels."; "Please set services.prometheus.globalConfig.external_labels.";
} }
]; ];
systemd.services.thanos-sidecar = { systemd.services.thanos-sidecar = {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" "prometheus2.service" ]; after = [ "network.target" "prometheus.service" ];
serviceConfig = { serviceConfig = {
User = "prometheus"; User = "prometheus";
Restart = "always"; Restart = "always";