Skip to content

Kubernetes Deployment

FluxiQ SPB is designed for production deployment on Kubernetes. This guide covers Helm chart configuration, resource management, autoscaling, and operational best practices for running the platform in a Kubernetes cluster.

Prerequisites

ToolVersionPurpose
Kubernetes>= 1.28Container orchestration
Helm>= 3.14Package management
kubectl>= 1.28Cluster management
Container registry-Store Docker images

Cluster Architecture

Kubernetes Cluster
├── Namespace: spb-production
│   ├── Deployment: api-gateway (3 replicas)
│   ├── Deployment: auth-service (2 replicas)
│   ├── Deployment: bacen-gateway (2 replicas)
│   ├── Deployment: message-processor (3 replicas)
│   ├── Deployment: user-management (2 replicas)
│   ├── Deployment: transaction-service (3 replicas)
│   ├── Deployment: securities-service (2 replicas)
│   ├── Deployment: settlement-service (2 replicas)
│   ├── Deployment: forex-service (2 replicas)
│   ├── Deployment: cash-service (2 replicas)
│   ├── Deployment: extract-service (2 replicas)
│   ├── Deployment: frontend (2 replicas)
│   ├── StatefulSet: postgresql (3 replicas, HA)
│   ├── StatefulSet: ibm-mq (2 replicas)
│   ├── Ingress: spb-ingress
│   ├── ConfigMap: spb-config
│   ├── Secret: spb-secrets
│   ├── HPA: per-service autoscalers
│   └── PDB: per-service disruption budgets
├── Namespace: spb-monitoring
│   ├── Deployment: prometheus
│   ├── Deployment: grafana
│   └── DaemonSet: otel-collector
└── Namespace: spb-staging
    └── (mirror of production)

Helm Chart

Installation

bash
# Add the FluxiQ Helm repository
helm repo add fluxiq https://charts.fluxiq.io
helm repo update

# Install the SPB chart
helm install spb fluxiq/spb \
  --namespace spb-production \
  --create-namespace \
  --values values-production.yaml

# Upgrade an existing installation
helm upgrade spb fluxiq/spb \
  --namespace spb-production \
  --values values-production.yaml

# Check installation status
helm status spb -n spb-production

Values File

yaml
# values-production.yaml
global:
  image:
    registry: registry.fluxiq.io/spb
    tag: "1.0.0"
    pullPolicy: IfNotPresent
  imagePullSecrets:
    - name: registry-credentials

  postgresql:
    host: postgresql-ha-pgpool.spb-production.svc
    port: 5432
    database: spb_production
    existingSecret: spb-db-credentials

  bacen:
    mode: production
    ispb: "12345678"
    mqHost: ibm-mq.spb-production.svc
    mqPort: 1414
    mqChannel: BACEN.SVRCONN
    mqQueueManager: QM1

apiGateway:
  replicaCount: 3
  image:
    repository: api-gateway
  service:
    type: ClusterIP
    port: 4000
  resources:
    requests:
      cpu: 250m
      memory: 256Mi
    limits:
      cpu: 1000m
      memory: 512Mi
  autoscaling:
    enabled: true
    minReplicas: 3
    maxReplicas: 10
    targetCPUUtilization: 70
    targetMemoryUtilization: 80
  env:
    - name: SECRET_KEY_BASE
      valueFrom:
        secretKeyRef:
          name: spb-secrets
          key: secret-key-base

authService:
  replicaCount: 2
  image:
    repository: auth-service
  service:
    port: 4001
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

bacenGateway:
  replicaCount: 2
  image:
    repository: bacen-gateway
  service:
    port: 4002
  resources:
    requests:
      cpu: 500m
      memory: 512Mi
    limits:
      cpu: 2000m
      memory: 1Gi

messageProcessor:
  replicaCount: 3
  image:
    repository: message-processor
  service:
    port: 4003
  resources:
    requests:
      cpu: 500m
      memory: 512Mi
    limits:
      cpu: 2000m
      memory: 1Gi
  autoscaling:
    enabled: true
    minReplicas: 3
    maxReplicas: 20
    targetCPUUtilization: 60
  env:
    - name: BROADWAY_CONCURRENCY
      value: "20"
    - name: BROADWAY_MAX_DEMAND
      value: "100"

transactionService:
  replicaCount: 3
  image:
    repository: transaction-service
  service:
    port: 4005
  resources:
    requests:
      cpu: 250m
      memory: 256Mi
    limits:
      cpu: 1000m
      memory: 512Mi
  autoscaling:
    enabled: true
    minReplicas: 3
    maxReplicas: 10
    targetCPUUtilization: 70

securitiesService:
  replicaCount: 2
  image:
    repository: securities-service
  service:
    port: 4006
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

settlementService:
  replicaCount: 2
  image:
    repository: settlement-service
  service:
    port: 4007
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

forexService:
  replicaCount: 2
  image:
    repository: forex-service
  service:
    port: 4008
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

cashService:
  replicaCount: 2
  image:
    repository: cash-service
  service:
    port: 4009
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

extractService:
  replicaCount: 2
  image:
    repository: extract-service
  service:
    port: 4010
  resources:
    requests:
      cpu: 250m
      memory: 512Mi
    limits:
      cpu: 1000m
      memory: 1Gi

