DEV Community

Alex Spinov
Alex Spinov

Posted on

HashiCorp Consul Has a Free API: Service Discovery and Configuration for Distributed Systems

Consul is a multi-networking tool that provides service discovery, service mesh, and configuration management. It enables services to discover each other, secure their communication, and manage runtime configuration.

What Is Consul?

Consul by HashiCorp provides a full-featured service mesh, service discovery via DNS or HTTP, health checking, and a distributed key-value store. It works across clouds and platforms.

Key Features:

  • Service discovery (DNS + HTTP API)
  • Health checking
  • KV store for dynamic configuration
  • Service mesh with mTLS
  • Multi-datacenter support
  • Intentions (service-to-service ACL)
  • Prepared queries
  • Watches and blocking queries

Quick Start

# Install
brew install consul

# Start dev agent
consul agent -dev

# Web UI at http://localhost:8500
Enter fullscreen mode Exit fullscreen mode

Consul HTTP API

import requests

CONSUL = "http://localhost:8500/v1"

# Register a service
requests.put(f"{CONSUL}/agent/service/register", json={
    "Name": "web-api",
    "ID": "web-api-1",
    "Port": 8080,
    "Tags": ["v2", "production"],
    "Meta": {"version": "2.1.0"},
    "Check": {
        "HTTP": "http://localhost:8080/health",
        "Interval": "10s",
        "Timeout": "3s"
    }
})

# Discover services
services = requests.get(f"{CONSUL}/health/service/web-api?passing=true").json()
for svc in services:
    addr = svc["Service"]["Address"] or svc["Node"]["Address"]
    port = svc["Service"]["Port"]
    print(f"Healthy instance: {addr}:{port}")

# DNS discovery
# dig @127.0.0.1 -p 8600 web-api.service.consul
Enter fullscreen mode Exit fullscreen mode

Key-Value Store

import base64

# Store configuration
requests.put(f"{CONSUL}/kv/config/database/host", data="prod-db.example.com")
requests.put(f"{CONSUL}/kv/config/database/port", data="5432")
requests.put(f"{CONSUL}/kv/config/features/dark-mode", data="true")

# Read configuration
response = requests.get(f"{CONSUL}/kv/config/database/host").json()
value = base64.b64decode(response[0]["Value"]).decode()
print(f"DB Host: {value}")

# List all keys with prefix
keys = requests.get(f"{CONSUL}/kv/config/?keys").json()
for key in keys:
    print(f"Key: {key}")

# Watch for changes (blocking query)
index = response[0]["ModifyIndex"]
updated = requests.get(
    f"{CONSUL}/kv/config/database/host?index={index}&wait=30s"
).json()
Enter fullscreen mode Exit fullscreen mode

Service Mesh (Connect)

# Create intention (allow frontend -> backend)
requests.put(f"{CONSUL}/connect/intentions/exact", params={
    "source": "frontend",
    "destination": "backend"
}, json={
    "Action": "allow",
    "Description": "Allow frontend to call backend"
})

# List intentions
intentions = requests.get(f"{CONSUL}/connect/intentions").json()
for intent in intentions:
    print(f"{intent['SourceName']} -> {intent['DestinationName']}: {intent['Action']}")
Enter fullscreen mode Exit fullscreen mode

Health Checks

# Get health of all nodes
nodes = requests.get(f"{CONSUL}/health/state/any").json()
for check in nodes:
    print(f"Service: {check['ServiceName']}, Status: {check['Status']}, Output: {check.get('Output', '')[:50]}")

# Get health of specific service
health = requests.get(f"{CONSUL}/health/checks/web-api").json()
for check in health:
    print(f"Check: {check['Name']}, Status: {check['Status']}")
Enter fullscreen mode Exit fullscreen mode

Resources


Need to scrape web data for your microservices? Check out my web scraping tools on Apify — production-ready actors for Reddit, Google Maps, and more. Questions? Email me at spinov001@gmail.com

Top comments (0)