Deploy to Kubernetes

This guide walks you through deploying Cube.js with Kubernetes. This particular deployment makes use of a hostPath volume to mount schema files into the containers.

This is an example of a production-ready deployment, but real-world deployments can vary significantly depending on desired performance and scale. For an example of deploying with Helm or plain Kubernetes, check out the respective examples here and here.

To deploy Cube.js, we will use Deployments and Services. We'll start by creating a Redis deployment in a file called redis-deployment.yaml:

And a corresponding service for the Redis deployment in a file named redis-service.yaml:

Next, create a file called cube-api-deployment.yaml with the following contents:

The exact set of CUBEJS_DB_* environment variables depends on your database; please reference Connecting to the Database page for specific configuration instructions.

We'll also create a corresponding service for this deployment in a file called cube-api-service.yaml:

Now that we've configured our Cube.js API, let's also set up a deployment for a Refresh Worker in cube-refresh-worker-deployment.yaml:

With our Cube.js API and Refresh Worker set up, we can now begin setting up Cube Store. We will make two StatefulSets with corresponding Services; one for the router node and one for the worker nodes.

Create a new file called cubestore-router-statefulset.yaml:

And a corresponding service declaration in a file called cubestore-router-service.yaml:

With the router set up, let's move onto setting up our worker nodes. Let's create a new file called cubestore-workers-statefulset.yaml:

Next, create its corresponding service in cubestore-workers-service.yaml. By specifying clusterIP: None, you create a headless service. For this use case, a headless service is the better solution.

In production, the Cube.js API should be served over an HTTPS connection to ensure security of the data in-transit. We recommend using a reverse proxy; as an example, let's assume we're running the Kubernetes cluster on a cloud provider such as AWS or GCP. We'll also assume we already have the SSL certificate and key available on our local filesystem.

You can also use a reverse proxy to enable HTTP 2.0 and GZIP compression

First, we'll run the following to create a secret in Kubernetes:

kubectl create secret tls <NAME_OF_CERTIFICATE> --key <PATH_TO_KEY_FILE> --cert <PATH_TO_CERT_FILE>

Next, we'll create a new ingress rule in a file called ingress.yml:

For more advanced configuration, or for platforms where ingress is manually managed, please refer to the Kubernetes documentation for Ingress Controllers. You can also find an example of an Ingress Controller here.

Cube.js can be configured to use industry-standard JSON Web Key Sets for securing its API and limiting access to data. To do this, we'll define the relevant options on our Cube.js API instance and Refresh Worker deployments:

If you're using queryRewrite for access control, then you must also configure scheduledRefreshContexts so the refresh workers can correctly create pre-aggregations.

apiVersion: apps/v1
kind: Deployment
...
spec:
  template:
    ...
    spec:
      containers:
        - env:
          ...
          - name: CUBEJS_JWK_URL
            value: https://cognito-idp.<AWS_REGION>.amazonaws.com/<USER_POOL_ID>/.well-known/jwks.json
          - name: CUBEJS_JWT_AUDIENCE
            value: <APPLICATION_URL>
          - name: CUBEJS_JWT_ISSUER
            value: https://cognito-idp.<AWS_REGION>.amazonaws.com/<USER_POOL_ID>
          - name: CUBEJS_JWT_ALGS
            value: RS256
          - name: CUBEJS_JWT_CLAIMS_NAMESPACE
            value: <CLAIMS_NAMESPACE>

All Cube Store nodes, both router and workers, should only be accessible to Cube.js API instances and refresh workers. To do this with Kubernetes, we need to make sure that none of the Cube Store services are exposed in our Ingress configuration. The Cube Store services should only be accessible from other services within the cluster.

All Cube.js logs can be found through the Kubernetes CLI:

kubectl logs

Specify the tag for the Docker image available from Docker Hub (currently v0.30.75). Then update your cube-api-deployment.yaml and cube-refresh-deployment.yaml to use the new tag:

apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    ...
    spec:
      containers:
        - name: cube-api
          image: cubejs/cube:v0.30.75

Similarly, for cubestore-router-statefulset.yaml and cubestore-workers-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
...
spec:
  ...
  template:
    ...
    spec:
      containers:
        - name: cube-api
          image: cubejs/cubestore:v0.30.75

Did you find this page useful?