Em sistemas distribuídos, é comum precisar garantir que apenas uma instância de um serviço execute uma tarefa crítica — seja backup, sincronização de dados ou processamento de eventos. O Kubernetes oferece a State Lock API exatamente para isso: coordenação segura entre múltiplos pods.
Neste post, vamos entender como usar State Lock API, quando usá-la, compará-la com outras abordagens e implementar um exemplo prático.
O que é State Lock API?
A State Lock API do Kubernetes (via leaderelection) é um mecanismo que permite que múltiplas réplicas de um aplicativo coordenem entre si para eleger um “líder” — uma única instância responsável por executar tarefas críticas.
Ela funciona através de:
- Recurso ConfigMap ou Lease: armazena informações sobre quem é o líder
- Renovação periódica: o líder renova seu “lock” em intervalos regulares
- Eleição automática: se o líder falhar, outro pod toma o lugar
Comparação com outras abordagens
1. State Lock API (Kubernetes-native)
✅ Integrado ao Kubernetes
✅ Não requer dependências externas
✅ Simples e confiável
❌ Limitado ao cluster Kubernetes
2. Banco de dados (PostgreSQL, MySQL)
✅ Funciona fora do Kubernetes
✅ Mais flexível
❌ Requer outro serviço
❌ Maior latência
3. Redis/Memcached
✅ Rápido
✅ Simples
❌ Não é persistente
❌ Requer cluster Redis
4. Etcd (direto)
✅ Muito consistente
✅ Usado pelo próprio Kubernetes
❌ Complexo de usar diretamente
❌ Overhead de gerenciamento
Recomendação: Use State Lock API para aplicações em Kubernetes. Para casos multi-cluster ou fora do K8s, considere banco de dados.
Como funciona internamente
A eleição de líder no Kubernetes usa um mecanismo baseado em leasing:
Pod A (candidato)
↓
Tenta adquirir lock em ConfigMap/Lease
↓
Se conseguir → Se torna líder e renova a cada 15s
↓
Se falhar → Aguarda e tenta novamente
↓
Se o líder cair → Outro pod adquire o lock após timeout
O Kubernetes fornece a biblioteca client-go com a função leaderelection que encapsula toda essa lógica.
Implementação prática
Aqui está um exemplo completo de um aplicativo que usa State Lock API:
package main
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
)
func main() {
// Configuração do cliente Kubernetes
config, err := rest.InClusterConfig()
if err != nil {
fmt.Fprintf(os.Stderr, "Erro ao carregar config K8s: %v\n", err)
os.Exit(1)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
fmt.Fprintf(os.Stderr, "Erro ao criar clientset: %v\n", err)
os.Exit(1)
}
podName := os.Getenv("POD_NAME")
namespace := os.Getenv("POD_NAMESPACE")
lockName := "my-app-lock"
// Define o lock (pode ser ConfigMap ou Lease)
lock := &resourcelock.LeaseLock{
LeaseMeta: metav1.ObjectMeta{
Name: lockName,
Namespace: namespace,
},
Client: clientset.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: podName,
},
}
// Configuração da eleição
leaderElectionConfig := leaderelection.LeaderElectionConfig{
Lock: lock,
LeaseDuration: 15 * time.Second,
RenewDeadline: 10 * time.Second,
RetryPeriod: 2 * time.Second,
ReleaseOnCancel: true,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
fmt.Println("🎯 Sou o líder! Iniciando tarefas críticas...")
runLeaderTasks(ctx)
},
OnStoppedLeading: func() {
fmt.Println("❌ Perdi a liderança")
},
OnNewLeader: func(identity string) {
if identity != podName {
fmt.Printf("✅ Novo líder: %s\n", identity)
}
},
},
}
// Inicia eleição
leaderelection.RunOrDie(context.Background(), leaderElectionConfig)
}
func runLeaderTasks(ctx context.Context) {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
fmt.Println("Parando tarefas do líder")
return
case <-ticker.C:
fmt.Println("Executando tarefa crítica...")
// Sua lógica aqui
}
}
}
Configuração no Kubernetes
Para que seu pod tenha permissão de criar/atualizar Leases, adicione RBAC:
apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: my-app-leader-election namespace: default rules: - apiGroups: ["coordination.k8s.io"] resources: ["leases"] verbs: ["get", "create", "update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: my-app-leader-election namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: my-app-leader-election subjects: - kind: ServiceAccount name: my-app-sa namespace: default
E no Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
serviceAccountName: my-app-sa
containers:
- name: app
image: my-app:latest
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
Boas práticas
1. Use Lease, não ConfigMap
A partir do Kubernetes 1.14+, use Lease em vez de ConfigMap para eleição. É mais leve e eficiente.
2. Configure timeouts realistas
LeaseDuration: quanto tempo o lock dura (ex: 15s)RenewDeadline: até quando tentar renovar (ex: 10s)RetryPeriod: quanto aguardar antes de tentar novamente (ex: 2s)
3. Monitore a liderança
Registre quando um pod se torna ou deixa de ser líder. Use métricas:
leaderMetric.WithLabelValues(podName).Set(1) // sou líder leaderMetric.WithLabelValues(podName).Set(0) // não sou líder
4. Evite tarefas bloqueantes
Se a tarefa do líder demorar muito, a renovação do lock pode falhar. Use contexts e timeouts.
Conclusão
State Lock API é a forma mais simples e nativa de implementar eleição de líder em Kubernetes. Se você precisa garantir que uma única instância execute uma tarefa crítica, esta é a solução recomendada.
A chave é entender os timeouts, usar Lease em vez de ConfigMap, e sempre implementar logging para visibilidade em produção.
Gostou do conteúdo?
- ✅ Inscreva-se na newsletter para receber mais dicas práticas sobre Go e Kubernetes diretamente no seu e-mail!
- 🚀 Conheça a Imersão Golang e leve seus conhecimentos em Go para o próximo nível!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.