Befindet sich Ihre Datenbank hinter einer Firewall mit nur einem offenen Port? Ist ein direktes Netzwerk-Routing zwischen Clients und Ihren Datenbanken nicht erwünscht oder möglich (z.B. IPv4 vs IPv6)? Oder möchten Sie als Datenbank-Betreiber Regeln definieren können, welche Netzwerke auf welche Datenbank zugreifen dürfen ? Das sind gängige Szenarien für den Einsatz des Oracle Connection Manager (CMAN) als Teil jeder Oracle Database Enterprise Edition Lizenz. Um CMAN zu betreiben sind einige Umstände zu beachten, die besonders bei dessen Einbindung unter Kubernetes auffallen.
Der Oracle Connection Manager fungiert als intelligenter Netzwerk-Proxy und wird zwischen Oracle Datenbanken und deren Clients platziert. Er kann für Datenbank-Umgebungen deutlich mehr tun als die Proxy-Klassiker haproxy und nginx, weil diese nur den TCP-IP Socket-Layer bedienen dürfen. Denn sie kennen das darüberliegende Oracle Net (auch ehemals bekannt als SQL*Net oder Net8) Protokoll nicht und können nicht darauf eingehen:
- CMAN verhindert, dass sich Clients auf einen anderen Listener oder einen anderen Port re-connecten müssen.