frontend:
  replicaCount: 2
  image:
    repository: frontend
  service:
    port: 3000

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
  hosts:
    - host: spb.fluxiq.io
      paths:
        - path: /api
          pathType: Prefix
          service: api-gateway
          port: 4000
        - path: /
          pathType: Prefix
          service: frontend
          port: 3000
  tls:
    - secretName: spb-tls
      hosts:
        - spb.fluxiq.io

Kubernetes Manifests

Deployment Example

yaml
# api-gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
  namespace: spb-production
  labels:
    app: api-gateway
    part-of: fluxiq-spb
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "4000"
        prometheus.io/path: "/metrics"
    spec:
      serviceAccountName: spb-service
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      containers:
        - name: api-gateway
          image: registry.fluxiq.io/spb/api-gateway:1.0.0
          ports:
            - containerPort: 4000
              name: http
              protocol: TCP
          envFrom:
            - configMapRef:
                name: spb-config
            - secretRef:
                name: spb-secrets
          resources:
            requests:
              cpu: 250m
              memory: 256Mi
            limits:
              cpu: 1000m
              memory: 512Mi
          livenessProbe:
            httpGet:
              path: /health/live
              port: http
            initialDelaySeconds: 15
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health/ready
              port: http
            initialDelaySeconds: 10
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health/live
              port: http
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 30
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: api-gateway

Horizontal Pod Autoscaler

yaml
# api-gateway-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-gateway
  namespace: spb-production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-gateway
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Pods
          value: 2
          periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Pods
          value: 1
          periodSeconds: 120

Pod Disruption Budget

yaml
# api-gateway-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-gateway
  namespace: spb-production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api-gateway

Secrets

bash
# Create secrets from literal values
kubectl create secret generic spb-secrets \
  --namespace spb-production \
  --from-literal=secret-key-base="$(openssl rand -hex 64)" \
  --from-literal=jwt-secret="$(openssl rand -hex 64)" \
  --from-literal=database-password="your-db-password"

# Or use sealed-secrets for GitOps
kubeseal --format=yaml < spb-secrets.yaml > spb-sealed-secrets.yaml

Database Migration

Run migrations as a Kubernetes Job:

yaml
# migration-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: spb-migrate
  namespace: spb-production
spec:
  template:
    spec:
      containers:
        - name: migrate
          image: registry.fluxiq.io/spb/api-gateway:1.0.0
          command: ["bin/service", "eval", "ApiGateway.Release.migrate()"]
          envFrom:
            - configMapRef:
                name: spb-config
            - secretRef:
                name: spb-secrets
      restartPolicy: OnFailure
  backoffLimit: 3
bash
kubectl apply -f migration-job.yaml
kubectl wait --for=condition=complete job/spb-migrate -n spb-production --timeout=120s

Monitoring

Prometheus ServiceMonitor

yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: spb-services
  namespace: spb-monitoring
spec:
  namespaceSelector:
    matchNames:
      - spb-production
  selector:
    matchLabels:
      part-of: fluxiq-spb
  endpoints:
    - port: http
      path: /metrics
      interval: 15s

Alerting Rules

yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: spb-alerts
  namespace: spb-monitoring
spec:
  groups:
    - name: spb.rules
      rules:
        - alert: HighErrorRate
          expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "High error rate on {{ $labels.service }}"

        - alert: BACENConnectionDown
          expr: bacen_mq_connection_status == 0
          for: 1m
          labels:
            severity: critical
          annotations:
            summary: "BACEN MQ connection is down"

        - alert: SettlementWindowMissed
          expr: settlement_window_deadline_seconds < 300
          for: 1m
          labels:
            severity: warning
          annotations:
            summary: "Settlement window closing in less than 5 minutes"

Operational Commands

bash
# Check deployment status
kubectl get deployments -n spb-production

# View pod logs
kubectl logs -f deployment/api-gateway -n spb-production

# Scale a service manually
kubectl scale deployment transaction-service --replicas=5 -n spb-production

# Rolling restart (zero-downtime)
kubectl rollout restart deployment/api-gateway -n spb-production

# Check rollout status
kubectl rollout status deployment/api-gateway -n spb-production

# Rollback to previous version
kubectl rollout undo deployment/api-gateway -n spb-production

# Port-forward for debugging
kubectl port-forward svc/api-gateway 4000:4000 -n spb-production

# Open a shell in a running pod
kubectl exec -it deployment/api-gateway -n spb-production -- bin/service remote

Production Checklist

Before going to production, verify the following:

  • [ ] All secrets are stored in Kubernetes Secrets (not ConfigMaps)
  • [ ] Resource requests and limits are configured for every container
  • [ ] Liveness, readiness, and startup probes are defined
  • [ ] Pod Disruption Budgets are set for critical services
  • [ ] Horizontal Pod Autoscalers are configured
  • [ ] Topology spread constraints distribute pods across availability zones
  • [ ] Network policies restrict inter-service communication
  • [ ] TLS is enabled on the Ingress
  • [ ] Database backups are configured and tested
  • [ ] Prometheus alerting rules are active
  • [ ] Log aggregation is configured (e.g., Loki, ELK)
  • [ ] IBM MQ TLS certificates are configured for BACEN production
  • [ ] HSM integration is tested with production key material
  • [ ] BACEN_MODE is set to production (not simulator)
  • [ ] Disaster recovery runbook is documented and tested

Plataforma de Integracao BACEN/SPB