← All Google Cloud AI guidesSection 5 · 5.1, 5.2

ML pipelines, retraining and CI/CD/CT

Section 5: Agent Platform Pipelines (Kubeflow Pipelines and TFX), Managed Service for Apache Airflow, Ray, data and model validation gates, keeping preprocessing consistent between training and serving, retraining policies, MLOps maturity levels and CI/CD/CT with Cloud Build. Includes a pipeline lab.

1. End-to-end ML pipelines

A pipeline turns notebook steps into a repeatable, versioned, automated workflow: ingest → validate data → transform → train → evaluate → validate the model → register → deploy → monitor. Each run records lineage, so you can answer "which data and code produced the model in production?"

Orchestrators

OrchestratorChoose when
Agent Platform PipelinesDefault for ML: serverless, runs Kubeflow Pipelines (KFP) v2 or TFX pipelines, automatic lineage in ML Metadata, caching, Google Cloud Pipeline Components, scheduling
Managed Service for Apache Airflow (formerly Cloud Composer)Orchestrating whole data platforms: many systems, ETL schedules, cross-team DAGs. It can trigger ML pipelines, but isn't ML-aware (no artifact lineage)
Ray on Agent PlatformPython-native distributed data processing, training and tuning (Ray Data, Ray Train, Ray Tune) on a managed Ray cluster
Kubeflow Pipelines on GKESelf-managed open source on your own cluster
TemplatesPrebuilt pipelines (Tabular Workflows, model evaluation, tuning templates) to start from instead of writing your own
from kfp import dsl, compiler
from google_cloud_pipeline_components.v1.custom_job import CustomTrainingJobOp

@dsl.component(base_image="python:3.11", packages_to_install=["pandas", "google-cloud-bigquery"])
def validate_data(table: str) -> bool:
    ...  # row counts, schema, nulls, ranges; return False to stop the run

@dsl.component(base_image="python:3.11")
def evaluate(model: dsl.Input[dsl.Model], metrics: dsl.Output[dsl.Metrics]) -> float:
    ...

@dsl.pipeline(name="churn-training")
def pipeline(table: str = "bq://PROJECT_ID.shop.train", min_auc_pr: float = 0.65):
    ok = validate_data(table=table)
    with dsl.If(ok.output == True):
        train = CustomTrainingJobOp(display_name="train", worker_pool_specs=[...])
        score = evaluate(model=...)
        with dsl.If(score.output >= min_auc_pr):      # model validation gate
            ...  # ModelUploadOp → ModelDeployOp (or register as "challenger")

compiler.Compiler().compile(pipeline, "pipeline.yaml")
# aiplatform.PipelineJob(display_name="churn", template_path="pipeline.yaml",
#                        enable_caching=True, parameter_values={...}).submit()
The KFP SDK's exact syntax (for example dsl.If versus the older dsl.Condition) varies by version; questions focus on concepts: components, artifacts, parameters, conditions, caching and lineage.

TFX components (TensorFlow Extended)

ComponentJob
ExampleGenIngest and split data
StatisticsGen, SchemaGen, ExampleValidatorData statistics, an inferred schema, and anomaly detection (TensorFlow Data Validation, TFDV)
TransformTensorFlow Transform: full-pass preprocessing (vocabularies, normalization) exported into the serving graph, so serving applies identical transforms
Trainer, TunerTrain and tune
EvaluatorTensorFlow Model Analysis: metrics overall and by slice; "blesses" the model only if it beats thresholds or the current model
InfraValidator, PusherCheck the model loads and serves; push blessed models to serving

Validating data and models

Consistent preprocessing between training and serving

ApproachHow it guarantees consistency
BigQuery ML TRANSFORMPreprocessing stored with the model, applied by ML.PREDICT
TensorFlow TransformTransform graph attached to the serving model
Preprocessing layers inside the model (Keras preprocessing, scikit-learn Pipeline)The saved artifact contains the logic
Feature StoreThe same feature definitions feed training (offline) and serving (online)
Custom prediction routineOne Python preprocessing function used in both

2. Retraining and CI/CD/CT

Retraining policy

TriggerGood forRisk
Schedule (daily, weekly)Steady data change; simple to runRetrains when nothing changed (cost) or too late when things change fast
New data volume (for example every 100k labelled rows)Label arrival drives valueNeeds data counting
Monitoring alert (drift or skew above threshold)Retrain when inputs changeDrift doesn't always hurt accuracy
Performance drop on ground truthRetrain when it mattersLabels may arrive weeks late
On demand (code change)New features or architectureThrough CI/CD, not by hand
Choose the policy from how fast the world changes, how soon labels arrive, and what retraining costs. Always gate an automatic retrain with evaluation against the current model before it reaches users.

