CRDs
The operator is bundled with the Custom Resource Definitions (CRDs) and cannot be deployed separately. Updating the operator will automatically update the respective CRDs.
TypesenseCluster
Typesense Kubernetes Operator is controlling the lifecycle of multiple Typesense instances in the same Kubernetes cluster by introducing TypesenseCluster, a new Custom Resource Definition:
TypesenseClusterSpec
| Name | Description | Optional | Default |
|---|---|---|---|
| image | Typesense image | ||
| imagePullSecrets | reference to the private registry authentication Secret | X | |
| adminApiKey | reference to the bootstrap Secret | X | |
| replicas | size of the cluster (allowed 1, 3, 5 or 7) | X | 3 |
| apiPort | REST/API port | X | 8108 |
| peeringPort | peering port | X | 8107 |
| resetPeersOnError | automatic reset of peers on error | X | true |
| enableCors | enables CORS | X | false |
| corsDomains | comma separated list of domains allowed for CORS | X | |
| resources | resources (request & limit) | X | 1000m/100m 512Mi/256Mi |
| healthProbeTimeoutInMilliseconds | timeout for waiting on the health endpoint response | X | 500 |
| affinity | group of affinity scheduling rules | X | |
| nodeSelector | node selection constraint | X | |
| tolerations | schedule pods with matching taints | X | |
| additionalServerConfiguration | a reference to a ConfigMap holding extra configuration | X | |
| statefulSetAnnotations | user-defined annotations | X | |
| podAnnotations | user-defined annotations | X | |
| podsInheritStatefulSetAnnotations | propagate all StatefulSet annotations to Pods | X | false |
| serviceAnnotations | user-defined annotations | X | |
| storage | check StorageSpec below | ||
| ingress | check IngressSpec below | X | |
| httpRoutes | array of HttpRouteSpec; check below | X | |
| scrapers | array of DocSearchScraperSpec; check below | X | |
| metrics | check MetricsSpec below | X | |
| healthcheck | check HealthCheckSpec below | X | |
| topologySpreadConstraints | how to spread a group of pods across topology domains | X | |
| priorityClassName | reference to a pod priority and preemption class | X | |
| securityContext | check SecurityContextSpec below | X | |
| ignoreAnnotationsFromExternalMutations | annotations to ignore when calculating hash (e.g. cattle.io/) | X | |
| incrementalQuorumRecovery | add nodes gradually to the StatefulSet while recovering | X | false |
- Add additional Typesense server configuration variables in a
ConfigMap, usingadditionalServerConfigurationas described in: https://typesense.org/docs/28.0/api/server-configuration.html#using-environment-variables. - Any Typesense server configuration variable that is defined in
TypesenseClusterSpecis overriding any additional reference of the same variable inadditionalServerConfiguration. You can find an example of providing an additionalConfigMapin: config/samples/ts_v1alpha1_typesensecluster_kind.yaml. - In heavy datasets is advised to set
incrementalQuorumRecoverytotrueand let the controller reconstruct the quorum node by node. That will smooth the leader election process while new nodes are joining but it will make recovery process last longer.
StorageSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| size | size of the underlying PV | X | 100Mi |
| storageClassName | StorageClass to be used | standard | |
| accessMode | access mode for underlying PV | ReadWriteOnce | |
| annotations | user-defined annotations | X |
As of v0.3.6, storage accessMode is introduced that supports ReadWriteOnce and ReadWriteMany.
-
If you are running on Open Telekom Cloud, you can take advantage of the additional annotations field
csi.storage.k8s.io/fstypethat controls how an S3 bucket is mounted into a Kubernetes pod. Usingcsi.storage.k8s.io/fstype: s3fsmounts an SFS Turbo, Scalable File System bucket using the S3-compatible API, which is useful when you want simple “filesystem-like” access but are okay with object-storage semantics that may not fully match POSIX behavior. Using the annotationcsi.storage.k8s.io/fstype: obsfsmounts the bucket using the native OBS filesystem driver and is generally the more “OBS-native” approach; it avoids some S3FS-specific limitations and is often preferred when you want better integration with OBS. One big advantage of using these annotations is that the respective S3 buckets can be provisioned dynamically by the CSI. -
If you are running on-premises clusters with democratic-csi installed as the CSI, you can use now use
accessMode: ReadWriteManyto provision NFS-backed persistent volumes to support Typesense data volumes. -
If you run on-premises clusters with custom S3-compatible storage (e.g., RustFS, SeaweedFS, JuiceFS, Ceph, CubeFS), you can now use
accessMode: ReadWriteManytogether with thejuicefs-csi-driverto mount S3 buckets as persistent volumes in pods as Typesense data volumes. -
If you run on-premises clusters or in any cloud provider, you can now attach any remote S3-compatible storage (e.g., AWS S3, Azure Blob Storage etc.), using
accessMode: ReadWriteManytogether with thejuicefs-csi-driverto mount S3 buckets as persistent volumes in pods as Typesense data volumes.
For more information about installing and configuring JuiceFS and JuiceFS CSI Driver for TyKO check the examples.
IngressSpec (deprecated)
As of v0.4.0-rc.1, following the events triggered by the Ingress NGINX retirement in March 2026 (see here the announcement of the Kubernetes SIG Network and the Security Response Committee), Ingress API support is deprecated in favor of the more flexible and powerful Gateway API.
Although the operator will continue to support Ingress resources for the foreseeable future without any breaking changes,
no new features or maintainance updates will be made to the Ingress implementation.
For that reason, it is recommended to transition to use HttpRoute for new deployments or when updating existing ones.
Additionally, bear in mind that the Kubernetes project itself recommends the following regarding Ingress API (exerpt from the Kubernetes documentation/Ingress):
"The Kubernetes project recommends using Gateway instead of Ingress. The Ingress API has been frozen.
This means that:
-The Ingress API is generally available, and is subject to the stability guarantees for generally available APIs. The Kubernetes project has no plans to remove Ingress from Kubernetes.
-The Ingress API is no longer being developed, and will have no further changes or updates made to it."
| Name | Description | Optional | Default |
|---|---|---|---|
| image | nginx image to use | X | nginx:alpine |
| referer | FQDN allowed to access reverse proxy | X | empty or the value of spec.corsDomains if set |
| HttpDirectives | nginx proxy HttpDirectives | X | |
| serverDirectives | nginx proxy ServerDirectives | X | |
| locationDirectives | nginx proxy LocationDirectives | X | |
| host | Ingress host | ||
| path | HTTP Ingress path | X | / |
| pathType | interpretation of the path matching | X | ImplementationSpecific |
| clusterIssuer | cert-manager ClusterIssuer | X | |
| tlsSecretName | TLS Secret name to use | X | |
| ingressClassName | Ingress to be used | ||
| serviceAnnotations | user-defined annotations | X | |
| annotations | user-defined annotations | X | |
| resources | resources (request & limit) | X | 150m/100m 64Mi/32Mi |
| readOnlyRootFilesystem | check ReadOnlyRootFilesystemSpec below | X |
ReadOnlyRootFilesystemSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| securityContext | security conf for the container | X | SecurityContext{ReadOnlyRootFilesystem: true} |
| volumes | additional volumes | X | |
| volumeMounts | additional mounts in the container | X |
1️⃣ This feature makes use of the existence of cert-manager in the cluster, but does not actively enforce it with an error. If no clusterIssuer is specified a valid certificate must be stored in a secret and the secret name must be provided in the tlsSecretName config.
If you are targeting Open Telekom Cloud, you might be interested in provisioning additionally the designated DNS solver webhook for Open Telekom Cloud. You can find it here.
2️⃣ Although in official Typesense documentation under Production Best Practices -> Configuration is stated:
"Typesense comes built-in with a high performance HTTP server that is used by likes of Fastly in their edge servers at scale. So Typesense can be directly exposed to incoming public-facing internet traffic, without the need to place it behind another web server like Nginx/Apache or your backend API."
It is highly recommended, from this operator's perspective, to always expose Typesense behind a reverse proxy (using the referer option).
HttpRouteSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| name | name of the route | ||
| enabled | enable this route | X | true |
| parentRef | reference to the parent Gateway; check GatewayParentRef below | ||
| hostnames | array of hostnames to match for this route | ||
| path | path to match for this route | X | / |
| pathType | interpretation of the path matching | X | ImplementationSpecific |
| labels | user-defined labels | X | |
| annotations | user-defined annotations | X | |
| referenceGrant | enable cross-namespace reference to the parent Gateway | X | false |
1️⃣ The operator does not configure or manage Gateway(s). A Gateway setup is intentionally left out of scope because it is highly platform-specific and tightly coupled to cluster networking, security,
and organizational policies. All required Gateway resources must be provisioned and maintained in advance by your platform or cluster engineering team.
To expose your Typesense cluster via a Gateway, certain prerequisites must already be present in your Kubernetes cluster:
🚧 You will need:
- a gateway controller present (example is using Traefik Gateway Controller).
- a
GatewayClassand aGatewayconfigured. - cert-manager to be present that takes care of the TLS certiicates.
2️⃣ Activating the HttpRoute confiruration will automatically deactivate/ignore the Ingress one if it exists, but the Ingress resource which might be present in the cluster
will not be automatically deleted. It can be safely deleted manually, if not needed anymore.
GatewayParentRef
| Name | Description | Optional | Default |
|---|---|---|---|
| name | name of the parent Gateway | ||
| namespace | namespace of the parent Gateway | ||
| sectionName | section of the parent Gateway to route to (e.g. "websecure") | X |
DocSearchScraperSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| name | name of the scraper | ||
| image | container image to use | ||
| config | config to use | ||
| schedule | cron expression; no timezone; no seconds | ||
| authConfiguration | a reference to a Secret holding auth configuration | X |
If you need to scrape a target that requires authentication, you can add the authentication configuration as environment variables via authConfiguration. In order to see which options are supported currently out of the box, consult the official documentation: https://typesense.org/docs/guide/docsearch.html#authentication
As of Typesense version 30.0, breaking changes were introduced in the API for transferring the synonyms and curation sets that created a compatibility issue with DocSearch Scraper version prior to 0.12.0.rc14. For that reason,
it is advised to upgrade Typesense and DocSearch Scraper simultaneously if you are upgrading to Typesense 30.x+ from earlier major versions.
Compatibility Matrix:
| Typesense | DocSearch Scraper |
|---|---|
| 29.x | 0.11.0 |
| 30.x+ | 0.12.0.rc14+ |
You can follow the related thread in the Typesense Slack channel here for more information.
MetricsSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| image | container image to use | X | akyriako78/typesense-prometheus-exporter:0.1.9 |
| release | Prometheus release to become a target of | ||
| interval | interval in seconds between two scrapes | X | 15 |
| resources | resources (request & limit) | X | 100m/100m 64Mi/32Mi |
If you've provisioned Prometheus via kube-prometheus-stack, you can find the corresponding release value of your Prometheus instance by checking the labels of the Prometheus operator pod e.g:
kubectl describe pod {kube-prometheus-stack-operator-pod} -n {kube-prometheus-stack-namespace}
name: promstack-kube-prometheus-operator-755485dc68-dmkw2
Namespace: monitoring
[...]
Labels: app=kube-prometheus-stack-operator
app.kubernetes.io/component=prometheus-operator
app.kubernetes.io/instance=promstack
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=kube-prometheus-stack-prometheus-operator
app.kubernetes.io/part-of=kube-prometheus-stack
app.kubernetes.io/version=67.8.0
chart=kube-prometheus-stack-67.8.0
heritage=Helm
pod-template-hash=755485dc68
release=promstack
[...]
HealthCheckSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| image | container image to use | X | akyriako78/typesense-healthcheck:0.1.8 |
| resources | resources (request & limit) | X | 100m/100m 64Mi/32Mi |
SecurityContextSpec (optional)
| Name | Description | Optional | Default |
|---|---|---|---|
| pod | pod security contenxt | X | check specs |
| typesense | container security contenxt | X | |
| healthcheck | container security contenxt | X | |
| metric | container security contenxt | X |
TypesenseClusterStatus
| Name | Description |
|---|---|
| phase | Typesense Cluster/Controller Operational Phase |
| conditions | metav1.Conditions related to the outcome of the reconciliation (see table below) |
Conditions Summary
| Condition | Value | Reason | Description |
|---|---|---|---|
| ConditionReady | true | QuorumReady | Cluster is Operational |
| false | QuorumNotReady | Cluster is not Operational | |
| false | QuorumNotReadyWaitATerm | Cluster is not Operational; Waits a Term | |
| false | QuorumPurged | Cluster is not Operational; Recreating all Pods | |
| false | QuorumDowngraded | Cluster is not Operational; Scheduled to Single-Instance | |
| false | QuorumUpgraded | Cluster is Operational; Scheduled to Original Size | |
| false | QuorumNeedsAttentionXXX | Cluster is not Operational; Administrative Action Required |