Skip to content

Commit

Permalink
Openshift (#36)
Browse files Browse the repository at this point in the history
* adding initial support for OpenShift

* update scc and statefulset

* fix references to OpenShift

* remove hardcoded values

* add Openshift support for OPG

* update Sentinel

* disable hardcoded routerCanonicalHostname and fix end of file

* fix logics and detect other container types

* clean up logic

* remove html formatting from Notes file

* modify readme file

* add a file listing known issues and limitations

* Add options to control creation of ClusterRole and ClusterRoleBinding

* Revert "fix logics and detect other container types"

This reverts commit 64a8224.

* add initial doc for 1.1.0-Beta1

* allow pull secrets to be used by minion; fix a small bug in values schema for pull secrets

* remove extra file

* Merging changes (#35)

* NMS-16166 - Allow user to control allowPrivilegeEscalation, allowedCapabilities, defaultAddCapabilities

* Disable Ingress if className is not set

* remove defaultAddCapabilities from values file

* clean up

* Update chart version

* fix a typo

* address lint issues

* remove extra logic

* enable the security context for plugins and clean up

* drop all capabilities when CAP is not assigned

* fix the securityContext options

* fix lint issues

* fix lint issue in core

* clean up the logic for setting fsGroup

* add imagePullSecrets to post-config job

* change the default etcUpdatePolicy policy

* Add OpenShift docs for Horizon and Minion

* fix a small bug with opg route

* remove comments

* fix a small issue with password change path

* fix a small bug in minion deployment

* Update horizon/templates/grafana-helm.route.yaml

Co-authored-by: DJ Gregor <dgregor@opennms.com>

* fix spacing

* fix lint issue

* fix indentations

* fix lint issue

* add logic for using latest datasources and password

---------

Co-authored-by: DJ Gregor <dgregor@opennms.com>

---------

Co-authored-by: DJ Gregor <dgregor@opennms.com>
  • Loading branch information
mershad-manesh and deejgregor authored Oct 18, 2023
1 parent 15313e8 commit 56a1c2e
Show file tree
Hide file tree
Showing 37 changed files with 1,993 additions and 304 deletions.
2 changes: 1 addition & 1 deletion docs/antora.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: opennmshelmcharts
version: '1.0.0'
version: '1.1.0'
title: Helm Charts (Kubernetes)
nav:
- modules/ROOT/nav.adoc
6 changes: 3 additions & 3 deletions horizon/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: v2
name: horizon
description: A Helm chart for running OpenNMS Horizon in Kubernetes
description: A Helm chart for running OpenNMS Horizon in Kubernetes and Red Hat OpenShift
home: https://github.com/OpenNMS/helm-charts
icon: https://www.opennms.com/wp-content/uploads/2021/04/OpenNMS_Favicon_36px.png

Expand All @@ -17,13 +17,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 1.0.0
version: 1.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "32.0.0"
appVersion: "32.0.4"

maintainers:
- name: The OpenNMS Group Inc.
Expand Down
33 changes: 33 additions & 0 deletions horizon/OpenShift_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# OpenNMS Helm Charts with OpenShift: Documentation (1.1.0)

OpenNMS Helm Charts makes it easier for users to run OpenNMS Horizon on a Red Hat OpenShift or Kubernetes environment. It provides a package that includes all the resources needed to deploy Horizon.
This documentation provides basic information on how to install Horizon on Red Hat OpenShift. For information on how to use Red Hat OpenShift, refer to the [product documentation](https://access.redhat.com/documentation/en-us/openshift_container_platform/).

## Limitations and Known Issues

* Removing `CAP_NET_RAW` capability or setting allowPrivilegeEscalation to false will impact ICMP and auto discovery features.
* **WORKAROUND:** Use a Minion that is located outside of the OpenShift cluster.

## Install OpenNMS Horizon on OpenShift
> **NOTE:** By default, OpenNMS will create a ClusterRole, ClusterRoleBinding, Route, SecurityContextConstraints, and ServiceAccount. The user used to install OpenNMS must have the required permissions to make these modifications the OpenShift Cluster, including admin access. There are options to disable the creation of these elements, but if you do so, you will need to figure out a way to get the pods to work.
1. Log in to OpenShift and switch to Developer view.
2. Create a project with a unique name.
3. Go to the Helm section.
4. In the Create drop-down menu, select Repository.
* In the Create Repository page,
* Add a unique name and display name.
* Use https://opennms.github.io/helm-charts/ for the URL.
* Save the changes.
5. In the Create drop-down menu, select Helm Release.
6. Under Repository, select the newly created repository entry.
7. Click on Horizon.
8. Make sure that the project name matches the name you set in step 2.
* Skip this step if you are setting “CreateNamespace” option to true.
9. Make the required modifications (for example, set the PostgreSQL information).
10. Click Create.
11. Wait for the pods to come up. This may take a few minutes.

**NOTE:** The process to install the Minion is similar.


88 changes: 1 addition & 87 deletions horizon/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OpenNMS Helm Charts -- Horizon

OpenNMS Helm Charts makes it easier for users to run OpenNMS Horizon locally in a Kubernetes cluster.
OpenNMS Helm Charts makes it easier for users to run OpenNMS Horizon locally in a Kubernetes cluster or Red Hat OpenShift.
It is not yet available for a Cloud environment.

Each deployment through OpenNMS Helm Charts has a single Core server, Grafana, and a custom Ingress that shares the RRD files and some configuration files, and multiple Sentinels for flow processing.
Expand All @@ -26,95 +26,9 @@ helm repo add opennms https://opennms.github.io/helm-charts
helm install monms opennms/horizon --set domain=domain1.com --create-namespace
```

## Architecture

The following illustrates the general architecture for the OpenNMS Helm Charts solution, with a Kubernetes container environment, ingress controller, and three unique namespaces.
It also displays external dependencies: Loki, PostgreSQL, Elasticsearch, Kafka, and Cortex.
For more detailed information on Kubernetes and containerized environments, see the [Kubernetes documentation](https://kubernetes.io/docs/home/).

### General architecture

![General architecture for OpenNMS Helm Charts](../diagrams/helm-charts-diagrams.001.png)

### Customer namespace deployment

![Customer Namespace Deployment Diagram](../diagrams/helm-charts-diagrams.002.png)

Deployment in each namespace includes OpenNMS Horizon Core, OpenNMS Sentinel, Grafana, and application scripts and configuration files.
All components on a single `namespace` represent a single OpenNMS environment or customer deployment or a single tenant.
The name of the `namespace` is used as follows:

* A customer/deployment identifier.
* The name of the deployed Helm application.
* A prefix for the OpenNMS and Grafana databases in PostgreSQL.
* A prefix for the index names in Elasticsearch when processing flows.
* A prefix for the topics in Kafka (requires configuring the OpenNMS instance ID on Minions).
* A prefix for the Consumer Group IDs in OpenNMS and Sentinel.
* Part of the subdomain used by the Ingress Controller to expose Web UIs.

## Design

The solution is based and tested against the latest Horizon.
It is not available for Meridian at this point, but will be in the future.

### Scripts and core configuration

Due to how the current Docker images were designed and implemented, the solution requires multiple specialized scripts to configure each application properly.
You could build your images and move the logic from the scripts executed via `initContainers` to your custom entry point script and simplify the Helm Chart.

The scripts configure only a certain number of things.
Each deployment would likely need additional configuration, which is the main reason for using a Persistent Volume Claim (PVC) for the configuration directory of the Core OpenNMS instance.

We must place the core configuration on a PVC configured as `ReadWriteMany` to allow the use of independent UI servers so that the Core can make changes and the UI instances can read from them.
One advantage of configuring that volume is allowing backups and access to the files without accessing the OpenNMS instances running in Kubernetes.

### Time series databases

Similarly, when using RRDtool instead of Newts/Cassandra or Cortex, a shared volume with `ReadWriteMany` is required for the same reasons (the Core would be writing to it, and the UI servers would be reading from it).
Additionally, when switching strategies and migration are required, you could work outside Kubernetes.

Note that the volumes would still be configured that way even if you decide not to use UI instances, unless you modify the logic of the Helm Chart.

### Scaling

To alleviate load from OpenNMS, you can optionally start Sentinel instances for flow processing.
That requires having an Elasticsearch cluster available.
When Sentinels are present, Telemetryd is disabled in OpenNMS.

The OpenNMS Core and Sentinels are backed by a `StatefulSet` but keep in mind that there can be one and only one Core instance.
To have multiple Sentinels, make sure you have enough partitions for the flow topics in your Kafka clusters, as all of them would be part of the same consumer group.

### Log files and Grafana Loki

The current OpenNMS instances are not friendly when accessing log files.
The Helm Chart allows you to configure [Grafana Loki](https://grafana.com/oss/loki/) to centralize all the log messages.
When the Loki server is configured, the Core instance, the UI instances, and the Sentinel instances will forward logs to Loki.
The current solution employs the sidecar pattern using [Grafana Promtail](https://grafana.com/docs/loki/latest/clients/promtail/) to deliver the logs.

### Docker images

You can customize all of the Docker images via Helm Values.
The solution lets you configure custom Docker registries to access your custom images, or when all the images you plan to use will not be in Docker Hub or when your Kubernetes cluster will not have internet access.
Keep in mind that your custom images should be based on those currently in use.

### Plugins

Containers are bundled with default plugins. Additional plugins can be added by building your own container image (see [kar-container](kar-container/README.md) for an example).

### External dependencies

The Helm Chart assumes that all external dependencies are running somewhere else.
None of them would be initialized or maintained here.
Those are Loki, PostgreSQL, Elasticsearch, Kafka, and Cortex (when applied).
The solution provides a script to start up a set of dependencies for testing as a part of the same cluster but **this is not intended for production use.**

## Product documentation
For information on requirements, installation, manual configuration, and troubleshooting tips, see the [product documentation](https://docs.opennms.com/opennmshelmcharts/latest/installation/introduction.html#requirements).

## Problems/Limitations

When using Newts, the resource cache will not exist on the UI servers (maintained by Collectd), meaning all requests will hit Cassandra, slowing down the graph generation.

## Version compatibility

| Helm chart version | Horizon version(s) | Meridian version(s) |
Expand Down
104 changes: 84 additions & 20 deletions horizon/scripts/onms-core-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,17 @@ OPENNMS_DATABASE_CONNECTION_MAXPOOL=${OPENNMS_DATABASE_CONNECTION_MAXPOOL-50}
KAFKA_SASL_MECHANISM=${KAFKA_SASL_MECHANISM-PLAIN}
KAFKA_SECURITY_PROTOCOL=${KAFKA_SECURITY_PROTOCOL-SASL_PLAINTEXT}

# See if we can get the OpenNMS package name and version from the package manager
if command -v rpm >/dev/null 2>&1; then
PKG=$(rpm -qa | egrep '(meridian|opennms)-core')
VERSION=$(rpm -q --queryformat '%{VERSION}' $PKG)
elif command -v dpkg-query >/dev/null 2>&1; then
if PKG=$(dpkg-query -f '${Package}\n' -W | grep -Fx -e opennms-common -e meridian-common); then
VERSION=$(dpkg-query -f '${Version}\n' -W "${PKG}")
else
PKG="unknown"
fi
# Retrieve OpenNMS package name and version
if command -v unzip >/dev/null 2>&1; then
PKG=$(unzip -q -c "/opt/opennms/lib/opennms_install.jar" installer.properties | grep "install.package.name" | cut -d '=' -f 2)
VERSION=$(tail -1 "/opt/opennms/jetty-webapps/opennms/WEB-INF/version.properties" | cut -d '=' -f 2)
else
PKG="unknown"
# Assume opennms PKG
PKG=opennms
VERSION=$(tail -1 "/opt/opennms/jetty-webapps/opennms/WEB-INF/version.properties" | cut -d '=' -f 2)
fi

if [[ "${PKG}" == "unknown" ]]; then
if [[ "${PKG}" == "unknown" ]] || [[ "${PKG}" == "" ]]; then
if [[ ! -e jetty-webapps/opennms/WEB-INF/version.properties ]]; then
echo >&2 "Couldn't determine version number from package manager (which is normal for newer containers) and jetty-webapps/opennms/WEB-INF/version.properties does not exist. Aborting."; exit 1;
fi
Expand All @@ -108,6 +104,12 @@ echo "Package: ${PKG}"
echo "Version: ${VERSION}"
echo "Major: ${MAJOR}"

IFS=. read -r MAJOR MINOR PATCH <<<"$VERSION"
echo "Minor: ${MINOR}"
PATCH=${PATCH//-SNAPSHOT}
echo "Patch: ${PATCH}"


# Verify if Twin API is available
USE_TWIN="false"
if [[ "$PKG" == *"meridian"* ]]; then
Expand All @@ -116,7 +118,7 @@ if [[ "$PKG" == *"meridian"* ]]; then
USE_TWIN=true
fi
else
echo "OpenNMS Horizon $MAJOR detected"
echo "OpenNMS Core $MAJOR detected"
if (( $MAJOR > 28 )); then
USE_TWIN=true
fi
Expand Down Expand Up @@ -269,11 +271,26 @@ acknowledged-at=Sun Mar 01 00\:00\:00 EDT 2020
EOF

# Configure Database access
USE_UPDATED_DATASOURCE=false
if [ "${MAJOR}" -eq 32 ];then
if [ "${MINOR}" -gt 0 ];then
USE_UPDATED_DATASOURCE=true
elif [ "${MINOR}" -eq 0 ] && [ "${PATCH}" -ge 4 ];then
USE_UPDATED_DATASOURCE=true
else
USE_UPDATED_DATASOURCE=false
fi
elif [ "${MAJOR}" -ge 33 ] && [ "${MAJOR}" -lt 2000 ]; then
USE_UPDATED_DATASOURCE=true
else
USE_UPDATED_DATASOURCE=false
fi
echo "USE_UPDATED_DATASOURCE: $USE_UPDATED_DATASOURCE"
cat <<EOF > ${CONFIG_DIR_OVERLAY}/opennms-datasources.xml
<?xml version="1.0" encoding="UTF-8"?>
<datasource-configuration xmlns:this="http://xmlns.opennms.org/xsd/config/opennms-datasources"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.opennms.org/xsd/config/opennms-datasources
<datasource-configuration xmlns:this="http://xmlns.opennms.org/xsd/config/opennms-datasources"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.opennms.org/xsd/config/opennms-datasources
http://www.opennms.org/xsd/config/opennms-datasources.xsd ">
<connection-pool factory="org.opennms.core.db.HikariCPConnectionFactory"
Expand All @@ -283,13 +300,43 @@ cat <<EOF > ${CONFIG_DIR_OVERLAY}/opennms-datasources.xml
maxPool="50"
maxSize="${OPENNMS_DATABASE_CONNECTION_MAXPOOL}" />
<jdbc-data-source name="opennms"
database-name="${OPENNMS_DBNAME}"
class-name="org.postgresql.Driver"
<jdbc-data-source name="opennms"
database-name="${OPENNMS_DBNAME}"
class-name="org.postgresql.Driver"
url="jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/${OPENNMS_DBNAME}?sslmode=${POSTGRES_SSL_MODE}&amp;sslfactory=${POSTGRES_SSL_FACTORY}"
user-name="${OPENNMS_DBUSER}"
password="${OPENNMS_DBPASS}" />
EOF
if $USE_UPDATED_DATASOURCE; then
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms-datasources.xml
<jdbc-data-source name="opennms-admin"
database-name="template1"
class-name="org.postgresql.Driver"
url="jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/template1?sslmode=${POSTGRES_SSL_MODE}&amp;sslfactory=${POSTGRES_SSL_FACTORY}"
user-name="${POSTGRES_USER}"
password="${POSTGRES_PASSWORD}">
<connection-pool idleTimeout="600"
minPool="0"
maxPool="10"
maxSize="${OPENNMS_DATABASE_CONNECTION_MAXPOOL}" />
</jdbc-data-source>
<jdbc-data-source name="opennms-monitor"
database-name="postgres"
class-name="org.postgresql.Driver"
url="jdbc:postgresql://${POSTGRES_HOST}:${POSTGRES_PORT}/postgres?sslmode=${POSTGRES_SSL_MODE}&amp;sslfactory=${POSTGRES_SSL_FACTORY}"
user-name="${POSTGRES_PASSWORD}"
password="${POSTGRES_PASSWORD}">
<connection-pool idleTimeout="600"
minPool="0"
maxPool="10"
maxSize="${OPENNMS_DATABASE_CONNECTION_MAXPOOL}" />
</jdbc-data-source>
</datasource-configuration>
EOF
else
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms-datasources.xml
<jdbc-data-source name="opennms-admin"
database-name="template1"
class-name="org.postgresql.Driver"
Expand All @@ -298,6 +345,7 @@ cat <<EOF > ${CONFIG_DIR_OVERLAY}/opennms-datasources.xml
password="${POSTGRES_PASSWORD}"/>
</datasource-configuration>
EOF
fi

# Enable storeByGroup to improve performance
# RRD Strategy is enabled by default
Expand Down Expand Up @@ -514,7 +562,23 @@ if [[ ${ENABLE_GRAFANA} == "true" ]]; then
fi
else
echo "Grafana is not enabled, not running onms-grafana-init.sh"
if [[ -e "${CONFIG_DIR}/opennms.properties.d/grafana.properties" ]];then
echo "Found ${CONFIG_DIR}/opennms.properties.d/grafana.properties, we are going to remove it."
rm "${CONFIG_DIR}/opennms.properties.d/grafana.properties" >/dev/null 2>&1;
fi
fi

echo "Updating admin password"
perl /scripts/onms-set-admin-password.pl ${CONFIG_DIR}/users.xml admin "${OPENNMS_ADMIN_PASS}"
if [[ -e "/opt/opennms/bin/password" ]];then
cp ${CONFIG_DIR}/users.xml /opt/opennms/etc/users.xml
echo "RUNAS=$(whoami)" > /opt/opennms/etc/opennms.conf
/opt/opennms/bin/runjava -s -q
/opt/opennms/bin/password "admin" "${OPENNMS_ADMIN_PASS}"
rm /opt/opennms/etc/opennms.conf /opt/opennms/etc/java.conf
cp /opt/opennms/etc/users.xml ${CONFIG_DIR}/users.xml
elif command -v perl >/dev/null 2>&1; then
perl /scripts/onms-set-admin-password.pl ${CONFIG_DIR}/users.xml admin "${OPENNMS_ADMIN_PASS}"
else
echo "We are unable to update Admin password. Exiting."
exit 1
fi
3 changes: 2 additions & 1 deletion horizon/scripts/onms-grafana-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# GRAFANA_SERVER
# GF_SERVER_DOMAIN
# GF_SECURITY_ADMIN_PASSWORD
# GF_SERVER_ROOT_URL

set -euo pipefail
trap 's=$?; echo >&2 "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
Expand Down Expand Up @@ -71,7 +72,7 @@ org.opennms.grafanaBox.apiKey=${GRAFANA_KEY}
org.opennms.grafanaBox.link.protocol=https
org.opennms.grafanaBox.link.hostname=${GF_SERVER_DOMAIN}
org.opennms.grafanaBox.link.port=443
org.opennms.grafanaBox.link.basePath=/
org.opennms.grafanaBox.link.basePath=${GF_SERVER_ROOT_URL}
EOF
fi
22 changes: 20 additions & 2 deletions horizon/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,37 @@ Your release is named "{{ .Release.Name }}", used for:
- Prefix for PostgreSQL database names.
- Prefix for Kafka consumer groups.

{{- if eq (include "onOpenShift" .) "true" }}

OpenNMS is running in Red Hat OpenShift environment.

Resources URLs:

OpenNMS Core: https://onms-core.{{ include "core.domain" . }}/opennms/index.jsp
* OpenNMS Core: https://onms-core.{{ include "core.domain" . }}/opennms/index.jsp


{{- if gt ((.Values.grafana).replicaCount|int) 0 }}
Grafana: https://grafana.{{ include "core.domain" . }}/
* Grafana: https://grafana-{{ include "core.domain" . }}/
{{- end }}

{{- else }}

Resources URLs:


* OpenNMS Core: https://onms-core.{{ include "core.domain" . }}/opennms/index.jsp

{{- if gt ((.Values.grafana).replicaCount|int) 0 }}
* Grafana: https://grafana.{{ include "core.domain" . }}/
{{- end }}


To learn more about the release, try:

$ helm status {{ .Release.Name }}
$ helm get all {{ .Release.Name }}
$ kubectl get all -n {{ .Release.Name }}
{{- end }}

{{- if not .Values.core.configuration.alwaysRollDeployment }}

Expand Down
Loading

0 comments on commit 56a1c2e

Please sign in to comment.