CI/CD/CT

PracticeMeaning in MLGoogle Cloud pieces
Continuous integration (CI)On every commit: unit-test components and data checks, build containers, compile the pipelineCloud Build triggers on the repository, Artifact Registry for images and pipeline templates
Continuous delivery (CD)Deploy the new pipeline (and, after validation, models) to staging then productionCloud Build, Cloud Deploy, approvals
Continuous training (CT)The pipeline itself retrains on schedule or triggerPipeline schedules, Cloud Scheduler, Pub/Sub or Eventarc triggers, Cloud Run functions

Google's MLOps maturity levels: level 0 is manual notebooks and hand deployment; level 1 automates training with a pipeline (CT); level 2 automates the pipeline's own build, test and deployment (CI/CD of the pipeline).

# cloudbuild.yaml (sketch): test, build the trainer image, compile and upload the pipeline
steps:
- name: python:3.11
  entrypoint: bash
  args: ["-c", "pip install -r requirements.txt && pytest tests/"]
- name: gcr.io/cloud-builders/docker
  args: ["build", "-t", "us-docker.pkg.dev/PROJECT_ID/ml/trainer:$SHORT_SHA", "trainer/"]
- name: python:3.11
  entrypoint: bash
  args: ["-c", "pip install kfp && python compile_pipeline.py && python upload_template.py"]
images: ["us-docker.pkg.dev/PROJECT_ID/ml/trainer:$SHORT_SHA"]

3. MLOps maturity at a glance

LevelWhat it looks likeTypical exam fix
0: manualNotebooks, CSV exports, hand-uploaded models, no lineageMove training into a pipeline reading BigQuery directly; register models
1: pipeline automation (CT)Pipeline retrains on schedule or trigger with validation gatesAdd data and model validation, evaluation against production, scheduled or triggered runs
2: CI/CD of the pipelineCode changes are tested, built and deployed automaticallyCloud Build triggers, Artifact Registry, staged rollout with approvals
Gate before you ship: validate data → train → evaluate against the champion → register only if better → deploy gradually.

4. Lab: a Kubeflow pipeline with a validation gate

  1. Create three lightweight components: validate_data (checks row count and nulls), train, and evaluate (returns a metric).
  2. Wire them with conditions so training only runs when validation passes, and registration happens only when the metric beats the current production model.
  3. Compile to YAML, submit with PipelineJob(enable_caching=True), then re-run unchanged and watch cached steps skip.
  4. Open the lineage view for the resulting model and trace it back to the dataset and run parameters.
  5. Add a Cloud Build trigger that runs component unit tests and recompiles the pipeline on each commit.
  6. Create a weekly schedule for the pipeline; then delete the schedule.

5. "Which orchestrator?" chooser

Pick an item to see what it means, why, and the tempting wrong choice.

Pick one above.

6. Sample outputs

What the tools return. Expand an item to see a typical result and what to read in it.

Illustrative output, not captured from a real project. IDs, numbers and some field names are invented or simplified, and formats change between releases. Learn the shape and the fields called out under each one.
Pipeline run (console summary)A run where the model validation gate stopped deployment
Run: churn-training-20261114-0200   State: SUCCEEDED
  validate-data        SUCCEEDED   (cached)
  train                SUCCEEDED   41m
  evaluate             SUCCEEDED   3m     output: 0.612
  condition-1 (score >= 0.65)  SKIPPED
    model-upload       NOT_TRIGGERED
    model-deploy       NOT_TRIGGERED

What to look at: The run succeeded, but the new model scored 0.612, below the 0.65 gate, so nothing was registered or deployed: the pipeline did its job. The data validation step reused a cached result because its inputs didn't change.

7. Scenarios

Exam-style situations: how to diagnose each one, the likely cause and the fix.

8. Searchable reference

ItemMeaning

9. Flashcards (click to flip)

10. Common gotchas in one list

  1. Agent Platform Pipelines for ML lineage; Airflow for data-platform orchestration.
  2. Never auto-deploy without an evaluation gate against the current model.
  3. Retraining policy follows the data: schedules, data volume, drift or performance triggers.
  4. Late labels mean you can't wait for accuracy drops; use drift and schedules.
  5. CI tests code and builds images; CT retrains; CD deploys.
  6. Caching needs deterministic inputs.
  7. Validate data before training; schema changes otherwise train garbage.
  8. Build containers in CI and tag by commit for reproducibility.
  9. Composer is now Managed Service for Apache Airflow; the gcloud composer commands remain.

11. Practice quiz (18 questions)

Score: 0 / 0
← Serving and scalingNext: Security, responsible AI and monitoring →