Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make multi-tenant support and release namespace optional #49

Merged
merged 4 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion horizon/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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.1.5
version: 1.1.6

# 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
Expand Down
4 changes: 3 additions & 1 deletion horizon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ kubectl create configmap -n $instance $configmap --from-file=lots-of-zeros.zip
| core.resources.requests.cpu | string | `"2"` | |
| core.resources.requests.memory | string | `"4Gi"` | |
| core.terminationGracePeriodSeconds | int | `120` | |
| createNamespace | bool | `false` | |
| createNamespace | bool | `false` | Whether to create the namespace when releaseNamespace=true. Has no effect otherwise. |
| dependencies.clusterRole | bool | `true` | |
| dependencies.clusterRoleBinding | bool | `true` | |
| dependencies.cortex.bulkheadMaxWaitDuration | string | `"9223372036854775807"` | |
Expand Down Expand Up @@ -211,11 +211,13 @@ kubectl create configmap -n $instance $configmap --from-file=lots-of-zeros.zip
| ingress.annotations | object | `{}` | |
| ingress.certManager.clusterIssuer | string | `"opennms-issuer"` | |
| ingress.className | string | `"nginx"` | |
| multiTenant | bool | `false` | Enable multi-tenant mode. This will use the release name as the per-tenant identifier for the OpenNMS instance ID, databases, Kakfa topics, ElasticSearch indices, and Prometheus organization ID. |
| promtail.image.pullPolicy | string | `"IfNotPresent"` | |
| promtail.image.repository | string | `"grafana/promtail"` | |
| promtail.image.tag | string | `"latest"` | |
| promtail.resources.limits.cpu | string | `"50m"` | |
| promtail.resources.limits.memory | string | `"64Mi"` | |
| releaseNamespace | bool | `false` | Install resource objects into namespace named for the Helm release. See also createNamespace. |
| sentinel.configuration.database.poolSize | int | `25` | |
| sentinel.image.pullPolicy | string | `"IfNotPresent"` | |
| sentinel.image.repository | string | `"opennms/sentinel"` | |
Expand Down
37 changes: 26 additions & 11 deletions horizon/scripts/onms-core-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,17 @@ mkdir -p ${CONFIG_DIR_OVERLAY}/opennms.properties.d ${CONFIG_DIR_OVERLAY}/featur
# Apply common OpenNMS configuration settings
# Configure the instance ID
# Required when having multiple OpenNMS backends sharing a Kafka cluster or an Elasticsearch cluster.
if [[ ${OPENNMS_INSTANCE_ID} ]]; then
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
echo "Creating ${CONFIG_DIR_OVERLAY}/opennms.properties.d/instanceid.properties with our instance ID '${OPENNMS_INSTANCE_ID}'"
cat <<EOF > ${CONFIG_DIR_OVERLAY}/opennms.properties.d/instanceid.properties
# Used for Kafka Topics and Elasticsearch Index Prefixes
org.opennms.instance.id=${OPENNMS_INSTANCE_ID}
EOF
else
OPENNMS_INSTANCE_ID="OpenNMS"
if [[ -e "${CONFIG_DIR}/opennms.properties.d/instanceid.properties" ]]; then
echo "Found ${CONFIG_DIR}/opennms.properties.d/instanceid.properties, we are going to remove it."
rm "${CONFIG_DIR}/opennms.properties.d/instanceid.properties"
fi
fi

# Disable data choices (optional)
Expand Down Expand Up @@ -393,8 +396,10 @@ readTimeoutInMs=${CORTEX_READ_TIMEOUT}
metricCacheSize=${CORTEX_METRIC_CACHE_SIZE}
externalTagsCacheSize=${CORTEX_EXTERNAL_TAGS_CACHE_SIZE}
bulkheadMaxWaitDuration=${CORTEX_BULKHEAD_MAX_WAIT_DURATION}
organizationId=${OPENNMS_INSTANCE_ID}
EOF
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
echo "organizationId=${OPENNMS_INSTANCE_ID}" >> ${CONFIG_DIR_OVERLAY}/org.opennms.plugins.tss.cortex.cfg
fi

mkdir -p ${CONFIG_DIR_OVERLAY}/featuresBoot.d

