Module 10 — MLOps & On-Premises Deployment
Same theory-first structure as Modules 1–9: for every technique below, what it is, why it exists — the specific problem it was invented to solve — what else you could use instead, and a real financial example. Nine modules have built real, tested models that have only ever run inside a notebook. Module 10 asks how RR Finance actually RUNS one — on its own infrastructure, not a third-party cloud.
Recap — what RR Finance already has
Module 10 is not a fresh start. Here's exactly what it inherits before deploying any of it.
A real, saved, validated classifier pipeline — the exact model this module wraps in a real running API, unchanged.
A real fairness and explainability audit — the governance work that has to precede letting this model answer real requests.
Federated training and a real privacy focus — this module's mTLS and on-premises framing extends that same discipline to the deployment layer.
From notebook to production
On-premises, specifically — not cloud, and that choice shapes everything in this module.
Why on-premises
RR Finance's applicant data is exactly what Module 7's privacy work and typical financial-sector regulation push toward keeping inside an institution's own infrastructure.
The honest-testing constraint
This sandbox has no Docker daemon, no live Kubernetes cluster, and can't reach Vault's server binary — every real tool is attempted honestly, with disclosed, working alternatives where this sandbox specifically can't reach something.
What ties it together
Every layer in this module — API, container, scan, cluster, secrets, TLS — wraps the SAME model from Module 1, unchanged, all the way through.
FastAPI Model Serving
The boundary between a notebook experiment and a system.
FastAPI, with Pydantic for request validation, wraps a trained model in a real HTTP API — run by uvicorn, a real ASGI server — so it can answer requests from any real caller, not just a notebook cell.
✓ What the notebook demonstrates
- A real server, started as a real subprocess, wrapping Module 1's ACTUAL saved pipeline — a valid request returns a real prediction (200), an invalid one (credit score 9999) is rejected before it ever reaches the model (422)
✗ What this is NOT
- A retrained or simplified stand-in model — this is the exact object Module 1 fitted and Module 6 audited, loaded unchanged
ge, le, gt) are simple range checks enforced BEFORE the request reaches the model, not a modelling technique. The model itself is Module 1's already-fitted logistic regression pipeline, unchanged.Containerization with Docker
Making 'works on my machine' into 'works on their machine.'
A Docker container packages the API, its exact Python dependencies, and the model artifact into one portable, reproducible unit, built from a versioned Dockerfile recipe.
✓ What the notebook demonstrates
- A real, valid Dockerfile — with a non-root
USERand aHEALTHCHECKalready included, deliberately, before Concept 3 shows exactly why those two lines matter
✗ An honest limitation, stated plainly
- This sandbox has no Docker daemon (no privileged container-in-container access) — the Dockerfile is real and correct, but was never actually built into a running image here
COPY requirements.txt and RUN pip install come before COPY app.py — application code changes far more often than dependencies, so ordering this way avoids re-installing packages on every code change.DevSecOps Scanning with Trivy
A real automated gate, catching a real, common mistake.
Trivy, downloaded directly from its real GitHub release, scans Dockerfiles (and container images, dependencies, and infrastructure-as-code more broadly) for known security misconfigurations — the automated check a real CI/CD pipeline runs before any container reaches production.
✓ What the notebook demonstrates
- A real before/after: a naive Dockerfile fails 2 real checks (HIGH: running as root; LOW: no healthcheck); Concept 2's actual deployment Dockerfile, which already fixed both, scans clean
✗ An honest limitation, stated plainly
- This sandbox cannot reach
mirror.gcr.io, the host Trivy normally pulls its latest vulnerability database and policy bundle from — Trivy handles this gracefully by falling back to its embedded checks, disclosed directly in the notebook's output rather than hidden
DS-0002, non-root user) is a specific, named, documented check, not a statistical prediction.Kubernetes Deployment
Surviving a crashed pod, and being reachable by one stable name.
Kubernetes orchestrates multiple copies (replicas) of a containerized service, automatically restarting failed ones and giving them one stable internal address via a Service — a Deployment manifest describes exactly how.
✓ What the notebook demonstrates
- A real, valid, parseable Kubernetes manifest — 3 replicas, liveness and readiness probes pointed at the SAME
/healthendpoint Concept 1 actually tested, a non-root security context
✗ An honest limitation, stated plainly
- This sandbox has no running Kubernetes cluster — the manifest would
kubectl applycleanly on a real one, but was never actually deployed anywhere here, and the notebook says so directly rather than implying otherwise
livenessProbe and readinessProbe reuse Concept 1's own /health endpoint — a probe failure is what actually TRIGGERS a pod restart or removal from traffic routing.Secrets Management: From Vault to a Real Local Alternative
Never storing a credential in plaintext.
HashiCorp Vault stores secrets encrypted at rest, behind access policies and an audit log, accessed via a client library rather than a config file — attempted here first via the real hvac client, exactly as this course's discipline requires.
✓ What the notebook demonstrates
- A real, honest attempt to connect to a local Vault server (fails, because Vault's server binary is hosted at
releases.hashicorp.com, unreachable here), followed by a real, working AES-based (Fernet) local encryption-at-rest fallback — genuinely unreadable on disk without the key
✗ What the fallback does NOT claim
- Access-control policies, audit logging, dynamic secret leasing, and multi-node durability are real, substantial Vault capabilities this fallback does not have — only the ONE guarantee actually tested (no plaintext at rest) is claimed
app.py or a Dockerfile in plaintext, is retrieved at runtime from a secrets store — Vault in a real deployment, the notebook's tested local encryption-at-rest fallback here.Mutual TLS
Both sides prove who they are, or the connection never completes.
Mutual TLS (mTLS) requires BOTH the server AND the client to present a valid certificate, signed by a trusted Certificate Authority, before a connection completes — encryption plus two-way authentication, not just one.
✓ What the notebook demonstrates
- A real X.509 certificate chain (CA, server cert, client cert) generated with real OpenSSL, and a real running HTTPS server that REJECTS a request with no client certificate at the TLS handshake itself, before any application code runs, and ACCEPTS one with a valid client certificate
✗ A real detail this lesson caught directly
- Modern TLS clients verify hostname against the certificate's SAN (Subject Alternative Name) field, not the legacy CN field alone — a certificate signed without SAN genuinely fails verification in Python's
sslmodule, exactly the kind of real, specific detail this course surfaces rather than glossing over
ca.crt) can verify that signature, confirming the certificate is genuinely CA-issued without ever needing the CA's private key themselves.--ssl-cert-reqs 2 (uvicorn's CERT_REQUIRED) is what makes the client-side check mandatory rather than optional.Module 10 hand-off
The notebook wraps Module 1's real saved pipeline in a real, running FastAPI service, writes a real Trivy-scanned Dockerfile (catching a genuine before/after: 2 real findings, then 0), writes a real, valid Kubernetes manifest, builds a real working secrets-encryption fallback where Vault's server binary is unreachable, and runs a real, tested mutual-TLS boundary around the API -- with a metrics summary saved as an artifact for the next module.