Featured image for Cryostat (was ContainerJFR) topics.

Cryostat is a container-native JVM application that provides a secure API for profiling and monitoring containers with JDK Flight Recorder (JFR). Among other features, Cryostat 2.0 introduced the Cryostat Operator, which is now available as part of the OperatorHub.io catalog. Using the Cryostat Operator is an easy way to install Cryostat in your existing Kubernetes environment. This article guides you through the installation procedure.

Prerequisites

To get started, you'll need a running Kubernetes cluster with cert-manager installed. The steps outlined in this article assume a local Minikube cluster.

Step 1. Install the Cryostat Operator

Start by heading over to the Cryostat Operator page on OperatorHub.io. This page contains useful information about the Cryostat Operator, such as a brief overview, prerequisites, Kubernetes custom resource definitions (CRDs), and links to more information about Cryostat. Clicking Install opens a pop-up window with the steps required to install the operator in your cluster.

As instructed, begin by installing the Operator Lifecycle Manager (OLM):

curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.19.1/install.sh | bash -s v0.19.1

Once the command finishes, verify that the install was successful:

kubectl get pods -n olm

The output should look like something like this:

​NAME                               READY  STATUS    RESTARTS  AGE
catalog-operator-84976fd7df-9w7ds  1/1    Running   0         44s
olm-operator-844b4b88f8-pvrtn      1/1    Running   0         44s
operatorhubio-catalog-5p87x        1/1    Running   0         43s
packageserver-5b7c7b9c65-7nfwc     1/1    Running   0         42s
packageserver-5b7c7b9c65-stvq8     1/1    Running   0         42s

Next, install the Cryostat Operator. The following command will deploy the operator in the my-cryostat-operator namespace:

kubectl create -f https://operatorhub.io/install/cryostat-operator.yaml

Note: See OperatorHub.io for more information about what this command does.

It will take 20 to 30 seconds for the Cryostat Operator to deploy. You can watch it happen using the following command:

kubectl get csv -n my-cryostat-operator -w

Once the operator phase reads Succeeded, you're almost ready to create a Cryostat deployment. However, you need to tackle some networking setup first.

Step 2. Configure the Ingress routing

On Kubernetes, the Cryostat Operator requires Ingress configurations for each of its services to make them available outside of the cluster. For a more detailed explanation, see the Network Options section of the Cryostat Operator's documentation. (The documentation also contains information regarding other Cryostat configuration options to suit a variety of needs.)

In order to set up the required Ingress configurations, you need an Ingress Controller running on your cluster. There are various Ingress Controller options for Kubernetes, but for this demonstration, you'll use the NGINX Ingress Controller.

The Kubernetes documentation provides helpful information on how to set up Ingress on Minikube using the NGINX Ingress Controller. Begin by enabling the Ingress Controller:

minikube addons enable ingress

Next, verify that the NGINX Ingress Controller is running as expected:

kubectl get pods -n ingress-nginx

When the output looks something like the following, with the controller pod READY, you can move on to the next step.

​NAME                                       READY  STATUS      RESTARTS  AGE
ingress-nginx-admission-create--1-9x9s4    0/1    Completed   0         37s
ingress-nginx-admission-patch--1-76m8b     0/1    Completed   1         37s
ingress-nginx-controller-5f66978484-ntw6f  1/1    Running     0         37s

Step 3. Create a deployment of Cryostat

To deploy the Cryostat instance, you need to create a Cryostat object, using a YAML file to represent the Cryostat CRD. The Network Options section of the Cryostat Operator's documentation provides an example with Ingress specifications that will work for this demonstration after you've made a couple of small changes.

First, you need to add the minimal field under spec, as this is a required field in the Cryostat CRD, and set it to false. This ensures that you will have a non-minimal Cryostat deployment.

Second, under the annotations field for all three Ingress configurations, increase the proxy-read-timeout and proxy-send-timeout values to 3600 seconds from default 60. Doing this will avoid closing the web socket connection Cryostat relies upon.

Once you've modified the example, it should look like this:

​apiVersion: operator.cryostat.io/v1beta1
kind: Cryostat
metadata:
 name: cryostat-sample