Expand Down Expand Up @@ -440,15 +445,19 @@ EOF
# Configure Elasticsearch to allow Helm/Grafana to access Flow data
if [[ -v ELASTICSEARCH_SERVER ]]; then
echo "Configuring Elasticsearch for Flows..."
PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
echo "Creating ${CONFIG_DIR_OVERLAY}/org.opennms.features.flows.persistence.elastic.cfg"
cat <<EOF > ${CONFIG_DIR_OVERLAY}/org.opennms.features.flows.persistence.elastic.cfg
elasticUrl=https://${ELASTICSEARCH_SERVER}
globalElasticUser=${ELASTICSEARCH_USER}
globalElasticPassword=${ELASTICSEARCH_PASSWORD}
elasticIndexStrategy=${ELASTICSEARCH_INDEX_STRATEGY_FLOWS}
EOF
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/org.opennms.features.flows.persistence.elastic.cfg
indexPrefix=${PREFIX}
EOF
fi
fi


Expand Down Expand Up @@ -478,11 +487,6 @@ fi

# Configure Sink and RPC to use Kafka, and the Kafka Producer.
if [[ -v KAFKA_BOOTSTRAP_SERVER ]]; then
if [[ ${OPENNMS_INSTANCE_ID} == "" ]]; then
echo >&2 "OPENNMS_INSTANCE_ID cannot be empty. Aborting."
exit 1
fi

echo "Configuring Kafka for IPC..."

echo "Creating ${CONFIG_DIR_OVERLAY}/opennms.properties.d/amq.properties"
Expand All @@ -500,16 +504,19 @@ EOF

# TWIN
org.opennms.core.ipc.twin.kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
EOF
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms.properties.d/kafka.properties
org.opennms.core.ipc.twin.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-Twin
EOF
fi
fi

cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms.properties.d/kafka.properties

# SINK
org.opennms.core.ipc.sink.initialSleepTime=60000
org.opennms.core.ipc.sink.kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
org.opennms.core.ipc.sink.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-Sink

# SINK Consumer (verify Kafka broker configuration)
org.opennms.core.ipc.sink.kafka.session.timeout.ms=30000
Expand All @@ -519,7 +526,6 @@ org.opennms.core.ipc.sink.kafka.max.poll.records=50
org.opennms.core.ipc.rpc.kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
org.opennms.core.ipc.rpc.kafka.ttl=30000
org.opennms.core.ipc.rpc.kafka.single-topic=true
org.opennms.core.ipc.rpc.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-RPC

# RPC Consumer (verify Kafka broker configuration)
org.opennms.core.ipc.rpc.kafka.request.timeout.ms=30000
Expand All @@ -532,6 +538,15 @@ org.opennms.core.ipc.rpc.kafka.acks=0
org.opennms.core.ipc.rpc.kafka.linger.ms=5
EOF

if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${CONFIG_DIR_OVERLAY}/opennms.properties.d/kafka.properties

# org.opennms.instance.id-prefixed groups for multi-tenant operation
org.opennms.core.ipc.sink.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-Sink
org.opennms.core.ipc.rpc.kafka.group.id=${OPENNMS_INSTANCE_ID}-Core-RPC
EOF
fi

MODULES="rpc sink"
if [[ "$USE_TWIN" == "true" ]]; then
MODULES="twin $MODULES"
Expand Down
24 changes: 15 additions & 9 deletions horizon/scripts/onms-sentinel-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,12 @@ OVERLAY_DIR=/opt/sentinel-etc-overlay

# Configure the instance ID and Interface-to-Node cache
# Required when having multiple OpenNMS backends sharing a Kafka cluster or an Elasticsearch cluster.
CUSTOM_PROPERTIES=${OVERLAY_DIR}/custom.system.properties
if [[ ${OPENNMS_INSTANCE_ID} ]]; then
cat <<EOF >> ${CUSTOM_PROPERTIES}
if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${OVERLAY_DIR}/custom.system.properties
# Used for Kafka Topics
org.opennms.instance.id=${OPENNMS_INSTANCE_ID}
# Refresh Interface-to-Node cache every 2 hours
org.opennms.interface-node-cache.refresh-timer=7200000
EOF
else
OPENNMS_INSTANCE_ID="OpenNMS"
fi

cat <<EOF > ${OVERLAY_DIR}/org.opennms.netmgt.distributed.datasource.cfg
Expand Down Expand Up @@ -122,17 +118,22 @@ adapters.0.class-name=org.opennms.netmgt.telemetry.protocols.netflow.adapter.net
queue.threads=${NUM_LISTENER_THREADS}
EOF

PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
cat <<EOF > ${OVERLAY_DIR}/org.opennms.features.flows.persistence.elastic.cfg
elasticUrl=https://${ELASTICSEARCH_SERVER}
globalElasticUser=${ELASTICSEARCH_USER}
globalElasticPassword=${ELASTICSEARCH_PASSWORD}
elasticIndexStrategy=${ELASTICSEARCH_INDEX_STRATEGY_FLOWS}
indexPrefix=${PREFIX}
# The following settings should be consistent with your ES cluster
settings.index.number_of_shards=${ELASTICSEARCH_NUM_SHARDS}
settings.index.number_of_replicas=${ELASTICSEARCH_REPLICATION_FACTOR}
EOF

