The agent always requires a main config file on a local filesystem, but values within that config can pull from other sources. These sources include other files on the filesystem or KV stores such as Zookeeper, Etcd, and Consul. Additional stores can be easily added.
A remote config value looks like this in the main config file:
signalFxAccessToken: {"#from": "/etc/signalfx/token"}
The remote config specification is a YAML map object that includes the #from
key. The value of that key is the path from which to get the config value.
The value of the #from
key has the form <source>:<path>
. If it is only a
path with no <source>:
, it is assumed to be a file path on the local
filesystem. All non-filesystem sources must be configured in the
sourceConfig
section of the main config file.
If the source is a reference to a single path, that value is deserialized by YAML and inserted into the config as if it had been literally in the config as such. The replacement is done in such a way that you don't need to worry about matching indentation of remote values.
For information on the sources for remote configuration, along with a full list of config sources and their options, see configSources option in the main agent config file.
The most basic way to reference a value is to use a single, non-globbed path. The content stored at that path can be simple scalar values such as strings or integers, or YAML collections such as sequences or maps. The only requirement is that they deserialize from YAML properly. Note that JSON is a subset of YAML, so any valid JSON can also be used.
Only supported by Vault remote config.
The Vault remote config source supports reaching into secret data that is of a map type and pulling out a specific value. This is necessary in Vault because of how secrets are structured.
Accessing nested data uses a syntax similar to many programming languages for
accessing a "map-like" object: square brackets. E.g. to access the password
field of a Vault secret, you would use the following:
{"#from": "vault:secret/my-database[password]"}
You can also reach into nested map values by separating the keys by .
. For
example, when using the KV v2 secret engine in Vault, all data will be nested
under a separate data
map within the secret. You would access the same
password field in that by doing:
{"#from": "vault:secret/data/my-database[data.password]"}
If the given key doesn't exist in the secret, the value will resolve to null
and the agent config will fail to load (unless the option has optional: true
on it, see below).
Unless debug logging is enabled, the secret values will never be logged.
Not supported by Vault remote config.
Some config sources support globbing in the source path. If there is a glob in the source path, the YAML content of the matching paths will be read and deserialized. All of the values must be YAML collections of the same type (i.e. either all a sequence or all a map), or else an error is raised. All of those collections will be merged together and treated as one collection.
You can flatten both sequences and maps into the parent of the item where the remote value is specified. For example:
monitors:
- type: collectd/mysql
username: signalfx
databases:
- name: admin
- {"#from": "zk:/signalfx-agent/mysql/databases/*", flatten: true}
Given the following znodes name and values in ZooKeeper:
/signalfx-agent/mysql/databases/app1
:[{name: my-db1}, {name: my-db2}]
/signalfx-agent/mysql/databases/app2
:[{name: their-db1}, {name: their-db2}]
The final resolved config would look like this:
monitors:
- type: collectd/mysql
username: signalfx
databases:
- name: admin
- name: my-db1
- name: my-db2
- name: their-db1
- name: their-db2
You may want to allow for globbed paths that don't actually match anything. This is very useful for specifying a directory of extra monitor configurations that may be empty, such as the following:
signalFxAccessToken: abcd
monitors:
- {"#from": "/etc/signalfx/conf2/*.yaml", flatten: true, optional: true}
- type: cpu
- type: filesystems
The key here is the optional: true
value, which makes it accept globs that
don't match anything. optional
defaults to false
so it must be explicitly
stated that you are ok with no matches.
optional
also works in scalar contexts as well, assuming that the config value
is not required by the agent.
If you have values in files/KV stores that you don't want interpreted as YAML,
but rather as plain strings, you can add the raw: true
option to the remote
value specification. Everything else acts as it would otherwise.
The config file also supports environment variable interpolation with the
${VARNAME}
syntax (the curly brackets are required). Environment variables
are interpolated after all of the remote config values are interpolated,
which means that remote config values can contain references to envvars, if so
desired. Envvars cannot, however, contain remote config values.
For more advanced environment variable interpolation you can use the remote
config value syntax with the env
type. For example:
signalFxAccessToken: {"#from": "env:SIGNALFX_ACCESS_TOKEN"}
will interpolate the given environment variable to that place in the config
file. The advantage of this format over the plain ${VARNAME}
syntax is that
you can use all of the advanced features of remote config, such as flattening
and defaults, which are not possible with the ${}
syntax.
The env var remote config source does not pick up changes to envvars that happen after the initial source resolution.
You can further process the remote config values by using the jsonPath: "<json path expression>"
option on the remote config #from
object. This will
treat each of the values that the path resolves to as JSON and will pull out
the value(s) expressed by the JSON Path expression. For more information on
JSONPath syntax, see https://goessner.net/articles/JsonPath/.
For example, if you had the environment variable SYSTEM_INFO
with the value
{"host": "foobar.com", "os": "linux", "env": "prod1"}
and wanted to set a
global dimension on the agent with the value of the env
key, you could use the
following agent config:
hostname: {"#from": "env:SYSTEM_INFO", jsonPath: "$.env"}
If you need more sophisticated interpolation of config values from KV stores, we recommend using a third-party templating solution such as confd, or writing your own custom script.