Опирается на правила:
R-OBS-CFG-1…R-OBS-CFG-4иR-OBS-CFG-X1…R-OBS-CFG-X3из Observability Style Guide → раздел 5. Конфигурация.
Важно знать
- Отдельный management port (
management.server.port: 8081) для изоляции actuator от business traffic и сетевой защиты.- Explicit exposure список —
health,info,metrics,prometheus. Не'*'.- Percentiles-histogram + SLO buckets для
http.server.requests—100ms,500ms,1s,5s.- Стандартные tags через
management.metrics.tags.service/env/versionглобально, не в каждой метрике.- Logback-spring.xml с двумя springProfile: dev/test (text pattern) и prod/staging (
LogstashEncoderс MDC).- Запрет публичных
/actuator/env,/heapdump,/threaddump— содержат секреты и memory dumps.- Запрет одного port для business + actuator в проде — невозможно сетевая изоляция.
Конфигурация observability собирается из четырёх частей: application.yml (Actuator, Micrometer, OTel), logback-spring.xml (формат логов), build.gradle.kts (зависимости + git-commit-id-plugin), K8s манифесты (probes на management port). Эта статья — про первые два.
Отдельный management port
R-OBS-CFG-1: business и actuator на разных портах.
server:
port: 8080
management:
server:
port: 8081
Что это даёт:
- Network policy в K8s разрешает Prometheus scraper подключаться на
8081, не на8080. Ingress публикует только8080. - Actuator-нагрузка (scraping каждые 15s, healthchecks каждые 5s) не блокирует thread pool business-tomcat'а.
- Тесты на staging можно делать на
8081(heapdump, threaddump) без риска зацепить production-traffic.
Если один port — невозможно «закрыть actuator извне», NetworkPolicy не разделит endpoints по path.
Explicit exposure
R-OBS-CFG-2: явный список endpoints, не wildcard.
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
Дефолт Spring — только health + info. Production — добавляем metrics (для дебага через JSON) и prometheus (для scraper-а).
Не добавляем без явной причины: env, beans, mappings, loggers, heapdump, threaddump, configprops — это либо secrets exposure, либо attack surface (heap dump может содержать в памяти credentials, токены).
Percentiles и SLO buckets
R-OBS-CFG-3: точные квантили для критичных метрик.
management:
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 100ms,500ms,1s,5s
tags:
service: ${spring.application.name}
env: ${ENV:dev}
version: ${BUILD_VERSION:unknown}
percentiles-histogram: true— Micrometer публикует full histogram (~64 bucket-ов) дляhttp.server.requests_seconds_bucket, что даёт точныйhistogram_quantile()в Prometheus.slo: 100ms,500ms,1s,5s— добавляет explicit SLO buckets. В Prometheushttp_server_requests_seconds_bucket{le="0.5"}даёт «сколько запросов уложились в 500ms» без интерполяции.tags.service/env/version— глобальные, см. Metrics.
BUILD_VERSION инжектится из CI как env var.
Logback-spring.xml с двумя профилями
R-OBS-CFG-4: текстовый pattern для dev, JSON для prod.
<configuration>
<springProfile name="dev,test">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level [%thread] %X{traceId:-} %logger{30} - %msg%n</pattern>
</encoder>
</appender>
</springProfile>
<springProfile name="prod,staging">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeMdcKeyName>traceId</includeMdcKeyName>
<includeMdcKeyName>spanId</includeMdcKeyName>
<includeMdcKeyName>requestId</includeMdcKeyName>
<includeMdcKeyName>userId</includeMdcKeyName>
</encoder>
</appender>
</springProfile>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
springProfile — Logback-расширение Spring Boot, активирует appender только на матчинг профиля.
%X{traceId:-} в dev pattern — кладёт traceId из MDC, дефолт пустая строка. Для глаз достаточно: видишь короткий trace-id в логе, по нему ищешь в Tempo/Jaeger.
В prod — LogstashEncoder пишет JSON с явно перечисленными MDC-полями, остальные ключи MDC попадают в mdc блок автоматически.
Что запрещено
Exposing /actuator/env, /heapdump, /threaddump
R-OBS-CFG-X1: эти endpoints — security risk.
/actuator/envпоказывает все configs включая возможные secrets в plain (если они попали туда мимо Vault — например, через${ENV:default})./actuator/heapdump— full heap dump. В нём в памяти могут быть JWT-токены, credentials, PII./actuator/threaddump— стек всех threads, может раскрыть внутреннюю структуру + class names attack surface.
Если очень нужно (debug в проде) — Spring Security + roles: ADMIN + audit log на каждый вызов. Дефолт — не expose.
Один port для business + actuator в проде
R-OBS-CFG-X2: тогда /actuator/health доступен извне через тот же Ingress, что /api/orders. NetworkPolicy не разделит по path. Уязвимости в актуаторе становятся доступны attacker'у.
exposure.include: '*' в проде
R-OBS-CFG-X3: открывает всё, включая env, beans, mappings, loggers, configprops. Каждое из них — отдельный leak.
# ОПАСНО
management.endpoints.web.exposure.include: '*'
# ХОРОШО
management.endpoints.web.exposure.include: health,info,metrics,prometheus
В Spring Boot 3+ есть management.endpoints.web.exposure.exclude — можно использовать чтобы убрать конкретные после '*', но default-deny с explicit-allow надёжнее.
Что запрещено — таблица
| Антипаттерн | Правило | Что взамен |
|---|---|---|
/actuator/env exposed публично | R-OBS-CFG-X1 | не expose / ADMIN-only |
/actuator/heapdump exposed | R-OBS-CFG-X1 | не expose |
| Один port для business + actuator в проде | R-OBS-CFG-X2 | management.server.port: 8081 |
exposure.include: '*' | R-OBS-CFG-X3 | explicit list |
percentiles-histogram: false для критичных | R-OBS-CFG-3 | true + SLO buckets |
| Один Logback-pattern для dev и prod | R-OBS-CFG-4 | springProfile dev/test vs prod/staging |
| MDC keys не в encoder include list | R-OBS-CFG-4 | <includeMdcKeyName>traceId</includeMdcKeyName> |
Куда дальше
- Observability → раздел 5. Конфигурация — нормативные формулировки.
- Logging — детали LogstashEncoder и pattern.
- Metrics — стандартные tags, RED/USE.
- Tracing —
otel.*settings. - Health checks — probes на management port.
- Security style guide — почему
/actuator/envнельзя публично.