What it is
HashiCorp Consul is a tool for service discovery, configuration, and segmentation, enabling a distributed system to discover and communicate with each other. You reach for it when you need a robust, centralized way to manage services in dynamic, distributed environments.
Installation
Linux
# Download the latest version
wget https://releases.hashicorp.com/consul/1.15.0/consul_1.15.0_linux_amd64.zip
# Unzip the binary
unzip consul_1.15.0_linux_amd64.zip
# Move to a directory in your PATH
sudo mv consul /usr/local/bin/
# Verify installation
consul --version
macOS
# Download the latest version
curl -LO https://releases.hashicorp.com/consul/1.15.0/consul_1.15.0_darwin_amd64.zip
# Unzip the binary
unzip consul_1.15.0_darwin_amd64.zip
# Move to a directory in your PATH
sudo mv consul /usr/local/bin/
# Verify installation
consul --version
Windows
Download the appropriate .zip file from the Consul releases page. Extract the consul.exe file and place it in a directory included in your system’s PATH environment variable.
Core Concepts
- Agent: Every Consul node runs an agent. Agents can operate in either
clientorservermode.- Client Agent: Lightweight, forwards requests to a server. Typically runs on every application node.
- Server Agent: Stateful, holds the cluster state, processes requests, and communicates with other servers. A cluster needs at least 3 servers for fault tolerance.
- Service: A logical unit of functionality (e.g.,
web-app,database). Services are registered with Consul. - Check: A health check associated with a service or a node. Consul uses checks to determine the health of services and nodes.
- Service Discovery: Clients can query Consul to find the network locations (IP address and port) of healthy instances of a service.
- Key/Value Store: Consul provides a distributed, highly available key/value store for dynamic configuration.
- Consul Catalog: A registry of all services and their associated health checks.
- Consul Connect: Provides service-to-service communication with automatic TLS encryption and identity.
Commands / Usage
Starting Consul Agents
Starting a Development Server (Single Node)
This is useful for local testing and development. It runs a single server agent and a client agent on the same machine.
consul agent -dev
Explanation: Starts Consul in development mode, suitable for a single machine.
Starting a Server Agent
This command starts a server agent. You’ll typically run this on dedicated nodes for your Consul cluster.
consul agent -server -ui -node=server-1 -bootstrap-expect=3 -data-dir=/opt/consul -client=0.0.0.0
Explanation:
-server: Starts the agent in server mode.-ui: Enables the Consul web UI.-node=server-1: Assigns a unique name to this node.-bootstrap-expect=3: Specifies the expected number of server nodes in the cluster for initial bootstrapping.-data-dir=/opt/consul: Specifies the directory where Consul stores its state.-client=0.0.0.0: Binds the client interface to all network interfaces, allowing other machines to connect.
Starting a Client Agent
This command starts a client agent. It needs to join a Consul cluster.
consul agent -node=client-1 -join=<server_ip_address> -data-dir=/opt/consul -client=0.0.0.0
Explanation:
-node=client-1: Assigns a unique name to this node.-join=<server_ip_address>: Joins an existing Consul cluster by connecting to a server agent at the given IP address.-data-dir=/opt/consul: Specifies the directory where Consul stores its state.-client=0.0.0.0: Binds the client interface to all network interfaces.
Service Registration
Registering a Service from a Configuration File
Create a JSON file (e.g., web-app.json):
{
"service": {
"name": "web-app",
"tags": ["frontend", "production"],
"port": 8080,
"check": {
"http": "http://localhost:8080/health",
"interval": "10s"
}
}
}
Then register it:
consul services register web-app.json
Explanation: Registers the web-app service defined in web-app.json with Consul.
Registering a Service with Inline Flags
consul services register -name="api-service" -port=5000 -tag="backend" -check-http="http://localhost:5000/health" -check-interval="15s"
Explanation: Registers a service named api-service with specified port, tag, and health check directly via command-line flags.
Registering a Service with a Script Check
Create a script check file (e.g., redis-check.json):
{
"service": {
"name": "redis",
"port": 6379
},
"check": {
"script": "/usr/local/bin/check_redis.sh",
"interval": "30s"
}
}
Then register it:
consul services register redis-check.json
Explanation: Registers the redis service and associates it with a script-based health check.
Service Discovery
Discovering Services by Name
consul services -name=web-app
Explanation: Lists all registered instances of the web-app service.
Discovering Services with a Specific Tag
consul services -tag=production
Explanation: Lists all services that have the production tag.
Discovering Services and their Health Status
consul services --tag=production --healthy
Explanation: Lists only the healthy instances of services tagged with production.
Querying for Service Addresses
consul services -name=database -format=json | jq '.[].ServiceAddress'
Explanation: Retrieves the IP addresses of all healthy database service instances using jq for JSON parsing.
Health Checks
Listing All Checks
consul checks
Explanation: Lists all health checks registered in Consul.
Listing Checks for a Specific Node
consul checks -node=server-1
Explanation: Lists all health checks associated with the node named server-1.
Listing Checks for a Specific Service
consul checks -service=web-app
Explanation: Lists all health checks associated with the web-app service.
Deregistering a Check
consul checks deregister <check_id>
Explanation: Removes a specific health check from Consul using its ID.
Key/Value Store
Setting a Key
consul kv put config/database/url "postgres://user:pass@host:5432/db"
Explanation: Stores the value postgres://user:pass@host:5432/db under the key config/database/url.
Getting a Key
consul kv get config/database/url
Explanation: Retrieves the value associated with the key config/database/url.
Listing Keys
consul kv list config/
Explanation: Lists all keys under the config/ prefix.
Deleting a Key
consul kv delete config/database/url
Explanation: Removes the key config/database/url and its associated value from Consul.
Watching for Key Changes
consul kv watch config/api/timeout
Explanation: Continuously monitors the key config/api/timeout and prints its value whenever it changes.
ACLs (Access Control Lists)
Creating a Policy
Create a policy file (e.g., readonly.hcl):
policy "readonly" {
description = "Read-only access to services and kv"
rules = {
"service" = {
"*" = {
"policy" = "read"
}
}
"kv" = {
"*" = {
"policy" = "read"
}
}
}
}
Then create the policy:
consul acl policy create -name="readonly" -description="Read-only access to services and kv" -rules-file="readonly.hcl"
Explanation: Creates a new ACL policy named "readonly" with defined read-only rules.
Creating a Token
consul acl token create -policy-name="readonly" -accessor-id="my-readonly-accessor" -name="web-app-token"
Explanation: Creates a new ACL token associated with the "readonly" policy, giving it a specific accessor ID and name.
Listing Tokens
consul acl token list
Explanation: Lists all ACL tokens in the Consul cluster.
Updating a Token
consul acl token update -id=<token_id> -name="updated-web-app-token"
Explanation: Updates the name of an existing ACL token identified by <token_id>.
Revoking a Token
consul acl token revoke -id=<token_id>
Explanation: Revokes (invalidates) an ACL token.
Consul Connect (Service Mesh)
Enabling Connect on a Service Definition
Modify your service registration file (e.g., api-service.json):
{
"service": {
"name": "api-service",
"port": 5000,
"connect": {
"sidecar_service": {}
}
}
}
Register the service:
consul services register api-service.json
Explanation: Registers the api-service and automatically provisions a sidecar proxy for it, enabling Consul Connect.
Proxying Traffic Through a Service Mesh
consul connect proxy -service=web-app -upstream=api-service:5000
Explanation: Starts a proxy that listens locally, forwarding traffic to the api-service via the Consul Connect mesh.
Executing a Command with a Service Identity
consul connect call api-service ./my-client-app --target=localhost:5000
Explanation: Runs my-client-app with the identity of the web-app service, allowing it to securely connect to api-service.
Common Patterns
Running Consul in Docker
docker run -d -p 8500:8500 -p 8600:8600/udp consul agent -dev -client=0.0.0.0
Explanation: Starts a single-node Consul agent in a Docker container, exposing the HTTP and DNS ports.
Joining a Consul Cluster
On a new client or server node:
consul join <existing_server_ip_1> <existing_server_ip_2>
Explanation: Tells the current Consul agent to join the cluster by connecting to one or more existing server nodes.
Registering a Service and its Health Check
consul services register -name="my-app" -port=9000 -check-http="http://localhost:9000/health" -check-interval="5s"
Explanation: A common way to quickly register a service with its health check, ensuring Consul knows its status.
Getting all healthy instances of a service
consul services -name=user-service --healthy -format=json | jq -r '.[] | "\(.ServiceAddress):\(.ServicePort)"'
Explanation: Fetches all healthy instances of user-service and outputs them as IP:PORT strings, useful for dynamic load balancing.
Using Consul KV for application configuration
Ensure your application reads configuration from Consul:
# Example: Node.js app reading a config value
const consul = require('consul');
consul().kv.get('config/my-app/feature-flag', (err, data) => {
if (!err && data) {
console.log('Feature flag is:', data.Value);
}
});
Explanation: Applications can dynamically fetch their configuration from Consul’s KV store, enabling zero-downtime configuration updates.
Setting up Consul Connect for secure inter-service communication
- Register services with
connect.sidecar_service. - Use
consul connect proxyorconsul connect callto interact.# Example: Proxying a request from a client to a backend service consul connect proxy -register -service=my-client-proxy -upstream=backend-service:8080 -listen-addr=127.0.0.1:9090 & curl http://127.0.0.1:9090
Explanation: Establishes secure, encrypted communication paths between services without application code changes.
Gotchas
agent -devis not for production: The-devmode runs a single-node cluster, lacks fault tolerance, and isn’t suitable for production environments.- Server Mode is Stateful: Server agents store the cluster state. Losing a majority of servers can lead to data loss or cluster unavailability. Ensure you have at least 3 servers for HA.
bootstrap-expect: This flag is crucial for bootstrapping a new HA cluster. Once the cluster is formed, it should not be changed without careful consideration.- Client Interface Binding (
-client): By default, Consul agents bind the client interface to127.0.0.1. If you need other machines to reach your Consul agent (e.g., for service discovery queries), you must explicitly set-clientto0.0.0.0or a specific IP address. - DNS Interface Binding: Similar to the client interface, the DNS interface also defaults to
127.0.0.1. If you want other machines to use Consul’s DNS for service discovery, you need to configure this. The-dnsflag can be used, or ensure the agent is bound to0.0.0.0and firewall rules allow access. - Service Registration vs. Deregistration: If a Consul agent process dies unexpectedly, its registered services and checks might remain in the catalog until their TTL expires or they are manually deregistered. Ensure proper shutdown procedures or use health checks with appropriate timeouts.
- ACLs and Bootstrapping: If ACLs are enabled, the first token used to interact with Consul (often created during bootstrapping) must have sufficient permissions to manage ACLs.
- Consul Connect TLS Certificates: Consul automatically manages TLS certificates for Connect services. Ensure the agents have write access to their
data-dirfor certificate storage. - HTTP API vs. CLI: While the CLI is convenient, the HTTP API is the underlying mechanism. Understanding the API can be helpful for complex integrations or troubleshooting.