if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
PREFIX=$(echo ${OPENNMS_INSTANCE_ID} | tr '[:upper:]' '[:lower:]')-
cat <<EOF >> ${OVERLAY_DIR}/org.opennms.features.flows.persistence.elastic.cfg
indexPrefix=${PREFIX}
EOF
fi
fi

if [[ -v KAFKA_BOOTSTRAP_SERVER ]]; then
Expand All @@ -149,11 +150,16 @@ EOF

cat <<EOF > ${FILE_PREFIX}.consumer.cfg
# Consumers
group.id=${OPENNMS_INSTANCE_ID}_Sentinel
bootstrap.servers=${KAFKA_BOOTSTRAP_SERVER}
max.partition.fetch.bytes=5000000
EOF

if [ -n "${OPENNMS_INSTANCE_ID}" ]; then
cat <<EOF >> ${FILE_PREFIX}.consumer.cfg
group.id=${OPENNMS_INSTANCE_ID}_Sentinel
EOF
fi

for f in ${FILE_PREFIX}.cfg ${FILE_PREFIX}.consumer.cfg; do
cat <<EOF >> $f
# Security
Expand Down
45 changes: 36 additions & 9 deletions horizon/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,40 @@
{{/*
Define namespace option for Helm commands
*/}}
{{- define "helm.namespace" -}}
{{- if ne .Release.Namespace "default" }}
{{- printf " -n %s" .Release.Namespace }}
{{- else }}
{{- printf "" }}
{{- end }}
{{- end }}

{{/*
Define namespace option for kubectl commands
*/}}
{{- define "kubectl.namespace" -}}
{{- if ne (include "namespace" .) "default" }}
{{- printf " -n %s" (include "namespace" .) }}
{{- else }}
{{- printf "" }}
{{- end }}
{{- end }}

Thank you for installing OpenNMS {{ .Values.core.image.tag | default .Chart.AppVersion }}.

Your release is named "{{ .Release.Name }}", used for:
Your release is named "{{ .Release.Name }}" and is installed into the
"{{ include "namespace" . }}" namespace. The release name is used as
the sub-domain for the ingress controller.
{{- if .Values.multiTenant }}

Multi-tenant mode is enabled, so the release name "{{ .Release.Name }}"
is also used for:
- Customer/Deployment identifier.
- The namespace for all the resources.
- The sub-domain for the ingress controller.
- Prefix for PostgreSQL database names.
- The OpenNMS instance ID for your Minions (prefix for Kafka topics).
- Prefix for Elasticsearch indices.
- Prefix for PostgreSQL database names.
- Prefix for Kafka consumer groups.
{{- end }}

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

Expand Down Expand Up @@ -36,16 +63,16 @@ Resources URLs:

To learn more about the release, try:

$ helm status {{ .Release.Name }}
$ helm get all {{ .Release.Name }}
$ kubectl get all -n {{ .Release.Name }}
$ helm status {{ .Release.Name }}{{ include "helm.namespace" . }}
$ helm get all {{ .Release.Name }}{{ include "helm.namespace" . }}
$ kubectl get all -l app.kubernetes.io/name={{ .Release.Name }},app.kubernetes.io/instance={{ .Release.Name }}{{ include "kubectl.namespace" . }}
{{- end }}

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

If OpenNMS needs to be restarted to apply configuration changes, you'll need to restart it, e.g.:

$ kubectl rollout restart -n {{ .Release.Name }} statefulset/onms-core
$ kubectl rollout restart{{ include "kubectl.namespace" . }} statefulset/onms-core
{{- end }}

{{- if .Values.core.inspector.enabled }}
Expand All @@ -54,5 +81,5 @@ The inspector pod is enabled and OpenNMS pod is not running.

This is how you can connect to the inspector pod:

