| sidebar_position | 20 | ||
|---|---|---|---|
| sidebar_custom_props |
|
HashiCorp Consul is a service mesh solution that provides service discovery, health checking, and key-value storage. This guide shows how to integrate Spring Boot Admin with Consul.
With Consul integration:
- Applications register with Consul
- Spring Boot Admin Server discovers applications via Consul
- Built-in health checks
- No Spring Boot Admin Client library required
flowchart LR
Apps[Applications]
Agent[Consul Agent]
Server[Consul Server<br/>Service Registry]
Admin[Spring Boot Admin<br/>Server]
Apps -->|Register| Agent
Agent -->|Sync| Server
Admin -->|Discover| Server
Admin -.->|Monitor| Apps
# macOS
brew install consul
# Linux
wget https://releases.hashicorp.com/consul/1.17.0/consul_1.17.0_linux_amd64.zip
unzip consul_1.17.0_linux_amd64.zip
sudo mv consul /usr/local/bin/
# Docker
docker run -d --name=consul -p 8500:8500 consul:latest# Development mode
consul agent -dev
# Production mode
consul agent -server -bootstrap-expect=1 -data-dir=/tmp/consulAccess Consul UI at: http://localhost:8500
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
</dependencies>import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@EnableAdminServer
@SpringBootApplication
public class SpringBootAdminConsulApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAdminConsulApplication.class, args);
}
}spring:
application:
name: spring-boot-admin-server
cloud:
consul:
host: localhost
port: 8500
discovery:
preferIpAddress: true
health-check-interval: 10s
health-check-path: /actuator/health
instance-id: ${spring.application.name}:${random.value}
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYSDon't monitor Consul itself:
spring:
boot:
admin:
discovery:
ignored-services: consul<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>@EnableDiscoveryClient
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}spring:
application:
name: my-application
cloud:
consul:
host: localhost
port: 8500
discovery:
metadata:
management-context-path: ${management.server.base-path:/actuator}
health-path: ${management.endpoints.web.path-mapping.health:health}
management:
endpoints:
web:
exposure:
include: "*"
base-path: /actuator
endpoint:
health:
show-details: ALWAYS:::warning
Consul does not allow dots (.) in metadata keys. Use dashes (-) or underscores (_) instead.
:::
Wrong:
metadata:
user.name: admin # ❌ Won't work
user.password: secret # ❌ Won't workCorrect:
metadata:
user-name: admin # ✅ Works
user-password: secret # ✅ Worksspring:
cloud:
consul:
discovery:
metadata:
management-context-path: /actuator
health-path: /ping
user-name: ${spring.security.user.name}
user-password: ${spring.security.user.password}
tags-environment: production
tags-region: us-east-1
team: platformConsul supports tags for grouping:
spring:
cloud:
consul:
discovery:
tags:
- production
- us-east-1
- platform-teamserver:
port: 8080
management:
server:
port: 9090
endpoints:
web:
base-path: /management
spring:
cloud:
consul:
discovery:
metadata:
management-port: 9090
management-context-path: /managementmanagement:
endpoints:
web:
path-mapping:
health: /ping
base-path: /actuator
spring:
cloud:
consul:
discovery:
health-check-path: /actuator/ping
metadata:
health-path: /pingConsul automatically creates HTTP health check:
spring:
cloud:
consul:
discovery:
health-check-interval: 10s
health-check-timeout: 5s
health-check-path: /actuator/healthspring:
cloud:
consul:
discovery:
health-check-url: https://my-app.example.com/actuator/health
health-check-interval: 15s
health-check-critical-timeout: 30sUse TTL-based health check instead of HTTP:
spring:
cloud:
consul:
discovery:
health-check-interval: 10s
heartbeat:
enabled: true
ttl-value: 15
ttl-unit: sspring:
boot:
admin:
discovery:
ignored-services: consul,config-server@Bean
public InstanceFilter consulInstanceFilter() {
return registration -> {
// Only monitor services with 'monitor' tag
Map<String, String> metadata = registration.getMetadata();
return "true".equals(metadata.get("monitor"));
};
}@Bean
public InstanceFilter tagBasedFilter() {
return registration -> {
String tags = registration.getMetadata().get("tags");
return tags != null && tags.contains("production");
};
}spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
acl-token: ${CONSUL_ACL_TOKEN}spring:
cloud:
consul:
host: localhost
port: 8501
scheme: https
tls:
enabled: true
cert-path: /path/to/cert.pem
key-path: /path/to/key.pem
ca-cert-path: /path/to/ca.pemversion: '3'
services:
consul:
image: consul:latest
ports:
- "8500:8500"
- "8600:8600/udp"
command: agent -server -ui -bootstrap-expect=1 -client=0.0.0.0
spring-boot-admin:
build: ./admin-server
ports:
- "8080:8080"
environment:
- SPRING_CLOUD_CONSUL_HOST=consul
depends_on:
- consul
my-application:
build: ./my-app
ports:
- "8081:8081"
environment:
- SPRING_CLOUD_CONSUL_HOST=consul
depends_on:
- consulFor Kubernetes, use Consul Connect:
spring:
cloud:
consul:
host: consul.service.consul
port: 8500
discovery:
preferIpAddress: false
hostname: ${HOSTNAME}.my-app.default.svc.cluster.local
metadata:
k8s-namespace: ${POD_NAMESPACE:default}
k8s-pod: ${HOSTNAME}-
Check Consul registration:
curl http://localhost:8500/v1/catalog/services curl http://localhost:8500/v1/health/service/my-application
-
Verify health check:
consul catalog services consul catalog nodes -service=my-application
-
Check metadata:
curl http://localhost:8500/v1/catalog/service/my-application | jq
Ensure no dots in keys:
# Wrong
metadata:
user.name: admin
# Correct
metadata:
user-name: adminVerify endpoint is accessible:
curl http://localhost:8081/actuator/healthCheck Consul health status:
consul catalog nodes -service=my-application -detailedConfigure critical timeout:
spring:
cloud:
consul:
discovery:
health-check-critical-timeout: 30s-
Use Instance IDs: Ensure unique instance identifiers
spring: cloud: consul: discovery: instance-id: ${spring.application.name}:${random.value}
-
Configure Health Checks: Set appropriate intervals
spring: cloud: consul: discovery: health-check-interval: 10s health-check-critical-timeout: 1m
-
Use Metadata for Credentials: Avoid hardcoding
spring: cloud: consul: discovery: metadata: user-name: ${ACTUATOR_USER} user-password: ${ACTUATOR_PASSWORD}
-
Prefer IP Address: For container environments
spring: cloud: consul: discovery: preferIpAddress: true
-
Use Tags: For service categorization
spring: cloud: consul: discovery: tags: - production - microservice
-
Enable Deregistration: Clean up on shutdown
spring: cloud: consul: discovery: deregister: true
-
Monitor Consul Health: Ensure Consul is operational
consul members consul info
See the spring-boot-admin-sample-consul project for a complete working example.
- Service Discovery - Service discovery overview
- Consul Sample - Detailed sample walkthrough
- Metadata - Working with metadata
- Security - Securing discovered services