
Uma das maiores dores em microsserviços não é o código – é a configuração. URLs de banco de dados, chaves de API, endpoints de serviços vizinhos, credenciais, feature flags, timeouts… Tudo isso muda entre ambientes (desenvolvimento, homologação, produção) e precisa ser gerenciado de forma segura, auditable e sem exigir rebuild das imagens.
Em Go, a abordagem idiomática é usar variáveis de ambiente combinadas com arquivos de configuração (quando necessário). Em Kubernetes, entram os ConfigMaps e Secrets. Em sistemas mais críticos, ferramentas como HashiCorp Vault ou AWS Secrets Manager entram em cena.
Neste post, vamos explorar as melhores práticas para gerenciar configurações em microsserviços, com exemplos em Go, desde o desenvolvimento local até a produção em Kubernetes.
Por que configuração é um desafio em microsserviços?
Em um monólito, você tem um único arquivo de configuração. Em microsserviços, cada serviço tem suas próprias configurações – e elas podem variar por réplica, ambiente e região. Os principais desafios:
- Segurança: credenciais não podem ficar no código ou em repositórios.
- Consistência: mesma configuração para todas as réplicas de um serviço.
- Rotação: trocar senhas sem reiniciar o serviço.
- Auditoria: saber quem mudou o quê e quando.
1. Variáveis de ambiente: o padrão ouro para configuração em Go
A 12-factor app recomenda armazenar configurações em variáveis de ambiente. Go lê isso de forma trivial:
package main
import (
"fmt"
"log"
"os"
"strconv"
)
type Config struct {
Port int
DatabaseURL string
RedisAddr string
LogLevel string
}
func LoadConfig() *Config {
port, _ := strconv.Atoi(getEnv("PORT", "8080"))
return &Config{
Port: port,
DatabaseURL: getEnv("DATABASE_URL", "postgres://localhost:5432/app?sslmode=disable"),
RedisAddr: getEnv("REDIS_ADDR", "localhost:6379"),
LogLevel: getEnv("LOG_LEVEL", "info"),
}
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
func main() {
cfg := LoadConfig()
fmt.Printf("Rodando na porta %d\n", cfg.Port)
}
Vantagens: simples, universal, segura (se você não logar as variáveis).
Desvantagens: para muitas configurações, o comando de execução fica enorme; difícil gerenciar hierarquias.
2. Arquivos de configuração (YAML, JSON, TOML) – quando usar
Para configurações estruturadas (ex: múltiplos bancos, timeouts por endpoint), arquivos são mais limpos.
import "github.com/spf13/viper"
func LoadConfigWithViper() (*Config, error) {
viper.SetConfigName("config") // config.yaml
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("/etc/app/")
viper.AutomaticEnv() // override por env vars
if err := viper.ReadInConfig(); err != nil {
return nil, err
}
var cfg Config
if err := viper.Unmarshal(&cfg); err != nil {
return nil, err
}
return &cfg, nil
}
Exemplo de config.yaml:
port: 8080
database_url: postgres://localhost:5432/app
redis_addr: localhost:6379
features:
checkout_v2: true
use_new_recommendations: false
Vantagem: hierarquia, legibilidade.
Desvantagem: arquivo pode ficar desatualizado entre ambientes; risco de commitar segredos.
Boa prática: nunca commite segredos no arquivo. Use variáveis de ambiente ou secrets para valores sensíveis.
3. Configuração em Kubernetes: ConfigMaps e Secrets
No Kubernetes, a configuração é injetada no pod via:
- ConfigMap: para configurações não sensíveis (URLs, log levels, feature flags).
- Secret: para dados sensíveis (senhas, tokens, chaves API) – armazenados em base64 (mas não é criptografia; use encryption at rest no cluster).
Criando um ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
REDIS_ADDR: redis-service.default.svc.cluster.local:6379
config.yaml: |
port: 8080
features:
checkout_v2: true
Criando um Secret
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DATABASE_URL: cG9zdGdyZXM6Ly91c2VyOnBhc3NAcG9zdGdyZXM6NTQzMi9hcHA=
Usando no Deployment
spec:
containers:
- name: api
image: myapp:latest
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secret
key: DATABASE_URL
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
configMap:
name: app-config
4. Ferramentas avançadas: Vault, AWS Secrets Manager, Doppler
Para produção com alta segurança, variáveis de ambiente e Secrets do K8s podem não ser suficientes (secrets são base64 e podem ser vistos por quem tem acesso ao cluster). Use:
| Ferramenta | Ideal para | Go SDK |
|---|---|---|
| HashiCorp Vault | Segredos dinâmicos, rotação, auditoria | github.com/hashicorp/vault/api |
| AWS Secrets Manager | Ambiente AWS, rotação automática | AWS SDK for Go |
| Doppler | Gerenciamento centralizado (SaaS) | github.com/dopplerhq/doppler-go-sdk |
Exemplo com Vault:
import vault "github.com/hashicorp/vault/api"
client, _ := vault.NewClient(vault.DefaultConfig())
client.SetToken(os.Getenv("VAULT_TOKEN"))
secret, _ := client.Logical().Read("secret/data/database")
dbPassword := secret.Data["data"].(map[string]interface{})["password"]
5. Hot reload: atualizando configuração sem restart
Em Go, você pode recarregar configuração dinamicamente usando:
- FSNotify para monitorar arquivos.
- Polling periódico de variáveis de ambiente ou Secrets.
- Integração com Vault com leases e renovação.
func WatchConfig(ctx context.Context, cfg *Config) {
ticker := time.NewTicker(30 * time.Second)
go func() {
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
// recarrega de fonte externa
newCfg := reloadFromVault()
cfg.mu.Lock()
*cfg = *newCfg
cfg.mu.Unlock()
}
}
}()
}
Atenção: hot reload só é seguro para configurações que não afetam estruturas críticas (ex: pool de conexões). Para mudanças profundas, prefira restart.
6. Boas práticas para configurações em Go
| Prática | Por quê |
|---|---|
✅ Use os.Getenv com defaults razoáveis | Desenvolvimento local funciona sem setup |
| ✅ Valide a configuração no startup (fail fast) | Evita operação com erro silencioso |
| ✅ Não logue segredos nunca | Um log pode expor credenciais |
| ✅ Separe configuração por ambiente (DEV, HOM, PROD) | Evita acidentes |
| ✅ Use variáveis de ambiente para segredos em desenvolvimento | Simples e seguro |
| ✅ Em produção, prefira Secrets + Vault | Mais segurança |
Exemplo prático: serviço Go com configuração flexível
type Config struct {
HTTPPort int
DatabaseURL string
RedisURL string
Features FeatureFlags
}
type FeatureFlags struct {
NewCheckout bool
AIRecommend bool
}
func LoadConfig() (*Config, error) {
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.AutomaticEnv()
viper.SetEnvPrefix("APP")
viper.BindEnv("http_port", "PORT")
viper.BindEnv("database_url", "DATABASE_URL")
viper.BindEnv("redis_url", "REDIS_URL")
viper.BindEnv("features.new_checkout")
viper.BindEnv("features.ai_recommend")
if err := viper.ReadInConfig(); err != nil {
log.Printf("Nenhum arquivo de configuração encontrado, usando defaults")
}
var cfg Config
if err := viper.Unmarshal(&cfg); err != nil {
return nil, err
}
return &cfg, nil
}
Caso real: modernização com gestão de configurações
Um cliente da Jacobus operava com dezenas de variáveis de ambiente hardcoded em scripts de deploy. Cada ambiente (dev, staging, prod) exigia rebuild da imagem. Implementamos:
- ConfigMaps para configurações comuns.
- Secrets (via Kubernetes) para credenciais de banco.
- Vault para chaves de API de provedores externos (rotação automática).
- Viper no código Go para fallback e hierarquia.
Resultado: tempo de deploy caiu 80%. Rotação de segredos passou a ser automática. Zero credenciais em repositórios.
Conclusão
Gerenciar configurações em microsserviços exige disciplina, mas as ferramentas são maduras. Comece com variáveis de ambiente e arquivos YAML locais. Em Kubernetes, use ConfigMaps e Secrets. Para segurança máxima, adicione Vault. O importante é nunca, jamais, colocar segredos no código ou no repositório.
Na Jacobus Software, aplicamos essas práticas em todos os projetos. Configuração é infraestrutura – trate-a com o mesmo rigor que trata o código.
🔐 Quer organizar a configuração dos seus microsserviços?
Nossos especialistas implementam pipelines de configuração com Kubernetes, Vault e CI/CD – seguros, auditáveis e fáceis de gerenciar.
