What's Actually Happening
Your service fails to register with Consul, preventing service discovery. Applications cannot find each other through Consul's DNS or HTTP API.
The Error You'll See
Registration failed:
```bash $ curl -XPUT http://localhost:8500/v1/agent/service/register -d '{"Name":"myservice","Port":8080}'
{"error":"Registration failed: service ID already exists"} ```
Health check failing:
```bash $ consul catalog services
consul # myservice not listed! ```
DNS lookup failed:
```bash $ dig @localhost -p 8600 myservice.service.consul
;; QUESTION SECTION: ;myservice.service.consul. IN A
;; AUTHORITY SECTION: consul. 0 IN SOA ns.consul. hostmaster.consul. 0 3600 600 86400 0 # No answer! ```
Why This Happens
- 1.Agent not running - Consul agent not started
- 2.Wrong address - Service registering wrong address
- 3.Health check failing - Health endpoint not responding
- 4.ACL token missing - No permission to register
- 5.Network partition - Agent cannot reach servers
- 6.Port conflict - Service ID already registered
- 7.Invalid payload - Malformed registration JSON
- 8.TLS issues - Certificate verification failed
Step 1: Check Consul Agent Status
```bash # Check if agent is running: consul members
# Output should show agents: # Node Address Status Type Build Protocol # consul-1 10.0.0.1:8301 alive server 1.15 2 # consul-2 10.0.0.2:8301 alive server 1.15 2
# Check agent mode: consul info | grep server
# Check if agent is leader: consul operator raft list-peers
# Check agent logs: journalctl -u consul -f
# Check agent configuration: consul config read -kind service-defaults ```
Step 2: Verify Service Registration
```bash # List all services: consul catalog services
# List services with details: consul catalog services -tags
# Get service instances: consul catalog nodes -service=myservice
# Via API: curl http://localhost:8500/v1/catalog/service/myservice
# Check local services: curl http://localhost:8500/v1/agent/services
# Check health status: curl http://localhost:8500/v1/health/service/myservice?passing
# Check specific node: curl http://localhost:8500/v1/catalog/node/$(hostname) ```
Step 3: Fix Registration Payload
```bash # Correct service registration: curl -XPUT http://localhost:8500/v1/agent/service/register -d '{ "Name": "myservice", "ID": "myservice-1", "Tags": ["v1", "primary"], "Address": "10.0.0.10", "Port": 8080, "Check": { "HTTP": "http://10.0.0.10:8080/health", "Interval": "10s", "Timeout": "1s", "DeregisterCriticalServiceAfter": "30m" } }'
# Registration with TTL check: curl -XPUT http://localhost:8500/v1/agent/service/register -d '{ "Name": "myservice", "ID": "myservice-2", "Port": 8080, "Check": { "TTL": "30s", "DeregisterCriticalServiceAfter": "1m" } }'
# Deregister service: curl -XPUT http://localhost:8500/v1/agent/service/deregister/myservice-1
# File-based registration: # /etc/consul.d/myservice.json: { "service": { "name": "myservice", "port": 8080, "check": { "http": "http://localhost:8080/health", "interval": "10s" } } }
# Reload configuration: consul reload ```
Step 4: Fix Health Check Issues
```bash # Check health status: consul checks
# Via API: curl http://localhost:8500/v1/agent/checks
# Common health check failures:
# 1. Check endpoint not accessible: curl -v http://localhost:8080/health # Must return 200
# 2. Check timeout: curl -m 1 http://localhost:8080/health
# 3. Check interval too short: # Increase interval to at least 5s
# Fix health check configuration: curl -XPUT http://localhost:8500/v1/agent/service/register -d '{ "Name": "myservice", "Port": 8080, "Check": { "HTTP": "http://localhost:8080/health", "Interval": "10s", "Timeout": "5s", "FailuresBeforeCritical": 3, "SuccessBeforePassing": 1 } }'
# TTL check - must send heartbeat: curl -XPUT http://localhost:8500/v1/agent/check/pass/service:myservice-1
# Or fail: curl -XPUT http://localhost:8500/v1/agent/check/fail/service:myservice-1 ```
Step 5: Handle ACL Configuration
```bash # Check if ACLs enabled: consul acl policy list
# Create token for service registration: consul acl token create -name "myservice-token" -policy-name "service-registration"
# Service registration policy: consul acl policy create -name service-registration -rules '{ "service_prefix \"\" { policy = "write" } }'
# Use token in registration: curl -XPUT http://localhost:8500/v1/agent/service/register?token=YOUR_TOKEN -d '{...}'
# Configure agent with token: # /etc/consul/consul.hcl: acl { enabled = true default_policy = "deny" enable_token_persistence = true tokens { default = "YOUR_TOKEN" agent = "YOUR_TOKEN" } }
# Verify token: consul acl token read -id YOUR_TOKEN ```
Step 6: Fix Network Connectivity
```bash # Check agent connectivity: consul operator raft list-peers
# Test port connectivity: nc -zv localhost 8300 # RPC nc -zv localhost 8301 # Serf LAN nc -zv localhost 8302 # Serf WAN nc -zv localhost 8500 # HTTP API nc -zv localhost 8600 # DNS
# Check firewall rules: iptables -L -n | grep 8300 iptables -L -n | grep 8500
# Add firewall rules: iptables -A INPUT -p tcp --dport 8300 -j ACCEPT iptables -A INPUT -p tcp --dport 8301 -j ACCEPT iptables -A INPUT -p tcp --dport 8500 -j ACCEPT iptables -A INPUT -p udp --dport 8600 -j ACCEPT
# Check advertise address: consul config read -kind agent | grep advertise
# Fix advertise address in config: # /etc/consul/consul.hcl: advertise_addr = "10.0.0.10" ```
Step 7: Debug DNS Issues
```bash # Test DNS resolution: dig @localhost -p 8600 myservice.service.consul
# With full output: dig @localhost -p 8600 myservice.service.consul +trace
# SRV record: dig @localhost -p 8600 myservice.service.consul SRV
# With tag: dig @localhost -p 8600 primary.myservice.service.consul
# Test from application: nslookup myservice.service.consul localhost
# DNS recursor configuration: # /etc/consul/consul.hcl: recursors = ["8.8.8.8", "8.8.4.4"]
# Check DNS configuration: consul info | grep dns
# Enable DNS in resolv.conf: # /etc/resolv.conf: nameserver 127.0.0.1 options ndots:2 ```
Step 8: Monitor Service Health
```bash # Watch service changes: consul watch -type=service -service=myservice "echo 'Service changed'"
# Monitor via API: watch -n 5 'curl -s http://localhost:8500/v1/health/service/myservice | jq ".[].Service.Address"'
# Prometheus metrics: curl http://localhost:8500/v1/agent/metrics?format=prometheus
# Key metrics: # consul_client_rpc # consul_client_rpc_exceeded # consul_health_service_status
# Monitoring script: cat << 'EOF' > /usr/local/bin/consul-service-check.sh #!/bin/bash
SERVICE="myservice" CONSUL="http://localhost:8500"
HEALTH=$(curl -s "$CONSUL/v1/health/service/$SERVICE?passing" | jq length) TOTAL=$(curl -s "$CONSUL/v1/catalog/service/$SERVICE" | jq length)
echo "Service: $SERVICE" echo "Healthy instances: $HEALTH" echo "Total instances: $TOTAL"
if [ "$HEALTH" -eq 0 ] && [ "$TOTAL" -gt 0 ]; then echo "ALERT: All instances unhealthy!" elif [ "$TOTAL" -eq 0 ]; then echo "ALERT: Service not registered!" fi EOF
chmod +x /usr/local/bin/consul-service-check.sh ```
Step 9: Implement Service Mesh
```hcl # Service defaults for Connect: # /etc/consul.d/service-defaults.hcl: kind = "service-defaults" name = "myservice" protocol = "http"
# Proxy defaults: # /etc/consul.d/proxy-defaults.hcl: kind = "proxy-defaults" name = "global" config { bind_address = "0.0.0.0" }
# Service with Connect: { "service": { "name": "myservice", "port": 8080, "connect": { "sidecar_service": { "port": 20000, "check": { "interval": "10s", "tcp": "localhost:20000" } } } } }
# Register upstream: { "service": { "name": "web", "port": 8080, "connect": { "sidecar_service": { "proxy": { "upstreams": [{ "destination_name": "myservice", "local_bind_port": 5000 }] } } } } } ```
Step 10: Production Service Registration
# Kubernetes service registration with Consul:
apiVersion: v1
kind: ServiceAccount
metadata:
name: myservice
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myservice
spec:
selector:
matchLabels:
app: myservice
template:
metadata:
labels:
app: myservice
annotations:
"consul.hashicorp.com/connect-inject": "true"
"consul.hashicorp.com/connect-service": "myservice"
"consul.hashicorp.com/connect-service-port": "8080"
"consul.hashicorp.com/connect-service-upstreams": "db:5432"
spec:
serviceAccountName: myservice
containers:
- name: myservice
image: myservice:latest
ports:
- containerPort: 8080
env:
- name: CONSUL_HTTP_ADDR
value: "http://consul:8500"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10```python # Python service registration: import consul import time
client = consul.Consul(host='localhost', port=8500)
# Register service: client.agent.service.register( name='myservice', service_id='myservice-1', address='10.0.0.10', port=8080, check=consul.Check.http( url='http://10.0.0.10:8080/health', interval='10s', timeout='1s' ) )
# Heartbeat for TTL check: def ttl_heartbeat(): while True: client.agent.check.ttl_pass('service:myservice-1') time.sleep(15)
# Discover service: services = client.catalog.service('myservice') for service in services[1]: print(f"Service at {service['Address']}:{service['Port']}")
# Deregister on shutdown: client.agent.service.deregister('myservice-1') ```
Consul Service Registration Checklist
| Check | Command | Expected |
|---|---|---|
| Agent running | consul members | Node listed |
| Service registered | catalog services | Service listed |
| Health passing | health service | Passing status |
| DNS resolves | dig | A record returned |
| ACL valid | token read | Valid token |
| Network ok | nc ports | Connected |
Verify the Fix
```bash # After fixing registration:
# 1. Check service registered consul catalog services | grep myservice # Output: myservice
# 2. Check health passing consul checks | grep myservice # Output: passing
# 3. DNS resolves dig @localhost -p 8600 myservice.service.consul +short # Output: 10.0.0.10
# 4. API returns instances curl -s http://localhost:8500/v1/catalog/service/myservice | jq '.[].Address' # Output: Service address
# Compare before/after: # Before: Service not found, DNS failed # After: Service registered, health passing, DNS works ```
Related Issues
- [Fix Vault Seal Failed](/articles/fix-vault-seal-failed)
- [Fix Nomad Job Failed](/articles/fix-nomad-job-failed)
- [Fix Consul DNS Not Resolving](/articles/fix-consul-dns-not-resolving)