Dieser Vorgang ist oftmals Bestandteil eines scheinbar einfachen Datenbank-Connects und gerne problematisch hinter Firewalls oder anders abgeschotteten Netzwerken. - CMAN kann für eine SSL Terminierung sorgen – er bietet verschlüsselte Netzwerkzugänge an, die angesprochenen Datenbanken sprechen über unverschlüsselte Kanäle und liegen beispielsweise in einem separaten, abgeschotteten Netzwerk.
- CMAN kann die Zahl der Connections zu einer Datenbank durch eigene Connection Pools reduzieren.
- CMAN kann aktiv beteiligt sein bei einem Connection Failover.
Ein Client behält meist seine Datenbank-Session trotz Datenbank-switch durch downtime. - Der Umzug einer Datenbank oder PDB auf einen anderen Server kann ohne Anpassung der Client Konfiguration erfolgen
- Datenbanken können sich bei CMAN registrieren wie bei einem REMOTE_LISTENER.
Der manuelle Konfigurationsaufwand wird reduziert. - Policies können festlegen, welche Clients Zugriff auf bestimmte Datenbanken haben.
Das umfasst sowohl IP Adressbereiche als auch Oracle Net Dienste (Datenbank-Dienste, Extproc Agenten, Gateways,…) - Ab Version 23 besitzt CMAN eine REST API zur Remote Konfiguration und Administration.
Diese kann auf Wunsch aktiviert werden, sie ist per default abgeschaltet.
Detailliertere Erklärungen und Features wie der “Traffic Director Modus” werden in der CMAN Dokumentation aufgeführt.
Was spricht spontan für den Einsatz des CMAN unter Kubernetes ?
- Es gibt CMAN als container image in Version 23.5 auf container-registry.oracle.com
Es muss kein Image manuell aus einem Installations-Skript erzeugt werden - Es gibt dennoch ein offizielles Container Build Skript auf github.com/oracle
Für eigene Images, z.B. bedingt durch Hotfixes - CMAN ist leicht zu konfigurieren, braucht eigentlich keine persistenten Volumes
Eine Konfigurationsdatei “cman.ora” und eventuelle SSL Zertifikate genügen. Sie lassen sich besonders leicht unter Kubernetes an den Container anhängen. Die vereinfachte Inbetriebnahme per Container ist ebenfalls auf container-registry.oracle.com dokumentiert - CMAN ist einer von mehreren “Datenbank-Satelliten” wie ORDS, Observability Exporter, GoldenGate
und könnte im gleichen Umfeld betrieben werden. - Die in Kubernetes enthaltene Clusterware startet abgebrochene Container schnell nach, es gibt ein automatisches Load Balancing und bessere Verfügbarkeit mit Container Replica,
wenn auch zwingend mit Session Affinity. Kommen wir daher zu den Erschwernissen.
Was erschwert (mental) den Einsatz von CMAN unter Kubernetes ?
- Nach der reinen Microservices-Lehre sollten Container “stateless” sein, so daß sie in großer Zahl und jederzeit gestartet und gestoppt werden können. Da sich heutzutage auch ganze Virtuelle Maschinen und Datenbanken unter Kubernetes betreiben lassen wurde dieses Prinzip aufgeweicht. Dies gesagt muss ich nun mitteilen: CMAN ist stateful. Er verwaltet und hält Datenbank-Sessions. Stirbt der CMAN Prozess und damit der Container, sind auch die Datenbank-Sessions verlorengegangen. Diese können durch einen überlebenden CMAN Container mit vorangeschaltetem Load Balancer erneut aufgebaut werden, aber es kann dabei zu Fehlermeldungen in Clients kommen. Es ist also (nicht nur unter Kubernetes!) zu verhindern, dass CMAN Container spontan auf andere Knoten umziehen oder die Container nach Konfigurations-Änderungen mal eben durchgestartet werden. Das ist jedoch gut erzielbar. Mit PriorityClass, preemptionPolicy und ferngesteuertem live-refresh der Konfiguration ohne Neustart des Containers.
- CMAN verwendet das Oracle Net Protokoll, er spricht nicht in HTTP oder HTTPS. Damit sind Kubernetes Ingresses und reine HTTP Gateways nicht nutzbar, aber es geht dennoch:
Ist der angelegte CMAN Service vom Typ ClusterIP muss er vom eingerichteten Gateway (meistens auf Basis des altbekannten nginx) direkt auf Socket-Ebene beproxied werden, also ohne Ingress. Das Gateway selbst ist meist vom Typ LoadBalancer, und dann gilt auch dafür der folgende Satz:
Ist der angelegte CMAN Service (oder das Gateway) vom Typ LoadBalancer, muss der dem Cluster vorangestellte externe Loadbalancer auf Socket Ebene fungieren. In der Oracle Cloud hieße das, einen Network Load Balancer Service zu verwenden und keinen regulären Load Balancer Service. Das ist z.B. über Kubernetes Annotationen steuerbar.
Im Load Balancer muss Session Affinity eingestellt sein, z.B. auf Basis der Client Adresse, falls mehrere CMAN container gestartet werden.
Ist der angelegte CMAN Service vom Typ NodePort muss man nichts weiter beachten außer die üblichen Nachteile des NodePort Services zu akzeptieren. Das wären manuelles Load Balancing und die per Definition relativ geringe Zahl freier Ports im Cluster. - Kubernetes verwendet oft ein internes, eigenes Overlay-Netzwerk (flannel). Dadurch entstandene zusätzliche Routings sowie Tunnel und Proxies im vorigen Absatz erhöhen die Latenz. Datenbank Connections und -Operationen dauern einfach etwas länger. Es wäre anzuraten, Kubernetes mit aktuelleren Netzwerk-Anbindungen zu konfigurieren wie dem “VCN native networking” in der Oracle Cloud oder Calico networking, bei dem jeder Container seine eigene externe IP Adresse erhält und die Zahl der Proxies und Load Balancer etwas zu reduzieren. Das gilt natürlich auch in einer Konfiguration ohne Kubernetes !
- Der CMAN REST Service (zugegeben – HTTPS Protokoll wenn auch an untergeordneter Stelle) zur remote Administration funktioniert im Container (noch) nicht. Er wird nicht aktiviert, wenn CMAN beim Start eine Container Umgebung erkennt. Um den Container bei eher seltenen Konfigurations-Änderungen nicht durchstarten zu müssen kann der CMAN Prozess benachrichtigt werden, seine Konfiguration im laufenden Betrieb neu einzulesen. Das geschieht entweder über die REST Schnittstelle oder, wie in der Dokumentation und auch auf container-registry.oracle.com aufgeführt, durch eine mit dem Container verbundene Shell und dem Kommando “cmctl reload”
Möchten Sie es dennoch versuchen ?
Um Ihnen Tests und Versuche zu erleichtern und die Bereitstellung zu beschleunigen erspare ich Ihnen diesmal längere Erklärungen über Deployments mit Containern, Volumes, Secrets, zugehörigen Services und nicht vorhandene weil unnötige Ingresses. Ich habe ein relativ komfortables helm chart für Sie erzeugt, das Sie mit dem Kubernetes Paketmanager helm leicht installieren können. Auch der Quellcode für das helm chart, bestehend aus Kubernetes YAMLs als templates mit einigen Variablen darin ist für Sie zugänglich.
Um das helm chart zu installieren fügen Sie mittels helm Kommando ein neues Chart Repository hinzu. Das Tool helm sollte am besten dort vorhanden sein, wo Sie bereits mittels kubectl Kommando auf Ihr Kubernetes Cluster zugreifen können. Das einzubindende Repository enthält weitere charts wie z.B. cloudbeaver , sqlcl oder ords, die aber noch aufgrund ihres Alters nachgepflegt werden müssen. Daher beachten Sie diese bitte nicht weiter.
$ helm repo add myorarepo https://ilfur.github.io/VirtualAnalyticRooms/ $ helm repo list NAME URL artifact-hub https://artifacthub.github.io/helm-charts/ bitnami https://charts.bitnami.com/bitnami argo https://argoproj.github.io/argo-helm myorarepo https://ilfur.github.io/VirtualAnalyticRooms/ $ helm show chart myorarepo/cman apiVersion: v2 appVersion: 23.5.0.0 description: Oracle Connection Manager icon: https://ilfur.github.io/VirtualAnalyticRooms/cman.png name: cman type: application version: 1.0.4
Dann legen Sie einen neuen Kubernetes Namespace an, zum Beispiel “cman”.
$ kubectl create namespace cman namespace/cman created
Holen Sie sich die Parameter-Datei values.yaml vom chart ab, speichern sie und passen Sie danach die darin vorgeschlagenen Parameter an Ihre Gegebenheiten an.
$ helm show values myorarepo/cman > values.yaml $ vi values.yaml
Es folgen nun Auszüge aus der Datei values.yaml mit einigen Anmerkungen und auch ein oder zwei todos. Im ersten Abschnitt geht es darum, den CMAN Container in Ihr Kubernetes cluster zu laden:
## Please provide a docker registry type secret and enter its name ## if needed, download the container image to Your location and specify that location here image: repository: container-registry.oracle.com/database/cman:23.5.0.0 pullPolicy: IfNotPresent pullSecretName: oraregistry-secret
Um den Container herunterzuladen benötigt Ihr Kubernetes Cluster einen Internet Zugang, um auf container-registry.oracle.com zuzugreifen. Der Download des Container Image ist kennwort-geschützt. Sie sollten sich zunächst auf container-registry.oracle.com anmelden mit Ihrem Oracle technet account und auf der cman – Infomationsseite die Lizenzvereinbarung bestätigen.


