Skip to main content

Deploy on Kubernetes

Deploy LicOps on Kubernetes when the workloads you want to gate run in the cluster, or when the cluster is where you already run shared services. You install the Router with one Helm chart, connect it to OpenLM Platform, and optionally install a second chart: an admission webhook that makes the admit, dispatch, and release requests for pods you annotate.

For Slurm or LSF, you don't need Kubernetes. A Docker Compose deployment is simpler. See Deploy OpenLM LicOps.

Before you begin​

Confirm these prerequisites:

  • A cluster that meets the requirements for Kubernetes, and kubectl and Helm 3 configured for it.
  • MongoDB 7.x and Redis 7.0 or higher that the cluster can reach, configured as described in System requirements.
  • The LicOps Helm charts. OpenLM supplies them in the LicOps deployment bundle: openlm-router installs the Router, and openlm-gke installs the admission webhook. Contact OpenLM to get the bundle.
  • Your cluster's pod network range, its pod CIDR. On many clusters kubectl cluster-info dump | grep -m1 cluster-cidr prints it.

Create the secrets​

The charts read their connection strings and certificate from secrets you create beforehand. They never create these secrets themselves. Run these commands in the namespace you deploy to:

export NS=openlm-licops

kubectl create namespace $NS

kubectl -n $NS create secret generic openlm-generic-mongo-db-credentials \
--from-literal=MONGODB__CONNECTIONSTRING='mongodb://<user>:<password>@<mongo-host>:27017/?authSource=admin'

kubectl -n $NS create secret generic openlm-generic-redis-connection-credentials \
--from-literal=REDIS__CONNECTIONSTRING='<redis-host>:6379,abortConnect=false'

kubectl -n $NS create secret tls openlm-lb-cert --cert=<certificate.pem> --key=<private-key.pem>

The TLS secret openlm-lb-cert is needed only while Traefik serves HTTPS, with traefik.enabled and traefik.tls.enabled both true, which is the default.

Then create the encryption key, once, on the first installation only:

kubectl -n $NS create secret generic openlm-router-platform-encryption \
--from-literal=ADMISSION_PLATFORM_ENCRYPTION_KEY="$(openssl rand -base64 32)"
Create the encryption key once and keep it

The key decrypts the OpenLM Platform credentials stored in MongoDB. On an upgrade the secret already exists and this command fails. That is correct, so skip it. Do not delete and recreate the secret to get past the error: that replaces the key, and the stored OpenLM Platform credentials become unreadable.

Pass the key as plain text, exactly as openssl printed it. --from-literal encodes it for you. If you write the secret as a manifest instead, put the key under stringData:, not data:, or it is encoded twice and the first save of the OpenLM Platform connection fails.

Install the Router​

Create a values file, licops-values.yaml, that makes the Router a LicOps Router managed from OpenLM Platform:

routerapi:
tag: "1.261006.0752" # olm-routerapi
encryptionKey:
secretName: openlm-router-platform-encryption
admissionController:
proxyProtocol:
trustedCidrs:
- <your-pod-CIDR>
extraEnv:
# Required. The Router takes its configuration and rules from the OpenLM Platform.
- name: licOpsConfiguration__enabled
value: "true"
- name: LICOPSCONFIGURATION_ENABLED
value: "true"
# Required. Declares a LicOps Router. Fixed at the first start.
- name: ROUTER_CONFIG_BOOTSTRAP_MODE
value: loadBalancer
# Keep the background-job dashboard off.
- name: hangfire__dashboard__enabled
value: "false"

routerui:
tag: "1.261008.0932" # olm-routerui

To install the chart, run this command:

helm upgrade --install openlm-router ./licops-deploy/helm/openlm-router \
-n $NS --set namespace=$NS -f licops-values.yaml

Set these values carefully:

  • --set namespace=$NS: The chart places its resources in the namespace named in its own values, openlm by default, whatever namespace you pass to Helm. Set both to the same namespace.
  • tag: The chart has no default tag. A missing tag renders an image reference ending in a colon, which fails only when the image is pulled.
  • trustedCidrs: The Router uses it to trust the identity the webhook's sidecar sends with each checkout. Set it to your pod CIDR. An empty list stops the Router from starting. A range that does not cover your pod network passes that check with no error, but the Router then does not read the job identity the sidecar sends, so checkouts from those pods are not matched to their jobs.
  • The extraEnv entries: The chart does not set OpenLM Platform management or the LicOps mode by itself. Without them, nothing you define in LicOps Configuration reaches the Router.

The chart creates two Services: openlm-router-api, the admission API on port 8100, and openlm-router-data, the LicOps listen port 30001. Workloads in the cluster use the API at http://openlm-router-api.<namespace>.svc:8100.

