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. 1.Agent not running - Consul agent not started
  2. 2.Wrong address - Service registering wrong address
  3. 3.Health check failing - Health endpoint not responding
  4. 4.ACL token missing - No permission to register
  5. 5.Network partition - Agent cannot reach servers
  6. 6.Port conflict - Service ID already registered
  7. 7.Invalid payload - Malformed registration JSON
  8. 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

yaml
# 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

CheckCommandExpected
Agent runningconsul membersNode listed
Service registeredcatalog servicesService listed
Health passinghealth servicePassing status
DNS resolvesdigA record returned
ACL validtoken readValid token
Network oknc portsConnected

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 ```

  • [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)