836 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			836 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | |
| 
 | |
| with lib;
 | |
| 
 | |
| let
 | |
|   cfg = config.services.thanos;
 | |
| 
 | |
|   nullOpt = type: description: mkOption {
 | |
|     type = types.nullOr type;
 | |
|     default = null;
 | |
|     inherit description;
 | |
|   };
 | |
| 
 | |
|   optionToArgs = opt: v  : optional (v != null)  ''--${opt}="${toString v}"'';
 | |
|   flagToArgs   = opt: v  : optional v            ''--${opt}'';
 | |
|   listToArgs   = opt: vs : map               (v: ''--${opt}="${v}"'') vs;
 | |
|   attrsToArgs  = opt: kvs: mapAttrsToList (k: v: ''--${opt}=${k}=\"${v}\"'') kvs;
 | |
| 
 | |
|   mkParamDef = type: default: description: mkParam type (description + ''
 | |
| 
 | |
|     Defaults to <literal>${toString default}</literal> in Thanos
 | |
|     when set to <literal>null</literal>.
 | |
|   '');
 | |
| 
 | |
|   mkParam = type: description: {
 | |
|     toArgs = optionToArgs;
 | |
|     option = nullOpt type description;
 | |
|   };
 | |
| 
 | |
|   mkFlagParam = description: {
 | |
|     toArgs = flagToArgs;
 | |
|     option = mkOption {
 | |
|       type = types.bool;
 | |
|       default = false;
 | |
|       inherit description;
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   mkListParam = opt: description: {
 | |
|     toArgs = _opt: listToArgs opt;
 | |
|     option = mkOption {
 | |
|       type = types.listOf types.str;
 | |
|       default = [];
 | |
|       inherit description;
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   mkAttrsParam = opt: description: {
 | |
|     toArgs = _opt: attrsToArgs opt;
 | |
|     option = mkOption {
 | |
|       type = types.attrsOf types.str;
 | |
|       default = {};
 | |
|       inherit description;
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   mkStateDirParam = opt: default: description: {
 | |
|     toArgs = _opt: stateDir: optionToArgs opt "/var/lib/${stateDir}";
 | |
|     option = mkOption {
 | |
|       type = types.str;
 | |
|       inherit default;
 | |
|       inherit description;
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   toYAML = name: attrs: pkgs.runCommandNoCC name {
 | |
|     preferLocalBuild = true;
 | |
|     json = builtins.toFile "${name}.json" (builtins.toJSON attrs);
 | |
|     nativeBuildInputs = [ pkgs.remarshal ];
 | |
|   } ''json2yaml -i $json -o $out'';
 | |
| 
 | |
|   thanos = cmd: "${cfg.package}/bin/thanos ${cmd}" +
 | |
|     (let args = cfg.${cmd}.arguments;
 | |
|      in optionalString (length args != 0) (" \\\n  " +
 | |
|          concatStringsSep " \\\n  " args));
 | |
| 
 | |
|   argumentsOf = cmd: concatLists (collect isList
 | |
|     (flip mapParamsRecursive params.${cmd} (path: param:
 | |
|       let opt = concatStringsSep "." path;
 | |
|           v = getAttrFromPath path cfg.${cmd};
 | |
|       in param.toArgs opt v)));
 | |
| 
 | |
|   mkArgumentsOption = cmd: mkOption {
 | |
|     type = types.listOf types.str;
 | |
|     default = argumentsOf cmd;
 | |
|     description = ''
 | |
|       Arguments to the <literal>thanos ${cmd}</literal> command.
 | |
| 
 | |
|       Defaults to a list of arguments formed by converting the structured
 | |
|       options of <option>services.thanos.${cmd}</option> to a list of arguments.
 | |
| 
 | |
|       Overriding this option will cause none of the structured options to have
 | |
|       any effect. So only set this if you know what you're doing!
 | |
|     '';
 | |
|   };
 | |
| 
 | |
|   mapParamsRecursive =
 | |
|     let noParam = attr: !(attr ? toArgs && attr ? option);
 | |
|     in mapAttrsRecursiveCond noParam;
 | |
| 
 | |
|   paramsToOptions = mapParamsRecursive (_path: param: param.option);
 | |
| 
 | |
|   params = {
 | |
| 
 | |
|     log = {
 | |
| 
 | |
|       log.level = mkParamDef (types.enum ["debug" "info" "warn" "error" "fatal"]) "info" ''
 | |
|         Log filtering level.
 | |
|       '';
 | |
| 
 | |
|       log.format = mkParam types.str ''
 | |
|         Log format to use.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     tracing = cfg: {
 | |
|       tracing.config-file = {
 | |
|         toArgs = _opt: path: optionToArgs "tracing.config-file" path;
 | |
|         option = mkOption {
 | |
|           type = with types; nullOr str;
 | |
|           default = if cfg.tracing.config == null then null
 | |
|                     else toString (toYAML "tracing.yaml" cfg.tracing.config);
 | |
|           defaultText = ''
 | |
|             if config.services.thanos.<cmd>.tracing.config == null then null
 | |
|             else toString (toYAML "tracing.yaml" config.services.thanos.<cmd>.tracing.config);
 | |
|           '';
 | |
|           description = ''
 | |
|             Path to YAML file that contains tracing configuration.
 | |
| 
 | |
|             See format details: <link xlink:href="https://thanos.io/tracing.md/#configuration"/>
 | |
|           '';
 | |
|         };
 | |
|       };
 | |
| 
 | |
|       tracing.config =
 | |
|         {
 | |
|           toArgs = _opt: _attrs: [];
 | |
|           option = nullOpt types.attrs ''
 | |
|             Tracing configuration.
 | |
| 
 | |
|             When not <literal>null</literal> the attribute set gets converted to
 | |
|             a YAML file and stored in the Nix store. The option
 | |
|             <option>tracing.config-file</option> will default to its path.
 | |
| 
 | |
|             If <option>tracing.config-file</option> is set this option has no effect.
 | |
| 
 | |
|             See format details: <link xlink:href="https://thanos.io/tracing.md/#configuration"/>
 | |
|           '';
 | |
|         };
 | |
|     };
 | |
| 
 | |
|     common = cfg: params.log // params.tracing cfg // {
 | |
| 
 | |
|       http-address = mkParamDef types.str "0.0.0.0:10902" ''
 | |
|         Listen <literal>host:port</literal> for HTTP endpoints.
 | |
|       '';
 | |
| 
 | |
|       grpc-address = mkParamDef types.str "0.0.0.0:10901" ''
 | |
|         Listen <literal>ip:port</literal> address for gRPC endpoints (StoreAPI).
 | |
| 
 | |
|         Make sure this address is routable from other components.
 | |
|       '';
 | |
| 
 | |
|       grpc-server-tls-cert = mkParam types.str ''
 | |
|         TLS Certificate for gRPC server, leave blank to disable TLS
 | |
|       '';
 | |
| 
 | |
|       grpc-server-tls-key = mkParam types.str ''
 | |
|         TLS Key for the gRPC server, leave blank to disable TLS
 | |
|       '';
 | |
| 
 | |
|       grpc-server-tls-client-ca = mkParam types.str ''
 | |
|         TLS CA to verify clients against.
 | |
| 
 | |
|         If no client CA is specified, there is no client verification on server side.
 | |
|         (tls.NoClientCert)
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     objstore = cfg: {
 | |
| 
 | |
|       objstore.config-file = {
 | |
|         toArgs = _opt: path: optionToArgs "objstore.config-file" path;
 | |
|         option = mkOption {
 | |
|           type = with types; nullOr str;
 | |
|           default = if cfg.objstore.config == null then null
 | |
|                     else toString (toYAML "objstore.yaml" cfg.objstore.config);
 | |
|           defaultText = ''
 | |
|             if config.services.thanos.<cmd>.objstore.config == null then null
 | |
|             else toString (toYAML "objstore.yaml" config.services.thanos.<cmd>.objstore.config);
 | |
|           '';
 | |
|           description = ''
 | |
|             Path to YAML file that contains object store configuration.
 | |
| 
 | |
|             See format details: <link xlink:href="https://thanos.io/storage.md/#configuration"/>
 | |
|           '';
 | |
|         };
 | |
|       };
 | |
| 
 | |
|       objstore.config =
 | |
|         {
 | |
|           toArgs = _opt: _attrs: [];
 | |
|           option = nullOpt types.attrs ''
 | |
|             Object store configuration.
 | |
| 
 | |
|             When not <literal>null</literal> the attribute set gets converted to
 | |
|             a YAML file and stored in the Nix store. The option
 | |
|             <option>objstore.config-file</option> will default to its path.
 | |
| 
 | |
|             If <option>objstore.config-file</option> is set this option has no effect.
 | |
| 
 | |
|             See format details: <link xlink:href="https://thanos.io/storage.md/#configuration"/>
 | |
|           '';
 | |
|         };
 | |
|     };
 | |
| 
 | |
|     sidecar = params.common cfg.sidecar // params.objstore cfg.sidecar // {
 | |
| 
 | |
|       prometheus.url = mkParamDef types.str "http://localhost:9090" ''
 | |
|         URL at which to reach Prometheus's API.
 | |
| 
 | |
|         For better performance use local network.
 | |
|       '';
 | |
| 
 | |
|       tsdb.path = {
 | |
|         toArgs = optionToArgs;
 | |
|         option = mkOption {
 | |
|           type = types.str;
 | |
|           default = "/var/lib/${config.services.prometheus.stateDir}/data";
 | |
|           defaultText = "/var/lib/\${config.services.prometheus.stateDir}/data";
 | |
|           description = ''
 | |
|             Data directory of TSDB.
 | |
|           '';
 | |
|         };
 | |
|       };
 | |
| 
 | |
|       reloader.config-file = mkParam types.str ''
 | |
|         Config file watched by the reloader.
 | |
|       '';
 | |
| 
 | |
|       reloader.config-envsubst-file = mkParam types.str ''
 | |
|         Output file for environment variable substituted config file.
 | |
|       '';
 | |
| 
 | |
|       reloader.rule-dirs = mkListParam "reloader.rule-dir" ''
 | |
|         Rule directories for the reloader to refresh.
 | |
|       '';
 | |
| 
 | |
|     };
 | |
| 
 | |
|     store = params.common cfg.store // params.objstore cfg.store // {
 | |
| 
 | |
|       stateDir = mkStateDirParam "data-dir" "thanos-store" ''
 | |
|         Data directory relative to <literal>/var/lib</literal>
 | |
|         in which to cache remote blocks.
 | |
|       '';
 | |
| 
 | |
|       index-cache-size = mkParamDef types.str "250MB" ''
 | |
|         Maximum size of items held in the index cache.
 | |
|       '';
 | |
| 
 | |
|       chunk-pool-size = mkParamDef types.str "2GB" ''
 | |
|         Maximum size of concurrently allocatable bytes for chunks.
 | |
|       '';
 | |
| 
 | |
|       store.grpc.series-sample-limit = mkParamDef types.int 0 ''
 | |
|         Maximum amount of samples returned via a single Series call.
 | |
| 
 | |
|         <literal>0</literal> means no limit.
 | |
| 
 | |
|         NOTE: for efficiency we take 120 as the number of samples in chunk (it
 | |
|         cannot be bigger than that), so the actual number of samples might be
 | |
|         lower, even though the maximum could be hit.
 | |
|       '';
 | |
| 
 | |
|       store.grpc.series-max-concurrency = mkParamDef types.int 20 ''
 | |
|         Maximum number of concurrent Series calls.
 | |
|       '';
 | |
| 
 | |
|       sync-block-duration = mkParamDef types.str "3m" ''
 | |
|         Repeat interval for syncing the blocks between local and remote view.
 | |
|       '';
 | |
| 
 | |
|       block-sync-concurrency = mkParamDef types.int 20 ''
 | |
|         Number of goroutines to use when syncing blocks from object storage.
 | |
|       '';
 | |
| 
 | |
|       min-time = mkParamDef types.str "0000-01-01T00:00:00Z" ''
 | |
|         Start of time range limit to serve.
 | |
| 
 | |
|         Thanos Store serves only metrics, which happened later than this
 | |
|         value. Option can be a constant time in RFC3339 format or time duration
 | |
|         relative to current time, such as -1d or 2h45m. Valid duration units are
 | |
|         ms, s, m, h, d, w, y.
 | |
|       '';
 | |
| 
 | |
|       max-time = mkParamDef types.str "9999-12-31T23:59:59Z" ''
 | |
|         End of time range limit to serve.
 | |
| 
 | |
|         Thanos Store serves only blocks, which happened eariler than this
 | |
|         value. Option can be a constant time in RFC3339 format or time duration
 | |
|         relative to current time, such as -1d or 2h45m. Valid duration units are
 | |
|         ms, s, m, h, d, w, y.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     query = params.common cfg.query // {
 | |
| 
 | |
|       grpc-client-tls-secure = mkFlagParam ''
 | |
|         Use TLS when talking to the gRPC server
 | |
|       '';
 | |
| 
 | |
|       grpc-client-tls-cert = mkParam types.str ''
 | |
|         TLS Certificates to use to identify this client to the server
 | |
|       '';
 | |
| 
 | |
|       grpc-client-tls-key = mkParam types.str ''
 | |
|         TLS Key for the client's certificate
 | |
|       '';
 | |
| 
 | |
|       grpc-client-tls-ca = mkParam types.str ''
 | |
|         TLS CA Certificates to use to verify gRPC servers
 | |
|       '';
 | |
| 
 | |
|       grpc-client-server-name = mkParam types.str ''
 | |
|         Server name to verify the hostname on the returned gRPC certificates.
 | |
|         See <link xlink:href="https://tools.ietf.org/html/rfc4366#section-3.1"/>
 | |
|       '';
 | |
| 
 | |
|       web.route-prefix = mkParam types.str ''
 | |
|         Prefix for API and UI endpoints.
 | |
| 
 | |
|         This allows thanos UI to be served on a sub-path. This option is
 | |
|         analogous to <option>web.route-prefix</option> of Promethus.
 | |
|       '';
 | |
| 
 | |
|       web.external-prefix = mkParam types.str ''
 | |
|         Static prefix for all HTML links and redirect URLs in the UI query web
 | |
|         interface.
 | |
| 
 | |
|         Actual endpoints are still served on / or the
 | |
|         <option>web.route-prefix</option>. This allows thanos UI to be served
 | |
|         behind a reverse proxy that strips a URL sub-path.
 | |
|       '';
 | |
| 
 | |
|       web.prefix-header = mkParam types.str ''
 | |
|         Name of HTTP request header used for dynamic prefixing of UI links and
 | |
|         redirects.
 | |
| 
 | |
|         This option is ignored if the option
 | |
|         <literal>web.external-prefix</literal> is set.
 | |
| 
 | |
|         Security risk: enable this option only if a reverse proxy in front of
 | |
|         thanos is resetting the header.
 | |
| 
 | |
|         The setting <literal>web.prefix-header="X-Forwarded-Prefix"</literal>
 | |
|         can be useful, for example, if Thanos UI is served via Traefik reverse
 | |
|         proxy with <literal>PathPrefixStrip</literal> option enabled, which
 | |
|         sends the stripped prefix value in <literal>X-Forwarded-Prefix</literal>
 | |
|         header. This allows thanos UI to be served on a sub-path.
 | |
|       '';
 | |
| 
 | |
|       query.timeout = mkParamDef types.str "2m" ''
 | |
|         Maximum time to process query by query node.
 | |
|       '';
 | |
| 
 | |
|       query.max-concurrent = mkParamDef types.int 20 ''
 | |
|         Maximum number of queries processed concurrently by query node.
 | |
|       '';
 | |
| 
 | |
|       query.replica-label = mkParam types.str ''
 | |
|         Label to treat as a replica indicator along which data is
 | |
|         deduplicated.
 | |
| 
 | |
|         Still you will be able to query without deduplication using
 | |
|         <literal>dedup=false</literal> parameter.
 | |
|       '';
 | |
| 
 | |
|       selector-labels = mkAttrsParam "selector-label" ''
 | |
|         Query selector labels that will be exposed in info endpoint.
 | |
|       '';
 | |
| 
 | |
|       store.addresses = mkListParam "store" ''
 | |
|         Addresses of statically configured store API servers.
 | |
| 
 | |
|         The scheme may be prefixed with <literal>dns+</literal> or
 | |
|         <literal>dnssrv+</literal> to detect store API servers through
 | |
|         respective DNS lookups.
 | |
|       '';
 | |
| 
 | |
|       store.sd-files = mkListParam "store.sd-files" ''
 | |
|         Path to files that contain addresses of store API servers. The path
 | |
|         can be a glob pattern.
 | |
|       '';
 | |
| 
 | |
|       store.sd-interval = mkParamDef types.str "5m" ''
 | |
|         Refresh interval to re-read file SD files. It is used as a resync fallback.
 | |
|       '';
 | |
| 
 | |
|       store.sd-dns-interval = mkParamDef types.str "30s" ''
 | |
|         Interval between DNS resolutions.
 | |
|       '';
 | |
| 
 | |
|       store.unhealthy-timeout = mkParamDef types.str "5m" ''
 | |
|         Timeout before an unhealthy store is cleaned from the store UI page.
 | |
|       '';
 | |
| 
 | |
|       query.auto-downsampling = mkFlagParam ''
 | |
|         Enable automatic adjustment (step / 5) to what source of data should
 | |
|         be used in store gateways if no
 | |
|         <literal>max_source_resolution</literal> param is specified.
 | |
|       '';
 | |
| 
 | |
|       query.partial-response = mkFlagParam ''
 | |
|         Enable partial response for queries if no
 | |
|         <literal>partial_response</literal> param is specified.
 | |
|       '';
 | |
| 
 | |
|       query.default-evaluation-interval = mkParamDef types.str "1m" ''
 | |
|         Set default evaluation interval for sub queries.
 | |
|       '';
 | |
| 
 | |
|       store.response-timeout = mkParamDef types.str "0ms" ''
 | |
|         If a Store doesn't send any data in this specified duration then a
 | |
|         Store will be ignored and partial data will be returned if it's
 | |
|         enabled. <literal>0</literal> disables timeout.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     rule = params.common cfg.rule // params.objstore cfg.rule // {
 | |
| 
 | |
|       labels = mkAttrsParam "label" ''
 | |
|         Labels to be applied to all generated metrics.
 | |
| 
 | |
|         Similar to external labels for Prometheus,
 | |
|         used to identify ruler and its blocks as unique source.
 | |
|       '';
 | |
| 
 | |
|       stateDir = mkStateDirParam "data-dir" "thanos-rule" ''
 | |
|         Data directory relative to <literal>/var/lib</literal>.
 | |
|       '';
 | |
| 
 | |
|       rule-files = mkListParam "rule-file" ''
 | |
|         Rule files that should be used by rule manager. Can be in glob format.
 | |
|       '';
 | |
| 
 | |
|       eval-interval = mkParamDef types.str "30s" ''
 | |
|         The default evaluation interval to use.
 | |
|       '';
 | |
| 
 | |
|       tsdb.block-duration = mkParamDef types.str "2h" ''
 | |
|         Block duration for TSDB block.
 | |
|       '';
 | |
| 
 | |
|       tsdb.retention = mkParamDef types.str "48h" ''
 | |
|         Block retention time on local disk.
 | |
|       '';
 | |
| 
 | |
|       alertmanagers.urls = mkListParam "alertmanagers.url" ''
 | |
|         Alertmanager replica URLs to push firing alerts.
 | |
| 
 | |
|         Ruler claims success if push to at least one alertmanager from
 | |
|         discovered succeeds. The scheme may be prefixed with
 | |
|         <literal>dns+</literal> or <literal>dnssrv+</literal> to detect
 | |
|         Alertmanager IPs through respective DNS lookups. The port defaults to
 | |
|         <literal>9093</literal> or the SRV record's value. The URL path is
 | |
|         used as a prefix for the regular Alertmanager API path.
 | |
|       '';
 | |
| 
 | |
|       alertmanagers.send-timeout = mkParamDef types.str "10s" ''
 | |
|         Timeout for sending alerts to alertmanager.
 | |
|       '';
 | |
| 
 | |
|       alert.query-url = mkParam types.str ''
 | |
|         The external Thanos Query URL that would be set in all alerts 'Source' field.
 | |
|       '';
 | |
| 
 | |
|       alert.label-drop = mkListParam "alert.label-drop" ''
 | |
|         Labels by name to drop before sending to alertmanager.
 | |
| 
 | |
|         This allows alert to be deduplicated on replica label.
 | |
| 
 | |
|         Similar Prometheus alert relabelling
 | |
|       '';
 | |
| 
 | |
|       web.route-prefix = mkParam types.str ''
 | |
|         Prefix for API and UI endpoints.
 | |
| 
 | |
|         This allows thanos UI to be served on a sub-path.
 | |
| 
 | |
|         This option is analogous to <literal>--web.route-prefix</literal> of Promethus.
 | |
|       '';
 | |
| 
 | |
|       web.external-prefix = mkParam types.str ''
 | |
|         Static prefix for all HTML links and redirect URLs in the UI query web
 | |
|         interface.
 | |
| 
 | |
|         Actual endpoints are still served on / or the
 | |
|         <option>web.route-prefix</option>. This allows thanos UI to be served
 | |
|         behind a reverse proxy that strips a URL sub-path.
 | |
|       '';
 | |
| 
 | |
|       web.prefix-header = mkParam types.str ''
 | |
|         Name of HTTP request header used for dynamic prefixing of UI links and
 | |
|         redirects.
 | |
| 
 | |
|         This option is ignored if the option
 | |
|         <option>web.external-prefix</option> is set.
 | |
| 
 | |
|         Security risk: enable this option only if a reverse proxy in front of
 | |
|         thanos is resetting the header.
 | |
| 
 | |
|         The header <literal>X-Forwarded-Prefix</literal> can be useful, for
 | |
|         example, if Thanos UI is served via Traefik reverse proxy with
 | |
|         <literal>PathPrefixStrip</literal> option enabled, which sends the
 | |
|         stripped prefix value in <literal>X-Forwarded-Prefix</literal>
 | |
|         header. This allows thanos UI to be served on a sub-path.
 | |
|       '';
 | |
| 
 | |
|       query.addresses = mkListParam "query" ''
 | |
|         Addresses of statically configured query API servers.
 | |
| 
 | |
|         The scheme may be prefixed with <literal>dns+</literal> or
 | |
|         <literal>dnssrv+</literal> to detect query API servers through
 | |
|         respective DNS lookups.
 | |
|       '';
 | |
| 
 | |
|       query.sd-files = mkListParam "query.sd-files" ''
 | |
|         Path to file that contain addresses of query peers.
 | |
|         The path can be a glob pattern.
 | |
|       '';
 | |
| 
 | |
|       query.sd-interval = mkParamDef types.str "5m" ''
 | |
|         Refresh interval to re-read file SD files. (used as a fallback)
 | |
|       '';
 | |
| 
 | |
|       query.sd-dns-interval = mkParamDef types.str "30s" ''
 | |
|         Interval between DNS resolutions.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     compact = params.log // params.tracing cfg.compact // params.objstore cfg.compact // {
 | |
| 
 | |
|       http-address = mkParamDef types.str "0.0.0.0:10902" ''
 | |
|         Listen <literal>host:port</literal> for HTTP endpoints.
 | |
|       '';
 | |
| 
 | |
|       stateDir = mkStateDirParam "data-dir" "thanos-compact" ''
 | |
|         Data directory relative to <literal>/var/lib</literal>
 | |
|         in which to cache blocks and process compactions.
 | |
|       '';
 | |
| 
 | |
|       consistency-delay = mkParamDef types.str "30m" ''
 | |
|         Minimum age of fresh (non-compacted) blocks before they are being
 | |
|         processed. Malformed blocks older than the maximum of consistency-delay
 | |
|         and 30m0s will be removed.
 | |
|       '';
 | |
| 
 | |
|       retention.resolution-raw = mkParamDef types.str "0d" ''
 | |
|         How long to retain raw samples in bucket.
 | |
| 
 | |
|         <literal>0d</literal> - disables this retention
 | |
|       '';
 | |
| 
 | |
|       retention.resolution-5m = mkParamDef types.str "0d" ''
 | |
|         How long to retain samples of resolution 1 (5 minutes) in bucket.
 | |
| 
 | |
|         <literal>0d</literal> - disables this retention
 | |
|       '';
 | |
| 
 | |
|       retention.resolution-1h = mkParamDef types.str "0d" ''
 | |
|         How long to retain samples of resolution 2 (1 hour) in bucket.
 | |
| 
 | |
|         <literal>0d</literal> - disables this retention
 | |
|       '';
 | |
| 
 | |
|       startAt = {
 | |
|         toArgs = _opt: startAt: flagToArgs "wait" (startAt == null);
 | |
|         option = nullOpt types.str ''
 | |
|           When this option is set to a <literal>systemd.time</literal>
 | |
|           specification the Thanos compactor will run at the specified period.
 | |
| 
 | |
|           When this option is <literal>null</literal> the Thanos compactor service
 | |
|           will run continuously. So it will not exit after all compactions have
 | |
|           been processed but wait for new work.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       downsampling.disable = mkFlagParam ''
 | |
|         Disables downsampling.
 | |
| 
 | |
|         This is not recommended as querying long time ranges without
 | |
|         non-downsampled data is not efficient and useful e.g it is not possible
 | |
|         to render all samples for a human eye anyway
 | |
|       '';
 | |
| 
 | |
|       block-sync-concurrency = mkParamDef types.int 20 ''
 | |
|         Number of goroutines to use when syncing block metadata from object storage.
 | |
|       '';
 | |
| 
 | |
|       compact.concurrency = mkParamDef types.int 1 ''
 | |
|         Number of goroutines to use when compacting groups.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     downsample = params.log // params.tracing cfg.downsample // params.objstore cfg.downsample // {
 | |
| 
 | |
|       stateDir = mkStateDirParam "data-dir" "thanos-downsample" ''
 | |
|         Data directory relative to <literal>/var/lib</literal>
 | |
|         in which to cache blocks and process downsamplings.
 | |
|       '';
 | |
| 
 | |
|     };
 | |
| 
 | |
|     receive = params.common cfg.receive // params.objstore cfg.receive // {
 | |
| 
 | |
|       remote-write.address = mkParamDef types.str "0.0.0.0:19291" ''
 | |
|         Address to listen on for remote write requests.
 | |
|       '';
 | |
| 
 | |
|       stateDir = mkStateDirParam "tsdb.path" "thanos-receive" ''
 | |
|         Data directory relative to <literal>/var/lib</literal> of TSDB.
 | |
|       '';
 | |
| 
 | |
|       labels = mkAttrsParam "labels" ''
 | |
|         External labels to announce.
 | |
| 
 | |
|         This flag will be removed in the future when handling multiple tsdb
 | |
|         instances is added.
 | |
|       '';
 | |
| 
 | |
|       tsdb.retention = mkParamDef types.str "15d" ''
 | |
|         How long to retain raw samples on local storage.
 | |
| 
 | |
|         <literal>0d</literal> - disables this retention
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|   };
 | |
| 
 | |
|   assertRelativeStateDir = cmd: {
 | |
|     assertions = [
 | |
|       {
 | |
|         assertion = !hasPrefix "/" cfg.${cmd}.stateDir;
 | |
|         message =
 | |
|           "The option services.thanos.${cmd}.stateDir should not be an absolute directory." +
 | |
|           " It should be a directory relative to /var/lib.";
 | |
|       }
 | |
|     ];
 | |
|   };
 | |
| 
 | |
| in {
 | |
| 
 | |
|   options.services.thanos = {
 | |
| 
 | |
|     package = mkOption {
 | |
|       type = types.package;
 | |
|       default = pkgs.thanos;
 | |
|       defaultText = "pkgs.thanos";
 | |
|       description = ''
 | |
|         The thanos package that should be used.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     sidecar = paramsToOptions params.sidecar // {
 | |
|       enable = mkEnableOption
 | |
|         "the Thanos sidecar for Prometheus server";
 | |
|       arguments = mkArgumentsOption "sidecar";
 | |
|     };
 | |
| 
 | |
|     store = paramsToOptions params.store // {
 | |
|       enable = mkEnableOption
 | |
|         "the Thanos store node giving access to blocks in a bucket provider.";
 | |
|       arguments = mkArgumentsOption "store";
 | |
|     };
 | |
| 
 | |
|     query = paramsToOptions params.query // {
 | |
|       enable = mkEnableOption
 | |
|         ("the Thanos query node exposing PromQL enabled Query API " +
 | |
|          "with data retrieved from multiple store nodes");
 | |
|       arguments = mkArgumentsOption "query";
 | |
|     };
 | |
| 
 | |
|     rule = paramsToOptions params.rule // {
 | |
|       enable = mkEnableOption
 | |
|         ("the Thanos ruler service which evaluates Prometheus rules against" +
 | |
|         " given Query nodes, exposing Store API and storing old blocks in bucket");
 | |
|       arguments = mkArgumentsOption "rule";
 | |
|     };
 | |
| 
 | |
|     compact = paramsToOptions params.compact // {
 | |
|       enable = mkEnableOption
 | |
|         "the Thanos compactor which continuously compacts blocks in an object store bucket";
 | |
|       arguments = mkArgumentsOption "compact";
 | |
|     };
 | |
| 
 | |
|     downsample = paramsToOptions params.downsample // {
 | |
|       enable = mkEnableOption
 | |
|         "the Thanos downsampler which continuously downsamples blocks in an object store bucket";
 | |
|       arguments = mkArgumentsOption "downsample";
 | |
|     };
 | |
| 
 | |
|     receive = paramsToOptions params.receive // {
 | |
|       enable = mkEnableOption
 | |
|         ("the Thanos receiver which accept Prometheus remote write API requests " +
 | |
|          "and write to local tsdb (EXPERIMENTAL, this may change drastically without notice)");
 | |
|       arguments = mkArgumentsOption "receive";
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   config = mkMerge [
 | |
| 
 | |
|     (mkIf cfg.sidecar.enable {
 | |
|       assertions = [
 | |
|         {
 | |
|           assertion = config.services.prometheus.enable;
 | |
|           message =
 | |
|             "Please enable services.prometheus when enabling services.thanos.sidecar.";
 | |
|         }
 | |
|         {
 | |
|           assertion = !(config.services.prometheus.globalConfig.external_labels == null ||
 | |
|                         config.services.prometheus.globalConfig.external_labels == {});
 | |
|           message =
 | |
|             "services.thanos.sidecar requires uniquely identifying external labels " +
 | |
|             "to be configured in the Prometheus server. " +
 | |
|             "Please set services.prometheus.globalConfig.external_labels.";
 | |
|         }
 | |
|       ];
 | |
|       systemd.services.thanos-sidecar = {
 | |
|         wantedBy = [ "multi-user.target" ];
 | |
|         after    = [ "network.target" "prometheus.service" ];
 | |
|         serviceConfig = {
 | |
|           User = "prometheus";
 | |
|           Restart = "always";
 | |
|           ExecStart = thanos "sidecar";
 | |
|         };
 | |
|       };
 | |
|     })
 | |
| 
 | |
|     (mkIf cfg.store.enable (mkMerge [
 | |
|       (assertRelativeStateDir "store")
 | |
|       {
 | |
|         systemd.services.thanos-store = {
 | |
|           wantedBy = [ "multi-user.target" ];
 | |
|           after    = [ "network.target" ];
 | |
|           serviceConfig = {
 | |
|             DynamicUser = true;
 | |
|             StateDirectory = cfg.store.stateDir;
 | |
|             Restart = "always";
 | |
|             ExecStart = thanos "store";
 | |
|           };
 | |
|         };
 | |
|       }
 | |
|     ]))
 | |
| 
 | |
|     (mkIf cfg.query.enable {
 | |
|       systemd.services.thanos-query = {
 | |
|         wantedBy = [ "multi-user.target" ];
 | |
|         after    = [ "network.target" ];
 | |
|         serviceConfig = {
 | |
|           DynamicUser = true;
 | |
|           Restart = "always";
 | |
|           ExecStart = thanos "query";
 | |
|         };
 | |
|       };
 | |
|     })
 | |
| 
 | |
|     (mkIf cfg.rule.enable (mkMerge [
 | |
|       (assertRelativeStateDir "rule")
 | |
|       {
 | |
|         systemd.services.thanos-rule = {
 | |
|           wantedBy = [ "multi-user.target" ];
 | |
|           after    = [ "network.target" ];
 | |
|           serviceConfig = {
 | |
|             DynamicUser = true;
 | |
|             StateDirectory = cfg.rule.stateDir;
 | |
|             Restart = "always";
 | |
|             ExecStart = thanos "rule";
 | |
|           };
 | |
|         };
 | |
|       }
 | |
|     ]))
 | |
| 
 | |
|     (mkIf cfg.compact.enable (mkMerge [
 | |
|       (assertRelativeStateDir "compact")
 | |
|       {
 | |
|         systemd.services.thanos-compact =
 | |
|           let wait = cfg.compact.startAt == null; in {
 | |
|             wantedBy = [ "multi-user.target" ];
 | |
|             after    = [ "network.target" ];
 | |
|             serviceConfig = {
 | |
|               Type    = if wait then "simple" else "oneshot";
 | |
|               Restart = if wait then "always" else "no";
 | |
|               DynamicUser = true;
 | |
|               StateDirectory = cfg.compact.stateDir;
 | |
|               ExecStart = thanos "compact";
 | |
|             };
 | |
|           } // optionalAttrs (!wait) { inherit (cfg.compact) startAt; };
 | |
|       }
 | |
|     ]))
 | |
| 
 | |
|     (mkIf cfg.downsample.enable (mkMerge [
 | |
|       (assertRelativeStateDir "downsample")
 | |
|       {
 | |
|         systemd.services.thanos-downsample = {
 | |
|           wantedBy = [ "multi-user.target" ];
 | |
|           after    = [ "network.target" ];
 | |
|           serviceConfig = {
 | |
|             DynamicUser = true;
 | |
|             StateDirectory = cfg.downsample.stateDir;
 | |
|             Restart = "always";
 | |
|             ExecStart = thanos "downsample";
 | |
|           };
 | |
|         };
 | |
|       }
 | |
|     ]))
 | |
| 
 | |
|     (mkIf cfg.receive.enable (mkMerge [
 | |
|       (assertRelativeStateDir "receive")
 | |
|       {
 | |
|         systemd.services.thanos-receive = {
 | |
|           wantedBy = [ "multi-user.target" ];
 | |
|           after    = [ "network.target" ];
 | |
|           serviceConfig = {
 | |
|             DynamicUser = true;
 | |
|             StateDirectory = cfg.receive.stateDir;
 | |
|             Restart = "always";
 | |
|             ExecStart = thanos "receive";
 | |
|           };
 | |
|         };
 | |
|       }
 | |
|     ]))
 | |
| 
 | |
|   ];
 | |
| }
 | 