The chart publishes the Router through Traefik

By default the chart routes /router-management and /api/v1 on your Traefik entry point to the Router, for any host name. These paths lead to the administration interfaces of the Router. Allow access to them only from your administration network, and do not publish them to the internet. Set traefik.host to a host name only your administrators use and restrict access to it, or set traefik.enabled=false and reach the Router with kubectl port-forward.

Traefik is optional. With Traefik turned on, the chart expects the entry points web, websecure, and a TCP entry point routertcp on port 30001, and routertcp publishes the LicOps listen port on the load balancer. Without Traefik, both Services are reachable only from inside the cluster.

To confirm the Router started, run these commands. Until you connect the Router to OpenLM Platform, the pod status is Running with 0/1 Ready, so kubectl rollout status does not finish. The API is reachable through the port-forward meanwhile.

kubectl -n $NS get pods
kubectl -n $NS port-forward svc/openlm-router-api 8100:8100

In a second terminal, run this command:

curl http://localhost:8100/api/v1/status

The response reads "status": "unconfigured" with "shape": "serviceManaged", as described in Deploy OpenLM LicOps. The Router is running and is not connected to OpenLM Platform.

Connect the Router to OpenLM Platform​

With the port-forward running, connect the Router as described in Configure OpenLM LicOps. Use the REST commands there against http://localhost:8100. If you kept Traefik turned on, you can also open the Router UI at https://<traefik-address>/router-management/.

A port-forward is for your own terminal only and stops when you close it. Workloads in the cluster use the Service address, never localhost.

Install the admission webhook​

The webhook is optional. It licenses pods without any change to their images: for every pod you annotate, it calls admit when the pod is created, adds init containers that dispatch and redirect the pod's license traffic, and adds a sidecar that releases the seat when the pod ends. If each job calls the API itself, skip this section and see Kubernetes workloads.

Pre-release

The sidecar and the two init containers, tagged dev-8f79e85, are pre-release builds. The webhook image itself is a numbered release.

helm upgrade --install openlm-gke ./licops-deploy/helm/openlm-gke -n $NS \
--set image.tag=dev-8f79e85 \
--set image.webhookTag=1.260819.1521 \
--set certManager.enabled=false \
--set router.restEndpoint=http://openlm-router-api.$NS.svc:8100 \
--set router.host=openlm-router-data.$NS.svc
  • Two tags: image.tag sets the sidecar and init-container images, and image.webhookTag sets the webhook. They are released separately.
  • The certificate: The webhook needs a certificate the Kubernetes API server trusts. certManager.enabled=false makes the chart generate a self-signed certificate that is valid for 365 days. The chart makes a new one each time you run this helm upgrade --install command, and the webhook loads it only when it starts. After every run, restart the webhook with kubectl -n $NS rollout restart deployment/openlm-gke. If the certificate expires, every pod you opted in is rejected. To generate it, the chart pulls alpine/k8s from Docker Hub and might install openssl, so it needs internet access. For production, run cert-manager and pass --set certManager.issuerRef.name=<your-issuer> instead. With neither, the installation fails at once.
  • The Router addresses: router.restEndpoint and router.host are required. Give router.restEndpoint the Service address and port only. The webhook adds the API path itself, so a value that already ends in /api/v1/admission-controller makes every admit fail and every opted-in pod is rejected.
An unavailable webhook blocks pod creation

The webhook is registered with a failure policy of Fail, so while it is unavailable, no pod can be created in a namespace you opted in. That keeps pods from starting without a LicOps seat during a webhook outage. To let pods start without a seat, install with --set webhook.failurePolicy=Ignore. This setting covers the webhook only: when the webhook runs but cannot reach LicOps, it lets pods through unchanged, as described in Kubernetes workloads.

The chart pulls the images olm-pod-sidecar, olm-dispatch-init, and olm-iptables-init.

To opt namespaces and pods in, see Kubernetes workloads.

Upgrade​

Change the tags in licops-values.yaml, then run the same helm upgrade --install command. If you installed the admission webhook, upgrade it too: run its helm upgrade --install command again with the new image.tag and image.webhookTag. If you use the self-signed certificate, then restart the webhook with kubectl -n $NS rollout restart deployment/openlm-gke. Skip the encryption-key secret: it already exists and must not change. To list the available builds, see Find the newest build. The configuration and rules live in OpenLM Platform, and the open sessions live in Redis, so they survive the upgrade.

The documentation team might draft this page using a large language model. A technical writer reviews every page and verifies it against the product before publishing it. A human makes the final decision.