consul-template
Template rendering, notifier, and supervisor for @HashiCorp Consul and Vault data.
Top Related Projects
The Prometheus monitoring system and time series database.
Production-Grade Container Scheduling and Management
Library for configuration management API
AWS Service registry for resilient mid-tier load balancing and failover.
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.
Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more.
Quick Overview
Consul Template is a tool that watches a set of templates on the file system, renders them to the destination whenever the watched data changes, and can optionally reload the dependent service. It is primarily used in conjunction with Consul, but can also be used with Vault and other key/value stores.
Pros
- Dynamic Configuration: Consul Template allows you to dynamically update your application's configuration based on changes in your service discovery or key-value store.
- Templating Capabilities: It provides a powerful templating engine that allows you to generate complex configuration files from multiple data sources.
- Reliability: Consul Template is designed to be highly reliable, with features like retries, backoffs, and health checks to ensure that your configuration updates are applied successfully.
- Extensibility: Consul Template can be extended with custom functions and data sources, making it a flexible tool for a variety of use cases.
Cons
- Complexity: Consul Template can be complex to set up and configure, especially for larger or more complex environments.
- Dependency on Consul: While Consul Template can work with other key-value stores, it is primarily designed to work with Consul, which may not be the best fit for all use cases.
- Performance Overhead: Depending on the complexity of your templates and the frequency of changes, Consul Template can add some performance overhead to your application.
- Limited Error Handling: Consul Template's error handling can be limited, which can make it difficult to troubleshoot issues in some cases.
Code Examples
Consul Template is a command-line tool, so there are no code examples to provide. However, here's an example of a basic Consul Template configuration file:
template {
source = "/path/to/template.ctmpl"
destination = "/path/to/rendered.conf"
command = "restart_service.sh"
}
vault {
address = "https://vault.example.com"
token = "your-vault-token"
}
consul {
address = "consul.example.com:8500"
}
This configuration file tells Consul Template to watch the template.ctmpl
file, render it to the rendered.conf
file, and run the restart_service.sh
script whenever the template changes. It also configures Consul Template to connect to a Vault instance and a Consul cluster.
Getting Started
To get started with Consul Template, follow these steps:
-
Download the Consul Template binary from the GitHub releases page.
-
Create a configuration file (e.g.,
config.hcl
) that specifies the templates you want to watch and the actions you want to take when they change. -
Run Consul Template with the configuration file:
consul-template -config=config.hcl
-
Consul Template will start watching the specified templates and rendering them to the destination files. Whenever the watched data changes, Consul Template will re-render the templates and execute the specified commands.
You can find more detailed instructions and examples in the Consul Template documentation.
Competitor Comparisons
The Prometheus monitoring system and time series database.
Pros of Prometheus
- Prometheus is a powerful and widely-adopted open-source monitoring and alerting system, making it a robust and reliable choice for monitoring infrastructure and applications.
- The Prometheus query language, PromQL, provides a flexible and expressive way to analyze and visualize time-series data, enabling advanced monitoring and troubleshooting capabilities.
- Prometheus has a large and active community, with a wealth of documentation, plugins, and integrations available, making it easy to extend and customize for specific use cases.
Cons of Prometheus
- Prometheus can be more complex to set up and configure compared to Consul Template, especially for larger and more complex environments.
- The resource requirements of Prometheus, particularly in terms of storage and processing power, can be higher than those of Consul Template, which may be a consideration for some use cases.
- Prometheus does not provide the same level of service discovery and configuration management capabilities as Consul Template, which may be important for some users.
Code Comparison
Prometheus:
func main() {
log.Info("Starting Prometheus Server")
// Set up the Prometheus server
promServer := web.New()
promServer.Run()
// Wait for termination signal
<-promServer.Ready()
log.Info("Prometheus Server Stopped")
}
Consul Template:
func main() {
config := config.DefaultConfig()
config.Merge(flag.CommandLine)
// Create a new Consul Template runner
runner, err := runner.NewRunner(config)
if err != nil {
log.Fatalf("Failed to create Consul Template runner: %v", err)
}
// Run the Consul Template runner
runner.Run()
}
Production-Grade Container Scheduling and Management
Pros of Kubernetes
- Kubernetes is a comprehensive and feature-rich container orchestration platform, providing a wide range of capabilities beyond what Consul Template offers.
- Kubernetes has a large and active community, with extensive documentation, resources, and ecosystem support.
- Kubernetes offers advanced scheduling, scaling, and self-healing capabilities for containerized applications.
Cons of Kubernetes
- Kubernetes has a steeper learning curve compared to Consul Template, requiring more time and effort to set up and configure.
- Kubernetes can be resource-intensive, requiring more hardware and infrastructure to run effectively.
- Kubernetes may be overkill for simpler use cases where Consul Template's more focused functionality might be sufficient.
Code Comparison
Consul Template:
template {
source = "/etc/consul-template/templates/nginx.ctmpl"
destination = "/etc/nginx/conf.d/default.conf"
command = "nginx -s reload"
}
Kubernetes:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Library for configuration management API
Pros of Archaius
- Archaius provides a more comprehensive set of features for managing application configuration, including support for dynamic updates, type conversion, and hierarchical configuration sources.
- Archaius has a larger and more active community, with more contributors and a wider range of use cases.
- Archaius is more tightly integrated with the Netflix ecosystem, which may be beneficial for organizations already using other Netflix tools.
Cons of Archaius
- Archaius has a steeper learning curve and more complex API compared to Consul Template, which may be a barrier for some users.
- Archaius is primarily focused on the Java ecosystem, while Consul Template is language-agnostic and can be used with a wider range of applications.
- Archaius may have higher resource requirements and a larger footprint compared to Consul Template, which is designed to be lightweight and efficient.
Code Comparison
Consul Template:
template {
source = "/path/to/template.ctmpl"
destination = "/path/to/rendered.txt"
command = "restart_app.sh"
}
Archaius:
DynamicPropertyFactory dynamicPropertyFactory = DynamicPropertyFactory.getInstance();
DynamicStringProperty myProperty = dynamicPropertyFactory.getStringProperty("my.property", "default value");
String value = myProperty.get();
AWS Service registry for resilient mid-tier load balancing and failover.
Pros of Eureka
- Eureka provides a simple and lightweight service discovery mechanism, making it easy to integrate into existing applications.
- Eureka has a well-documented and easy-to-use API, allowing developers to quickly integrate it into their projects.
- Eureka is highly scalable and can handle a large number of registered services, making it suitable for large-scale applications.
Cons of Eureka
- Eureka is primarily focused on service discovery and does not provide additional features like configuration management or health checking, which may be required in more complex environments.
- Eureka is tightly coupled with the JVM and may not be the best choice for non-Java-based applications.
- Eureka's client-side load balancing may not be as flexible or feature-rich as other service discovery solutions.
Code Comparison
Consul Template:
template {
source = "nginx.conf.ctmpl"
destination = "/etc/nginx/nginx.conf"
command = "/usr/local/bin/nginx -s reload"
}
Eureka:
public class EurekaInstanceConfig implements InstanceInfo.InstanceInfoGenerator {
@Override
public InstanceInfo get(ApplicationInfoManager applicationInfoManager) {
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();
// Set instance information
return builder.build();
}
}
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.
Pros of Ribbon
- Ribbon provides a client-side load balancing solution, which can be beneficial in certain scenarios where server-side load balancing is not feasible or desirable.
- Ribbon supports a wide range of load balancing algorithms, including Round Robin, Weighted Round Robin, and Least Connections, allowing for more flexibility in load balancing strategies.
- Ribbon integrates with other Netflix projects, such as Eureka, which can simplify the overall service discovery and load balancing setup.
Cons of Ribbon
- Ribbon is primarily focused on client-side load balancing, while Consul Template is a more general-purpose tool that can be used for a wider range of use cases, such as generating configuration files from Consul data.
- Ribbon may have a higher learning curve compared to Consul Template, as it requires more integration with other Netflix projects and a deeper understanding of client-side load balancing concepts.
- Ribbon is primarily used within the Netflix ecosystem, while Consul Template has a broader user base and is more widely adopted across different organizations and industries.
Code Comparison
Consul Template:
template {
source = "nginx.conf.ctmpl"
destination = "/etc/nginx/nginx.conf"
command = "/usr/sbin/nginx -s reload"
}
Ribbon:
ILoadBalancer lb = ClientFactory.getNamedLoadBalancer("myService");
Server server = lb.chooseServer("myInstanceId");
Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more.
Pros of Zuul
- Zuul provides a dynamic routing and filtering mechanism, allowing for more flexible and scalable API management.
- Zuul supports a wide range of features, including load balancing, security, and monitoring, making it a comprehensive API gateway solution.
- Zuul's integration with other Netflix projects, such as Eureka and Ribbon, can simplify the overall microservices architecture.
Cons of Zuul
- Zuul's complexity and feature set may be overkill for smaller projects or simpler API management requirements.
- Zuul's dependency on the Netflix ecosystem may make it less suitable for non-Netflix-based environments.
- Zuul's documentation and community support may not be as extensive as that of Consul Template.
Code Comparison
Consul Template:
template {
source = "nginx.conf.ctmpl"
destination = "/etc/nginx/nginx.conf"
command = "/usr/local/bin/nginx -s reload"
}
Zuul:
@EnableZuulProxy
@SpringBootApplication
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Consul Template
This project provides a convenient way to populate values from Consul
into the file system using the consul-template
daemon.
The daemon consul-template
queries a Consul, Vault, or Nomad
cluster and updates any number of specified templates on the file system. As an
added bonus, it can optionally run arbitrary commands when the update process
completes. Please see the examples folder for some scenarios where
this functionality might prove useful.
The documentation in this README corresponds to the main branch of Consul Template. It may contain unreleased features or different APIs than the most recently released version.
Please see the Git tag that corresponds to your version of Consul Template for the proper documentation.
Table of Contents
- Community Support
- Installation
- Quick Example
- Learn Guides
- Configuration
- Command Line Flags
- Configuration File
- Reload Configuration and Templates
- Templating Language
- Observability
- Logging
- Modes
- Once Mode
- De-Duplication Mode
- Exec Mode
- Plugins
- Caveats
- Docker Image Use
- Dots in Service Names
- Termination on Error
- Commands
- Multi-phase Execution
- Debugging
- FAQ
- Contributing
Community Support
If you have questions about how consul-template works, its capabilities or anything other than a bug or feature request (use github's issue tracker for those), please see our community support resources.
Community portal: https://discuss.hashicorp.com/tags/c/consul/29/consul-template
Other resources: https://www.consul.io/community.html
Additionally, for issues and pull requests, we'll be using the :+1: reactions as a rough voting system to help gauge community priorities. So please add :+1: to any issue or pull request you'd like to see worked on. Thanks.
Installation
-
Download a pre-compiled, released version from the Consul Template releases page.
-
Extract the binary using
unzip
ortar
. -
Move the binary into
$PATH
.
To compile from source, please see the instructions in the contributing section.
Quick Example
This short example assumes Consul is installed locally.
- Start a Consul cluster in dev mode:
$ consul agent -dev
- Author a template
in.tpl
to query the kv store:
{{ key "foo" }}
- Start Consul Template:
$ consul-template -template "in.tpl:out.txt" -once
- Write data to the key in Consul:
$ consul kv put foo bar
- Observe Consul Template has written the file
out.txt
:
$ cat out.txt
bar
For more examples and use cases, please see the examples folder in this repository.
Learn Guides
In addition to these examples, HashiCorp has published guides and official documentation to help walk through a few common use cases for Consul Template.
Configuration
Configuration documentation has been moved to docs/configuration.md.
Reload Configuration and Templates
While there are multiple ways to run Consul Template, the most common pattern is to run Consul Template as a system service. When Consul Template first starts, it reads any configuration files and templates from disk and loads them into memory. From that point forward, changes to the files on disk do not propagate to running process without a reload.
The reason for this behavior is simple and aligns with other tools like haproxy.
A user may want to perform pre-flight validation checks on the configuration or
templates before loading them into the process. Additionally, a user may want to
update configuration and templates simultaneously. Having Consul Template
automatically watch and reload those files on changes is both operationally
dangerous and against some of the paradigms of modern infrastructure. Instead,
Consul Template listens for the SIGHUP
syscall to trigger a configuration
reload. If you update configuration or templates, simply send HUP
to the
running Consul Template process and Consul Template will reload all the
configurations and templates from disk.
Templating Language
Templating Language documentation has been moved to docs/templating-language.md.
Caveats
Docker Image Use
The Alpine Docker image is configured to support an external volume to render shared templates to. If mounted you will need to make sure that the consul-template user in the docker image has write permissions to the directory. Also if you build your own image using these you need to be sure you have the permissions correct.
The consul-template user in docker has a UID of 100 and a GID of 1000.
This effects the in image directories /consul-template/config, used to add configuration when using this as a parent image, and /consul-template/data, exported as a VOLUME as a location to render shared results.
Previously the image initially ran as root in order to ensure the permissions allowed it. But this ran against docker best practices and security policies.
If you build your own image based on ours you can override these values with
--build-arg
parameters.
Dots in Service Names
Using dots .
in service names will conflict with the use of dots for TAG
delineation in the
template. Dots already interfere with using
DNS
for service names, so we recommend avoiding dots wherever possible.
Termination on Error
By default Consul Template is highly fault-tolerant. If Consul is unreachable or
a template changes, Consul Template will happily continue running. The only
exception to this rule is if the optional command
exits non-zero. In this
case, Consul Template will also exit non-zero. The reason for this decision is
so the user can easily configure something like Upstart or God to manage Consul
Template as a service.
If you want Consul Template to continue watching for changes, even if the
optional command argument fails, you can append || true
to your command. Note
that ||
is a "shell-ism", not a built-in function. You will also need to run
your command under a shell:
$ consul-template \
-template "in.ctmpl:out.file:/bin/bash -c 'service nginx restart || true'"
In this example, even if the Nginx restart command returns non-zero, the overall
function will still return an OK exit code; Consul Template will continue to run
as a service. Additionally, if you have complex logic for restarting your
service, you can intelligently choose when you want Consul Template to exit and
when you want it to continue to watch for changes. For these types of complex
scripts, we recommend using a custom sh or bash script instead of putting the
logic directly in the consul-template
command or configuration file.
Commands
Environment
The current processes environment is used when executing commands with the following additional environment variables:
CONSUL_HTTP_ADDR
CONSUL_HTTP_TOKEN
CONSUL_HTTP_TOKEN_FILE
CONSUL_HTTP_AUTH
CONSUL_HTTP_SSL
CONSUL_HTTP_SSL_VERIFY
NOMAD_ADDR
NOMAD_NAMESPACE
NOMAD_TOKEN
These environment variables are exported with their current values when the
command executes. Other Consul tooling reads these environment variables,
providing smooth integration with other Consul tools (like consul maint
or
consul lock
). Additionally, exposing these environment variables gives power
users the ability to further customize their command script.
Multiple Commands
The command configured for running on template rendering must take one of two forms.
The first is as a list of the command and arguments split at spaces. The command can use an absolute path or be found on the execution environment's PATH and must be the first item in the list. This form allows for single or multi-word commands that can be executed directly with a system call. For example...
command = ["echo", "hello"]
command = ["/opt/foo-package/bin/run-foo"]
command = ["foo"]
Note that if you give a single command without the list denoting square
brackets ([]
) it is converted into a list with a single argument.
This:
command = "foo"
is equivalent to:
command = ["foo"]
The second form is as a single quoted command using system shell features. This
form requires a shell named sh
be on the executable search path (eg. PATH
on *nix). This is the standard on all *nix systems and should work out of the
box on those systems. This won't work on, for example, Docker images with only
the executable and without a minimal system like Alpine. Using this form you
can join multiple commands with logical operators, &&
and ||
, use pipelines
with |
, conditionals, etc. Note that the shell sh
is normally /bin/sh
on
*nix systems and is either a POSIX shell or a shell run in POSIX compatible
mode, so it is best to stick to POSIX shell syntax in this command. For
example..
command = "/opt/foo && /opt/bar"
command = "if /opt/foo ; then /opt/bar ; fi"
Using this method you can run as many shell commands as you need with whatever logic you need. Though it is suggested that if it gets too long you might want to wrap it in a shell script, deploy and run that.
Shell Commands and Exec Mode
Using the system shell based command has one additional caveat when used for the Exec mode process (the managed, executed process to which it will propagate signals). That is to get signals to work correctly means not only does anything the shell runs need to handle signals, but the shell itself needs to handle them. This needs to be managed by you as shells will exit upon receiving most signals.
A common example of this would be wanting the SIGHUP signal to trigger a reload
of the underlying process and to be ignored by the shell process. To get this
you have 2 options, you can use trap
to ignore the signal or you can use
exec
to replace the shell with another process.
To use trap
to ignore the signal, you call trap
to catch the signal in the
shell with no action. For example if you had an underlying nginx process you
wanted to run with a shell command and have the shell ignore it you'd do..
command = "trap '' HUP; /usr/sbin/nginx -c /etc/nginx/nginx.conf"
The trap '' HUP;
bit is enough to get the shell to ignore the HUP signal. If
you left off the trap
command nginx would reload but the shell command would
exit but leave the nginx still running, not unmanaged.
Alternatively using exec
will replace the shell's process with a sub-process,
keeping the same PID and process grouping (allowing the sub-process to be
managed). This is simpler, but a bit less flexible than trap
, and looks
like..
command = "exec /usr/sbin/nginx -c /etc/nginx/nginx.conf"
Where the nginx process would replace the enclosing shell process to be managed
by consul-template, receiving the Signals directly. Basically exec
eliminates
the shell from the equation.
See your shell's documentation on trap
and/or exec
for more details on this.
Multi-phase Execution
Consul Template does an n-pass evaluation of templates, accumulating dependencies on each pass. This is required due to nested dependencies, such as:
{{ range services }}
{{ range service .Name }}
{{ .Address }}
{{ end }}{{ end }}
During the first pass, Consul Template does not know any of the services in Consul, so it has to perform a query. When those results are returned, the inner-loop is then evaluated with that result, potentially creating more queries and watches.
Because of this implementation, template functions need a default value that is
an acceptable parameter to a range
function (or similar), but does not
actually execute the inner loop (which would cause a panic). This is important
to mention because complex templates must account for the "empty" case. For
example, the following will not work:
{{ with index (service "foo") 0 }}
# ...
{{ end }}
This will raise an error like:
<index $services 0>: error calling index: index out of range: 0
That is because, during the first evaluation of the template, the service
key is returning an empty slice. You can account for this in your template like
so:
{{ with service "foo" }}
{{ with index . 0 }}
{{ .Node }}{{ end }}{{ end }}
This will still add the dependency to the list of watches, but will not evaluate the inner-if, avoiding the out-of-index error.
Debugging
Consul Template can print verbose debugging output. To set the log level for
Consul Template, use the -log-level
flag:
$ consul-template -log-level info ...
<timestamp> [INFO] (cli) received redis from Watcher
<timestamp> [INFO] (cli) invoking Runner
# ...
You can also specify the level as debug:
$ consul-template -log-level debug ...
<timestamp> [DEBUG] (cli) creating Runner
<timestamp> [DEBUG] (cli) creating Consul API client
<timestamp> [DEBUG] (cli) creating Watcher
<timestamp> [DEBUG] (cli) looping for data
<timestamp> [DEBUG] (watcher) starting watch
<timestamp> [DEBUG] (watcher) all pollers have started, waiting for finish
<timestamp> [DEBUG] (redis) starting poll
<timestamp> [DEBUG] (service redis) querying Consul with &{...}
<timestamp> [DEBUG] (service redis) Consul returned 2 services
<timestamp> [DEBUG] (redis) writing data to channel
<timestamp> [DEBUG] (redis) starting poll
<timestamp> [INFO] (cli) received redis from Watcher
<timestamp> [INFO] (cli) invoking Runner
<timestamp> [DEBUG] (service redis) querying Consul with &{...}
# ...
FAQ
Q: How is this different than confd?
A: The answer is simple: Service Discovery as a first class citizen. You are also encouraged to read this Pull Request on the project for more background information. We think confd is a great project, but Consul Template fills a missing gap. Additionally, Consul Template has first class integration with Vault, making it easy to incorporate secret material like database credentials or API tokens into configuration files.
Q: How is this different than Puppet/Chef/Ansible/Salt?
A: Configuration management tools are designed to be used in unison with Consul Template. Instead of rendering a stale configuration file, use your configuration management software to render a dynamic template that will be populated by Consul.
Q: How does compatibility with Consul look like?
A: The following table shows the compatibility of Consul Template with Consul versions:
Consul v1.16 | Consul v1.17 | Consul v1.18 | Consul v1.16+ent | Consul v1.17+ent | |
---|---|---|---|---|---|
CT v0.37 | â | â | â | â | â |
CT v0.36 | â | â | â | N/A | N/A |
CT v0.35 | â | â | â | N/A | N/A |
CT v0.34 | â | â | â | N/A | N/A |
N/A = ENT tests were not supported before this version
Contributing
To build and install Consul-Template locally, you will need to install Go.
Clone the repository:
$ git clone https://github.com/hashicorp/consul-template.git
To compile the consul-template
binary for your local machine:
$ make dev
This will compile the consul-template
binary into bin/consul-template
as
well as your $GOPATH
and run the test suite.
If you want to run the tests, first install consul, nomad and vault locally, then:
$ make test
Or to run a specific test in the suite:
go test ./... -run SomeTestFunction_name
Top Related Projects
The Prometheus monitoring system and time series database.
Production-Grade Container Scheduling and Management
Library for configuration management API
AWS Service registry for resilient mid-tier load balancing and failover.
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.
Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot