Skip to content

Latest commit

 

History

History
127 lines (102 loc) · 4.11 KB

File metadata and controls

127 lines (102 loc) · 4.11 KB

Development

Toolchain

  • Rust 1.85+ (stable). MSRV is 1.85 due to edition = "2024" and cargo resolver-3.
  • A reachable Kubernetes cluster (kind, k3s, Docker Desktop, real cluster).
  • kubectl configured against it.

Layout

inferenced-operator/
├── Cargo.toml
├── Dockerfile                  # multi-stage, distroless
├── README.md
├── LICENSE
├── crds/                       # raw CRD YAML (generated; checked in)
│   ├── inferencehost.yaml
│   └── inferencemodel.yaml
├── examples/
│   ├── host-amelia.yaml
│   └── model-qwen-3b.yaml
├── charts/inferenced-operator/ # Helm chart that installs everything
│   ├── Chart.yaml
│   ├── values.yaml
│   ├── crds/                   # copied from ../../crds at chart-package time
│   └── templates/
│       ├── _helpers.tpl
│       ├── deployment.yaml
│       ├── rbac.yaml
│       └── serviceaccount.yaml
├── docs/
│   ├── architecture.md
│   ├── installation.md
│   ├── crds.md
│   ├── development.md          # ← you are here
│   └── troubleshooting.md
└── src/
    ├── main.rs                 # entry, --print-crds, controller wiring
    ├── crds.rs                 # CRD types, derive(CustomResource)
    ├── error.rs                # operator-wide Error
    ├── bridge_client.rs        # HTTP client to the inferenced daemon
    └── reconcile/
        ├── mod.rs              # Context shared by both controllers
        ├── host.rs             # InferenceHost reconciler
        └── model.rs            # InferenceModel reconciler

Run locally against a cluster

The fastest dev loop is to run the operator out-of-cluster against your current kubectl context:

cargo run

# In another shell:
kubectl apply -f crds/
kubectl create namespace inferenced
kubectl apply -f examples/host-amelia.yaml
kubectl apply -f examples/model-qwen-3b.yaml
kubectl get im qwen-3b -w

The operator picks up KUBECONFIG (or ~/.kube/config) like any other client. No image build required.

RUST_LOG=inferenced_operator=debug,kube=info cargo run for verbose reconcile output.

Regenerate CRD YAML

Whenever you change src/crds.rs:

cargo run -- --print-crds > crds/_all.yaml
# Then split _all.yaml at the `---` separator into the two per-kind files.
# The Helm chart auto-picks up files in charts/inferenced-operator/crds/.
cp crds/inferencehost.yaml crds/inferencemodel.yaml charts/inferenced-operator/crds/

Build the container image

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t ghcr.io/dormlab/inferenced-operator:dev \
  --push .

The Dockerfile uses the distroless/cc-debian12:nonroot base, ~25 MB final image.

Tests

cargo test

Add new unit tests beside the code under mod tests. Integration tests that need a real cluster live in tests/ (none yet).

Project conventions

  • error::Error is the only error type crossing reconcile boundaries. Map every external error into an Error::* variant or Error::Other(String).
  • No global mutable state. All shared state lives on reconcile::Context.
  • Reconcilers must be idempotent. Use kube::api::Patch::Apply with force(true) server-side-apply, never Replace.
  • Owner references. Every secondary resource the operator creates gets an OwnerReference to its parent CRD so deletion cascades cleanly.
  • #[serde(rename_all = "camelCase")] on every CRD struct for K8s-conventional field names.

Contributing

Pull requests welcome. For larger changes, open an issue first to discuss direction. By contributing you agree to license your work under the project's MIT license.

A handful of targeted small wins:

  • Add kube::runtime::leader_election so >1 replica is safe.
  • Add Prometheus metrics (the dependency is already in Cargo.toml).
  • Add an admission webhook for spec validation.
  • Add structured Event emission on reconcile errors.
  • Watch InferenceHost from the model reconciler for instant placement on host changes.