๐ฎ๐น Italiano
๐ฎ๐น Italiano
Appearance
๐ฎ๐น Italiano
๐ฎ๐น Italiano
Appearance
Deliverable D2.1.3: Specifiche Infrastruttura Hosting
L'infrastruttura MAPS viene costruita da zero su un account DigitalOcean dedicato al progetto GST-MAPS. Il provisioning utilizza Pulumi come strumento IaC (Infrastructure as Code) con lo stesso stack tecnologico descritto nel deliverable D2.1.2: DOKS per l'orchestrazione container, cert-manager per i certificati TLS, external-secrets per la gestione dei segreti, CloudNative PostgreSQL (CNPG) per il database.
Il dominio di riferimento รจ maps.gransassotech.it (o equivalente assegnato da GST). La gestione DNS avviene tramite AWS Route53, con un hosted zone dedicato al progetto.
Prima di avviare il provisioning, devono essere disponibili:
| Risorsa | Tipo | Note |
|---|---|---|
| Account DigitalOcean | Nuovo account GST o progetto separato | Con billing attivo |
| Token API DigitalOcean | Personal Access Token con scope read+write | Per Pulumi provider DO |
| Account AWS | Per Route53 e AWS Parameter Store | Account GST dedicato al progetto |
| Hosted zone Route53 | Per il dominio maps.gransassotech.it | Zone ID necessario per Pulumi |
| IAM credentials AWS | Access Key + Secret Key con permessi Route53 + SSM | Per external-dns e external-secrets |
| Bucket S3 | Per lo stato Pulumi | Es. gst-maps-pulumi-state |
| Chiave KMS AWS | Per cifratura stato Pulumi | Alias pulumi-maps |
Il provisioning viene realizzato con uno stack Pulumi maps strutturato come segue:
pulumi/maps/
โโโ __main__.py # Entry point
โโโ cluster.py # Creazione cluster DOKS
โโโ components.py # Installazione componenti Helm
โโโ security.py # IAM, network policies, segreti
โโโ dns.py # Record DNS Route53
โโโ services.py # Namespace e configurazione servizi
โโโ utils.py # Helper
โโโ Pulumi.yaml # Definizione progetto
โโโ Pulumi.maps.yaml # Configurazione stack maps
โโโ helm/
โ โโโ maps/ # Valori Helm per lo stack maps
โ โโโ cert-manager.yaml
โ โโโ external-secrets.yaml
โ โโโ cnpg.yaml
โ โโโ ingress-nginx.yaml
โ โโโ external-dns.yaml
โ โโโ metrics-server.yaml
โโโ manifests/
โโโ maps/ # Manifest Kubernetes aggiuntivi
โโโ cluster-issuer.yaml# Pulumi.maps.yaml (estratto)
config:
env: maps
defaultDOregion: fra1
route53Domains:
- maps.gransassotech.it
cluster:
name: maps
version: "1.33" # Aggiornare alla versione stabile piรน recente disponibile
control_plane_high_availability: false
node_pools:
- name: general-purpose
size: s-2vcpu-4gb
count: 2
- name: workloads
size: s-4vcpu-8gb
autoscale:
min: 1
max: 3Il pool general-purpose (2 nodi fissi, 2vCPU/4GB) ospita i componenti di sistema: ingress-nginx, cert-manager, external-dns, external-secrets. Il pool workloads (1-3 nodi autoscaling, 4vCPU/8GB) ospita i servizi applicativi: Prefect, PostgreSQL (CNPG), OpenMetadata, CKAN. Il dimensionamento รจ coerente con quello descritto nel deliverable D2.1.2: in condizioni ordinarie 1 nodo workloads รจ sufficiente, con picchi ETL che attivano l'autoscaling fino a 3 nodi.
| Componente | Chart | Repo | Namespace | Note |
|---|---|---|---|---|
| metrics-server | metrics-server | kubernetes-sigs | kube-system | Metriche HPA |
| cert-manager | cert-manager | jetstack | cert-manager | CRDs abilitati |
| ingress-nginx | ingress-nginx | kubernetes-nginx | ingress-nginx | LoadBalancer DO |
| external-dns | external-dns | kubernetes-sigs | kube-system | Provider AWS Route53 |
| external-secrets | external-secrets | external-secrets | external-secrets | CRDs abilitati |
| cnpg | cloudnative-pg | cloudnative-pg | cnpg-system | Operator PostgreSQL |
I valori Helm per ciascun componente sono configurazioni standard per ognuno dei chart elencati, con i soli adattamenti relativi al dominio e alle credenziali del progetto.
# manifests/maps/cluster-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: admin@gransassotech.org
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
ingressClassName: nginx| Record | Tipo | Destinazione |
|---|---|---|
maps.k8s.maps.gransassotech.it | A | IP Load Balancer DOKS (gestito da Pulumi/external-dns) |
prefect.maps.gransassotech.it | CNAME | maps.k8s.maps.gransassotech.it |
metadata.maps.gransassotech.it | CNAME | maps.k8s.maps.gransassotech.it |
ckan.maps.gransassotech.it | CNAME | maps.k8s.maps.gransassotech.it |
Il record A del Load Balancer viene creato automaticamente da Pulumi tramite setup_public_lb_dns_record(). I record CNAME per i singoli servizi vengono creati automaticamente da external-dns alla lettura degli Ingress Kubernetes.
Pulumi crea automaticamente un utente IAM external-dns-maps con policy limitata a route53:ChangeResourceRecordSets sulla hosted zone di maps.gransassotech.it. Le credenziali vengono iniettate come Kubernetes Secret nel namespace kube-system.
I segreti applicativi sono archiviati in AWS Parameter Store con il seguente schema di path:
/maps/{service}/{parameter}
Esempi:
/maps/postgres/password
/maps/prefect/secret-key
/maps/openmetadata/jwt-secret
/maps/ckan/api-keyPer ciascun servizio applicativo, Pulumi crea:
external-secrets-{service}-maps con policy di accesso in lettura ai parametri ssm:GetParameter* sul path /maps/{service}/*SecretStore che referenzia le credenzialiExternalSecret che mappa i parametri SSM verso Kubernetes SecretsI segreti vengono sincronizzati con refresh interval di 1 ora.
I segreti di sistema (non applicativi) vengono archiviati cifrati in Pulumi.maps.yaml tramite AWS KMS:
external-dns-credentials: credenziali IAM per external-dnsgitlab-runner-secret: token runner CI/CD (se configurato)Il database PostgreSQL del progetto MAPS viene gestito tramite l'operatore CNPG, giร installato nel cluster. La risorsa Cluster CNPG per MAPS specifica:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: maps-postgres
namespace: maps
spec:
instances: 2
imageName: ghcr.io/cloudnative-pg/postgis:17
postgresql:
parameters:
shared_buffers: "256MB"
max_connections: "100"
storage:
size: 100Gi
storageClass: do-block-storage
backup:
barmanObjectStore:
destinationPath: s3://gst-maps-backups/postgres
s3Credentials:
accessKeyId:
name: maps-backup-credentials
key: ACCESS_KEY_ID
secretAccessKey:
name: maps-backup-credentials
key: SECRET_ACCESS_KEY
wal:
retention: "7d"
retentionPolicy: "30d"CNPG gestisce automaticamente: replica sincrona tra le 2 istanze, failover automatico, backup WAL continuo su S3, point-in-time recovery.
ร richiesto un bucket S3 dedicato (DigitalOcean Spaces o AWS S3) gst-maps-backups con le relative credenziali di accesso in scrittura per CNPG.
I servizi applicativi MAPS vengono distribuiti nel namespace maps:
apiVersion: v1
kind: Namespace
metadata:
name: maps
labels:
environment: production
project: gst-mapsL'esecuzione di pulumi up --stack maps dalla directory pulumi/maps/ esegue le seguenti operazioni nell'ordine:
# Strumenti necessari sulla macchina di provisioning
pulumi >= 3.0
python >= 3.11
poetry
kubectl
doctl (DigitalOcean CLI)
aws CLI (configurato con profilo maps)# 1. Configurare profilo AWS
export AWS_PROFILE=maps
# 2. Login stato Pulumi su S3
pulumi login s3://gst-maps-pulumi-state
# 3. Selezione stack
pulumi stack select maps
# 4. Preview (verifica senza applicare)
pulumi preview
# 5. Applicazione
pulumi up| Servizio | URL | Autenticazione |
|---|---|---|
| Prefect UI | https://prefect.maps.gransassotech.it | Credenziali Prefect |
| OpenMetadata | https://metadata.maps.gransassotech.it | Admin OIDC |
| CKAN | https://ckan.maps.gransassotech.it | Admin CKAN |
| PostgreSQL | Interno al cluster (porta 5432) | Solo da pod interni |
| Voce | Configurazione | Costo mensile |
|---|---|---|
| DOKS control plane | Managed | $12 |
| Pool general-purpose | 2x s-2vcpu-4gb | $48 ($24/nodo) |
| Pool workloads (min) | 1x s-4vcpu-8gb | $48 |
| Pool workloads (max) | 3x s-4vcpu-8gb | $144 |
| Block storage CNPG | 100 GB | $10 |
| Block storage Bronze | 100 GB | $10 |
| Load Balancer | Ingress HTTPS | $12 |
| Spaces (backup) | 250 GB | $5 |
| Totale (min) | ~$145/mese | |
| Totale (max, picco ETL) | ~$241/mese |
La differenza rispetto alla stima del D2.1.2 ($311/mese) รจ dovuta all'adozione di CNPG self-hosted invece del Managed PostgreSQL ($80/mese), e al meccanismo di autoscaling che riduce i costi nelle fasi di inattivitร .