Skip to content
Install

Install

Practical commands for running kleym-operator, deploying it, testing it, and previewing the documentation site locally. CLI usage is documented separately in CLI Usage.

Prerequisites

  • Go 1.26+
  • Docker
  • kubectl
  • Access to a Kubernetes cluster
  • Gateway API Inference Extension (GAIE) CRD for InferencePool, plus InferenceObjective when using PerObjective
  • SPIFFE Runtime Environment (SPIRE) Controller Manager with the ClusterSPIFFEID CRD
  • Docker for Kind-backed e2e; the e2e targets bootstrap kind and Chainsaw under bin/
  • Hugo Extended 0.146+ for docs preview/build

The repository bootstraps local tool binaries under bin/ through make targets, so you do not need to install controller-gen, kustomize, setup-envtest, golangci-lint, kind, or Chainsaw globally.

For identity-system background, see SPIFFE overview and SPIRE concepts.

Run Locally

Run the controller against your current kubeconfig:

make run

make run supplies --trust-domain=kleym.sonda.red by default. Override the operator identity settings when your local SPIRE install uses different values:

make run TRUST_DOMAIN=example.org CLUSTERSPIFFEID_CLASS_NAME=kleym

Build the operator binary:

make build-operator

Deploy

Install the CRD into the current cluster:

make install

Deploy the controller image:

make deploy IMG=<registry>/kleym-operator:<tag>

Render the local consolidated installer manifest into dist/install.yaml:

make build-installer

dist/install.yaml is generated output and is not committed to the repository.

For Kustomize, Flux, or Argo CD installs, use the root deployment/ kustomization described below.

GitOps Install

Use the root deployment/ kustomization when Flux or Argo CD should manage the kleym operator.

The path installs the kleym CRD, namespace, RBAC, controller Deployment, and metrics Service. It does not install external dependency CRDs: Gateway API Inference Extension CRDs and SPIRE Controller Manager, including the ClusterSPIFFEID CRD, must already be installed.

Install the latest operator manifests directly from main:

kubectl apply -k https://github.com/sonda-red/kleym//deployment?ref=main

For release-pinned installs, pin both the manifest ref and controller image tag with a Kustomize overlay:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/sonda-red/kleym//deployment?ref=vX.Y.Z
images:
- name: ghcr.io/sonda-red/kleym-operator
  newTag: vX.Y.Z

Apply that overlay:

kubectl apply -k .

Flux example using latest manifests from main:

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: kleym
  namespace: flux-system
spec:
  interval: 1h
  url: https://github.com/sonda-red/kleym
  ref:
    branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: kleym
  namespace: flux-system
spec:
  interval: 1h
  path: ./deployment
  prune: false
  sourceRef:
    kind: GitRepository
    name: kleym
  wait: true

Argo CD example using latest manifests from main:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kleym
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/sonda-red/kleym.git
    targetRevision: main
    path: deployment
  destination:
    server: https://kubernetes.default.svc
    namespace: kleym-system
  syncPolicy:
    automated:
      prune: false
      selfHeal: true

The examples leave pruning disabled because deleting a CRD also deletes its custom resources.

Pinned Flux example using release manifests and a matching controller image tag:

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: kleym
  namespace: flux-system
spec:
  interval: 1h
  url: https://github.com/sonda-red/kleym
  ref:
    tag: vX.Y.Z
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: kleym
  namespace: flux-system
spec:
  interval: 1h
  path: ./deployment
  prune: false
  sourceRef:
    kind: GitRepository
    name: kleym
  images:
  - name: ghcr.io/sonda-red/kleym-operator
    newTag: vX.Y.Z
  wait: true

Pinned Argo CD example using release manifests and a matching controller image tag:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kleym
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/sonda-red/kleym.git
    targetRevision: vX.Y.Z
    path: deployment
    kustomize:
      images:
      - ghcr.io/sonda-red/kleym-operator:vX.Y.Z
  destination:
    server: https://kubernetes.default.svc
    namespace: kleym-system
  syncPolicy:
    automated:
      prune: false
      selfHeal: true

A raw commit SHA pins manifest content at that commit. Use an image override when the controller image must also be pinned.

Helm is not needed for this installation path. The manifests are static, GitOps tools can pin the manifest ref and image tag directly, and Flux or Argo CD can consume the kustomization without a chart. A chart should be revisited when kleym needs a larger templated install surface for operator-specific options.

Operator Metrics

kleym-operator publishes Kleym-owned Prometheus metrics on the existing controller-runtime /metrics endpoint. The endpoint remains the authenticated controller-runtime metrics surface; Kleym status conditions and events remain the per-object debugging surface for a specific InferenceIdentityBinding.

To enable the shipped ServiceMonitor from a remote GitOps overlay, add config/prometheus next to the default install and set the install namespace so the ServiceMonitor and metrics Service are rendered together:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: kleym-system
resources:
- github.com/sonda-red/kleym/config/default?ref=main
- github.com/sonda-red/kleym/config/prometheus?ref=main

If you build from a local checkout, you can instead uncomment the ../prometheus entry in config/default/kustomization.yaml and keep the metrics deployment patch enabled.

Prometheus still needs RBAC to read the authenticated metrics endpoint. The default install publishes the kleym-metrics-reader ClusterRole, so bind your Prometheus service account to it:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus-kleym-metrics-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kleym-metrics-reader
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: monitoring

The public Kleym metrics are:

  • kleym_identity_binding_outcomes_total{condition,reason,mode}: counter of terminal reconcile outcomes.
  • kleym_identity_bindings{condition,reason,mode}: scrape-time gauge of current binding outcomes aggregated from status.

Test

Run controller and API tests:

make test

Run lint:

make lint

Run the Kind-backed Chainsaw reconciliation check (primary e2e path):

make test-e2e-chainsaw

Keep the Kind cluster for faster local iteration:

make test-e2e-chainsaw KEEP_KIND=true

Use the smallest command set that proves the change. See contributing for the repository validation expectations.

Preview Docs

Serve the Hextra docs site locally:

make docs-serve

Build the static site locally:

make docs-build

Override the port if you need something other than 1313:

make docs-serve DOCS_PORT=8080
Last updated on