Kubernetes operator (kube-rs, edition 2024) that manages Meilisearch clusters and access:
- Server (v1beta1): StatefulSet + Service, generates/stores master key, waits for health.
- Index (v1alpha1): creates indexes and can provision an admin key per index.
- Key (v1alpha1): creates API keys and writes them into Secrets.
- Policy (v1alpha1): placeholder for future policy management.
- Cross-namespace networking out of the box (Helm NetworkPolicies enabled by default).
- PVC retention tuned: delete storage on Server removal, retain on scale-down.
- Duplicate key protection: adopts existing Meili keys (exact or relaxed match) and writes Secrets; prevents flooding.
- Admin key adoption for Index: reuses pre-existing admin keys when found.
- Fast teardown: deleting a Server force-cleans related Keys/Indexes CRs without Meili calls.
- Minimal, static container: MUSL-linked binary on distroless:static.
- Optional signed webhooks on resource ready events.
You can deploy via Helm charts provided in charts/ (operator and sample resources), or apply manifests under manifests/ for a minimal setup.
Optional commands (adjust to your environment):
# Generate CRDs from code (optional; Helm includes CRDs too)
cargo run --bin crdgen > manifests/crds.yaml
# Apply base manifests (RBAC/Deployment/Samples)
kubectl apply -f manifests/crds.yaml
kubectl apply -f manifests/rbac.yaml
kubectl apply -f manifests/deployment.yaml
kubectl apply -f manifests/samples.yamlHelm (recommended):
# Operator (values default to allow egress to DNS/API server and Meili namespaces)
helm upgrade --install meilisearch-operator charts/meilisearch-operator \
--namespace meilisearch-operator --create-namespace
# Samples (a Server, Index, and Keys)
helm upgrade --install meilisearch-samples charts/meilisearch-samples \
--namespace meilisearch-testing --create-namespaceNetworkPolicy note: if your API server IP/CIDR differs, set charts/meilisearch-operator value networkPolicy.egress.kubeApi.cidrs accordingly.
- Rust: stable 1.90+ (MSRV tracks CI; edition 2024)
- Lint: clippy (warnings as errors)
cargo build
cargo test
cargo clippy -- -D warningsOutside the cluster, the operator uses your kubeconfig. Set the operator namespace for cross-namespace master key copies:
export OPERATOR_NAMESPACE=meilisearch-operator
export KUBECONFIG=$HOME/.kube/config
cargo run --bin meilisearch-operatorThe Dockerfile builds a static MUSL binary and ships on gcr.io/distroless/static:nonroot.
docker build -t meilisearch-operator:dev .
# Optional: run against your kubeconfig
docker run --rm -e OPERATOR_NAMESPACE=meilisearch-operator \
-v $HOME/.kube/config:/home/nonroot/.kube/config:ro \
meilisearch-operator:dev- Server (v1beta1): image?, replicas (default 1), storage?, service_type (ClusterIP), port (7700), incompatiblePolicy (Fail|ResetData, default Fail), data.migrateOnUpdate (default true)
- Index (v1alpha1): server_ref, uid, primary_key?, delete_on_finalize (false), admin_key?
- Key (v1alpha1): server_ref, name?, description?, actions[], indexes[], expires_at?, secret_namespace, secret_name
- Policy (v1alpha1): reserved for future use
Each CRD supports an optional spec.notifications block:
notifications:
webhook_url: https://example.com/meili-events
secret_ref:
name: meili-webhook-secret
namespace: meilisearch-testing # optional; defaults to CR namespace
key: hmacKey # optional; defaults to hmacKey
events: ["ready"] # optional; empty => all
timeout_seconds: 5 # optional; default 5If secret_ref is provided, requests include X-Meili-Operator-Signature: sha256=<hex> where <hex> is HMAC-SHA256 of the JSON body using the secret value. Body shape:
{
"event": "ready",
"resource": "my-index",
"namespace": "meilisearch-testing",
"payload": {"index": "movies", "ready": true, "serverRef": "meili-a"},
"timestamp": "2025-11-09T12:34:56Z"
}Events currently emitted: ready (resource becomes Ready). Future events may include status transitions or migration phases.
Generate CRDs:
cargo run --bin crdgen > manifests/crds.yaml- Server
- Generates a 64-char master key and stores it in the Server namespace and in the operator namespace.
- Waits for
/healthbefore marking ready. - On engine/database version incompatibility:
- If
spec.data.migrateOnUpdate=trueand a previous image is known, orchestrates a dump/import migration using two Jobs (old image to dump, new image to import), then scales back up; emits Kubernetes Events for start/complete/failure. - Else if
spec.incompatiblePolicy=ResetData, scales to 0, deletes PVCs, and recreates with a fresh store. - Else, surfaces an error and leaves the pod stopped.
- If
- On deletion: removes operator copy Secret and fast-deletes related Index/Key CRs (removes their finalizers and deletes the CRs).
The operator exposes Prometheus metrics on /metrics (bind address via METRICS_ADDR, default 0.0.0.0:9090). It reports counts of Servers/Indexes/Keys and per-index document totals labeled by namespace/server/index.
-
Index
- Creates the index; optionally creates or adopts an admin key scoped to the index (
<uid>-admin). - On deletion: if the Server is not deleting and
delete_on_finalize=true, deletes the Meili index; otherwise just removes finalizer.
- Creates the index; optionally creates or adopts an admin key scoped to the index (
-
Key
- Creates Meili keys and writes them into the configured Secret (defaults name to CR name if
spec.nameis omitted). - Adoption logic: prefers existing Secret value if valid; otherwise adopts exact or relaxed matches from Meili to avoid duplicates.
- On deletion: if the Server is not deleting and we own a
uid, deletes the Meili key; otherwise just removes finalizer.
- Creates Meili keys and writes them into the configured Secret (defaults name to CR name if
- API connect refused (10.43.0.1:443 or similar): ensure the operator NetworkPolicy permits egress to the Kubernetes API (TCP/443). Set
networkPolicy.egress.kubeApi.cidrsfor your cluster. - Cross-namespace access blocked: confirm NetworkPolicies are enabled for operator egress and sample chart ingress.
- Key duplication: verify adoption paths—existing Secrets, exact match (name/description/actions/indexes/expiry), and relaxed match (actions/indexes/expiry) are in effect.
crates/meilisearch-operator/— Rust operator code (controllers, CRDs, tests)charts/meilisearch-operator/— Helm chart for the operator (RBAC, Deployment, NetworkPolicy)charts/meilisearch-samples/— Sample Server/Index/Key resourcesmanifests/— Raw manifests for CRDs, RBAC, Deployment, Samples