spec:
 minimal: false
 networkOptions:
   coreConfig:
     annotations:
       nginx.ingress.kubernetes.io/backend-protocol : HTTPS
       nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
       nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
     ingressSpec:
       tls:
       - {}
       rules:
       - host: testing.cryostat
         http:
           paths:
           - path: /
             pathType: Prefix
             backend:
               service:
                 name: cryostat-sample
                 port:
                   number: 8181
   commandConfig:
     annotations:
       nginx.ingress.kubernetes.io/backend-protocol : HTTPS
       nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
       nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
     ingressSpec:
       tls:
       - {}
       rules:
       - host: testing.cryostat-command
         http:
           paths:
           - path: /
             pathType: Prefix
             backend:
               service:
                 name: cryostat-sample-command
                 port:
                   number: 9090
   grafanaConfig:
     annotations:
       nginx.ingress.kubernetes.io/backend-protocol : HTTPS
       nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
       nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
     ingressSpec:
       tls:
       - {}
       rules:
       - host: testing.cryostat-grafana
         http:
           paths:
           - path: /
             pathType: Prefix
             backend:
               service:
                 name: cryostat-sample-grafana
                 port:
                   number: 3000

Copy this code into a file named cryostat-sample.yaml. Once the file is ready to go, you can use it to create a deployment of Cryostat in the my-cryostat-operator namespace:

kubectl apply -f cryostat-sample.yaml -n my-cryostat-operator

Next, verify the health of the deployment:

kubectl get pods -n my-cryostat-operator -w

Once all three containers comprising the cryostat-sample pod are READY, you can proceed.

​NAME                                                   READY  STATUS             RESTARTS  AGE
cryostat-operator-controller-manager-6f7fdb5c68-cwgc5  1/1    Running            0         85s
cryostat-sample-d57dd74bb-5bqj9                        0/3    Pending            0          0s
cryostat-sample-d57dd74bb-5bqj9                        0/3    Pending            0          0s
cryostat-sample-d57dd74bb-5bqj9                        0/3    ContainerCreating  0          0s
cryostat-sample-d57dd74bb-5bqj9                        2/3    Running            0          2s
cryostat-sample-d57dd74bb-5bqj9                        2/3    Running            0         11s
cryostat-sample-d57dd74bb-5bqj9                        3/3    Running            0         11s

Step 4. Route the Cryostat service URLs to Minikube

Next, you need to get the Ingress configurations available to you:

kubectl get ingress -n my-cryostat-operator

If your setup so far has been correct, the output from this command should look similar to the following:

​NAME                     CLASS  HOSTS                     ADDRESS    PORTS    AGE
cryostat-sample          nginx  testing.cryostat          localhost  80, 443  5m4s
cryostat-sample-command  nginx  testing.cryostat-command  localhost  80, 443  5m4s
cryostat-sample-grafana  nginx  testing.cryostat-grafana  localhost  80, 443  5m4s

Since you're running Minikube locally, the IPv4 address in the ADDRESS column is actually the internal address of the three services. To get the external address, through which the services in the cluster will be exposed, run the following command:

minikube ip

Note: For the purpose of this article, IP_ADDRESS will stand in for the address this command returns to you.

In the next step, you'll need to edit the /etc/hosts file on your computer. (That file path is valid for both Linux and macOS users; on Windows, the path is C:\Windows\System32\Drivers\etc\hosts.) Please note that editing this file requires administrator privileges:

SUDO_EDITOR=gedit sudoedit /etc/hosts

Add the following line to the bottom of the file:

{IP_ADDRESS} testing.cryostat testing.cryostat-command testing.cryostat-grafana

Remember: {IP_ADDRESS} is the result you got from running the minikube ip command above.

This addition ensures that your web browser will route requests for HTTPS URLs containing any of the above three hosts to Minikube. The testing.cryostat-grafana host provides access to the Grafana dashboard that is linked to the current Cryostat instance. The testing.cryostat-command host is a leftover from the deprecated command channel.

With your hosts file modified, you can now access the Cryostat web client UI at https://testing.cryostat.

Conclusion

After you've installed the Cryostat Operator using the steps described in this article, there are several things you could do next. You could configure a Java application to work with Cryostat, so that it can be monitored using the web client. You could also configure custom targets for monitoring Java applications. To explore other useful features new in Cryostat 2.0, see the Cryostat 2.0 announcement blog post. For more about what you can do with Cryostat, check out this introduction to JDK Flight Recorder on Red Hat Developer.

Last updated: November 17, 2023