Налаштування Config Server (Consul/etcd) для мікросервісів
Централізоване управління конфігурацією дозволяє змінювати налаштування сервісів без перебудови образів і рестарту. Database URL, feature flags, таймаути, API-ключі — все зберігається в одному місці, версіонується і оновлюється динамічно.
Огляд інструментів
| Інструмент | Сильні сторони |
|---|---|
| Consul KV | Інтеграція з Service Discovery, health checks |
| etcd | Основа для 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 дні