Dann haben Sie geraume Zeit die Möglichkeit, den Container wiederholt herunterzuladen. Auch das Kubernetes Cluster benötigt Ihren Oracle technet Benutzernamen und dessen Kennwort für den Download in einem Kubernetes Secret, hier mit dem Namen oraregistry-secret angegeben. Bevor Sie das helm chart installieren, legen Sie bitte zuerst ein entsprechendes Secret im Namespace cman an, wie zum Beispiel:
$ kubectl create secret docker-registry oraregistry-secret -n cman \
--docker-username=marcel.pfeifer@oracle.com \
--docker-password=myComplexPwd123 \
--docker-server=container-registry.oracle.com
secret/oraregistry-secret created
Im nächsten Abschnitt geht es um die Netzwerk-Anbindung des CMAN Containers. Es werden wie bereits erwähnt keinerlei Ingresses definiert, da der Dienst nicht mit HTTP oder HTTPS Protokoll kommuniziert. Das schnellste Ergebnis erhalten Sie, wenn Sie den type des Service auf NodePort setzen. Die dann erhaltene IP Adresse ist außerhalb des Netzwerkes erreichbar, Ihre Oracle Net Clients können diese Adresse dann in ihrem Connect String verwenden.
## For external access, if You have a LoadBalancer implementation installed, use the LoadBalancer type. ## Optionally, specify ClusterIP as type and configure Your Gateway to forward TCP traffic to the ClusterIP service. ## CMAN traffic is non-http, so please do not use an Ingress . service: type: LoadBalancer port: 1521
Ist der type wie hier auf LoadBalancer gesetzt, ist die IP Adresse des Load Balancers zu verwenden. Obendrein darf der eingesetzte externe Load Balancer NICHT HTTP Load Balancing betreiben, sondern muss auf Socket-Ebene bleiben.
In der Oracle Cloud erzielen Sie dies, indem Sie eine entsprechende Annotation an den Service anhängen, in die Sektion metadata hinein:
metadata:
annotations:
oci.oraclecloud.com/load-balancer-type: nlb
Diese Annotation erledigt das Helm Chart automatisch für Sie, falls Sie den typ LoadBalancer eingetragen haben. Sollten Sie nicht in der Oracle Cloud unterwegs sein, ist diese Annotation harmlos und bewirkt nichts. Schauen wir uns nun die Einträge für zusätzliche Persistenz der Log Dateien und Konfiguration an, hier per Default auf “false” gesetzt:
## if the toPVC param is set to false, no PVC is created and config and logs are gone on container restart.
## ideally, use an NFS type strage class for external shared acess and manipulation.
storage:
log:
toPVC: false
storageClass: rook-ceph-block
storage: 50Gi
config:
toPVC: false
storage: 1Gi
storageClass: rook-ceph-block
Sollen log informationen und auch die Konfiguration persistent abgelegt werden ? Das Container-Log enthält bereits die Standard-Ausgaben des CMAN und zeigen Start, Konfiguration und Zugriffe sehr schön. Zusätzliche Trace Dateien könnten Sie in persistente Volumes ablegen, idealerweise auf ein shared Filesystem wie NFS. Bitte geben Sie eine dafür vorhandene storageClass an, z.B. oci-bv für Block Volumes in der Oracle Cloud oder wie hier rook-ceph-block – wenn vorhanden. Danach können Sie auch von außen auf die Log Informationen zugreifen. Das gleiche gilt für die CMAN Konfiguration: die Konfiguration wird bei jedem Start des CMAN normalerweise über eine sogenannte ConfigMap “eingeschossen”. Ist bereits eine persistente Konfiguration in einem Volume vorhanden, wird diese verwendet. Die ConfigMap wird befüllt über den nachfolgenden Abschnitt in der values.yaml Datei, der einen Großteil einer cman.ora Datei enthält.:
## the initial configuration is copied to a ConfigMap.
## The NAME of the cman configuration is auto-generated, please do not specify that here.
initialConfig: |
(configuration=
(address=(protocol=tcp)(host=0.0.0.0)(port=1521))
(parameter_list =
(registration_invited_nodes=*)
(aso_authentication_filter=off)
(connection_statistics=yes)
(remote_admin=on)
(max_connections=256)
(idle_timeout=0)
(inbound_connect_timeout=0)
(log_level=user)
(session_timeout=0)
(outbound_connect_timeout=0)
(max_gateway_processes=16)
(min_gateway_processes=2)
(trace_timestamp=on)
(trace_filelen=1000)
(trace_fileno=5)
(trace_level=off)
(max_cmctl_sessions=4)
(event_group=init_and_term,memory_ops)
)
(rule_list=
(rule=
(src=*)(dst=*)(srv=*)(act=accept)
(action_list=(aut=off)(moct=0)(mct=0)(mit=0)(conn_stats=on))
)
)
)
In diesem Konfigurations-Abschnitt fehlt eigentlich nur der Name des CMAN. Denn dieser besteht u.a. aus dem Namen des Netzwerk-Dienstes und des Namespace und wird für Sie durch das helm chart zusammengesetzt. Das bedeutet aber auch, dass es pro CMAN Container nur einen CMAN geben kann mit genau einem internen Port 1521. Wenn Sie mehrere CMANs haben möchten, benötigen Sie einfach mehrere Container. Den Port 1521 können Sie überall beibehalten, jeder Container bekommt eine eigene IP Adresse und es gibt dann keine Überlappungen.
Sie können die einmal durch die Installation erzeugte ConfigMap auch nachträglich verändern (kubectl edit configmap ... ) und nach Belieben weitere Routing Regeln hinzufügen oder selbst einmal versuchen, den REST Service zu aktivieren. Was Sie bitte nicht ändern sollten wäre die IP Adresse 0.0.0.0, auf der CMAN lauscht. Durch den Eintrag 0.0.0.0 wird auf beliebige IP Adressen reagiert. Solch ein Container unter Kubernetes erhält eine eigene interne IP Adresse, und diese ist dynamisch und auch nicht von außen durch Netzwerk Clients erreichbar. Sie müßten die IP Adresse Ihrer Load Balancer dort eintragen, aber ich finde wir sind auch so bereits sicher und abgeschottet genug unterwegs.
Haben Sie nun Ihre values.yaml Datei an Ihre Bedürfnisse angepaßt? Dann können wir die Installation wagen ! Das geschieht durch einen helm install Aufruf ähnlich diesem:
$ helm install my-cman myorarepo/cman --values values.yaml -n cman NAME: my-cman LAST DEPLOYED: Fri Dec 6 15:15:51 2024 NAMESPACE: cman STATUS: deployed REVISION: 1 TEST SUITE: None
Die Installation sollte in den viel weiter oben angelegten Namespace cman hinein erfolgen. Dort sollten recht schnell ein Pod, Service, ConfigMap und andere Ressourcen zu sehen sein:
$ kubectl get configmap -n cman NAME DATA AGE my-cman-config 4 3m40s $ kubectl get service -n cman NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-cman-svc LoadBalancer 10.106.92.132 10.10.2.247 1521:30663/TCP 4m16s $ kubectl get pod -n cman NAME READY STATUS RESTARTS AGE my-cman-cman-6c7d9945d-bd92t 1/1 Running 0 5m6s
Und mit ein wenig Glück startet Ihr CMAN und Sie können anfangen, Datenbanken zu registrieren. Das sehen Sie an der Standard Log-Ausgabe des CMAN containers:
$ kubectl logs pod/my-cman-cman-6c7d9945d-bd92t -n cman
Defaulted container "app" out of: app, init-config (init)
12-06-2024 15:15:53 UTC : : Creating /tmp/orod.log
sudo: unable to send audit message: Operation not permitted
sudo: unable to send audit message: Operation not permitted
12-06-2024 15:15:53 UTC : : Using the user defined cman.ora file=[/scripts/cman.ora]
12-06-2024 15:15:53 UTC : : Copying CMAN file to /u01/app/oracle/product/23ai/client_1/network/admin
12-06-2024 15:15:55 UTC : : Starting CMAN
CMCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 06-DEC-2024 15:15:55
Copyright (c) 1996, 2024, Oracle. All rights reserved.
Current instance CMAN_my-cman-svc.cman.svc.cluster.local is not yet started
Connecting to (DESCRIPTION=(address=(protocol=tcp)(host=0.0.0.0)(port=1521)))
Starting Oracle Connection Manager instance CMAN_my-cman-svc.cman.svc.cluster.local. Please wait...
CMAN for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
Status of the Instance
----------------------
Instance name cman_my-cman-svc.cman.svc.cluster.local
Version CMAN for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
Start date 06-DEC-2024 15:15:56
Uptime 0 days 0 hr. 0 min. 9 sec
Num of gateways started 2
Average Load level 0
Log Level USER
Trace Level OFF
Instance Config file /u01/app/oracle/product/23ai/client_1/network/admin/cman.ora
Instance Log directory /u01/app/oracle/diag/netcman/my-cman-cman-6c7d9945d-bd92t/cman_my-cman-svc.cman.svc.cluster.local/alert
Instance Trace directory /u01/app/oracle/diag/netcman/my-cman-cman-6c7d9945d-bd92t/cman_my-cman-svc.cman.svc.cluster.local/trace
The command completed successfully.
12-06-2024 15:16:05 UTC : : Reloading CMAN
CMCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 06-DEC-2024 15:16:05
Copyright (c) 1996, 2024, Oracle. All rights reserved.
Current instance CMAN_my-cman-svc.cman.svc.cluster.local is already started
Connecting to (DESCRIPTION=(address=(protocol=tcp)(host=0.0.0.0)(port=1521)))
The command completed successfully.
12-06-2024 15:16:05 UTC : : Checking CMAN Status
CMCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 06-DEC-2024 15:16:05
Copyright (c) 1996, 2024, Oracle. All rights reserved.
Current instance CMAN_my-cman-svc.cman.svc.cluster.local is already started
Connecting to (DESCRIPTION=(address=(protocol=tcp)(host=0.0.0.0)(port=1521)))
Services Summary...
Proxy service "cmgw" has 1 instance(s).
Instance "cman", status READY, has 2 handler(s) for this service...
Handler(s):
"cmgw001" established:0 refused:0 current:0 max:256 state:ready
<machine: localhost, pid: 41>
(ADDRESS=(PROTOCOL=ipc)(KEY=#41.1)(KEYPATH=/var/tmp/.oracle_5432100))
"cmgw000" established:0 refused:0 current:0 max:256 state:ready
<machine: localhost, pid: 39>
(ADDRESS=(PROTOCOL=ipc)(KEY=#39.1)(KEYPATH=/var/tmp/.oracle_5432100))
Service "cmon" has 1 instance(s).
Instance "cman", status READY, has 1 handler(s) for this service...
Handler(s):
"cmon" established:1 refused:0 current:1 max:4 state:ready
<machine: localhost, pid: 33>
(ADDRESS=(PROTOCOL=ipc)(KEY=#33.1)(KEYPATH=/var/tmp/.oracle_5432100))
The command completed successfully.
12-06-2024 15:16:05 UTC : : cman [CMAN_my-cman-svc.cman.svc.cluster.local] started sucessfully
12-06-2024 15:16:05 UTC : : ################################################
12-06-2024 15:16:05 UTC : : CONNECTION MANAGER IS READY TO USE!
12-06-2024 15:16:05 UTC : : ################################################
12-06-2024 15:16:05 UTC : : cman started sucessfully
12-06-2024 15:15:53 UTC : : Using the user defined cman.ora file=[/scripts/cman.ora]
12-06-2024 15:15:53 UTC : : Copying CMAN file to /u01/app/oracle/product/23ai/client_1/network/admin
12-06-2024 15:15:55 UTC : : Starting CMAN
12-06-2024 15:16:05 UTC : : Reloading CMAN
12-06-2024 15:16:05 UTC : : Checking CMAN Status
12-06-2024 15:16:05 UTC : : cman [CMAN_my-cman-svc.cman.svc.cluster.local] started sucessfully
12-06-2024 15:16:05 UTC : : ################################################
12-06-2024 15:16:05 UTC : : CONNECTION MANAGER IS READY TO USE!
12-06-2024 15:16:05 UTC : : ################################################
12-06-2024 15:16:05 UTC : : cman started sucessfully
Schauen Sie sich gerne erst einmal im Container um. Verbinden Sie sich mit einer Shell und schauen Sie nach Verzeichnissen oder laden Sie die Konfiguration einmal neu zum Test. Dafür brauchen wir den Namen des Pods, den wir gerade vorhin mit “kubectl get pod -n cman” erfuhren und mit folgendem sinngemäßem kubectl Aufruf:
$ kubectl exec -it my-cman-cman-6c7d9945d-bd92t -n cman -- /bin/bash Defaulted container "app" out of: app, init-config (init) [oracle@my-cman-cman-6c7d9945d-bd92t ~]$
Jetzt befinden Sie sich innerhalb des Containers. Ein Aufruf von lsnrctl status zeigt Ihnen , dass es aktuell nur den cman Service gibt ohne registrierte Datenbanken.
Und Sie sehen auch das Verzeichnis im Container, in das hinein die Logs abgelegt werden. Das ORACLE_HOME ist immer gesetzt auf /u01/app/oracle/product/23ai/client_1 .
$ lsnrctl status LSNRCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 06-DEC-2024 15:32:10 Copyright (c) 1991, 2024, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=0.0.0.0)(PORT=1521))) STATUS of the LISTENER ------------------------ Alias cman_my-cman-svc.cman.svc.cluster.local Version TNSLSNR for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems Start Date 06-DEC-2024 15:15:56 Uptime 0 days 0 hr. 16 min. 14 sec Trace Level off Security OFF SNMP OFF Listener Parameter File /u01/app/oracle/product/23ai/client_1/network/admin/cman.ora Listener Log File /u01/app/oracle/diag/netcman/my-cman-cman-6c7d9945d-bd92t/cman_my-cman-svc.cman.svc.cluster.local/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521))) Services Summary... Proxy service "cmgw" has 1 instance(s). Instance "cman", status READY, has 2 handler(s) for this service... Service "cmon" has 1 instance(s). Instance "cman", status READY, has 1 handler(s) for this service... The command completed successfully [oracle@my-cman-cman-6c7d9945d-bd92t ~]$ echo $ORACLE_HOME /u01/app/oracle/product/23ai/client_1
Lassen Sie nun zum Test die Konfiguration des CMAN neu einlesen durch entsprechende cmctl Kommandos. Bitte beachten Sie dabei den Namen des angelegten CMAN, den Sie durch das lsnrctl status Kommando bereits erfuhren:
[oracle@my-cman-cman-6c7d9945d-bd92t ~]$ cmctl CMCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 06-DEC-2024 15:36:08 Copyright (c) 1996, 2024, Oracle. All rights reserved. Welcome to CMCTL, type "help" for information. CMCTL:CMAN_my-cman-cman-6c7d9945d-bd92t> admin cman_my-cman-svc.cman.svc.cluster.local Current instance cman_my-cman-svc.cman.svc.cluster.local is already started Connections refer to (DESCRIPTION=(address=(protocol=tcp)(host=0.0.0.0)(port=1521))). The command completed successfully. CMCTL:cman_my-cman-svc.cman.svc.cluster.local> reload The command completed successfully. CMCTL:cman_my-cman-svc.cman.svc.cluster.local> exit [oracle@my-cman-cman-6c7d9945d-bd92t ~]$ exit
Noch ein letzter Test: lassen Sie eine Datenbank beim CMAN registrieren, indem Sie deren REMOTE_LISTENER Parameter auf IP und Port des CMAN Containers bzw. dessen Load Balancer setzen. Erscheint der Datenbank-Service im CMAN, haben Sie eigentlich schon gewonnen. Vorausgesetzt, der Name der registrierten Datenbank ist vom CMAN aus auflösbar, also in umgekehrter Richtung als die Registrierung erfolgte. Damit das funktioniert muß ein entsprechender Eintrag im LOCAL_LISTENER Parameter der anzusprechenden Datenbank stehen. Ein Eintrag wie “localhost:1521” wäre beispielsweise vollkommen ungeeignet.
Um eine Datenbank bei CMAN testhalber zu registrieren musste ich zunächst herausfinden, welche Load Balancer Adresse dem CMAN zugeordnet war und diese im REMOTE_LISTENER Parameter meiner Datenbank einzutragen. Mein CMAN Service ist vom Typ LoadBalancer, daher erhielt er eine externe IP Adresse (die des Load Balancers) von 10.10.2.247:
$ kubectl get service -n cman NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-cman-svc LoadBalancer 10.106.92.132 10.10.2.247 1521:30663/TCP 2d18h
Dann verband ich mich mit meiner Datenbank bzw einer PDB meiner Wahl (chronin genannt in meinem Fall) als SYS Benutzer, trug auflösbare lokale und remote Adressen in der Datenbank Konfiguration ein und registrierte die Datenbank sowohl bei CMAN als auch beim lokalen Listener:
SQL> alter system set remote_listener='10.10.2.247:1521' sid='*' scope=both; System altered. SQL> alter system set local_listener='10.244.2.130:1521' sid='*' scope=both; System altered. SQL> alter system register ; System altered.
Dann öffnete ich in meiner Testumgebung wieder eine Shell zum CMAN Container und schaute nach, ob die Datenbank-Registrierung erfolgreich war:
$ kubectl exec -ti my-cman-cman-6c7d9945d-bd92t -n cman -- /bin/bash Defaulted container "app" out of: app, init-config (init) $ lsnrctl status LSNRCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 10-DEC-2024 10:58:33 Copyright (c) 1991, 2024, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=0.0.0.0)(PORT=1521))) STATUS of the LISTENER ------------------------ Alias cman_my-cman-svc.cman.svc.cluster.local Version TNSLSNR for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems Start Date 09-DEC-2024 12:34:36 Uptime 0 days 22 hr. 23 min. 57 sec Trace Level admin Security OFF SNMP OFF Listener Parameter File /u01/app/oracle/product/23ai/client_1/network/admin/cman.ora Listener Log File /u01/app/oracle/diag/netcman/my-cman-cman-6c7d9945d-tw7jr/cman_my-cman-svc.cman.svc.cluster.local/alert/log.xml Listener Trace File /u01/app/oracle/diag/netcman/my-cman-cman-6c7d9945d-tw7jr/cman_my-cman-svc.cman.svc.cluster.local/trace/cman_my-cman-svc_tnslsnr_206_139977477528512.trc Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521))) Services Summary... Proxy service "cmgw" has 1 instance(s). Instance "cman", status READY, has 2 handler(s) for this service... Service "28da2fd09e0c0fcbe0638202f40a6fbf" has 1 instance(s). Instance "ORCL1", status READY, has 1 handler(s) for this service... Service "chronin" has 1 instance(s). Instance "ORCL1", status READY, has 1 handler(s) for this service... Service "cmon" has 1 instance(s). Instance "cman", status READY, has 1 handler(s) for this service... The command completed successfully
Hier kann man sehen, dass der Datenbank-Service meiner PDB chronin erfolgreich registriert wurde. CMAN kennt nun den remote liegenden Datenbank Service. Ein cmctl Kommando “show services” listet weitere Details auf, z.B. den hoffentlich richtigen Host Namen / IP Adresse hinter dem Beispiel-Service chronin und sein Status ready, nicht etwa blocked:
$ cmctl
CMCTL for Linux: Version 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on 10-DEC-2024 11:23:25
Copyright (c) 1996, 2024, Oracle. All rights reserved.
Welcome to CMCTL, type "help" for information.
CMCTL> admin cman_my-cman-svc.cman.svc.cluster.local
Current instance cman_my-cman-svc.cman.svc.cluster.local is already started
Connections refer to (DESCRIPTION=(address=(protocol=tcp)(host=0.0.0.0)(port=1521))).
The command completed successfully.
CMCTL:cman_my-cman-svc.cman.svc.cluster.local> show services
Services Summary...
Proxy service "cmgw" has 1 instance(s).
Instance "cman", status READY, has 2 handler(s) for this service...
Handler(s):
"cmgw001" established:0 refused:0 current:0 max:256 state:ready
<machine: localhost, pid: 42>
(ADDRESS=(PROTOCOL=ipc)(KEY=#42.1)(KEYPATH=/var/tmp/.oracle_5432100))
"cmgw000" established:1 refused:0 current:0 max:256 state:ready
<machine: localhost, pid: 40>
(ADDRESS=(PROTOCOL=ipc)(KEY=#40.1)(KEYPATH=/var/tmp/.oracle_5432100))
Service "28da2fd09e0c0fcbe0638202f40a6fbf" has 1 instance(s).
Instance "ORCL1", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:1 refused:0 state:ready
REMOTE SERVER
(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=))(ADDRESS=(PROTOCOL=tcp)(HOST=10.244.2.130)(PORT=1521)))
Service "chronin" has 1 instance(s).
Instance "ORCL1", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:1 refused:0 state:ready
REMOTE SERVER
(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME=))(ADDRESS=(PROTOCOL=tcp)(HOST=10.244.2.130)(PORT=1521)))
Service "cmon" has 1 instance(s).
Instance "cman", status READY, has 1 handler(s) for this service...
Handler(s):
"cmon" established:5 refused:0 current:1 max:4 state:ready
<machine: localhost, pid: 34>
(ADDRESS=(PROTOCOL=ipc)(KEY=#34.1)(KEYPATH=/var/tmp/.oracle_5432100))
The command completed successfully.
Ein Client-Connect mit sqlplus an die Load Balancer Adresse und dem registrierten Service chronin müßte nun funktionieren:
$ sqlplus system@//10.10.2.247:1521/chronin SQL*Plus: Release 21.0.0.0.0 - Production on Tue Dec 10 10:49:25 2024 Version 21.16.0.0.0 Copyright (c) 1982, 2022, Oracle. All rights reserved. Enter password: Last Successful login time: Mon Dec 09 2024 16:43:07 +00:00 Connected to: Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production Version 21.3.0.0.0 SQL>
Falls der Connect auch in Ihrer Umgebung funktioniert: herzlichen Glückwunsch! Sie sind erfolgreich am Ende dieses Blogs angekommen.
Falls das in Ihrer Umgebung nicht funktioniert noch ein paar Tipps für Sie: prüfen Sie bitte nach ob der registrierte Service einen korrekten Host-Namen verwendet und ob der Listener auf Ihrem Datenbank-Host die Registrierung akzeptierte. Ein “show services” Kommando in cmctl zeigt die registrierten Services mit ihren hoffentlich richtigen Connect Strings und das listener.log auf Ihrem Datenbank-Host meldet Fehler bei der Registrierung des lokalen Service. Ein in CMAN registrierter Service, der aber beim lokalen Listener nicht registriert wurde, wird beim cmctl Kommando “show services” als blocked markiert. Es kann aber mehrere Gründe für blockierte Services geben, z.B. wird ein per Konfiguration nicht erlaubtes Protokoll benutzt (tcp statt tcps) und weitere Möglichkeiten.
Fazit und Ausblick
So ein scheinbar einfacher Container wie CMAN bietet zwei zu überwindende Hürden. Seine besondere Netzwerk-Konfiguration und seine nicht vorhandene Zustandslosigkeit oder auch statefulness. Er ist trotz seiner geringen Größe so wertvoll zu behandeln wie ein Datenbank-System, sprich vor Ausfall zu sichern und möglichst selten durchzustarten. Er darf sich zu keinem SPOF (single point of failure) durch zu geringfügige Konfiguration entwickeln, weder unter Kubernetes noch sonstwo. Für die Fernwartung des CMAN wäre ein funktionisfähiger REST Service Zugang auch im Container wünschenswert. Aber der Container läuft unter Kubernetes und erfüllt seinen Zweck im Gemenge der “Datenbank Satelliten” ORDS, GoldenGate, Observability Exporter und Co. Eine Einschränkung hinsichtlich erhöhter Latenz im standardmäßigen Kubernetes Netzwerk war bei unseren Tests tatsächlich nicht spürbar, trotz Overlay-Netzwerk. Weitere helm charts zu anderen Oracle Komponenten werden in weiteren Blogs nachfolgen.
Und nun wie immer: viel Spaß beim Testen und Ausprobieren !
In diesem Text verwendete Links:
Dokumentation des Oracle Connection Managers 23ai
Blog zum VM-basierten Setup des Connection Managers von Sinan Petrus Toma
Container des Connection Managers 23ai auf container-registry.oracle.com
Container Build Skripte für den Connection Manager auf github.com
Helm Chart Quellcode für den Connection Manager auf github.com