| sidebar_position | 40 | ||
|---|---|---|---|
| sidebar_custom_props |
|
The Consul sample demonstrates Spring Boot Admin Server integration with HashiCorp Consul for service discovery. This sample shows how to leverage Consul's powerful service registry and health checking capabilities to automatically discover and monitor Spring Boot applications.
Location: spring-boot-admin-samples/spring-boot-admin-sample-consul/
Features:
- Automatic service discovery via Consul
- No Admin Client required on monitored applications
- Consul health check integration
- Metadata-based configuration
- Custom actuator endpoint paths
- Spring Security integration
- Servlet-based deployment
- Java 17 or higher
- Maven 3.6+
- Consul installed and running
brew install consulwget 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/Download from: https://www.consul.io/downloads
docker run -d -p 8500:8500 -p 8600:8600/udp --name=consul consul agent -server -ui -bootstrap-expect=1 -client=0.0.0.0consul version# Development mode (single node)
consul agent -devVerify Consul is running: http://localhost:8500/ui
cd spring-boot-admin-samples/spring-boot-admin-sample-consul
mvn spring-boot:runAccess Admin UI at: http://localhost:8080
mvn spring-boot:run -Dspring-boot.run.arguments=\
--spring.cloud.consul.host=consul-servermvn spring-boot:run -Dspring-boot.run.profiles=insecure<dependencies>
<!-- Admin Server -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
</dependency>
<!-- Consul Discovery -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- Web (Servlet) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>@SpringBootApplication
@EnableDiscoveryClient // Enable Consul discovery
@EnableAdminServer // Enable Admin Server
public class SpringBootAdminConsulApplication {
static void main(String[] args) {
SpringApplication.run(SpringBootAdminConsulApplication.class, args);
}
}spring:
application:
name: consul-example
cloud:
config:
enabled: false # Disable config client
consul:
host: localhost
port: 8500
discovery:
metadata:
# IMPORTANT: Use dashes, not dots in metadata keys!
management-context-path: /foo
health-path: /ping
user-name: user
user-password: password
profiles:
active:
- secure
boot:
admin:
discovery:
ignored-services: consul # Don't monitor Consul itself
management:
endpoints:
web:
exposure:
include: "*"
base-path: /foo # Custom actuator base path
path-mapping:
health: /ping # Custom health endpoint path
endpoint:
health:
show-details: ALWAYS:::warning Metadata Key Restriction CRITICAL: Consul metadata keys cannot contain dots. Use dashes instead:
- ✅
management-context-path - ❌
management.context-path
This is a Consul limitation, not a Spring Boot Admin limitation. :::
For applications to be monitored:
spring:
application:
name: my-service
cloud:
consul:
host: localhost
port: 8500
discovery:
metadata:
management-context-path: /actuator # Use dashes!
health-path: /actuator/health
# For secured actuators
user-name: ${actuator.username}
user-password: ${actuator.password}
management:
endpoints:
web:
exposure:
include: "*"@Profile("insecure")
@Configuration
public static class SecurityPermitAllConfig {
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http)
throws Exception {
http.authorizeHttpRequests((authorizeRequests) ->
authorizeRequests.anyRequest().permitAll())
.csrf((csrf) -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
adminContextPath + "/instances",
adminContextPath + "/instances/*",
adminContextPath + "/actuator/**"
));
return http.build();
}
}@Profile("secure")
@Configuration
public static class SecuritySecureConfig {
@Bean
protected SecurityFilterChain filterChain(HttpSecurity http)
throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler =
new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(adminContextPath + "/");
http.authorizeHttpRequests((authorizeRequests) ->
authorizeRequests
.requestMatchers(adminContextPath + "/assets/**")
.permitAll()
.requestMatchers(adminContextPath + "/login")
.permitAll()
.anyRequest()
.authenticated())
.formLogin((formLogin) -> formLogin
.loginPage(adminContextPath + "/login")
.successHandler(successHandler))
.logout((logout) -> logout
.logoutUrl(adminContextPath + "/logout"))
.httpBasic(Customizer.withDefaults())
.csrf((csrf) -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
adminContextPath + "/instances",
adminContextPath + "/instances/*",
adminContextPath + "/actuator/**"
));
return http.build();
}
}-
Application Registration:
- Application registers with Consul on startup
- Sends service metadata including actuator paths
- Consul assigns service ID and health checks
-
Health Checking:
- Consul performs HTTP health checks
- Marks services as passing/failing
- Admin Server queries only healthy services
-
Admin Discovery:
- Admin Server queries Consul for registered services
- Reads metadata to locate actuator endpoints
- Begins monitoring discovered services
-
Deregistration:
- Application deregisters on shutdown
- Consul removes from registry
- Admin Server stops monitoring
Admin Server reads specific metadata keys from Consul:
spring:
cloud:
consul:
discovery:
metadata:
# Required for endpoint detection
management-context-path: /actuator # Dashes only!
management-port: 8081 # If different
# Optional - for secured actuators
user-name: admin
user-password: ${ACTUATOR_PASSWORD}
# Custom metadata
environment: production
version: 1.0.0
team: platformKey Mappings:
management-context-path→ Where to find actuator endpointsmanagement-port→ Management port if different from service porthealth-path→ Custom health endpoint pathuser-name/user-password→ Actuator credentials
This sample demonstrates custom actuator paths:
management:
endpoints:
web:
base-path: /foo # Actuator at /foo instead of /actuator
path-mapping:
health: /ping # Health at /foo/ping instead of /foo/healthAdmin Server discovers these via metadata:
spring:
cloud:
consul:
discovery:
metadata:
management-context-path: /foo
health-path: /ping- Access Consul UI:
http://localhost:8500/ui - Navigate to "Services"
- Should see:
consul-example(Admin Server)- Other registered services
In Consul UI, services should show:
- Status: Passing (green)
- Health check URL displayed
- Metadata visible
- Access Admin UI:
http://localhost:8080 - Should see services registered in Consul
- Click service to view:
- Health status
- Metrics
- Environment
- Custom /ping endpoint
Register a new service:
# Register via Consul API
curl -X PUT -d '{
"Name": "test-service",
"Address": "127.0.0.1",
"Port": 8081,
"Meta": {
"management-context-path": "/actuator"
},
"Check": {
"HTTP": "http://127.0.0.1:8081/actuator/health",
"Interval": "10s"
}
}' http://localhost:8500/v1/agent/service/registerService appears in Admin UI within seconds.
Consul supports multiple health check types:
spring:
cloud:
consul:
discovery:
health-check-path: /actuator/health
health-check-interval: 10s
health-check-timeout: 5sspring:
cloud:
consul:
discovery:
health-check-ttl: 30sApplication must send heartbeat to Consul every 30 seconds.
Add tags for filtering:
spring:
cloud:
consul:
discovery:
tags:
- production
- backend
- v1.0.0Filter services monitored by Admin:
spring:
boot:
admin:
discovery:
ignored-services:
- consul # Don't monitor Consul
- config-server # Don't monitor Config Server
services: # Only monitor these (if specified)
- my-service
- another-serviceSecure Consul with ACL tokens:
spring:
cloud:
consul:
token: ${CONSUL_TOKEN}
discovery:
acl-token: ${CONSUL_ACL_TOKEN}Connect to Consul over TLS:
spring:
cloud:
consul:
scheme: https
tls:
enabled: true
key-store-path: classpath:consul-keystore.p12
key-store-password: ${KEYSTORE_PASSWORD}Register in specific datacenter:
spring:
cloud:
consul:
discovery:
datacenter: dc1Use IP instead of hostname:
spring:
cloud:
consul:
discovery:
prefer-ip-address: true
ip-address: 192.168.1.100| Feature | Consul | Eureka |
|---|---|---|
| Health Checks | Built-in (HTTP, TCP, TTL, Script) | Via Spring Boot actuator only |
| Key-Value Store | Yes | No |
| ACL | Yes | Basic |
| Multi-DC | Native support | Requires setup |
| DNS Interface | Yes | No |
| Metadata Keys | No dots allowed | Dots allowed |
| Complexity | Higher | Lower |
| Ecosystem | HashiCorp ecosystem | Netflix stack |
Symptom: Admin Server can't find actuator endpoints
Cause: Used dots in metadata keys
Solution: Use dashes instead:
# Wrong
metadata:
management.context-path: /actuator
# Correct
metadata:
management-context-path: /actuatorCheck Consul connectivity:
# Test Consul API
curl http://localhost:8500/v1/catalog/services
# Check health
curl http://localhost:8500/v1/health/state/passingVerify Admin logs:
tail -f logs/spring-boot-admin.log | grep -i consulServices show as "failing" in Consul:
-
Verify health endpoint is accessible:
curl http://localhost:8080/actuator/health
-
Check health check interval:
spring: cloud: consul: discovery: health-check-interval: 30s # Increase if needed
-
Review Consul logs:
consul monitor
Increase timeout values:
spring:
cloud:
consul:
discovery:
health-check-timeout: 10s # Increase from defaultRun Consul in cluster mode (3 or 5 nodes):
# Server node 1
consul agent -server -bootstrap-expect=3 -data-dir=/consul/data \
-bind=192.168.1.10
# Server node 2
consul agent -server -data-dir=/consul/data \
-bind=192.168.1.11 -join=192.168.1.10
# Server node 3
consul agent -server -data-dir=/consul/data \
-bind=192.168.1.12 -join=192.168.1.10spring:
cloud:
consul:
token: ${CONSUL_MANAGEMENT_TOKEN}
discovery:
acl-token: ${CONSUL_SERVICE_TOKEN}Register Admin Server to monitor itself:
spring:
boot:
admin:
discovery:
ignored-services: [] # Don't ignore any servicesThis sample demonstrates:
✅ Consul Integration
- Service discovery via Consul
- Health check integration
✅ Metadata Handling
- Proper metadata key formatting (dashes not dots)
- Custom actuator paths
✅ Production Features
- ACL support
- TLS encryption
- Multi-datacenter awareness
✅ Flexibility
- Custom endpoint paths
- Secure and insecure modes
- Explore Eureka Sample for Netflix Eureka
- Review Zookeeper Sample for Apache Zookeeper
- Check Consul Integration Guide for detailed setup
- See Hazelcast Sample for clustering