Deploy Cortex on Kubernetes#
Deploy Cortex on a Kubernetes cluster using the StrangeBee Helm chart repository.
Dependency image
The default Elasticsearch image used by the dependency Helm chart comes from Bitnami.
Following Bitnami decision to stop maintaining multiple freely available image versions, StrangeBee Helm charts now reference the bitnamilegacy
repository for Elasticsearch. Bitnami latest public images ship Elasticsearch 9, which isn't compatible with Cortex.
This has important consequences:
- This legacy image won't receive security updates and will become increasingly vulnerable over time. You may continue to use it at your own risk, but it isn't production-ready.
- You can pay Bitnami for access to updated images and configure the Helm chart to reference them.
- Alternatively, you can deactivate the dependency Helm charts and bring your own Elasticsearch deployment.
Architecture overview#
The default deployment includes:
- Cortex application pods
- A two-node Elasticsearch cluster for search indexing
- Shared storage for analyzer job data
Infrastructure requirements#
- Kubernetes cluster v1.23.0 or later
- Helm v3.8.0 or later
- Minimum resources per node: see Cortex Installation System Requirements
- StorageClass supporting
ReadWriteMany
access mode - Network policies allowing inter-pod communication
Step 1: Ensure all users can access files on the shared filesystem#
Configuration errors
Improperly configured shared filesystems can cause errors when running jobs with Cortex.
Why a shared filesystem
When running on Kubernetes, Cortex launches a new pod for each analyzer or responder execution. After the job completes and Cortex retrieves the result, the pod is terminated. Without a shared filesystem accessible by both the Cortex pod and these analyzer and responder pods, they can't access the data they need to operate, causing the jobs to fail.
Kubernetes supports several methods for sharing filesystems between pods, including:
- PV using an NFS server
- Dedicated storage solutions like Longhorn or Rook
This guide focuses on configuring a PV using an NFS server, with an example for AWS Elastic File System (EFS).
At runtime, Cortex and its jobs run on different pods and may use different user IDs (UIDs) and group IDs (GIDs):
- Cortex defaults to uid:gid
1001:1001
. - Analyzers may use different uid:gid, such as
1000:1000
or0:0
if running as root.
To prevent permission errors when reading or writing files on the shared filesystem, configure the NFS server with the all_squash
parameter. This ensures all filesystem operations use uid:gid 65534:65534
, regardless of the user's actual UID and GID.
Step 2: Deploy Cortex#
Deploy with default configuration#
Service account
A service account (SA) allows a pod to authenticate and interact with the Kubernetes API, enabling it to perform specific actions within the cluster. When deploying Cortex, a dedicated SA is essential for creating and managing Kubernetes jobs that run analyzers and responders. Without proper configuration, Cortex can't execute these jobs.
Using an existing PV
The cortex
Helm Chart can operate without creating a new PV, provided that an existing PV—created by the cluster administrator—matches the PVC configuration specified in the Helm Chart.
Use the cortex
Helm chart to automate the creation of the PV, PVC, and SA during deployment.
The default configuration is designed for development environments and requires modifications for production use. See Production configuration for required adjustments.
-
Add the StrangeBee Helm repository
helm repo add strangebee https://strangebeecorp.github.io/helm-charts
-
Update your local Helm repositories
helm repo update
-
Create a release using the
cortex
Helm charthelm install <release_name> strangebee/cortex
First start
At first start, you must access the Cortex web page to update the Elasticsearch database.
For more options, see the Helm documentation for installation.
Dependency
The cortex
Helm chart relies on the Bitnami Elasticsearch Stack by default as the search index.
Upgrades
To upgrade your release to the latest version of the cortex
Helm chart, run:
helm upgrade <release_name> strangebee/cortex
Production configuration#
The default cortex
Helm chart bundles all dependencies for quick deployment but uses development-oriented configurations. Production deployments require adjustments to Cortex and its dependencies for security, performance, and reliability.
Use the following command to view all available configuration options for the cortex
Helm chart:
helm show values strangebee/cortex
For more information on customization, see the dedicated Helm documentation. You can also review the available options for the dependency.
Storage configuration#
Shared storage requirement
Cortex requires a shared PVC with ReadWriteMany
access mode to allow multiple pods to read and write data simultaneously—essential for job inputs and outputs.
By default, this chart attempts to create such a PVC using your cluster’s default StorageClass. Ensure this StorageClass supports ReadWriteMany
to avoid deployment issues or target a StorageClass in your cluster compatible with this access mode.
Common solutions include:
- Running an NFS server reachable from your cluster and creating a PV targeting it
- Using dedicated storage solutions like Longhorn or Rook
- Leveraging cloud provider-specific solutions like AWS EFS with the EFS CSI Driver
Also note that Cortex stores data in Elasticsearch. Regular backups are strongly recommended to prevent data loss, especially when deploying Elasticsearch on Kubernetes using the Bitnami Elasticsearch Stack.
Elasticsearch#
Elasticsearch support
Cortex currently supports only Elasticsearch version 7.x.
By default, this chart deploys an Elasticsearch cluster with two nodes, both master-eligible and general-purpose.
You can review the Bitnami Elasticsearch Helm chart for available configuration options.
Same Elasticsearch instance for both TheHive and Cortex
Using the same Elasticsearch instance for both TheHive and Cortex isn't recommended. If this setup is necessary, ensure proper connectivity and configuration for both pods and use Elasticsearch version 7.x. Be aware that sharing an Elasticsearch instance creates an interdependency that may lead to issues during updates or downtime.
Cortex server in TheHive#
See Add a Cortex Server for detailed instructions.
When TheHive and Cortex deploy in the same Kubernetes cluster, use the Cortex service DNS as the server URL.
http://cortex.<namespace>.svc:9001
Example: Deploy Cortex using AWS EFS#
Prerequisites#
Before setting up the PV for AWS EFS, complete the following steps:
- Create an Identity and Access Management (IAM) role to allow the EFS CSI driver to interact with EFS.
- Install the EFS CSI driver on your Kubernetes cluster using one of the following methods:
- EKS add-ons (recommended)
- Official Helm chart
- Create an EFS filesystem and note the associated EFS filesystem ID.
1. Create a StorageClass for EFS#
Reference example
The following manifests are based on the EFS CSI driver multiple pods example.
Create a StorageClass that references your EFS filesystem:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: efs-sc
provisioner: efs.csi.aws.com
# https://github.com/kubernetes-sigs/aws-efs-csi-driver?tab=readme-ov-file#storage-class-parameters-for-dynamic-provisioning
parameters:
provisioningMode: efs-ap # EFS access point provisioning mode
fileSystemId: fs-01234567 # Replace with your EFS filesystem ID
directoryPerms: "700" # Permissions for newly created directories
uid: 1001 # User ID to set file permissions
gid: 1001 # Group ID to set file permissions
ensureUniqueDirectory: "false" # Set to false to allow shared folder access between Cortex and job containers
subPathPattern: "${.PVC.namespace}/${.PVC.name}" # Optional subfolder structure inside the NFS filesystem
2. Create a PVC using the EFS StorageClass#
Kubernetes automatically creates a PV when defining a PVC with the EFS StorageClass.
Use the cortex
Helm chart to configure the storageClass value in the chart settings. This ensures the PVC is created automatically during deployment. To do so, open the values.yaml
file and look for the persistentVolumeClaim
section.