Deploy Ceilometer
OpenStack Ceilometer is the telemetry service within the OpenStack ecosystem, responsible for collecting and delivering usage data across various OpenStack services. Ceilometer plays a critical role in monitoring and metering the performance and resource consumption of cloud infrastructure, providing essential data for billing, benchmarking, and operational insights. By aggregating metrics such as CPU usage, network bandwidth, and storage consumption, Ceilometer enables cloud operators to track resource usage, optimize performance, and ensure compliance with service-level agreements. In this document, we will discuss the deployment of OpenStack Ceilometer using Genestack. With Genestack, the deployment of Ceilometer is made more efficient, ensuring that comprehensive and reliable telemetry data is available to support the effective management and optimization of cloud resources.
Create Secrets
Information about the secretes 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 ceilometer-keystone-admin-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 ceilometer-keystone-test-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 ceilometer-rabbitmq-password \
--type Opaque \
--from-literal=password="$(< /dev/urandom tr -dc _A-Za-z0-9 | head -c${1:-32};echo;)"
Run the package deployment
Run the Ceilometer deployment Script /opt/genestack/bin/install-ceilometer.sh
#!/bin/bash
# Description: Fetches the version for SERVICE_NAME from the specified
# YAML file and executes a helm upgrade/install command with dynamic values files.
# Disable SC2124 (unused array), SC2145 (array expansion issue), SC2294 (eval)
# shellcheck disable=SC2124,SC2145,SC2294
# Service
SERVICE_NAME="ceilometer"
SERVICE_NAMESPACE="openstack"
# Helm
HELM_REPO_NAME="openstack-helm"
HELM_REPO_URL="https://tarballs.opendev.org/openstack/openstack-helm"
# Base directories provided by the environment
GENESTACK_BASE_DIR="${GENESTACK_BASE_DIR:-/opt/genestack}"
GENESTACK_OVERRIDES_DIR="${GENESTACK_OVERRIDES_DIR:-/etc/genestack}"
# Define service-specific override directories based on the framework
SERVICE_BASE_OVERRIDES="${GENESTACK_BASE_DIR}/base-helm-configs/${SERVICE_NAME}"
SERVICE_CUSTOM_OVERRIDES="${GENESTACK_OVERRIDES_DIR}/helm-configs/${SERVICE_NAME}"
GLOBAL_OVERRIDES_DIR="${GENESTACK_OVERRIDES_DIR}/helm-configs/global_overrides"
# Read the desired chart version from VERSION_FILE
VERSION_FILE="${GENESTACK_OVERRIDES_DIR}/helm-chart-versions.yaml"
if [ ! -f "$VERSION_FILE" ]; then
echo "Error: helm-chart-versions.yaml not found at $VERSION_FILE" >&2
exit 1
fi
# Extract version dynamically using the SERVICE_NAME variable
SERVICE_VERSION=$(grep "^[[:space:]]*${SERVICE_NAME}:" "$VERSION_FILE" | sed "s/.*${SERVICE_NAME}: *//")
if [ -z "$SERVICE_VERSION" ]; then
echo "Error: Could not extract version for '$SERVICE_NAME' from $VERSION_FILE" >&2
exit 1
fi
echo "Found version for $SERVICE_NAME: $SERVICE_VERSION"
# Prepare an array to collect -f arguments
overrides_args=()
# Include all YAML files from the BASE configuration directory
if [[ -d "$SERVICE_BASE_OVERRIDES" ]]; then
echo "Including base overrides from directory: $SERVICE_BASE_OVERRIDES"
for file in "$SERVICE_BASE_OVERRIDES"/*.yaml; do
# Check that there is at least one match
if [[ -e "$file" ]]; then
echo " - $file"
overrides_args+=("-f" "$file")
fi
done
else
echo "Warning: Base override directory not found: $SERVICE_BASE_OVERRIDES"
fi
# Include all YAML files from the GLOBAL configuration directory
if [[ -d "$GLOBAL_OVERRIDES_DIR" ]]; then
echo "Including overrides from global config directory:"
for file in "$GLOBAL_OVERRIDES_DIR"/*.yaml; do
if [[ -e "$file" ]]; then
echo " - $file"
overrides_args+=("-f" "$file")
fi
done
else
echo "Warning: Global config directory not found: $GLOBAL_OVERRIDES_DIR"
fi
# Include all YAML files from the custom SERVICE configuration directory
if [[ -d "$SERVICE_CUSTOM_OVERRIDES" ]]; then
echo "Including overrides from service config directory:"
for file in "$SERVICE_CUSTOM_OVERRIDES"/*.yaml; do
if [[ -e "$file" ]]; then
echo " - $file"
overrides_args+=("-f" "$file")
fi
done
else
echo "Warning: Service config directory not found: $SERVICE_CUSTOM_OVERRIDES"
fi
echo
# --- Helm Repository and Execution ---
helm repo add "$HELM_REPO_NAME" "$HELM_REPO_URL"
helm repo update
# Collect all --set arguments, executing commands and quoting safely
set_args=(
--set "endpoints.identity.auth.admin.password=$(kubectl --namespace openstack get secret keystone-admin -o jsonpath='{.data.password}' | base64 -d)"
--set "endpoints.identity.auth.ceilometer.password=$(kubectl --namespace openstack get secret ceilometer-keystone-admin-password -o jsonpath='{.data.password}' | base64 -d)"
--set "endpoints.identity.auth.test.password=$(kubectl --namespace openstack get secret ceilometer-keystone-test-password -o jsonpath='{.data.password}' | base64 -d)"
--set "endpoints.oslo_messaging.auth.admin.username=$(kubectl --namespace openstack get secret rabbitmq-default-user -o jsonpath='{.data.username}' | base64 -d)"
--set "endpoints.oslo_messaging.auth.admin.password=$(kubectl --namespace openstack get secret rabbitmq-default-user -o jsonpath='{.data.password}' | base64 -d)"
--set "endpoints.oslo_messaging.auth.ceilometer.password=$(kubectl --namespace openstack get secret ceilometer-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)"
--set "endpoints.oslo_cache.auth.memcache_secret_key=$(kubectl --namespace openstack get secret os-memcached -o jsonpath='{.data.memcache_secret_key}' | base64 -d)"
--set "conf.ceilometer.keystone_authtoken.memcache_secret_key=$(kubectl --namespace openstack get secret os-memcached -o jsonpath='{.data.memcache_secret_key}' | base64 -d)"
--set "conf.ceilometer.oslo_messaging.transport_url=rabbit://ceilometer:$(kubectl --namespace openstack get secret ceilometer-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/ceilometer"
--set "conf.ceilometer.notification.messaging_urls.values={\
rabbit://ceilometer:$(kubectl --namespace openstack get secret ceilometer-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/ceilometer,\
rabbit://keystone:$(kubectl --namespace openstack get secret keystone-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/keystone,\
rabbit://glance:$(kubectl --namespace openstack get secret glance-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/glance,\
rabbit://nova:$(kubectl --namespace openstack get secret nova-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/nova,\
rabbit://neutron:$(kubectl --namespace openstack get secret neutron-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/neutron,\
rabbit://cinder:$(kubectl --namespace openstack get secret cinder-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/cinder,\
rabbit://heat:$(kubectl --namespace openstack get secret heat-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/heat,\
rabbit://octavia:$(kubectl --namespace openstack get secret octavia-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/octavia,\
rabbit://magnum:$(kubectl --namespace openstack get secret magnum-rabbitmq-password -o jsonpath='{.data.password}' | base64 -d)@rabbitmq.openstack.svc.cluster.local:5672/magnum}"
)
helm_command=(
helm upgrade --install "$SERVICE_NAME" "$HELM_REPO_NAME/$SERVICE_NAME"
--version "${SERVICE_VERSION}"
--namespace="$SERVICE_NAMESPACE"
--timeout 120m
--create-namespace
"${overrides_args[@]}"
"${set_args[@]}"
# Post-renderer configuration
--post-renderer "$GENESTACK_OVERRIDES_DIR/kustomize/kustomize.sh"
--post-renderer-args "$SERVICE_NAME/overlay"
"$@"
)
echo "Executing Helm command (arguments are quoted safely):"
printf '%q ' "${helm_command[@]}"
echo
# Execute the command directly from the array
"${helm_command[@]}"
Tip
You may need to provide custom values to configure your openstack services, for a simple single region or lab deployment you can supply an additional overrides flag using the example found at base-helm-configs/aio-example-openstack-overrides.yaml.
In other cases such as a multi-region deployment you may want to view the Multi-Region Support guide to for a workflow solution.
Verify Ceilometer Workers
As there is no Ceilometer API, we will do a quick validation against the
Gnocchi API via a series of openstack metric commands to confirm that
Ceilometer workers are ingesting metric and event data then persisting them
storage.
Verify metric resource types exist
The Ceilomter db-sync job will create the various resource types in Gnocchi.
Without them, metrics can't be stored, so let's verify they exist. The
output should include named resource types and some attributes for resources
like instance, instance_disk, network, volume, etc.
Verify metric resources
Confirm that resources are populating in Gnocchi
Verify metrics
Confirm that metrics can be retrieved from Gnocchi