Padronização de Nomenclatura de Serviços
Para manter a organização em clusters Kbuernetes, é fundamental adotar uma convenção de nomes clara para os repositórios e artefatos. Uma estrutura recomendada segue o padrão de função do serviço:
svc-vendas-provider
svc-vendas-consumer
svc-processamento-worker
Implementação de Health Checks Dinâmicos
A utilização de sondas (probes) do Kubernetes garante a resiliência do sistema. Abaixo, uma abordagem para criar um endpoint de verificação que permite controle manual sobre o estado de prontidão do serviço, útil para manutenções controladas.
Configuração sugerida para as sondas no manifesto do Kubernetes:
livenessProbe:
httpGet:
path: /manage/health/check
port: 9090
initialDelaySeconds: 20
periodSeconds: 10
readinessProbe:
httpGet:
path: /manage/health/check
port: 9090
initialDelaySeconds: 10
periodSeconds: 10
Desenvolvimento do Serviço Provedor (Provider)
Este serviço atua como o fornecedor de dados na arquitetura, registrado no Nacos.
Configuração do Projeto (pom.xml):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.4.0</version>
</dependency>
</dependencies>
Controlador de Recursos e Saúde:
package com.dev.provider.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/manage")
public class MonitoringController {
private static volatile boolean isSystemReady = true;
@GetMapping("/status/toggle")
public String toggleState(@RequestParam String mode) {
if ("disable".equalsIgnoreCase(mode)) {
isSystemReady = false;
return "Serviço marcado como indisponível";
} else if ("enable".equalsIgnoreCase(mode)) {
isSystemReady = true;
return "Serviço marcado como ativo";
}
return "Comando inválido";
}
@GetMapping("/health/check")
public String checkHealth() {
if (!isSystemReady) {
throw new RuntimeException("Service Unavailable");
}
return "UP";
}
@GetMapping("/data")
public String getData() {
return "Dados processados pelo Provider";
}
}
Dockerfile do Provedor:
FROM openjdk:11-jre-slim
WORKDIR /deployments
COPY target/svc-vendas-provider.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java", "-Duser.timezone=America/Sao_Paulo", "-jar", "app.jar", "--spring.config.location=/app/config/application.yml"]
Desenvolvimento do Serviço Consumidor (Consumer)
O consumidor utiliza OpenFeign para comunicação síncrona e LoadBalancer para distribuir as requisições entre as instâncias do provedor.
Interfcae Feign:
package com.dev.consumer.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "svc-vendas-provider")
public interface ProviderClient {
@GetMapping("/manage/data")
String fetchRemoteData();
}
Configuração de Log Customizada (logback-spring.xml):
Para ambientes K8s, é ideal que o nome do arquivo de log contenha o ID do Pod para facilitar o rastreamento em volumes compartilhados.
<configuration>
<springProperty scope="context" name="POD_ID" source="HOSTNAME" defaultValue="local-node"/>
<property name="LOG_PATH" value="/var/log/microservices/${POD_ID}.log"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{40} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
Gerenciamento de Imagens e Configuração Externa
O empacotamento e distribuição seguem o fluxo padrão de integração contínua:
mvn clean package -DskipTests
docker build -t registry.local/svc-provider:1.0.0 ./provider
docker push registry.local/svc-provider:1.0.0
Para desacoplar a configuração do código, utilizamos ConfigMaps para injetar o arquivo application.yml:
kubectl create configmap provider-config --from-file=application.yml=./configs/prod-provider.yml -n namespace-vendas
Orquestração no Kubernetes
Definição do volume persistente para logs e do deploy dos serviços.
PersistentVolumeClaim (PVC):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ms-log-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: nfs-client
Manifesto de Deployment (Exemplo Provider):
apiVersion: apps/v1
kind: Deployment
metadata:
name: svc-vendas-provider
spec:
replicas: 2
selector:
matchLabels:
app: provider-service
template:
metadata:
labels:
app: provider-service
spec:
containers:
- name: java-app
image: registry.local/svc-provider:1.0.0
env:
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- name: log-volume
mountPath: /var/log/microservices
- name: config-volume
mountPath: /app/config/application.yml
subPath: application.yml
volumes:
- name: log-volume
persistentVolumeClaim:
claimName: ms-log-pvc
- name: config-volume
configMap:
name: provider-config