Настройка Config Server (Consul/etcd) для микросервисов
Централизованное управление конфигурацией позволяет менять настройки сервисов без пересборки образов и рестарта. Database URL, feature flags, таймауты, API-ключи — всё хранится в одном месте, версионируется и обновляется динамически.
Варианты инструментов
| Инструмент | Сильные стороны |
|---|---|
| Consul KV | Интеграция с Service Discovery, health checks |
| etcd | Basis для Kubernetes, высокая надёжность |
| Vault | Секреты + конфигурация, шифрование |
| Spring Cloud Config | Конфигурация из Git-репозитория |
| AWS Parameter Store | Managed, интеграция с IAM |
Consul KV Store
import Consul from 'consul';
const consul = new Consul({ host: process.env.CONSUL_HOST });
class ConfigService {
private cache = new Map<string, string>();
async get(key: string): Promise<string | null> {
const result = await consul.kv.get(`config/order-service/${key}`);
return result?.Value ? Buffer.from(result.Value, 'base64').toString() : null;
}
async getAll(prefix: string): Promise<Record<string, string>> {
const results = await consul.kv.get({
key: `config/order-service/${prefix}`,
recurse: true
});
return results?.reduce((acc, item) => {
const shortKey = item.Key.replace(`config/order-service/${prefix}/`, '');
acc[shortKey] = Buffer.from(item.Value, 'base64').toString();
return acc;
}, {}) ?? {};
}
// Watch — динамическое обновление без рестарта
watch(key: string, callback: (value: string) => void): void {
const watcher = consul.watch({
method: consul.kv.get,
options: { key: `config/order-service/${key}` }
});
watcher.on('change', (data) => {
if (data?.Value) {
const value = Buffer.from(data.Value, 'base64').toString();
this.cache.set(key, value);
callback(value);
}
});
}
}
// Использование
const config = new ConfigService();
// Feature flags с hot reload
let enableNewCheckout = false;
config.watch('features/new-checkout', (value) => {
enableNewCheckout = value === 'true';
logger.info(`Feature new-checkout: ${enableNewCheckout}`);
});
etcd
import { Etcd3 } from 'etcd3';
const etcd = new Etcd3({ hosts: process.env.ETCD_HOSTS.split(',') });
// Запись конфигурации
await etcd.put('config/payment-service/timeout').value('5000');
await etcd.put('config/payment-service/retries').value('3');
// Чтение с namespace
const namespace = etcd.namespace('config/payment-service/');
const timeout = await namespace.get('timeout').number();
const retries = await namespace.get('retries').number();
// Watch на изменения
const watcher = await namespace.watch().key('timeout').create();
watcher.on('put', (res) => {
console.log('timeout changed to:', res.value.toString());
});
Spring Cloud Config
Git-репозиторий как источник конфигурации:
# config-server application.yml
spring:
cloud:
config:
server:
git:
uri: https://github.com/company/config-repo
search-paths: '{application}'
clone-on-start: true
Клиент (в каждом сервисе):
# bootstrap.yml
spring:
application:
name: order-service
config:
import: "configserver:http://config-server:8888"
profiles:
active: production
При старте сервис загружает order-service/production.yml из Git-репозитория.
HashiCorp Vault для секретов
import vault from 'node-vault';
const client = vault({
apiVersion: 'v1',
endpoint: process.env.VAULT_ADDR,
token: process.env.VAULT_TOKEN // в K8s — через ServiceAccount
});
// Чтение секрета
const secret = await client.read('secret/data/order-service/production');
const dbPassword = secret.data.data.db_password;
const stripeKey = secret.data.data.stripe_secret_key;
// Dynamic secrets — Vault генерирует временные credentials для PostgreSQL
const dbCreds = await client.read('database/creds/order-service-role');
// dbCreds.data.username, dbCreds.data.password — уникальны, истекают через TTL
Kubernetes ConfigMap и Secret
Нативное решение для K8s:
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-config
data:
PAYMENT_TIMEOUT_MS: "5000"
MAX_RETRIES: "3"
FEATURE_NEW_CHECKOUT: "false"
---
apiVersion: v1
kind: Secret
metadata:
name: order-service-secrets
type: Opaque
stringData:
DATABASE_PASSWORD: "super-secret"
STRIPE_SECRET_KEY: "sk_live_..."
# Deployment
envFrom:
- configMapRef:
name: order-service-config
- secretRef:
name: order-service-secrets
Недостаток ConfigMap — нет hot reload без пересоздания подов. Для динамических настроек — Consul/etcd + watch или External Secrets Operator с Vault.
Сроки реализации
- Consul KV с hot reload для feature flags — 2–3 дня
- Vault для секретов + Kubernetes External Secrets — 3–5 дней
- Spring Cloud Config с Git-репозиторием — 2–3 дня







