8. manent in produzione#
In questo tutorial
Porti manent da un singolo processo serve su SQLite a un servizio di piattaforma: Postgres, uno strato API e più worker su Kubernetes, accesso tramite il tuo identity provider, TLS, metriche e allarmi, log al SIEM, audit e backup. Ogni passo rimanda alla pagina di riferimento con tutte le opzioni.
Tempo: 45 minuti · Serve: un cluster Kubernetes ed Helm (o VM con systemd), Postgres, il tuo identity provider, Vault e Consul del tutorial 2
Topologia di arrivo#
flowchart LR
U["Utenti<br/>browser · CLI manent"] -->|HTTPS + OIDC| LB["Ingress / LB<br/>TLS"]
CI["Pipeline di CI<br/>token statici"] -->|HTTPS| LB
LB --> API1["manent-server api"]
LB --> API2["manent-server api"]
API1 & API2 --> PG[("Postgres<br/>schemi dbos · manent")]
W1["worker-0"] & W2["worker-1"] & W3["worker-2"] --> PG
W1 & W2 & W3 --> T["Target"]
W1 & W2 & W3 -.-> V[("Vault")]
W1 & W2 & W3 -.-> C[("Consul")]
API1 & W1 -.->|/metrics| P["Prometheus"]
API1 & W1 -.->|RFC 5424| S["SIEM"]
- L'API (
manent-server api) autentica, verifica e accoda. Non esegue mai deploy, quindi scala liberamente. - I worker (
manent-server worker) eseguono i deploy. Ognuno ha unexecutor_idstabile; dopo un riavvio riprende i propri deploy interrotti. - Postgres contiene tutto: code, workflow, storico, schedule, approvazioni, log, il registro dei worker. È l'unico componente con stato.
Perché API e worker sono separati#
Sul portatile serve esegue entrambi in un solo processo, e resta la scelta giusta per lo sviluppo e le installazioni piccole. In produzione la separazione conviene:
- Scalabilità indipendente. Le repliche dell'API seguono le richieste e l'interfaccia web; i worker seguono quanti deploy girano insieme (
dbos.concurrency,dbos.environment_concurrency). - Riavvii senza impatto. Un pod dell'API si può sostituire in qualunque momento. Un worker smette di prendere deploy, attende quelli in corso fino a
dbos.drain_timeoute riprende i propri deploy interrotti quando torna con lo stessoexecutor_id: per questo i worker sono uno StatefulSet. - Superficie esposta ridotta. L'API è ciò che raggiungono utenti e CI; solo i worker raggiungono i target e leggono chiavi SSH, token dei cluster e credenziali cloud. All'API non servono la rete verso i target,
helmné i plugin esterni. - Worker specializzati. Worker per region (
dbos.region), per plugin (dbos.plugins, per esempio un'immagine con Ansible), per coda di un tenant o per coda instradata (dbos.queues) sono possibili solo come processi separati.
Cosa deve raggiungere ogni processo:
| API | Worker | |
|---|---|---|
| Postgres | sì | sì |
| Identity provider (discovery e chiavi OIDC) | sì | no |
| Consul o Git (configurazione di ambiente) | sì, per rifiutare subito una richiesta non valida | sì |
| Vault | solo per i segreti che usa l'API stessa: credenziali degli artefatti per validate --check-artifact, signing secret di Slack, chiave HMAC dell'audit |
sì |
| Repository degli artefatti | solo per validate --check-artifact |
sì |
| Target (SSH, WinRM, API dei cluster e dei cloud) | no | sì |
| Sistemi di metriche, Alertmanager | no | sì, per i gate di salute |
| Chat, ITSM, destinatari dei callback | no (riceve le interazioni di Slack) | sì |
Se l'API non raggiunge Consul o Git, i deploy vengono comunque accettati e la verifica passa al worker: gli errori arrivano più tardi, non mai. La separazione non isola l'API dal database: le sue credenziali di Postgres possono agire direttamente su DBOS, quindi sono sensibili quanto quelle dei worker. Con SQLite i processi possono solo condividere un file sullo stesso host: separali solo su Postgres.
1. Postgres#
All'avvio manent crea gli schemi dbos e manent: i worker sempre, l'API solo se mancano. Più worker avviati insieme su un database vuoto vanno in race sulla migrazione, e manent ritenta finché uno vince.
kubectl create namespace manent
kubectl -n manent create secret generic manent-db \
--from-literal=url='postgres://manent:…@postgres.internal:5432/manent?sslmode=verify-full'
L'URL arriva ai processi tramite DBOS_SYSTEM_DATABASE_URL, mai tramite la ConfigMap. Chi ha queste credenziali può agire direttamente su DBOS scavalcando manent: vanno solo ai processi server e agli operatori della piattaforma.
2. Installa con Helm#
image:
tag: "0.1.0"
config:
dbos:
concurrency: 4
environment_concurrency: 1
drain_timeout: 5m
recovery:
auto_recover_after: 10m # i deploy di un pod rimosso li riprende un altro worker
retention:
max_age: 2160h # 90 giorni, tenendo sempre le ultime 10 release per ambiente
keep_releases: 10
# Qui va la configurazione dei tutorial precedenti: envconfig, secrets, artifacts,
# descriptor_policy, plugins, governance, auth e rbac (vedi i passi successivi).
api:
replicas: 2
worker:
replicas: 3
terminationGracePeriodSeconds: 360 # più lungo di dbos.drain_timeout
serviceMonitor:
enabled: true
extraEnv:
- name: CONSUL_HTTP_TOKEN
valueFrom: {secretKeyRef: {name: manent-consul, key: token}}
Il chart crea un Deployment per l'API, uno StatefulSet per i worker (il nome del pod manent-worker-0, -1… diventa l'executor_id), un PodDisruptionBudget e, a richiesta, un ServiceMonitor. I container girano come utente non root su un filesystem in sola lettura. Sulle VM le unit systemd in deploy/systemd fanno lo stesso: vedi Installazione.
3. TLS e l'indirizzo dell'API#
manent serve HTTP in chiaro: termina il TLS davanti, sull'Ingress, sul Gateway o sul load balancer, e pubblicalo come https://manent.example.com. Instrada tutti i percorsi al Service dell'API (l'interfaccia web è servita su /) e blocca /metrics dall'esterno: sonde e metriche non richiedono autenticazione.
Perché log e audit mostrino l'indirizzo degli utenti invece di quello del proxy, elenca il proxy in http.trusted_proxies (per esempio la rete dei pod, 10.42.0.0/16): X-Forwarded-For viene creduto solo da lì.
Utenti e CI poi puntano il client lì:
server: https://manent.example.com
token_file: ~/.config/manent/token
ca_file: /etc/ssl/certs/corporate-ca.pem # solo per una CA privata
4. Accesso con il tuo identity provider#
auth:
mode: enabled
oidc:
issuer: https://sso.example.com/realms/corp
audience: manent
username_claim: preferred_username
groups_claim: groups
ui:
client_id: manent-ui # client pubblico con PKCE, per l'interfaccia web
tokens_file: /etc/manent/tokens/tokens.yml # token della CI, montati da un Secret
rbac:
bindings:
- {groups: [team-*], role: deployer, applications: ["*"], environments: [dev, test, staging]}
- {groups: [team-*], role: tester, applications: ["*"], environments: [prod]}
- {groups: [release-managers], role: operator, applications: ["*"], environments: ["*"]}
- {groups: [cab], role: approver, applications: ["*"], environments: [prod]}
Identity provider OIDC riporta i passi per Keycloak, Microsoft Entra ID e Okta: il client dell'API, il client pubblico dell'interfaccia web, e i claim di audience e gruppi.
5. Impostazioni di produzione#
All'avvio serve e worker registrano configuration not fit for production per ogni impostazione ancora permissiva. Chiudile tutte:
artifacts:
allow_unlisted: false
sources:
- prefix: https://nexus.example.com/repository/releases/
auth: {type: basic, username: manent, secret_ref: "vault:secret/data/manent/nexus#password"}
callbacks:
allowed_hosts: ["*.example.com"]
descriptor_policy:
params:
remote-copy: [verify_checksum]
kubernetes: [wait_timeout, "helm_value.*"]
secret_refs: ["vault:secret/data/{application}/*"]
targets: false
post_test_hosts: ["*.example.com"]
secrets:
vault:
enabled: true
address: https://vault.example.com:8200
auth: kubernetes
kubernetes: {role: manent}
audit:
file: /var/log/manent/audit.jsonl # un volume scrivibile, un file per processo (extraVolumes)
max_size_mb: 100
hmac_key_ref: "vault:secret/data/manent/audit#key"
L'elenco completo è la checklist di produzione in Sicurezza; HashiCorp Vault e Repository degli artefatti spiegano le integrazioni.
6. Metriche, allarmi e tracce#
Con serviceMonitor.enabled Prometheus legge /metrics di API e worker (porta 9090 per i worker, che non hanno API). Parti da questi allarmi:
groups:
- name: manent
rules:
- alert: ManentWorkerLost
expr: max by (executor) (manent_executor_up) == 0
for: 5m
- alert: ManentQueueStuck
expr: max(manent_workflows{workflow="manent.deploy",status="ENQUEUED"}) > 20
for: 15m
- alert: ManentProductionDeployFailed
expr: sum by (application) (increase(manent_deployments_total{environment="prod",outcome="failed",dry_run="false"}[30m])) > 0
- alert: ManentPolicyStale
expr: max(manent_policy_age_seconds) > 600
Per le tracce, observability.tracing esporta span OpenTelemetry via OTLP: una traccia segue un deploy dalla richiesta della CI a ogni step sul worker. Vedi Osservabilità e Prometheus e Alertmanager.
7. Log al SIEM#
logging:
level: info
format: json
siem:
enabled: true
destinations:
- network: tcp
address: siem.example.com:6514
Ogni record, compresi DBOS e plugin, arriva al SIEM in RFC 5424 con gli attributi come structured data; le voci di audit hanno audit=true. Vedi SIEM e syslog.
8. Operatività quotidiana#
| Situazione | Cosa fare |
|---|---|
| Scalare in su o in giù | Cambia worker.replicas. I deploy in sospeso di un pod rimosso vengono ripresi dopo recovery.auto_recover_after. |
| Aggiornare manent | Una release senza cambio della versione dei workflow è un rolling update. Con una nuova versione dei workflow segui Versioni e aggiornamenti. |
| Un worker è sparito per sempre | manent-server admin executors, poi admin recover --executor <id>. Vedi Recovery. |
| Arresto ordinato | SIGTERM: il worker smette di prelevare deploy e attende quelli in corso fino a dbos.drain_timeout; nel frattempo /readyz risponde 503. |
| Cosa sta succedendo ora | manent activity, manent workers, o la pagina Attività dell'interfaccia web. |
| Integrità dell'audit | manent-server audit verify, pianificato, confrontato con il SIEM. |
| Backup | Backup continui di Postgres con point-in-time recovery. Prima di avviare i worker su un database ripristinato leggi Backup e ripristino. |
Cosa hai imparato#
- manent in produzione è fatto di processi senza stato su Postgres: uno strato API e worker con ID stabili.
- TLS, OIDC e RBAC stanno davanti a ogni azione; la CI usa token da un file ricaricabile.
- I default permissivi vengono segnalati all'avvio e si chiudono con la configurazione.
- Metriche, tracce, SIEM e audit rendono la piattaforma osservabile e verificabile.
Prossimo passo#
Collega gli strumenti che i tuoi team usano già: Integrazioni.