Deploy Qonos
QonoS v2 is a modern, extensible scheduling platform for executing time-based actions against OpenStack services. It provides cron-scheduled operations including server snapshots (Nova), volume full and incremental backups (Cinder), with Keystone authentication, trust-based delegation, retention policies, and RabbitMQ notifications.
Genestack deploys QonoS with three control-plane components — API, scheduler, and worker — backed by MariaDB and RabbitMQ.
This document outlines deploying QonoS using Genestack.
Supported action types
| Action type | Description |
|---|---|
server_snapshot |
Create a Glance image snapshot of a Nova server |
volume_backup_full |
Full Cinder backup of a block storage volume |
volume_backup_incremental |
Incremental Cinder backup |
Each schedule references an execution profile with Keystone trust delegation so tenant-scoped jobs run under the correct OpenStack project context.
Note
QonoS can be enabled during bin/setup-openstack.sh (component prompt Qonos (Scheduled Actions)) or installed later with /opt/genestack/bin/install-qonos.sh.
Create secrets
Information about the secrets used
Manual secret generation is only required if you haven't run the create-secrets.sh script located in /opt/genestack/bin.
Example secret generation
kubectl --namespace openstack \
create secret generic qonos-rabbitmq-password \
--type Opaque \
--from-literal=username="qonos" \
--from-literal=password="$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c${1:-64};echo;)"
kubectl --namespace openstack \
create secret generic qonos-db-password \
--type Opaque \
--from-literal=password="$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c${1:-32};echo;)"
kubectl --namespace openstack \
create secret generic qonos-admin \
--type Opaque \
--from-literal=password="$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c${1:-32};echo;)"
Configure Qonos
The install script renders qonos.conf into the qonos-etc secret. It prefers a site override, then falls back to the shipped default:
| Source | Path |
|---|---|
| Override | /etc/genestack/kustomize/qonos/base/qonos.conf |
| Default | /opt/genestack/base-kustomize/qonos/base/qonos.conf |
Tip
Copy the default template to /etc/genestack/kustomize/qonos/base/qonos.conf before install if you need region-specific timeouts, concurrency, or endpoints.
Run the package deployment
Run the Qonos deployment Script /opt/genestack/bin/install-qonos.sh
#!/usr/bin/env bash
set -euo pipefail
SERVICE_NAME="qonos"
SERVICE_NAMESPACE="openstack"
GENESTACK_BASE_DIR="${GENESTACK_BASE_DIR:-/opt/genestack}"
GENESTACK_OVERRIDES_DIR="${GENESTACK_OVERRIDES_DIR:-/etc/genestack}"
KUSTOMIZE_PATH="${GENESTACK_BASE_DIR}/base-kustomize/${SERVICE_NAME}/base"
QONOS_CONF_DEFAULT="${KUSTOMIZE_PATH}/qonos.conf"
QONOS_CONF_OVERRIDE="${GENESTACK_OVERRIDES_DIR}/kustomize/qonos/base/qonos.conf"
resolve_qonos_conf() {
if [ -f "${QONOS_CONF_OVERRIDE}" ]; then
echo "${QONOS_CONF_OVERRIDE}"
return 0
fi
if [ -f "${QONOS_CONF_DEFAULT}" ]; then
echo "${QONOS_CONF_DEFAULT}"
return 0
fi
echo "Error: qonos.conf not found. Looked for:" >&2
echo " ${QONOS_CONF_OVERRIDE}" >&2
echo " ${QONOS_CONF_DEFAULT}" >&2
exit 1
}
require_secret() {
local secret_name="$1"
if ! kubectl --namespace "${SERVICE_NAMESPACE}" get secret "${secret_name}" >/dev/null 2>&1; then
echo "Error: secret ${secret_name} not found in namespace ${SERVICE_NAMESPACE}" >&2
echo "Run bin/create-secrets.sh and apply /etc/genestack/kubesecrets.yaml first." >&2
exit 1
fi
}
get_secret_password() {
local secret_name="$1"
kubectl --namespace "${SERVICE_NAMESPACE}" get secret "${secret_name}" \
-o jsonpath='{.data.password}' | base64 -d
}
apply_qonos_etc_secret() {
local conf_template="$1"
local rendered_conf
local qonos_db_password
local qonos_rabbitmq_password
local qonos_admin_password
qonos_db_password="$(get_secret_password qonos-db-password)"
qonos_rabbitmq_password="$(get_secret_password qonos-rabbitmq-password)"
qonos_admin_password="$(get_secret_password qonos-admin)"
rendered_conf="$(mktemp)"
trap 'rm -f "${rendered_conf}"' RETURN
sed \
-e "s|__QONOS_DB_PASSWORD__|${qonos_db_password}|g" \
-e "s|__QONOS_RABBITMQ_PASSWORD__|${qonos_rabbitmq_password}|g" \
-e "s|__QONOS_ADMIN_PASSWORD__|${qonos_admin_password}|g" \
"${conf_template}" > "${rendered_conf}"
kubectl create secret generic qonos-etc \
--namespace "${SERVICE_NAMESPACE}" \
--from-file=qonos.conf="${rendered_conf}" \
--dry-run=client -o yaml | kubectl apply -f -
}
if [ ! -f "${KUSTOMIZE_PATH}/kustomization.yaml" ]; then
echo "Error: qonos kustomization not found at ${KUSTOMIZE_PATH}" >&2
exit 1
fi
QONOS_CONF_PATH="$(resolve_qonos_conf)"
echo "Installing qonos from ${KUSTOMIZE_PATH}"
echo "Rendering qonos.conf from ${QONOS_CONF_PATH}"
require_secret "keystone-keystone-admin"
require_secret "qonos-db-password"
require_secret "qonos-rabbitmq-password"
require_secret "qonos-admin"
apply_qonos_etc_secret "${QONOS_CONF_PATH}"
kubectl --namespace "${SERVICE_NAMESPACE}" delete job qonos-ks-user qonos-db-sync --ignore-not-found=true
kubectl kustomize "${KUSTOMIZE_PATH}" | kubectl apply -f -
kubectl --namespace "${SERVICE_NAMESPACE}" wait \
--for=condition=complete "job/qonos-ks-user" \
--timeout=15m
kubectl --namespace "${SERVICE_NAMESPACE}" wait \
--for=condition=complete "job/qonos-db-sync" \
--timeout=15m
for deployment in qonos-api qonos-scheduler qonos-worker; do
kubectl --namespace "${SERVICE_NAMESPACE}" rollout status "deployment/${deployment}" --timeout=15m
done
echo "qonos installed successfully"
Enable Skyline integration
The Skyline Scheduled Actions tab (QonoS) is hidden until Skyline is configured with the QonoS endpoint and service user id.
Add the following to /etc/genestack/helm-configs/skyline/skyline-helm-overrides.yaml:
conf:
skyline:
openstack:
qonos_endpoint: https://qonos.your.domain.tld/
qonos_user_id: <qonos-keystone-user-id>
Resolve the user id after QonoS is deployed:
kubectl --namespace openstack exec -ti openstack-admin-client -- \
openstack user show qonos --domain service -f value -c id
Set qonos_endpoint to the same public hostname used on the QonoS Gateway HTTPRoute, then re-run /opt/genestack/bin/install-skyline.sh so the override is applied.
Note
Without qonos_endpoint and qonos_user_id, the Scheduled Actions tab does not appear in Skyline.
Monitoring
| Component | Port | Path |
|---|---|---|
| API | 8080 |
/metrics |
| Worker | 8081 |
/metrics |
| Scheduler | 8082 |
/metrics |
Import etc/grafana-dashboards/qonos_v2_operations.json with the Grafana dashboard import script.
Validate functionality
kubectl --namespace openstack get pods -l app.kubernetes.io/name=qonos
kubectl --namespace openstack get jobs qonos-ks-user qonos-db-sync
kubectl --namespace openstack get servicemonitor -l app.kubernetes.io/name=qonos
kubectl --namespace openstack exec -ti openstack-admin-client -- \
openstack user show qonos --domain service