$ kubectl exec -it -n {{ .Release.Name }} pods/inspector -- /bin/bash
$ kubectl exec -it{{ include "kubectl.namespace" . }} pods/inspector -- /bin/bash
{{- end }}
19 changes: 16 additions & 3 deletions horizon/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ server:
http_listen_port: 9080
grpc_listen_port: 0
clients:
- tenant_id: {{ .Release.Name }}
url: {{ printf "%s://%s:%d/loki/api/v1/push" $scheme ((.Values.dependencies).loki).hostname (((.Values.dependencies).loki).port | int) }}
- url: {{ printf "%s://%s:%d/loki/api/v1/push" $scheme ((.Values.dependencies).loki).hostname (((.Values.dependencies).loki).port | int) }}
{{- if and ((.Values.dependencies).loki).username ((.Values.dependencies).loki).password }}
basic_auth:
username: {{ .Values.dependencies.loki.username }}
Expand All @@ -108,8 +107,11 @@ clients:
tls_config:
ca_file: /etc/jks/loki-ca.cert
{{- end }}
{{- if .Values.multiTenant }}
tenant_id: {{ .Release.Name }}
{{- end }}
external_labels:
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
scrape_configs:
- job_name: system
pipeline_stages:
Expand Down Expand Up @@ -148,3 +150,14 @@ Are we running in an Red Hat OpenShift cluster?
{{- printf "false" -}}
{{- end }}
{{- end }}

{{/*
Define Namespace
*/}}
{{- define "namespace" -}}
{{- if .Values.releaseNamespace }}
{{- printf "%s" .Release.Name -}}
{{- else }}
{{- printf "%s" .Release.Namespace -}}
{{- end }}
{{- end }}
2 changes: 1 addition & 1 deletion horizon/templates/app-credentials.secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: Secret
type: Opaque
metadata:
name: app-credentials
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data:
Expand Down
2 changes: 1 addition & 1 deletion horizon/templates/app-jks.secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: Secret
type: Opaque
metadata:
name: app-jks
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data: # To be mounted at /etc/java/jks
Expand Down
2 changes: 1 addition & 1 deletion horizon/templates/app-scripts.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: app-scripts
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data:
Expand Down
18 changes: 15 additions & 3 deletions horizon/templates/app-settings.configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
namespace: {{ .Release.Name }}
namespace: {{ include "namespace" . }}
labels:
{{- include "core.labels" . | nindent 4 }}
data:
Expand All @@ -19,9 +19,17 @@ data:
ENABLE_CORTEX: {{ ((.Values.core).configuration).enableCortex | quote }}
ENABLE_TSS_DUAL_WRITE: {{ ((.Values.core).configuration).enableTssDualWrite | quote }}
ENABLE_GRAFANA: {{ if gt ((.Values.grafana).replicaCount|int) 0 }}"true"{{ else }}"false"{{ end }}
{{- if .Values.multiTenant }}
OPENNMS_INSTANCE_ID: {{ .Release.Name | quote }}
OPENNMS_SERVER: {{ printf "onms-core.%s.svc" .Release.Name | quote }}
{{- else }}
OPENNMS_INSTANCE_ID: ""
{{- end }}
OPENNMS_SERVER: {{ include "namespace" . | printf "onms-core.%s.svc" | quote }}
{{- if .Values.multiTenant }}
OPENNMS_DBNAME: {{ printf "%s_opennms" .Release.Name | quote }}
{{- else }}
OPENNMS_DBNAME: "opennms"
{{- end }}
{{- if ((.Values.core).configuration).rras }}
OPENNMS_RRAS: {{ join ";" .Values.core.configuration.rras }}
{{- end }}
Expand All @@ -47,7 +55,7 @@ data:
KAFKA_SASL_MECHANISM: {{ .Values.dependencies.kafka.configuration.saslMechanism | quote }}
KAFKA_SECURITY_PROTOCOL: {{ .Values.dependencies.kafka.configuration.securityProtocol | quote }}
{{- end }}
GRAFANA_SERVER: {{ printf "grafana.%s.svc" .Release.Name | quote }}
GRAFANA_SERVER: {{ include "namespace" . | printf "grafana.%s.svc" | quote }}
{{- if eq (include "onOpenShift" .) "true" }}
GF_SERVER_DOMAIN: {{ printf "grafana-%s" (include "core.domain" .) | quote }} # Should match FQDN on the Ingress
GF_SERVER_ROOT_URL: ""
Expand All @@ -56,7 +64,11 @@ data:
GF_SERVER_ROOT_URL: "/"
{{- end }}
GF_DATABASE_TYPE: "postgres"
{{- if .Values.multiTenant }}
GF_DATABASE_NAME: {{ printf "%s_grafana" .Release.Name | quote }}
{{- else }}
GF_DATABASE_NAME: "grafana"
{{- end }}
GF_DATABASE_SSL_MODE: {{ (((.Values.grafana).configuration).database).sslmode | default "disable" | quote }}
GF_DATABASE_CA_CERT_PATH: "/etc/java/jks/postgresql-ca.crt"
GF_SESSION_PROVIDER: "postgres"
Expand Down
Loading