Deploy Prisma with MongoDB to Kubernetes
By: Grigor Khachatryan
Tags: Mongodb, JavaScript, Prisma, Docker, Kubernetes

Deploy Prisma to Kubernetes

Prerequisites

If you haven’t done that before, you need to fulfill the following prerequisites before you can deploy a Prisma cluster on Kubernetes. You need:

a running Kubernetes cluster (e.g. on the Google Cloud Platform)

a local version of kubectl which is configured to communicate with your running Kubernetes cluster

You can go ahead now and create a new directory on your local machine — call it prisma-k8s . This will be the reference directory for our journey.

Creating a separate namespace

As you may know, Kubernetes comes with a primitive called namespace . This allows you to group your workload logically. Before applying the actual namespace on the cluster, we have to write the definition file for it. Inside our project directory, create a file called namespace.yml with the following content:

This definition will lead to a new namespace, called prisma . Now, with the help of kubectl , you can apply the namespace by executing:

kubectl apply -f Namespace.ymal

Afterwards, you can perform a kubectl get namespaces in order to check if the actual namespace has been created. You should see the following on a fresh Kubernetes cluster:

❯ kubectl get namespaces

NAME STATUS AGE

default Active 2d

kube-public Active 2d

kube-system Active 2d

prisma Active 10s

MongoDB

Prisma supports a good range of different database systems. Although we use MongoDB for this tutorial, the steps can be easily adopted for a different database system, like PostgreSQL, MySQL etc.

You can setup MongoDB using this tutorial and skip MongoDB section:

or you can go step by step and setup MongoDB as is described in this section.

Disk provisioning

Now that we have a valid namespace in which we can rage, it is time to deploy MongoDB. Kubernetes separates between stateless and stateful deployments. A database is by nature a stateful deployment and needs a disk to actually store the data. So how do we tell our cluster to create a new disk on the cluster? By using a PersistentVolumeClaim:

Here we request a disk with a storage capacity of 10 GB. You can apply this PVC by executing:

Now where we have our disk for the database, it is time to create the actual deployment definition of our MongoDB instance. A short reminder: Kubernetes comes with the primitives of Pods and ReplicationControllers .

A Pod is like a "virtual machine" in which a containerized application runs. It gets an own internal IP address and (if configured) disks attached to it. The ReplicationController is responsible for scheduling your Pod on cluster nodes and ensuring that they are running and scaled as configured.

In older releases of Kubernetes it was necessary to configure those separately. In recent versions, there is a new definition resource, called Deployment . In such a configuration you define what kind of container image you want to use, how much replicas should be run and, in our case, which disk should be mounted.

The deployment definition of our MongoDB database looks like:

To actually apply that definition, execute:

You can check if the actual Pod has been scheduled by executing:

kubectl get pods --namespace prisma



NAME READY STATUS RESTARTS AGE

mongo-3199294884-93db4 1/1 Running 0 1m

Deploying the Service

Before diving into this section, here’s a short recap.

Our MongoDB database pod is now running and available within the cluster internally. Remember, Kubernetes assigns a local IP address to the Pod so that another application could access the database.

Now, imagine a scenario in which your database crashes. The cluster management system will take care of that situation and schedules the Pod again. In this case, Kubernetes will assign a different IP address which results in crashes of your applications that are communicating with the database.

To avoid such a situation, the cluster manager provides an internal DNS resolution mechanism. You have to use a different primitive, called Service , to benefit from this. A service is an internal load balancer that is reachable via the service name . Its task is to forward the traffic to your Pod(s) and make it reachable across the cluster by its name.

A service definition for our MongoDB database would look like:

The definition would create an internal load balancer with the name mongo . The service is then reachable by this name within the prisma namespace. A little explanation about the spec section:

ports: Here you map the service port to the actual container port. In this case the mapping is 27017 to 27017 .

to . selector: Kind of a query. The load balancer identifies Pods by selecting the ones with the specified labels.

After creating this file, you can apply it with:

To verify that the service is up, execute:

kubectl get services --namespace prisma



NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

mongo ClusterIP 10.6.231.114 <none> 27107/TCP 2m

Prisma

Okay, fair enough, the database is deployed. Next up: Deploying the actual Prisma server which is responsible for serving as an endpoint for the Prisma CLI.

This application communicates with the already deployed database service and uses it as the storage backend. Therefore, the Prisma server is a stateless application because it doesn't need any additional disk storage.

Deploying the ConfigMap

The Prisma server needs some configuration, like the database connection information and which connector Prisma should use. We will deploy this configuration as a so-called ConfigMap which acts like an ordinary configuration file, but whose content can be injected into an environment variable:

After defining the file, you can apply it via:

kubectl apply -f ConfigMap.prsima.yaml

Deploying the Pod

Deploying the actual Prisma server to run in a Pod is pretty straightforward. First of all you have to define the deployment definition:

This configuration looks similar to the deployment configuration of the MongoDB database. We tell Kubernetes that it should schedule one replica of the server and define the environment variable by using the previously deployed ConfigMap .

Afterwards, we are ready to apply that deployment definition:

kubectl apply -f Deployment.prisma.yaml

As in the previous sections: In order to check that the Prisma server has been scheduled on the Kubernetes cluster, execute:

kubectl get pods --namespace prisma NAME READY STATUS RESTARTS AGE

mongo-3199294884-93db4 1/1 Running 0 20m

prisma-1733176504-zlphg 1/1 Running 0 2m

Yay! The Prisma server is running! Off to our next and last step:

Deploying the Service

Okay, cool, the database Pod is running and has an internal load balancer in front of it, the Prisma server Pod is also running, but is missing the load balancer a.k.a. Service . Let's fix that:

Apply it via:

kubectl apply -f Service.prisma.yaml

Okay, done! The Prisma server is now reachable within the Kubernetes cluster via its name prisma .

That’s all. Prisma is running on Kubernetes!

The last step is to configure your local Prisma CLI so that you can communicate with the instance on the Kubernetes Cluster.

The upcoming last step is also necessary if you want to integrate prisma deploy into your CI/CD process.

Configuration of the Prisma CLI

The Prisma server is running on the Kubernetes cluster and has an internal load balancer. This is a sane security default, because you won’t expose the Prisma server to the public directly. Instead, you would develop a GraphQL API and deploy it to the Kubernetes cluster as well.

You may ask: “Okay, but how do I execute prisma deploy in order to populate my data model when I'm not able to communicate with the Prisma server directly?". That is indeed a very good question! kubectl comes with a mechanism that allows forwarding a local port to an application that lives on the Kubernetes cluster.

So every time you want to communicate with your Prisma server on the Kubernetes cluster, you have to perform the following steps:

kubectl get pods --namespace prisma to identify the pod name kubectl port-forward --namespace prisma <the-pod-name> 4467:4466 – This will forward from 127.0.0.1:4467 -> kubernetes-cluster:4466

The Prisma server is now reachable via http://localhost:4467 . This is the actual endpoint you have to specify in your prisma.yml . So when your service should have the name myservice and you want to deploy to stage production , your endpoint URL would look like: http://localhost:4467/myservice/production .

An example prisma.yml could look like:

endpoint: http://localhost:4467/myservice/production

datamodel: datamodel.graphql

With this in place, you can deploy the Prisma service via the Prisma CLI ( prisma deploy ) as long as your port forwarding to the cluster is active.

OR

you can create the migration contatiner which will include the right datamodel adn run it in you kubernetes env. (comming soon).

Like to learn?

Follow me on twitter where I post all about the latest and greatest AI, DevOps, VR/AR, Technology, and Science! Connect with me on LinkedIn too!