- Posted on
- • Artificial Intelligence
Artificial Intelligence Continuous Delivery
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Artificial Intelligence Continuous Delivery: Ship Models Like Code (From Your Linux Shell)
What if shipping a new model felt as boring—and safe—as shipping a bug fix? Most AI teams still push notebooks by hand, wrangle data in ad‑hoc folders, and “deploy” by copying files to servers. That’s brittle, slow, and impossible to audit. The value of Artificial Intelligence Continuous Delivery (AI CD) is turning ML into a repeatable, testable, and automated delivery system you can trust.
This guide shows you how to stand up AI CD on Linux using nothing but your terminal. You’ll learn why AI CD matters and walk away with a concrete, bash-first blueprint you can implement this week.
Why AI Continuous Delivery?
Reproducibility: You can rebuild the same model binary and environment—bit for bit—months later.
Safety: Automated tests, evals, and policy gates catch regressions before production.
Speed: Small, frequent, automated releases ship value faster and reduce risk.
Compliance: Versioned data, models, metrics, and infra are auditable by default.
Cost: Early failures in CI are cheaper than late failures in production.
Prerequisites: Install Core Tools
Pick Docker or Podman for container builds. The rest is common.
Common packages: git, Python 3, pip, venv, Git LFS, make, curl
Container runtime: Docker or Podman (choose one)
Optional for Kubernetes CD: kubectl
Debian/Ubuntu (apt):
sudo apt update
sudo apt install -y git python3 python3-venv python3-pip git-lfs make curl
# Docker (option A)
sudo apt install -y docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER" # log out/in to apply
# Podman (option B)
sudo apt install -y podman buildah skopeo
# Optional: kubectl (on some distros this may be kubernetes-client)
sudo apt install -y kubectl || sudo apt install -y kubernetes-client
Fedora/RHEL/CentOS (dnf):
sudo dnf install -y git python3 python3-pip git-lfs make curl
# Docker (option A, Fedora provides moby-engine)
sudo dnf install -y moby-engine docker-compose-plugin
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
# Podman (option B)
sudo dnf install -y podman buildah skopeo
# Optional: kubectl (kubernetes-client provides kubectl)
sudo dnf install -y kubernetes-client
openSUSE/SLES (zypper):
sudo zypper refresh
sudo zypper install -y git python3 python3-pip git-lfs make curl
# venv is typically included with python3; if missing try:
# sudo zypper install -y python3-venv
# Docker (option A)
sudo zypper install -y docker
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
# Podman (option B)
sudo zypper install -y podman buildah skopeo
# Optional: kubectl (package may be kubectl or kubernetes-client)
sudo zypper install -y kubectl || sudo zypper install -y kubernetes-client
If python3 -m venv fails on your distro, either install python3-venv (apt) or use pip install virtualenv as a fallback.
A Minimal, Practical AI CD Blueprint (5 Steps)
Below is a concrete path you can copy-paste on a fresh repo. It’s tool-agnostic, shell-first, and production-friendly.
1) Make builds reproducible
Pin your environment and automate repeatable commands.
Repo layout:
ai-cd-demo/
├─ data/ # DVC will track pointers, not blobs
├─ models/ # Model artifacts (via DVC)
├─ src/
│ ├─ train.py
│ └─ evaluate.py
├─ server/
│ └─ app.py # FastAPI inference server
├─ tests/
│ └─ test_eval.py
├─ requirements.txt
├─ dvc.yaml
├─ params.yaml
└─ Makefile
Example requirements.txt:
fastapi==0.111.0
uvicorn[standard]==0.30.1
scikit-learn==1.5.0
pandas==2.2.2
numpy==1.26.4
joblib==1.4.2
dvc[s3]==3.51.0
pytest==8.2.2
Create and use a venv:
python3 -m venv .venv
. .venv/bin/activate
pip install -U pip
pip install -r requirements.txt
Makefile for muscle memory:
.PHONY: venv train eval serve test
venv:
python3 -m venv .venv && . .venv/bin/activate && pip install -U pip -r requirements.txt
train:
. .venv/bin/activate && python -m src.train
eval:
. .venv/bin/activate && python -m src.evaluate
serve:
. .venv/bin/activate && uvicorn server.app:app --host 0.0.0.0 --port 8000
test:
. .venv/bin/activate && pytest -q
Minimal src/train.py:
# src/train.py
import joblib, pandas as pd
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
def main():
X, y = load_iris(return_X_y=True, as_frame=True)
clf = LogisticRegression(max_iter=200).fit(X, y)
joblib.dump(clf, "models/iris.joblib")
print("Saved models/iris.joblib")
if __name__ == "__main__":
main()
Minimal src/evaluate.py:
# src/evaluate.py
import json, joblib
from sklearn.datasets import load_iris
from sklearn.metrics import accuracy_score
def main():
X, y = load_iris(return_X_y=True, as_frame=True)
clf = joblib.load("models/iris.joblib")
acc = accuracy_score(y, clf.predict(X))
print(json.dumps({"accuracy": acc}))
if __name__ == "__main__":
main()
2) Version everything: code, data, models, metrics
Use Git for code, Git LFS for large binaries, and DVC for data/model artifacts and pipelines.
Initialize:
git init
git lfs install
dvc init
git add .dvc .gitignore
git commit -m "init dvc"
Track data and model artifacts:
mkdir -p data models
# Add your raw data into data/, then:
dvc add data
git add data.dvc .gitignore
git commit -m "track data with dvc"
Configure a DVC remote (S3 shown; you can use local, SSH, GCS, etc.):
dvc remote add -d origin s3://my-bucket/ai-cd-demo
dvc remote modify origin access_key_id "$AWS_ACCESS_KEY_ID"
dvc remote modify origin secret_access_key "$AWS_SECRET_ACCESS_KEY"
dvc remote modify origin endpointurl "https://s3.your-cloud.example"
git commit .dvc/config -m "configure dvc remote"
Define a simple DVC pipeline in dvc.yaml:
stages:
train:
cmd: python -m src.train
deps:
- src/train.py
- data
outs:
- models/iris.joblib
evaluate:
cmd: python -m src.evaluate > metrics.json
deps:
- src/evaluate.py
- models/iris.joblib
metrics:
- metrics.json:
cache: false
Run, then push artifacts:
dvc repro
dvc push
git add models/.gitignore dvc.yaml metrics.json
git commit -m "train + eval with dvc"
Now your code, data pointers, models, and metrics are versioned together.
3) Automate tests and evals in CI
Gate releases on metrics (e.g., accuracy) and tests.
Example tests/test_eval.py:
import json, subprocess
def test_accuracy_gate():
out = subprocess.check_output(["python", "-m", "src.evaluate"])
acc = json.loads(out)["accuracy"]
assert acc >= 0.90, f"Accuracy too low: {acc}"
GitHub Actions workflow .github/workflows/ci.yml:
name: ci
on:
push:
branches: [ "main" ]
pull_request:
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install deps
run: |
python -m pip install -U pip
pip install -r requirements.txt
- name: DVC pull data/models
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
DVC_NO_ANALYTICS: "1"
run: |
dvc pull || true # pull if available
- name: Train + Eval
run: |
python -m src.train
python -m src.evaluate > metrics.json
- name: Unit tests + metric gates
run: |
pytest -q
- name: Upload metrics
uses: actions/upload-artifact@v4
with:
name: metrics
path: metrics.json
This fails fast if accuracy regresses, preventing promotion.
4) Containerize inference and promote via environments
A tiny FastAPI server server/app.py:
from fastapi import FastAPI
import joblib
from pydantic import BaseModel
app = FastAPI()
model = joblib.load("models/iris.joblib")
class Sample(BaseModel):
features: list[float] # length 4 for iris
@app.post("/predict")
def predict(s: Sample):
return {"class": int(model.predict([s.features])[0])}
Dockerfile (works with Docker or Podman):
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -U pip && pip install -r requirements.txt
COPY models/ models/
COPY server/ server/
EXPOSE 8000
CMD ["uvicorn", "server.app:app", "--host", "0.0.0.0", "--port", "8000"]
Build and run locally:
Docker:
docker build -t ghcr.io/youruser/ai-cd-demo:$(git rev-parse --short HEAD) .
docker run --rm -p 8000:8000 ghcr.io/youruser/ai-cd-demo:$(git rev-parse --short HEAD)
Podman:
podman build -t ghcr.io/youruser/ai-cd-demo:$(git rev-parse --short HEAD) .
podman run --rm -p 8000:8000 ghcr.io/youruser/ai-cd-demo:$(git rev-parse --short HEAD)
Test inference:
curl -s -X POST localhost:8000/predict \
-H 'Content-Type: application/json' \
-d '{"features":[5.1,3.5,1.4,0.2]}'
Kubernetes deployment k8s/deploy.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-cd-demo
spec:
replicas: 2
selector:
matchLabels: { app: ai-cd-demo }
template:
metadata:
labels: { app: ai-cd-demo }
spec:
containers:
- name: app
image: ghcr.io/youruser/ai-cd-demo:REPLACEME_SHA
ports:
- containerPort: 8000
readinessProbe:
httpGet: { path: /docs, port: 8000 }
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: ai-cd-demo
spec:
selector: { app: ai-cd-demo }
ports:
- port: 80
targetPort: 8000
Apply to a cluster:
kubectl apply -f k8s/deploy.yaml
kubectl rollout status deploy/ai-cd-demo
Promotion tip:
Use tags like
:staging-<sha>and:prod-<sha>.Promote by updating just the image tag and letting your CD tool (e.g., Argo CD, Flux) sync.
Optional Argo CD application (argocd/app.yaml):
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ai-cd-demo
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
source:
repoURL: https://github.com/youruser/ai-cd-demo.git
targetRevision: main
path: k8s
syncPolicy:
automated:
prune: true
selfHeal: true
5) Observe and roll back with metric gates
Metric gates: Keep the
pytestthreshold or parsemetrics.jsonin CI to block bad models.Health and latency: Add a
/healthzendpoint and expose Prometheus metrics.Rollback: Use
kubectl rollout undo deploy/ai-cd-demoor revert the tag in Git; Argo CD/Flux will reconcile automatically.
Example gate in bash (CI step) to block promotion if accuracy < 0.92:
ACC=$(jq -r .accuracy metrics.json)
python - <<PY
import sys
acc = float("$ACC")
sys.exit(0 if acc >= 0.92 else 1)
PY
Real-World Patterns That Work
Shadow deployments: Mirror a slice of prod traffic to the new model; compare outputs offline before switching.
Blue/Green: Run both versions; flip Service selector when the new one passes SLOs.
Feature flags: Gate model usage by tenant or percentage rollouts.
Immutable artifacts: Image tags are content-addressed (use commit SHA); never reuse mutable tags for promotion.
Conclusion and Next Steps
AI CD makes ML boring—in the best way. You version everything, test automatically, gate on metrics, ship in containers, and promote with confidence.
Your next steps:
1) Initialize DVC in your repo and pin your Python environment.
2) Add a simple pytest gate that enforces a minimum metric.
3) Containerize your inference server and deploy to a staging namespace.
4) Wire an automated pipeline to build, test, and deploy on every merge.
If you found this useful, pick one step, implement it today, and iterate. Consistent, incremental automation beats big-bang “MLOps transformations” every time.