Dev Ops
Dev Ops
md 2026-05-07
Origini Tecnologiche
Benefici Principali
Self-service provisioning: Gli utenti possono attivare risorse di calcolo su richiesta per quasi ogni tipo
di carico di lavoro.
Elasticità: Capacità di scalare rapidamente (scale up) quando le esigenze aumentano e ridurre (scale
down) quando diminuiscono.
Pay-per-use: Le risorse sono misurate a livello granulare, permettendo di pagare solo per ciò che viene
effettivamente utilizzato (economia di scala).
Modelli di Distribuzione
1 / 62
[Link] 2026-05-07
IaaS (Infrastructure as a Service): Fornisce risorse di calcolo come server, rete e archiviazione (es.
AWS, Azure). Permette di scalare l'infrastruttura su richiesta senza investimenti in hardware fisico.
PaaS (Platform as a Service): Fornisce un ambiente completo per lo sviluppo e la distribuzione di
applicazioni web, gestendo il middleware e l'hosting (es. Google App Engine). Riduce la complessità
fornendo "middleware as a service".
SaaS (Software as a Service): Applicazioni basate su cloud accessibili via web, gestite da terzi (es.
Microsoft Office 365). I dati sono sicuri nel cloud anche in caso di guasto del computer locale.
Applicazioni Cloud-Native
Le applicazioni cloud-native sono progettate per girare su macchine virtuali o container. Si basano su:
2 / 62
[Link] 2026-05-07
2. Spring Boot
Spring Boot è una soluzione "opinionated" basata sul framework Spring che facilita la creazione di
applicazioni stand-alone di grado produttivo grazie al principio della convention-over-configuration.
Core Concepts
Inversion of Control (IoC): Principio per cui il controllo del flusso del programma viene trasferito al
framework.
Dependency Injection (DI): Meccanismo per realizzare l'IoC, permettendo al container di Spring di
iniettare le dipendenze necessarie tramite costruttori, setter o campi.
Spring IoC Container: Rappresentato dall'interfaccia ApplicationContext, è responsabile
dell'istanziazione, configurazione e assemblaggio dei "beans", gestendone l'intero ciclo di vita.
@Configuration: Indica che una classe è una sorgente di definizioni di bean. All'interno di queste classi
si definiscono i metodi per creare i componenti.
@Bean: Utilizzata sui metodi di una classe @Configuration per restituire un oggetto che Spring deve
registrare come bean nel contesto dell'applicazione. Per impostazione predefinita, i bean sono oggetti
singleton.
@Component: Utilizzata per l'auto-rilevamento (classpath scanning) e l'auto-configurazione dei bean.
Versioni specializzate sono @Service (per la logica di business) e @Repository (per l'accesso ai dati).
@Autowired: Marca un costruttore, un campo o un metodo setter affinché Spring possa iniettare
automaticamente la dipendenza richiesta.
3 / 62
[Link] 2026-05-07
L'integrazione con i database è gestita tramite standard moderni che risolvono il disallineamento tra oggetti e
tabelle relazionali:
4 / 62
[Link] 2026-05-07
Spring Web
MVC è il framework web originale di Spring, basato sulla Servlet API e progettato secondo il pattern Model-
View-Controller:
DispatcherServlet: Il cuore del framework che smista le richieste agli handler corretti.
@RestController: Contrassegna una classe come controller web, pronta per gestire richieste HTTP e
restituire tipicamente JSON.
@RequestMapping: Mapper per le richieste web (es. /users). Esistono varianti specifiche come
@GetMapping, @PostMapping, @PutMapping e @DeleteMapping.
Gestione Parametri:
@PathVariable: Per estrarre valori dal percorso dell'URL.
@RequestBody: Per mappare il corpo della richiesta (JSON) su un oggetto Java.
@RequestParam: Per gestire i parametri di query (es. ?name=John).
ResponseEntity: Utilizzato nei metodi del controller per avere pieno controllo sulla risposta HTTP
(status code, headers, body).
Auto-Configuration
Spring Boot Auto-Configuration è il meccanismo centrale di Spring Boot che applica il principio
convention-over-configuration:
@Configuration
@ConditionalOnClass([Link])
public class DataSourceAutoConfiguration { ... }
@SpringBootApplication(exclude = [Link])
Gli Starters sono dipendenze Maven/Gradle che semplificano il setup aggiungendo automaticamente tutte le
dipendenze transitive necessarie:
spring-boot-starter-web: Include Spring Web MVC, Tomcat embedded, Jackson per JSON.
spring-boot-starter-data-jpa: Include JPA, Hibernate, Spring Data.
spring-boot-starter-data-rest: Espone repository JPA come REST API automaticamente.
spring-boot-starter-security: Integra Spring Security per autenticazione e autorizzazione.
spring-boot-starter-actuator: Aggiunge endpoint di monitoraggio e health check.
spring-boot-starter-test: Include JUnit, Mockito, AssertJ per il testing.
Vantaggi: Evitano di specificare manualmente versioni compatibili; Spring Boot garantisce che i starter
funzionino insieme.
Configurazione dell'Applicazione
server:
port: 8080
servlet:
context-path: /api
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: secret
6 / 62
[Link] 2026-05-07
jpa:
hibernate:
ddl-auto: update
@Component
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private String version;
// getters/setters
}
JPA (Java Persistence API) è uno standard per l'ORM (Object-Relational Mapping) che astrae i dettagli della
persistenza. Spring Data JPA semplifica ulteriormente il lavoro fornendo repository generici.
Entity Definition: Un'entità è una classe Java che rappresenta una tabella del database:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@Column(nullable = false)
private String email;
@CreationTimestamp
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at")
private LocalDateTime updatedAt;
// getters/setters
}
7 / 62
[Link] 2026-05-07
Repository Pattern: Spring Data JPA fornisce interfacce generiche per il CRUD:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// CRUD automatico: save(), findById(), findAll(), delete(), deleteById()...
// Native SQL
@Query(value = "SELECT * FROM users WHERE name LIKE %?1%", nativeQuery = true)
List<User> searchByNameNative(String name);
// Pagination
Page<User> findAll(Pageable pageable);
// Deleting
@Modifying
@Transactional
void deleteByEmail(String email);
}
Query Method Naming Convention: Spring Data JPA genera query automaticamente dal nome del metodo:
8 / 62
[Link] 2026-05-07
findBy<PropertyName>In(Collection): IN clause.
findBy<PropertyName>GreaterThan: >, LessThan: <, etc.
findBy<PropertyName>Between: BETWEEN.
findBy<PropertyName>StartingWith / EndingWith: Per stringhe.
findBy<PropertyName1>And<PropertyName2>: AND logico.
findByNameIgnoreCase: Case-insensitive.
OrderBy<PropertyName>Desc / Asc: Ordinamento.
One-to-One:
@Entity
public class User {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@Entity
public class Profile {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@OneToOne(mappedBy = "profile")
private User user; // Lato inverse, non ha @JoinColumn
}
One-to-Many / Many-to-One:
@Entity
public class Author {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@Entity
public class Book {
@Id
@GeneratedValue(strategy = [Link])
9 / 62
[Link] 2026-05-07
@ManyToOne(fetch = [Link])
@JoinColumn(name = "author_id", nullable = false)
private Author author;
}
Many-to-Many:
@Entity
public class Student {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@Entity
public class Course {
@Id
@GeneratedValue(strategy = [Link])
private Long id;
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
}
[Link]: Carica i dati associati solo quando acceduti (di default per *-to-many). Più efficiente
ma rischia LazyInitializationException.
[Link]: Carica i dati associati immediatamente (di default per *-to-one). Semplice ma
genera query JOIN automatiche.
Cascade Types:
10 / 62
[Link] 2026-05-07
N+1 Problem e Soluzioni: Il problema N+1 si verifica quando per ogni entità principale si esegue una query
separata per caricarne le relazioni:
Soluzioni:
1. Eager Loading:
@OneToMany(fetch = [Link])
private Set<Book> books;
3. EntityGraph:
@EntityGraph(attributePaths = {"books"})
@Query("SELECT a FROM Author a")
List<Author> findAllWithBooksGraph();
@Transactional
public List<AuthorDTO> getAuthorsWithBooks() {
List<Author> authors = [Link]();
[Link](a -> [Link]().size()); // Forza il caricamento
return mapToDTO(authors);
}
Auditing con Entities: Spring Data JPA fornisce auditing automatico tramite @CreationTimestamp e
@UpdateTimestamp (Hibernate) oppure:
@Entity
@EntityListeners([Link])
public class User {
11 / 62
[Link] 2026-05-07
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String updatedBy;
}
@Entity
public class User {
@NotNull
@NotEmpty
private String name;
@Email
@NotNull
private String email;
@Min(18)
@Max(120)
private Integer age;
}
Paginazione e Sorting:
// Controller
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sortBy) {
// Response
{
"content": [...],
"pageable": { "pageNumber": 0, "pageSize": 10 },
"totalElements": 50,
"totalPages": 5,
12 / 62
[Link] 2026-05-07
"last": false,
"first": true,
"numberOfElements": 10,
"empty": false
}
@Service
public class UserService {
@Autowired
private UserRepository repository;
@Data
public class UserDTO {
private Long id;
private String name;
private String email;
@RestController
13 / 62
[Link] 2026-05-07
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler([Link])
public ResponseEntity<ErrorResponse>
handleNotFound(EntityNotFoundException e) {
return [Link](HttpStatus.NOT_FOUND).body(new
ErrorResponse([Link]()));
}
}
@PostMapping("/users")
public ResponseEntity<?> createUser(@Valid @RequestBody User user) {
return [Link](user);
}
@Valid: Istruisce Spring a validare il payload prima di passarlo al metodo; gli errori vengono raccolti in
BindingResult.
Transaction Management
Le transazioni garantiscono che le operazioni sul database rispettino le proprietà ACID (Atomicity,
Consistency, Isolation, Durability):
@Service
public class UserService {
@Transactional
14 / 62
[Link] 2026-05-07
Non-
Dirty Phantom
Livello Repeatable Descrizione
Read Read
Read
Problemi di Concorrenza:
Dirty Read: Una transazione legge dati modificati da un'altra transazione non ancora committata.
Non-Repeatable Read: Una riga letta due volte in una transazione ritorna valori diversi (altra
transazione l'ha modificata e committata).
Phantom Read: Una query eseguita due volte ritorna righe diverse (un'altra transazione ha
inserito/eliminato righe).
15 / 62
[Link] 2026-05-07
@Service
public class OrderService {
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation =
[Link])
public void processOrder(Order order) {
// operazioni critiche
}
}
Readonly Transactions: Per operazioni di sola lettura, impostare readOnly = true per ottimizzazioni:
@Transactional(readOnly = true)
public List<User> getAllUsers() {
return [Link]();
}
Per default, Spring esegue il rollback solo su eccezioni non-checked (RuntimeException e sottoclassi).
Per eccezioni checked (es. IOException), usare rollbackFor:
@Transactional(rollbackFor = [Link])
public void uploadFile(MultipartFile file) throws IOException {
// se IOException viene lanciata, la transazione eseguirà rollback
}
@Transactional(noRollbackFor = [Link])
public void updateData(Data data) {
// ValidationException non causa rollback
}
Timeout Transazionale:
@Transactional(propagation = [Link])
public void methodWithSavepoint() {
// Se questa transazione fallisce, il DB esegue rollback solo fino al
savepoint,
// la transazione padre continua
}
Spring Boot fornisce @SpringBootTest per test di integrazione che caricano il contesto completo:
@SpringBootTest
class UserControllerTest {
@MockBean
private UserService userService;
@Autowired
private TestRestTemplate restTemplate;
@Test
void testGetUser() {
[Link]([Link](1L)).thenReturn(new User(1L, "John"));
ResponseEntity<User> response = [Link]("/users/1",
[Link]);
assertEquals([Link], [Link]());
}
}
@WebMvcTest: Test slice che carica solo il layer web (controller), senza database.
@DataJpaTest: Test slice per il layer di persistenza (repository e JPA).
TestRestTemplate: Client HTTP per testare REST API in test di integrazione.
MockMvc: Alterna al TestRestTemplate, utile per test più granulari su controller.
GET /actuator/health: Stato di salute dell'applicazione (UP, DOWN). Include dettagli su database,
disco, ecc.
GET /actuator/metrics: Metriche raccolte (numero di richieste, latenza, memory usage).
GET /actuator/env: Proprietà di environment e configurazione.
17 / 62
[Link] 2026-05-07
@Component
@Endpoint(id = "custom")
public class CustomEndpoint {
@ReadOperation
public String getCustomInfo() {
return "Custom data";
}
}
[Link]=INFO
[Link]=DEBUG
[Link]=logs/[Link]
Configurazione avanzata: tramite file [Link] nella root di classpath per controllo
granulare su appenders, pattern, rolling policies.
Log nei bean: tramite SLF4J:
@Component
public class MyService {
private static final Logger logger =
[Link]([Link]);
Embedded Tomcat: Spring Boot Web MVC include un server Tomcat embedded (port di default 8080).
Embedded Jetty/Undertow: Alternative a Tomcat escludendo spring-boot-starter-tomcat e
aggiungendo l'starter Jetty/Undertow.
18 / 62
[Link] 2026-05-07
Fat JAR (Uber JAR): Generato con ./mvnw clean package. Contiene tutte le dipendenze e il server
embedded; può essere eseguito direttamente con java -jar [Link].
WAR Deploy: Se si vuole deployare su app server esterno, si può generare un WAR tramite estensione
di SpringBootServletInitializer.
HATEOAS è un vincolo del modello REST che dice che i client devono interagire con l'applicazione tramite
ipermedia (links) forniti dal server, anziché costruire URL hardcoded. Questo rende l'API più flessibile e auto-
descrittiva.
Concetto Chiave:
Invece di dover conoscere tutti gli endpoint in anticipo, il client riceve dal server i link verso le azioni
disponibili.
{
"id": 1,
"name": "John Doe",
"email": "john@[Link]"
}
Il client deve sapere che l'URL è /users/1 e che per aggiornare deve fare POST a /users/1/update.
{
"id": 1,
"name": "John Doe",
"email": "john@[Link]",
"_links": {
"self": { "href": "/users/1" },
"all_users": { "href": "/users" },
"update": { "href": "/users/1", "method": "PUT" },
"delete": { "href": "/users/1", "method": "DELETE" }
}
}
Spring HATEOAS: Spring HATEOAS è una libreria che semplifica l'implementazione di HATEOAS tramite
spring-boot-starter-hateoas:
19 / 62
[Link] 2026-05-07
// Dipendenza Maven
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
Implementazione pratica:
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public EntityModel<User> getUser(@PathVariable Long id) {
User user = [Link](id).orElseThrow();
linkTo(methodOn([Link]).getAllUsers()).withRel("all_users"),
linkTo(methodOn([Link]).updateUser(id,
null)).withRel("update"),
linkTo(methodOn([Link]).deleteUser(id)).withRel("delete")
);
}
@GetMapping
public CollectionModel<EntityModel<User>> getAllUsers() {
List<User> users = [Link]();
List<EntityModel<User>> userModels = [Link]()
.map(u -> [Link](u,
linkTo(methodOn([Link]).getUser([Link]())).withSelfRel()
))
.collect([Link]());
return [Link](userModels,
linkTo(methodOn([Link]).getAllUsers()).withSelfRel()
);
}
}
Link: Rappresenta un singolo link hypermedia con href (URL) e rel (relazione semantica):
20 / 62
[Link] 2026-05-07
linkTo() e methodOn(): DSL per generare link type-safe basati sui metodi del controller:
linkTo(methodOn([Link]).getUser(1L)).withSelfRel()
// Genera: href="/users/1", rel="self"
@GetMapping
public PagedModel<EntityModel<User>> getAllUsers(
@PageableDefault(size = 10) Pageable pageable) {
return [Link](
[Link](u -> [Link](u,
linkTo(methodOn([Link]).getUser([Link]())).withSelfRel()
)).getContent(),
new PageMetadata([Link](), [Link](),
[Link]()),
linkTo(methodOn([Link]).getAllUsers(pageable)).withSelfRel(),
21 / 62
[Link] 2026-05-07
linkTo(methodOn([Link]).getAllUsers([Link]())).withRel("n
ext"),
linkTo(methodOn([Link]).getAllUsers([Link]())).withRe
l("prev")
);
}
Vantaggi di HATEOAS:
Decoupling: Il client non deve conoscere hardcoded gli URL; li scopre dal server.
Flessibilità: Il server può cambiare gli URL senza rompere i client.
Discoverability: I client possono scoprire le operazioni disponibili navigando i link.
API auto-descrittiva: La risposta contiene istruzioni su come procedere.
Svantaggi di HATEOAS:
Principales Takeaway
3. Docker e Containerizzazione
Docker è un insieme di strumenti e un ambiente di esecuzione per la virtualizzazione a livello di sistema
operativo. Permette di creare, gestire ed eseguire dei "pacchetti" software chiamati container.
22 / 62
[Link] 2026-05-07
Perché Docker?
Isolamento: Ogni container è isolato dal resto del sistema, potendo accedere solo alle risorse
autorizzate (CPU, memoria, storage).
Consistenza: Garantisce che il software funzioni in modo uniforme indipendentemente
dall'infrastruttura sottostante ("it works on my laptop!" non è più un problema).
Leggerezza: A differenza delle macchine virtuali, i container condividono il kernel del sistema operativo
ospite, rendendoli molto più leggeri e rapidi da avviare.
Componenti Fondamentali
Docker Engine: L'ambiente di runtime che permette l'esecuzione dei container. Si basa su containerd e
runc.
Containerd: È un runtime di container standard del settore, creato con un'enfasi su semplicità,
robustezza e portabilità. Gestisce l'intero ciclo di vita dei container, inclusi il trasferimento delle
immagini, l'esecuzione dei container e lo storage. Donato alla Cloud Native Computing Foundation
(CNCF), implementa la Kubernetes Container Runtime Interface (CRI), rendendolo compatibile sia con
Docker Engine che direttamente con Kubernetes.
23 / 62
[Link] 2026-05-07
Immagini: Template di sola lettura, standalone ed eseguibili che contengono tutto il necessario per far
girare l'applicazione (codice, runtime, librerie, impostazioni).
Layer (Livelli): Ogni immagine è composta da una serie di layer a sola lettura generati dai
comandi del Dockerfile. Grazie ai union file system (come Overlay2), questi layer possono essere
riutilizzati da più immagini, risparmiando spazio su disco e riducendo i tempi di build.
24 / 62
[Link] 2026-05-07
Container: Istanze runtime delle immagini. Ogni container aggiunge un layer leggibile/scrivibile sopra i
layer a sola lettura dell'immagine originale. Sono più leggeri delle macchine virtuali perché condividono
il kernel dell'host ed eseguono processi isolati nello spazio utente.
Architettura e Strumenti
Client-Server: Il client Docker comunica con il demone (dockerd) tramite REST API.
Docker Compose: Strumento per definire e gestire applicazioni multi-container tramite file YAML.
Permette di avviare l'intero stack tecnologico con un unico comando.
Comandi principali:
docker-compose up: Crea e avvia i container definiti nel file YAML (usa -d per il
background).
docker-compose down: Ferma e rimuove i container, le reti e le immagini definite.
docker-compose build: Costruisce o ricostruisce i servizi.
docker-compose logs: Visualizza i log di tutti i servizi gestiti.
docker-compose ps: Elenca lo stato dei container gestiti dal file compose.
Docker Swarm: Trasforma un gruppo di motori Docker in un unico motore virtuale. Introduce il
concetto di Service (astrazione superiore al container), permettendo di gestire repliche, bilanciamento
del carico e health check.
Stacks: Una collezione di servizi che compongono un'applicazione in un ambiente specifico.
25 / 62
[Link] 2026-05-07
Integrazioni e Alternative
Kubernetes (K8s): Le versioni recenti di Docker includono un server e un client Kubernetes standalone
(single-node) per test locali. Quando abilitato, permette di distribuire carichi di lavoro in parallelo su
Kubernetes, Swarm o come container classici.
Buildpacks: Un'alternativa all'uso del Dockerfile per la creazione di immagini. Nati da Heroku nel 2011
e ora parte della CNCF, permettono di trasformare il codice sorgente in immagini container in modo
automatizzato senza scrivere istruzioni manuali di build.
Persistenza dei Dati (Volumi e Mount Points): Poiché i container sono effimeri e perdono i dati alla
rimozione, Docker fornisce meccanismi per la persistenza:
Volumi: Gestiti interamente da Docker nell'area di storage specifica del daemon. Sono il modo
raccomandato per persistere dati.
Bind Mounts: Mappano un file o una directory dell'host (macchina locale) all'interno del
container. Sono utili per condividere codice sorgente in fase di sviluppo.
Port Forwarding: Mapping tra porte della macchina host e del container tramite l'opzione -p (es. -p
8080:80). Questo permette all'applicazione di essere accessibile dall'esterno (es. tramite l'interfaccia
[Link] o un IP esterno).
bridge: Il driver di rete predefinito. Le reti user-defined bridge sono preferibili a quella di
default perché permettono ai container di risolversi reciprocamente tramite nome/alias (anziché
solo tramite IP).
host: Rimuove l'isolamento di rete tra il container e l'host Docker.
overlay: Collega più demoni Docker tra loro (usato in cluster come Docker Swarm).
none: Disabilita completamente il networking per il container.
Comandi utili: docker network create, docker network ls, docker network connect.
26 / 62
[Link] 2026-05-07
Workflow Principale
27 / 62
[Link] 2026-05-07
Creato script [Link] che ogni secondo scrive data e ora in /data/[Link] con un
loop infinito.
Creato Dockerfile:
FROM alpine
COPY [Link] /[Link]
VOLUME ["/data"]
CMD ["/[Link]"]
Avvio: docker-compose up -d
Log: docker-compose logs
Stop/cleanup: docker-compose down, docker-compose stop/start.
28 / 62
[Link] 2026-05-07
Docker Stack:
A5. Buildpacks
Usato il plugin Spring Boot (Cloud Native Buildpacks) per generare l’immagine automaticamente.
./mvnw spring-boot:build-image
Test esecuzione:
4. Introduction to DevOps
29 / 62
[Link] 2026-05-07
DevOps è un approccio culturale, organizzativo e tecnico che unisce sviluppo software (Dev) e
operation/infrastruttura (Ops) per rilasciare software in modo più rapido, stabile e ripetibile.
Obiettivi Principali
Modello tradizionale: sviluppo e operation lavorano separati, con handoff lenti e conflitti di
responsabilità.
DevOps: responsabilità condivisa lungo tutto il ciclo di vita applicativo (build, test, release,
monitoraggio, feedback).
CALMS Model
CI, CD e Pipeline
Continuous Integration (CI): integrazione frequente del codice con build e test automatici.
Continuous Delivery: artefatti sempre pronti al rilascio in produzione.
Continuous Deployment: ogni modifica valida viene rilasciata automaticamente.
30 / 62
[Link] 2026-05-07
DevSecOps
Benefici Attesi
DevOps non è solo un insieme di strumenti: è una cultura operativa che combina persone, processi e
automazione per fornire software di qualità in modo continuo.
31 / 62
[Link] 2026-05-07
Acronimo Definizione
Gli sviluppatori integrano il codice nel branch condiviso frequentemente (più volte al giorno).
Ogni push scatena automaticamente: build + test.
Se build o test falliscono, il team viene notificato immediatamente.
Principio chiave: non lasciare il branch principale in stato "broken" a lungo.
Pratiche essenziali di CI
Version Control (VCS): tutto il codice (inclusa config e IaC) è versionato in Git.
Automated Build: processo di build riproducibile e automatizzato (Maven, Gradle, npm…).
Automated Testing: test unitari e di integrazione eseguiti ad ogni commit.
Fast Feedback: la pipeline deve essere rapida (~10 minuti) per non bloccare il flusso.
Single Source of Truth: un solo repository, un solo processo di build.
Continuous Delivery
Continuous Deployment
Estensione della Continuous Delivery: il deploy avviene automaticamente dopo che i test in staging
sono superati.
Richiede alta fiducia nella copertura dei test e nei processi di rollback.
Adatto a organizzazioni mature con molti rilasci al giorno (es. Netflix, Amazon).
32 / 62
[Link] 2026-05-07
La Pipeline CI/CD
Una pipeline è una sequenza di step automatizzati che portano il codice dal repository alla produzione:
Stage tipici
Artefatti e Registri
Il risultato della build è un artefatto immutabile (es. [Link], immagine Docker taggata).
33 / 62
[Link] 2026-05-07
Gli artefatti vengono archiviati in un registry (es. Docker Hub, Nexus, Artifactory).
Lo stesso artefatto viene promosso tra gli ambienti (dev → staging → prod) senza essere ricostruito.
Branching Strategy e CI
Trunk-Based Development: tutti i developer lavorano su branch a vita breve e integrano spesso nel
branch principale. Favorisce la CI.
Feature Branch: ogni funzionalità vive su un branch separato; la CI viene eseguita su ogni branch prima
del merge.
GitFlow: modello strutturato con branch main, develop, feature/*, release/*, hotfix/*. Più
complesso, meno frequente nella CI pura.
GitHub Actions è uno strumento CI/CD integrato in GitHub. Definisce la pipeline tramite file YAML in
.github/workflows/:
name: CI Pipeline
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: ./mvnw clean package
- name: Run Tests
run: ./mvnw test
- name: Build Docker image
run: docker build -t my-app:${{ [Link] }} .
34 / 62
[Link] 2026-05-07
GitLab CI/CD è integrato direttamente in GitLab e usa il file .[Link] nella root del repository.
stages:
- build
- test
- package
variables:
MAVEN_OPTS: "-[Link]=.m2/repository"
cache:
paths:
- .m2/repository
build_job:
stage: build
image: maven:3.9.9-eclipse-temurin-17
script:
- mvn -B clean compile
test_job:
stage: test
image: maven:3.9.9-eclipse-temurin-17
script:
- mvn -B test
artifacts:
when: always
reports:
junit:
- target/surefire-reports/*.xml
package_job:
stage: package
image: maven:3.9.9-eclipse-temurin-17
script:
- mvn -B package -DskipTests
artifacts:
paths:
- target/*.jar
expire_in: 1 week
only:
- main
Pipeline: insieme completo dei job eseguiti per un commit o merge request.
35 / 62
[Link] 2026-05-07
Stages: macro-fasi ordinate (build, test, deploy...). I job nello stesso stage possono girare in parallelo.
Artifacts: file prodotti da un job e riutilizzabili negli step successivi (es. jar, report test).
Rules/Only/Except: controllo condizionale su quando eseguire un job (branch, tag, merge request,
variabili).
GitLab espone automaticamente molte variabili di ambiente utili nei job, senza doverle definire manualmente.
Regole su branch
CI_DEFAULT_BRANCH Branch principale del progetto
default
Naming
CI_PROJECT_PATH Namespace/progetto (group/project)
immagini/registry
Push immagine
CI_REGISTRY_IMAGE Nome completo immagine registry del progetto
versionata
36 / 62
[Link] 2026-05-07
docker_build:
stage: package
script:
- echo "Pipeline: $CI_PIPELINE_ID"
- echo "Commit: $CI_COMMIT_SHORT_SHA"
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
Nota: le variabili predefinite sono diverse dalle variabili custom e dai secret definiti nel progetto/gruppo.
Quelle sensibili (token, password, chiavi) vanno sempre salvate come variabili protette/masked nelle
impostazioni CI/CD.
Approfondimento: Jobs
Un job è l'unità atomica di lavoro della pipeline: esegue una lista di comandi su un runner e produce uno
stato finale (success, failed, canceled, skipped).
37 / 62
[Link] 2026-05-07
build_job:
stage: build
script:
- mvn -B clean compile
artifacts:
paths: [target/]
unit_test_job:
stage: test
needs: [build_job]
script:
- mvn -B test
security_scan_job:
stage: security
needs: [build_job]
script:
- echo "Eseguo dependency scan"
allow_failure: true
package_job:
stage: package
needs: [unit_test_job]
script:
- mvn -B package -DskipTests
artifacts:
paths: [target/*.jar]
expire_in: 1 week
deploy_prod_job:
stage: deploy
needs: [package_job]
script:
- echo "Deploy in produzione"
when: manual
only:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./mvnw -B clean compile
38 / 62
[Link] 2026-05-07
test:
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
java: [17, 21]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: ${{ [Link] }}
distribution: temurin
- run: ./mvnw -B test
package:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./mvnw -B package -DskipTests
Quality Gates
39 / 62
[Link] 2026-05-07
Rollback e Recovery
Vantaggi CI/CD
Strumento Tipo
CircleCI Cloud-based
A1. Prerequisiti
1.1 Creato account GitLab e progetto, clonato il repo e copiato il progetto Java Spring Boot.
1.2 Creato deploy token su GitLab (Settings → Repository → Deploy tokens) con scope
read_registry e username kubernetes-gitlab.
1.3 Creato cluster GKE su Google Cloud (us-central1-a, 1 nodo e2-medium).
1.4 Creato Kubernetes secret per autorizzare GKE a pullare immagini dal registry GitLab:
--docker-password=<deploy-token> \
--docker-email=<email>
Creato file .[Link] nella root del progetto con 3 stage in ordine: test → build → deploy.
Due job paralleli che testano il progetto Maven con JDK17 e JDK21. Risolto problema di permessi su mvnw con:
Job che builda l'immagine Docker e la pusha sul GitLab Container Registry usando docker:dind. Pushata sia
con tag $CI_COMMIT_SHORT_SHA che con tag latest.
Variabile GCP_SERVICE_KEY aggiunta in Settings → CI/CD → Variables con il JSON della service account
GCP.
Push su branch dev → pipeline parte automaticamente con i 3 stage in sequenza. IP esterno dell'app verificato
con:
41 / 62
[Link] 2026-05-07
Kubernetes (K8s) è una piattaforma open-source per distribuire, mantenere e scalare applicazioni
containerizzate.
Sta tra IaaS e PaaS: offre astrazioni di alto livello (deploy, scaling, self-healing) senza togliere flessibilità
infrastrutturale.
Non è un PaaS monolitico: fornisce building blocks componibili.
Non è solo “orchestrazione sequenziale” (A → B → C): lavora a stato desiderato con controller
indipendenti che riconciliano continuamente lo stato reale.
Control Plane (master): gestisce il cluster, prende decisioni globali, espone le API.
Worker Nodes: eseguono i workload (container dentro Pod).
In molti contesti il nodo control plane può anche eseguire workload, ma in produzione si tende a separare i
ruoli.
1. kubelet: agente del nodo, assicura che i Pod richiesti siano in esecuzione.
2. kube-proxy: gestisce le regole di rete e l'accesso ai servizi.
3. cAdvisor: raccoglie metriche e informazioni di utilizzo/performance dei container.
42 / 62
[Link] 2026-05-07
Regola pratica:
Esempio: app principale + container per forwarding log verso collector centrale.
Vantaggi: separazione responsabilità, fault isolation del componente ausiliario.
1. Init container
2. Sidecar container
3. Adapter container
4. Ambassador container
1. Imperativa
43 / 62
[Link] 2026-05-07
2. Dichiarativa (preferita)
apiVersion
kind
metadata
spec
Esempio minimale:
apiVersion: v1
kind: Pod
metadata:
name: rss-site
labels:
app: web
spec:
containers:
- name: front-end
image: nginx
ports:
- containerPort: 80
Kubernetes offre funzionalità tipiche PaaS (deploy, scaling, LB, monitoring/logging), ma:
44 / 62
[Link] 2026-05-07
# vedere i nodi
kubectl get nodes
# vedere i pod
kubectl get pods
# descrivere risorsa
kubectl describe pod <pod-name>
1. Demo 52 - Creating a Pod Si crea un Pod con manifest YAML (kubectl apply -f ...). Kubernetes
legge il file come stato desiderato e prova ad allineare il cluster.
2. Question 53 - Cosa succede se applico due volte lo stesso manifest? kubectl apply e
idempotente: se lo stato e gia uguale, non cambia nulla e non crea duplicati.
4. Pod Details (55) Ogni Pod ha IP unico nel cluster. Il Pod puo esporre volumi ai container interni. I Pod
possono essere gestiti direttamente via API oppure tramite controller.
5. Demo 56 - Updating a Pod L'aggiornamento avviene con la stessa logica dichiarativa: si cambia il
manifest e si riapplica; Kubernetes riconcilia lo stato.
6. Question 58 - Come vengono allocate CPU e memoria ai Pod? Di default le risorse sono condivise
tra Pod sul nodo. Se la memoria fisica non basta, un Pod puo essere terminato con OOM (Out Of
Memory).
7. CPU allocation (60) Kubernetes usa CFS (Completely Fair Scheduler): il tempo CPU e diviso in slice
(tipicamente 100 ms) e distribuito equamente. Se un Pod esaurisce la quota, viene rallentato fino alla
slice successiva.
45 / 62
[Link] 2026-05-07
10. Question 67 + Answer 68 - Come evitare che un Pod consumi tutto? Si impostano i limits (es.
memory/cpu) per impedire che un singolo Pod monopolizzi il nodo.
11. Pod memory limits (69) Il limite memoria e enforced dal kernel in modo reattivo: quando c'e memory
pressure, il container che supera il limite puo essere terminato (OOM kill).
12. Pod CPU limits (70) Il limite CPU e enforced con throttling: e un limite duro, quindi il container non
puo superare la quota CPU definita.
13. Question 72 + Answer 73 - Limite CPU basso ma app multi-thread Anche con piu thread, tutti
condividono la stessa quota totale CPU. Quindi aumenta la concorrenza interna, ma le performance
restano vincolate dal limite complessivo.
14. Slide 74 - Requests and limits setup Requests e limits migliorano stabilita e uso risorse, ma vanno
calibrati con monitoraggio reale dell'applicazione e tuning progressivo.
7. Kubernetes – Part 2
Riassunto completo
Anche i Pod hanno storage interno effimero: quando il Pod viene rimosso, i dati locali spariscono.
Lo storage interno del Pod e condiviso tra i container dello stesso Pod.
Per persistere i dati si usano due oggetti:
PersistentVolume (PV): rappresenta storage disponibile nel cluster.
PersistentVolumeClaim (PVC): richiesta di storage fatta da Pod/applicazione.
Kubernetes fa il binding tra PVC e PV compatibile (size, access mode, storage class, tipicamente anche
tipo filesystem/backend).
In cloud e comune il dynamic provisioning: spesso definisci solo il PVC e il volume viene creato
automaticamente.
Gli access mode definiscono da quanti nodi e con quali permessi un PV puo essere montato.
ReadWriteOnce (RWO): lettura/scrittura da un solo nodo alla volta (piu Pod sullo stesso nodo possono
condividerlo).
46 / 62
[Link] 2026-05-07
I namespace servono per isolare gruppi di risorse nello stesso cluster (ambienti/logica/team diversi).
Se non specifichi namespace, Kubernetes usa default.
I nomi delle risorse devono essere unici dentro un namespace, non globalmente.
Namespace di sistema tipici: kube-system, kube-public, kube-node-lease.
Il prefisso kube- e riservato ai namespace di sistema (tecnicamente creabili, ma da evitare in pratica).
Comandi utili:
kubectl get namespaces
kubectl get pods -n my-namespace
Risorse:
Namespaced: Pod, PVC, ConfigMap, Secret.
Cluster-wide: PV.
47 / 62
[Link] 2026-05-07
I Pod normali sono pensati per processi long-running; se il processo finisce, Kubernetes tende a
riavviarlo.
Per task brevi si usa Job (success/failure basato su exit code).
backoffLimit controlla i retry in caso di errore.
Per esecuzioni pianificate periodiche si usa CronJob (schedule + jobTemplate).
Exit code: 0 = successo, valore non zero = errore.
Il container termina con l'exit code del suo processo di entrypoint; il Pod eredita l'esito del container
principale.
Un Job puo orchestrare anche piu Pod; il successo finale dipende dalla policy configurata.
Nei Job si usa spesso restartPolicy: Never nel template Pod.
I CronJob supportano use case operativi periodici (es. log collection, metric aggregation) e includono
gestione storico/sospensione del planning.
48 / 62
[Link] 2026-05-07
1. Come persisto i dati oltre il ciclo di vita di un Pod? Definisco storage esterno con PV/PVC: il Pod
monta il claim e i dati restano anche se il Pod viene ricreato.
2. Come condivido un volume tra Pod? Piu Pod possono usare lo stesso PVC; la condivisione reale
dipende da access mode e supporto dello storage backend.
3. Come organizzo migliaia di workload nel cluster? Con i namespace: isolamento logico, naming
separato e gestione per team/ambiente.
4. Come condivido configurazioni non sensibili tra piu Pod? Con ConfigMap, referenziato come env
var o file montato.
5. Come condivido informazioni sensibili (es. credenziali DB)? Con Secret, che e l'oggetto dedicato ai
dati sensibili.
6. Come permetto a un Pod di scaricare immagini da registry privato? Creo secret docker-registry
e lo referenzio in imagePullSecrets nel manifest del Pod.
7. A cosa servono readiness, liveness e startup probe? Readiness controlla il traffico, liveness controlla i
riavvii, startup protegge i container lenti in avvio.
8. Quando uso Job e quando CronJob? Job per esecuzioni una tantum/batch; CronJob per esecuzioni
periodiche pianificate.
9. Che ruolo hanno gli exit code in Job/Pod? Un task e considerato riuscito se termina con 0; in caso di
errore (codice non zero) il Job puo ritentare fino al limite configurato.
10. Cosa succede se una liveness probe fallisce ripetutamente? Il kubelet riavvia il container; per app
lente all'avvio e meglio proteggersi con startup probe o delay iniziale.
11. Perche ConfigMap e Secret sono legati ai namespace? Perche sono risorse namespaced: esistono
solo nel namespace dove le crei, quindi puoi avere stessi nomi in namespace diversi.
12. Quali campi minimi devo ricordare per un CronJob? schedule (intervallo di esecuzione) e
jobTemplate (definizione del Job da lanciare).
49 / 62
[Link] 2026-05-07
8. Kubernetes – Part 3
Riassunto completo
Labels e Selectors
Le labels sono coppie chiave-valore nei metadata degli oggetti (es. Pod), utili per organizzarli e
raggrupparli logicamente.
Non devono essere uniche: piu oggetti possono avere le stesse labels.
I selectors servono a selezionare insiemi di oggetti tramite labels.
Tipi principali:
equality-based: ==, !=
set-based: in, notin, exists
Se un selector ha piu condizioni separate da virgola, valgono tutte (AND logico).
ReplicaSet
Deployment (stateless)
StatefulSet (stateful)
Versione stateful del Deployment per workload con identita/stato persistente (es. database).
Quando un Pod stateful cade, va recuperato in modo coerente col suo stato.
Principio pratico: evitare naked Pods (Pod non gestiti da controller), perche non garantiscono resilienza
in caso di failure del nodo.
HPA (HorizontalPodAutoscaler)
Automatizza scale up/down di Deployment o StatefulSet in base a metriche (es. CPU, memoria).
Flusso logico:
1. monitori metriche,
2. definisci target/soglie,
3. HPA regola il numero di repliche.
Campi chiave del manifest:
scaleTargetRef
minReplicas
maxReplicas
metrics
L'HPA controller rivaluta periodicamente (tipicamente ogni ~15s).
Con piu Pod dietro la stessa app, serve un punto di accesso stabile e bilanciato.
In Kubernetes questo e il Service: set logico di Pod + policy di accesso.
Service discovery: IP e DNS stabili lato Service, mentre i Pod possono cambiare.
Il traffico viene inoltrato ai Pod selezionati (kube-proxy; default round-robin, configurabile anche con
IPVS).
Tipi di Service
51 / 62
[Link] 2026-05-07
Ingress
Se devi esporre piu servizi su Internet, usare un LB per ogni Service e costoso/rigido.
Ingress fornisce regole L7 (tipicamente HTTP/HTTPS) per routing host/path verso servizi interni.
Componenti:
oggetto Ingress con regole e possibile defaultBackend
Ingress Controller (Nginx, Contour, Istio, ecc.) che implementa realmente il routing.
Vantaggi: un solo endpoint esterno, routing avanzato, integrazione TLS/certificati.
Kubernetes in locale
1. A cosa servono labels e selectors? A identificare e selezionare gruppi di oggetti in modo flessibile
(base di grouping/routing/scaling in K8s).
3. Quando scelgo Deployment e quando StatefulSet? Deployment per stateless; StatefulSet per
workload stateful che richiedono identita/stato coerente.
52 / 62
[Link] 2026-05-07
4. Perche evitare naked Pods? Senza controller non hai garanzie forti di ripristino/rischedulazione in caso
di failure.
5. Come scala automaticamente Kubernetes rispetto al carico? Con HPA, che osserva metriche e adatta
il numero di repliche entro i limiti min/max.
6. Perche serve un Service davanti ai Pod? Per avere endpoint stabile, discovery DNS e bilanciamento
verso Pod che cambiano nel tempo.
7. Quale tipo di Service usare? ClusterIP per interno, NodePort per esposizione semplice, LoadBalancer
per IP pubblico, ExternalName per alias DNS esterno.
8. Come espongo molti servizi HTTP sotto stesso dominio/IP? Con Ingress + controller, usando regole
host/path verso backend diversi.
9. Che problema risolve Helm? Evita gestione manuale di molti manifest: pacchettizza deployment
complessi in chart configurabili.
10. Qual e il setup pratico per sviluppo locale? Minikube/MicroK8s per cluster locale leggero; Dashboard
per osservare risorse e troubleshooting.
Domande chiave: posso fidarmi del servizio che sto contattando? Il traffico e leggibile in rete?
Con HTTP puro, i dati possono essere intercettati (man-in-the-middle), soprattutto se contengono
informazioni sensibili.
HTTPS e TLS
53 / 62
[Link] 2026-05-07
Simmetrica: stessa chiave per cifrare/decifrare (es. AES, Blowfish, Twofish, Serpent).
Asimmetrica: coppia chiave pubblica/privata (es. RSA, Diffie-Hellman per key exchange).
L'asimmetrica consente scambio sicuro iniziale e firma digitale; la simmetrica gestisce il traffico di
sessione.
Fasi principali:
1. Hello: client e server negoziano versione/cipher suite.
2. Certificate exchange: il server presenta il certificato per dimostrare identita.
3. Key exchange: viene stabilito il segreto condiviso usato dalla cifratura simmetrica.
Dopo handshake, richieste/risposte HTTP viaggiano cifrate.
Un certificato contiene identita proprietario, dominio, chiave pubblica, firma digitale e validita
temporale.
La fiducia dipende dalla catena CA: i client fidano CA note (es. Let's Encrypt, DigiCert, Comodo,
GoDaddy).
Self-signed:
utili per test/lab;
non adatti a connessioni pubbliche sensibili senza un modello di trust controllato.
54 / 62
[Link] 2026-05-07
Ruoli OAuth:
Resource Owner (utente)
Client (applicazione)
Authorization Server (emette token)
Resource Server (API protetta)
Authorization Code (consigliato): adatto a web/mobile; per SPA/public client usare PKCE.
Client Credentials: comunicazione service-to-service (nessun utente umano).
Device Code: dispositivi con input limitato (TV, console).
Implicit: legacy, non raccomandato.
Password: legacy/discontinuato in OAuth 2.1.
55 / 62
[Link] 2026-05-07
Spring Security supporta OAuth2 nativamente (provider/consumer), senza dipendenza legacy Spring
Security OAuth.
Riferimento pratico: configurare client/resource server seguendo i moduli OAuth2 moderni del
framework.
JWT e un formato standard compatto per trasmettere informazioni (claims) in modo verificabile tra
parti.
I token JWT possono essere firmati:
con segreto condiviso (es. HMAC);
con coppia chiave pubblica/privata (es. RSA/ECDSA).
Struttura compatta: [Link].
header: tipo token (JWT) + algoritmo (alg).
payload: claims (registered, public, private).
signature: firma digitale per verificare integrita e origine.
Importante: payload/header non sono cifrati di default (solo codifica Base64Url), quindi non vanno usati
per dati segreti se non con cifratura.
Dopo login, il client invia il token nelle richieste protette via header:
Authorization: Bearer <token>
JWT non sostituisce OAuth2: OAuth2 definisce il protocollo di autorizzazione, JWT e un possibile
formato del token (es. access token).
56 / 62
[Link] 2026-05-07
Keycloak (IAM)
Keycloak e una piattaforma open-source di Identity and Access Management (IAM) per aggiungere
autenticazione/autorizzazione alle applicazioni.
Punti chiave:
SSO/SLO per applicazioni browser.
Identity brokering (OIDC/SAML) e social login.
User federation con LDAP/Active Directory.
Console admin e console account utente (profilo, password, 2FA, ecc.).
1. Perche HTTP non basta in ambienti reali? Perche il traffico in chiaro puo essere
intercettato/modificato; con dati sensibili e un rischio diretto.
2. Cosa garantisce TLS in HTTPS? Identita del server, confidenzialita del traffico e integrita dei messaggi.
3. Perche TLS usa sia asimmetrica che simmetrica? L'asimmetrica serve per trust e key exchange iniziale;
la simmetrica per performance sul traffico continuo.
4. Quando evitare certificati self-signed? In produzione pubblica: senza catena di fiducia robusta non
garantiscono identita verificabile lato client.
5. Termination vs Pass-Through sul load balancer: come scelgo? Termination se vuoi controllo L7
semplice; pass-through se vuoi TLS fino al backend; bridging se vuoi entrambe le cose con costo
maggiore.
57 / 62
[Link] 2026-05-07
7. Qual e il grant type standard oggi per app web/mobile? Authorization Code, con PKCE quando il
client non puo custodire segreti in modo sicuro.
8. Quando usare Client Credentials? Per chiamate machine-to-machine dove il client agisce per se
stesso.
9. A cosa serve il refresh token? A rinnovare access token scaduti senza rifare login completo dell'utente.
10. Cosa cambia in Spring moderno per OAuth2? Il supporto e integrato in Spring Security corrente; non
serve la vecchia libreria dedicata legacy.
11. JWT e OAuth2 sono la stessa cosa? No: OAuth2 e un framework/protocollo di autorizzazione; JWT e
un formato di token che puo essere usato dentro OAuth2.
12. Quali sono le 3 parti di un JWT? Header, payload, signature ([Link]), con firma
usata per verificare integrita/autenticita.
13. Posso mettere password o segreti nel payload JWT? No, non in chiaro: payload/header sono leggibili
se non cifrati; usare solo claims necessari e non sensibili.
14. Che ruolo ha Keycloak in un'architettura cloud-native? Centralizza IAM: login, token, ruoli,
federazione identita e SSO per piu applicazioni.
15. Perche i realm di Keycloak sono importanti? Perche isolano utenti/ruoli/client tra contesti diversi
(ambienti, tenant, domini applicativi).
1. HTTPS/TLS risolve trust e cifratura del canale, non solo privacy ma anche autenticita endpoint.
2. Certificati + CA sono il cuore del modello di fiducia su Internet.
3. In presenza di load balancer, la scelta del punto di terminazione TLS impatta sicurezza, costo e
operativita.
4. OAuth2 abilita delega sicura dell'accesso alle risorse tramite token e scope.
5. Authorization Code (+ PKCE) e il flusso di riferimento moderno per client con utente.
6. Access token e refresh token vanno progettati insieme con lifetime coerente al rischio.
7. JWT e un formato token firmato: utile per claims e propagazione identita, ma non e un protocollo di
auth.
8. Header/payload JWT non vanno trattati come spazio sicuro per segreti.
9. Keycloak offre IAM completo (SSO, federation, ruoli, realm, client).
10. In Spring moderno, integrazione consigliata tramite OAuth2/OIDC standard di Spring Security.
58 / 62
[Link] 2026-05-07
L'architettura a microservizi sviluppa un sistema come insieme di servizi piccoli, ognuno in un proprio
processo.
I servizi comunicano con meccanismi leggeri (tipicamente HTTP/REST, ma anche messaggistica
asincrona).
Ogni servizio e costruito attorno a una capability di business e deve essere deployabile in modo
indipendente.
E possibile usare stack tecnologici diversi tra servizi (linguaggi, database, framework), con governance
centralizzata minima.
I microservizi sono visti come evoluzione pratica della SOA in contesti web/mobile/IoT moderni.
La loro diffusione e collegata alla necessita di rilasciare software piu velocemente e in modo piu
affidabile.
La crescita parallela di DevOps, CI/CD, containerizzazione e API Gateway ha reso questo modello
operativo su larga scala.
59 / 62
[Link] 2026-05-07
Principio guida del corso: non scegliere microservices se il monolite e ancora gestibile.
Valuta microservices quando la complessita nasce da:
team grandi o distribuiti;
multi-tenancy;
molte modalita di interazione utente;
necessita che funzioni di business evolvano indipendentemente;
esigenze di scaling differenziato;
monolite diventato troppo grande per modifiche/deploy rapidi.
Comunicazione inter-service
60 / 62
[Link] 2026-05-07
2. Perche i microservices sono associati a DevOps e CI/CD? Perche il valore del modello emerge
quando puoi rilasciare spesso e in modo automatizzato singoli servizi.
3. Qual e il principale limite del monolite in fase di crescita? Ogni modifica richiede impatti ampi
(build/test/deploy), rallentando team e rilascio.
4. In che senso i microservices migliorano la resilienza? Isolano i guasti: il fallimento di un servizio puo
degradare una sola funzione, non l'intero sistema.
61 / 62
[Link] 2026-05-07
5. Quando NON dovresti usare microservices? Quando il monolite e ancora gestibile e la complessita
distribuita supererebbe i benefici.
6. Loose coupling e high cohesion cosa significano in pratica? Servizi indipendenti nelle dipendenze
esterne e internamente focalizzati su responsabilita coerenti.
7. Sincrono o asincrono nella comunicazione tra servizi? Dipende dal caso d'uso: sincrono per
immediatezza/semplicita, asincrono per disaccoppiamento, resilienza e throughput.
8. Quali pattern usare contro failure parziali? Timeout, limiti di richieste concorrenti, circuit breaker e
fallback.
9. Perche ogni microservizio tende ad avere il proprio DB? Per ridurre accoppiamento e permettere
evoluzione indipendente del dominio dati del servizio.
10. Perche le migrazioni DB sono critiche con rolling update? Perche vecchia e nuova versione
convivono: lo schema deve restare compatibile durante il rollout.
11. Perche un rename diretto di colonna e rischioso in produzione? Perche rompe compatibilita tra
versioni applicative diverse ancora in esecuzione.
12. Quando usare message queue/pub-sub invece di REST puro? Quando vuoi disaccoppiare tempi di
risposta, assorbire picchi e gestire eventi asincroni.
13. Che contributo da Kubernetes ai microservices? Fornisce primitive operative standard: service
discovery, bilanciamento, health check, config management e rollout.
14. Qual e il ruolo di Spring Cloud in questo contesto? Riduce boilerplate offrendo implementazioni
pronte di pattern distribuiti comuni.
15. Come si inizia una migrazione da monolite? Con refactoring interno per isolare confini di dominio,
poi estrazione incrementale dei servizi piu adatti.
1. Microservices non sono un fine: sono una risposta a complessita tecnica/organizzativa specifica.
2. Il trade-off fondamentale e autonomia dei servizi vs complessita distribuita.
3. Le decisioni vanno prese su confini di business (bounded context), non solo su criteri tecnici.
4. Osservabilita, resilienza e automazione deploy sono prerequisiti operativi, non opzionali.
5. Comunicazione inter-service richiede scelta consapevole tra sync e async.
6. La gestione dati e il punto piu delicato: eventual consistency e migrazioni backward-compatible sono
centrali.
7. Rolling update impone strategie di schema evolution multi-step.
8. Kubernetes e Spring Cloud accelerano l'adozione ma non eliminano la complessita architetturale.
9. Team topology e architettura devono essere allineati per ottenere vero beneficio.
10. Regola pratica: partire monolitici quando possibile, passare a microservices quando la complessita lo
richiede davvero.
62 / 62