Skip to content

Deployment operations lessons

The deployment operations lessons are for the reader who wants to see how the same tutorial platform behaves when the runtime boundary is the Tinys k3s cluster.

The operator shape is explicit: laptop as thin human surface, Spark as the Kubernetes The Hard Way style jumpbox and AI workstation, Tinys as the runtime, and Azure as the cloud migration target.

The first lesson lives in tutorial/deployment/lesson-01-k3s-local-cluster.md.

It covers:

  • installing or attaching to the Tinys k3s cluster;
  • choosing three k3s server nodes with embedded etcd for quorum and failure learning;
  • configuring kubectl;
  • creating the fos-workbench namespace;
  • mapping Spark to the jumpbox role from Kubernetes The Hard Way;
  • checking cluster defaults that matter to this repo, including DNS, HTTP exposure, and local persistent volume claims;
  • mapping Kubernetes objects back to the tutorial vocabulary.

No fos-workbench workload is deployed in L01. That is deliberate: the first lesson establishes the operator boundary before adding manifests.

L01a - Kubernetes words with Tinys examples

Section titled “L01a - Kubernetes words with Tinys examples”

The primer lives in Kubernetes primer on the Tinys.

It covers:

  • reading kubectl get nodes, kubectl get pods, and Flux status output;
  • mapping containers, pods, Deployments, Services, Jobs, PVCs, and namespaces to the smoke workload that ran on the Tinys;
  • explaining control plane, k3s server, etcd, HA, and quorum with the exact three-node eigil/ingvild/dicte topology;
  • explaining GitRepository, Kustomization, and reconciliation from the fos-workbench GitOps source;
  • connecting snapshots, Azure migration, and power posture back to the same cluster vocabulary.

The second lesson lives in tutorial/deployment/lesson-02-app-contract-service.md.

It covers:

  • building the existing serving image from deploy/azure/containers/serving.Dockerfile;
  • pushing that image through a local localhost:5000 registry so k3s can pull it without direct containerd access;
  • applying tutorial/deployment/k8s/app-contract.yaml;
  • verifying the /healthz probe through a ClusterIP Service and kubectl port-forward;
  • naming why /articles can be empty until the next lesson mounts or seeds the raw Parquet data path.

The host-data mount lesson lives in tutorial/deployment/lesson-03-host-data-mount.md.

It covers:

  • why /healthz can pass while /articles returns an empty list;
  • replacing the pod’s temporary emptyDir with a local hostPath mount;
  • showing the repo’s data/raw/ebnerd/... Parquet files inside the pod at /app/data/raw/ebnerd/...;
  • calling /articles?limit=3 through the Kubernetes Service and seeing real rows.

The PVC persistence lesson lives in tutorial/deployment/lesson-03-data-persistence.md.

It then covers:

  • mounting the same DuckDB-readable data/ path at /app/data;
  • keeping SERVING_RAW_ROOT=/app/data/raw for the app contract;
  • using a local k3s PersistentVolumeClaim backed by the Local Path Provisioner;
  • distinguishing local rehearsal storage from the Azure ADLS Gen2 target;
  • stopping routine verification at a client dry-run with no live persistent-volume mutation.

The fourth lesson lives in tutorial/deployment/lesson-04-dlt-dbt-batch-job.md.

It covers:

  • running the existing serving.dlt_pipeline publisher loads as a Kubernetes Job;
  • running dbt build through python -m dataset_layout so the canonical raw Parquet globs still come from the storage module;
  • mounting the existing app-contract-data PVC at /app/data;
  • naming the Job’s inputs, outputs, persistence boundary, and failure inspection commands;
  • keeping routine verification to a client dry-run with no live cluster mutation.

The fifth lesson lives in tutorial/deployment/lesson-05-flux-gitops-portability.md.

It covers:

  • installing Flux only after k3s cluster smoke tests pass;
  • moving durable Kubernetes changes from one-off kubectl apply into Git;
  • separating Ansible’s node/bootstrap responsibility from Flux’s in-cluster reconciliation responsibility;
  • sketching the clusters/tinys, clusters/azure-aks, infrastructure, and apps GitOps layout;
  • mapping the Tinys path to Azure reliability services, Container Apps, AKS + Flux, and optional Azure Arc;
  • leaving real secret handling for a later explicit decision.

The sixth lesson lives in tutorial/deployment/lesson-06-tinys-power-idle.md.

It covers:

  • measuring wall power before tuning;
  • keeping workloads scale-to-idle through GitOps;
  • installing measurement tools without applying risky power changes;
  • avoiding casual powertop --auto-tune, NIC power saving, and suspend policies until recovery drills are understood;
  • using one-node tests before rolling host tuning across all three Tinys.
  • Compare the k3s mapping with the Azure target from ADR-0028 and the Flux portability layer from ADR-0034.