Install on Kubernetes
OSIE runs on Kubernetes as three components — the API, the client portal and the admin portal — backed by MongoDB and RabbitMQ. In production the databases are run by Kubernetes operators and OSIE itself by the official Helm chart.
An operator is a controller that knows how to run a stateful workload: it initialises the MongoDB replica set, generates the credentials, provisions the storage, takes scheduled backups with point-in-time recovery, and performs rolling upgrades. RabbitMQ cluster formation, plugin configuration and restarts are handled the same way. Without operators, every one of those procedures is yours to script and to get right during an incident.
All manifests and example values used on this page are maintained in the public
osie/deployment repository, under
kubernetes/. Clone it and adapt the files
to your environment rather than copying snippets from this page:
git clone https://github.com/osie/deployment.git
cd deployment/kubernetes
| Component | Kind | Managed by |
|---|---|---|
osie-api | StatefulSet | OSIE Helm chart |
osie-ui — client portal | Deployment | OSIE Helm chart |
osie-admin — admin portal | Deployment | OSIE Helm chart |
| MongoDB replica set | PerconaServerMongoDB | Percona Operator for MongoDB |
| RabbitMQ | RabbitmqCluster | RabbitMQ Cluster Operator |
For an evaluation or a small installation on one machine, use the Docker Compose installer, or the MicroK8S tutorial if you want Kubernetes without a cluster.
Prerequisites
- A Kubernetes cluster (1.30 or newer) with:
- a default
StorageClasswith dynamic provisioning - an ingress controller (
ingress-nginx, Traefik, …) exposed on a public IP address - cert-manager with a
ClusterIssuer named
letsencrypt, unless you provide your own TLS secret
- a default
- A DNS record for the hostname OSIE is served on —
osie.mycompany.com— pointing at the ingress IP address. All three components share that single hostname. kubectland Helm 3 on your workstation.
The single-node profile below needs about 2 vCPU and 4 GB of RAM and claims 35 GB of storage; the high-availability profile needs about 6 vCPU and 20 GB of RAM and claims 170 GB. Provide headroom on top of those figures.
Install the operators
Both operators are cluster-wide and installed once, however many OSIE installations the cluster later hosts.
# Percona Operator for MongoDB
helm repo add percona https://percona.github.io/percona-helm-charts
helm repo update
helm install percona-mongodb-operator percona/psmdb-operator \
--namespace percona-mongodb \
--create-namespace \
--version 1.22.0 \
--set watchAllNamespaces=true
# RabbitMQ Cluster Operator
kubectl apply -f https://github.com/rabbitmq/cluster-operator/releases/download/v2.20.0/cluster-operator.yml
Wait until both are available:
kubectl wait deployment percona-mongodb-operator-psmdb-operator \
-n percona-mongodb --for=condition=Available --timeout=300s
kubectl wait deployment rabbitmq-cluster-operator \
-n rabbitmq-system --for=condition=Available --timeout=300s
Deploy the databases
Create the namespace, then apply one MongoDB and one RabbitMQ resource. Each profile is a ready-made manifest in the deployment repository:
| Profile | MongoDB | RabbitMQ |
|---|---|---|
| Single node | psmdb.single-node.yml — 3-member replica set co-located on one node, 10 GB, minimal requests | rabbitmq.single-node.yml — 1 node, 5 GB |
| High availability | psmdb.ha.yml — 3-member replica set spread across nodes, 50 GB, scheduled S3 backups with point-in-time recovery | rabbitmq.ha.yml — 3 nodes, 20 GB |
kubectl apply -f infrastructure/namespace.yml
# MongoDB — pick one
kubectl apply -f infrastructure/percona-mongodb/psmdb.single-node.yml
#kubectl apply -f infrastructure/percona-mongodb/psmdb.ha.yml
# RabbitMQ — pick one
kubectl apply -f infrastructure/rabbitmq/rabbitmq.single-node.yml
#kubectl apply -f infrastructure/rabbitmq/rabbitmq.ha.yml
The manifests deploy into the osie namespace and leave storageClassName commented out, so the
cluster default applies. To install into a different namespace, change metadata.namespace in all
three files. Before applying psmdb.ha.yml, set your bucket in its backup.storages block and your
credentials in the mongodb-backup-s3 secret it defines.
Wait for both operators to report their cluster healthy. Until they do, the databases are scheduled but not accepting connections, and the API fails to start:
kubectl wait --for=jsonpath='{.status.state}'=ready psmdb/mongodb -n osie --timeout=600s
kubectl wait rabbitmqcluster/rabbitmq -n osie --for=condition=AllReplicasReady --timeout=600s
Each operator writes its generated credentials to a secret in the same namespace —
percona-server-mongodb-users and rabbitmq-default-user. The Helm chart reads them directly, so no
database password is ever copied into your values file.
Configure the values file
Start from values.example.yaml
in the deployment repository:
global:
ingress:
enabled: true
hostname: "osie.mycompany.com"
ingressClassName: "nginx"
annotations:
cert-manager.io/cluster-issuer: letsencrypt
tls: true
# MongoDB managed by the Percona operator
externalMongodb:
hosts: "mongodb-rs0"
port: 27017
database: osie
existingSecret: percona-server-mongodb-users
existingSecretUsernameKey: MONGODB_DATABASE_ADMIN_USER
existingSecretPasswordKey: MONGODB_DATABASE_ADMIN_PASSWORD
# RabbitMQ managed by the RabbitMQ operator
externalRabbitmq:
host: rabbitmq
port: 5672
existingSecret: rabbitmq-default-user
existingSecretUsernameKey: username
existingSecretPasswordKey: password
# The chart can also deploy its own databases. Disable them — the operators own that job.
mongodb:
enabled: false
rabbitmq:
enabled: false
keycloak:
enabled: false
externalMongodb.hostsis the service the Percona operator creates for the replica set, named<cluster-name>-<replset-name>—mongodb-rs0with these manifests. The connection string is completed with the chart defaultextraQueryParams: "authSource=admin&replicaSet=rs0", which matches them.mongodb,rabbitmqandkeycloakmust be disabled explicitly. They default to enabled, so that installations created before operator support keep working across chart upgrades.- No identity settings belong here. A new installation authenticates against OSIE's own identity service, and customer sign-in is configured afterwards per realm — see Identity management.
- Add
license.keyif you were given one, and thesmtpblock if OSIE should send email — invoices, invitations and password recovery all depend on it. Every setting the chart accepts is listed in its values.yaml.
High availability
With the high-availability database manifests applied, run the three components with more than one replica:
api:
replicaCount: 3
ui:
replicaCount: 3
admin:
replicaCount: 3
Scheduled work inside the API — billing runs, metric collection, invoice generation — is guarded by a lock held in MongoDB, so exactly one replica executes each job however many are running.
Install the chart
helm repo add osie https://helm.osie.io
helm repo update osie
helm --namespace osie upgrade --install osie osie/osie -f values.yaml
The API applies its database migrations at startup and reports ready only afterwards, so the first install takes a few minutes:
$ kubectl -n osie get pods
NAME READY STATUS RESTARTS AGE
mongodb-rs0-0 1/1 Running 0 8m
mongodb-rs0-1 1/1 Running 0 7m
mongodb-rs0-2 1/1 Running 0 7m
osie-admin-7c5fb75c85-28zjc 1/1 Running 0 3m
osie-api-0 1/1 Running 0 3m
osie-ui-5648b4b458-trl4d 1/1 Running 0 3m
rabbitmq-server-0 1/1 Running 0 8m
If a pod stays unready, its logs say why:
kubectl -n osie logs -f osie-api-0
Three ingress objects share the hostname — the client portal on /, the admin portal on
/osie_admin, and the API on its own paths:
$ kubectl -n osie get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
osie-admin nginx osie.mycompany.com 12.34.56.78 80, 443 3m
osie-api nginx osie.mycompany.com 12.34.56.78 80, 443 3m
osie-ui nginx osie.mycompany.com 12.34.56.78 80, 443 3m
First sign-in
Open https://osie.mycompany.com/osie_admin. On first access you are guided through onboarding, where
you create the administrator account and set its password. The client portal is served from
https://osie.mycompany.com/.
Save the encryption key
OSIE encrypts sensitive values in the database — OpenStack passwords, access keys and similar — with a
symmetric key passed to the API as OSIE_ENCRYPTION_DEFAULT_KEY. The chart generates one on first
install and stores it in the <release-name>-bcrypt secret. The same key is required to decrypt that
data: without a copy of it, a restore into a fresh installation cannot read what it restored.
kubectl -n osie get secret osie-bcrypt -o json | jq -r '.data."bcrypt-password"' | base64 -d
Keep the value outside the cluster. To reuse an existing key on a new installation, set
encryption.bcrypt.password, or point encryption.bcrypt.existingPasswordSecret at a secret you
manage yourself.
Upgrading
Upgrades use the same command as the install. Database migrations run when the new API pod starts, so watch its logs before declaring the upgrade done.
helm repo update osie
helm --namespace osie upgrade osie osie/osie -f values.yaml
kubectl -n osie logs -f osie-api-0
Changes to values.yaml are applied the same way. Take a backup first.
The databases are upgraded independently of OSIE: change crVersion and image in the MongoDB
manifest, or the operator version itself, and re-apply. The operators perform the rolling restart.
Next steps
- Configure automated backups of the installation with Velero. MongoDB backups are configured separately, in the Percona manifest.
- Add your own CA certificates if OSIE must reach systems that use a private CA.
- Set up sign-in for your customers and your administrators — see Identity management.
- Enable OpenStack notifications for a realtime experience in the portal.
- Continue with the Administrator's manual to add your first OpenStack region and configure billing.