Oracle GoldenGate unterstützt ab Version 23ai ausschliesslich eine Microservices Architektur mit eleganterem Browser Interface und REST services für Konfiguration , Betrieb und Skript-Automatisierung. Es passt jedoch nicht nur thematisch sehr gut, GoldenGate in einer typischen Laufzeitumgebung für Microservice Architekturen zu betreiben.
Warum also ist GoldenGate als Container unter Kubernetes so sinvoll?
- Es kann schnell zu einer größeren Zahl an GoldenGate Installationen kommen, die untereinander Daten-Logs austauschen: eine Installation pro Datenbank-Typ wie Postgres, Oracle, MySQL, SQL Server, DB2, BigData-typische Systeme wie MongoDB, Kafka usw. ist wegen der jeweils anderen enthaltenen Treiber und Extraktions/Applikations – Logik notwendig. Vielleicht möchten Sie darüberhinaus Testumgebungen von Produktiv-Umgebungen trennen ? Ein vielpropagiertes GoldenGate “Mesh” ist nicht nur über Rechenzentrumsgrenzen hinweg sinnvoll.
- Die GoldenGate 23ai “free” Edition kommt mit einem sehr ansprechenden Wizard daher, der bei Oracle Datenbanken alle nötigen Prüfungen und Einrichtungen durchführt wie Datenbank-Parameter, Benutzer und Berechtigungen, Checkpoint- und Heartbeat-Tabellen usw. Die “free” Edition könnte zusätzlich zu “full use” Installationen zwecks initialer Einrichtung verschiedener Oracle Datenbanken verwendet werden.
- Eine empfohlene best practise “advanced” Installation von GoldenGate ist in jedem Container bereits vorbereitet und in die eigene Infrastruktur einbindbar. So werden alle GoldenGate Microservices im Container hinter einem nginx Reverse Proxy zusammengefaßt und SSL Zertifikate vorab erzeugt und eingerichtet – mit der Möglichkeit, diese unter Kubernetes sehr leicht durch eigene auszutauschen. Beim Container-Start wird ein GoldenGate-eigenes “Deployment” automatisch eingerichtet, d.h. die Software Installation wird mit default Werten konfiguriert und man kann gleich beginnen, die Daten-Syncs einzurichten. Es bleibt nur die Angabe des Deployment-Namens und eines Admin-Benutzers mit Wunschkennwort.
- Technisch ist es ab Version 23ai viel einfacher möglich, GoldenGate unter Kubernetes zu betreiben. Ältere Versionen benötigten zwingend das Vorhandensein von Swap-Speicher und ließen sich ohne ihn nicht (vollständig) starten. Erst neuere Kubernetes Versionen (>=1.26) bieten Swap-Speicher für die anvertrauten Container an, aber vorerst nur als experimentelles Feature. Die neue GoldenGate 23ai Version erkennt beim Start, wenn kein Swap vorhanden ist und nutzt ihn dann auch nicht.
- In Ihrem Kubernetes Cluster wird sicherlich eine typische Umgebung für das Monitoring darin betriebener Container genutzt. Meist auf Basis von Prometheus und Grafana oder influxdb und Grafana. GoldenGate 23ai bietet die Möglichkeit, seine ohnehin gemessenen Metriken zu exportieren und so aus einem vorhandenen “Mesh” in ein zentraleres Überwachungssystem zusammenzuführen.
Was ist zu tun, um GoldenGate 23ai unter Kubernetes zu betreiben?
Eine Erklärung mit mehreren Beispielen:
- Ein Container Image mit einer “advanced” Installation darin erzeugen
- Ein Kubernetes Deployment mit persistentem Storage und Netzwerk Zugang definieren
- An ein Monitoring-System anbinden, den Metrik-Export aktivieren
Ein Container Image mit einer “advanced” Installation darin erzeugen
Alternative 1: Oracle bietet die GoldenGate “free” Edition als fertiges Container Image zum Download von der offiziellen Oracle Container Registry an.
Schauen Sie gerne einmal auf der zugehörigen Webseite vorbei: https://container-registry.oracle.com/ords/ocr/ba/goldengate/goldengate-free

Per docker oder podman “pull” Kommando erhalten Sie das Image direkt von Oracle, oder Sie übertragen dieses Image nach dem Download in Ihr eigenes Repository.
Nachfolgende Kommandos müssen Sie nicht zwingend ausführen, denn den “pull” übernimmt Kubernetes für Sie. Merken Sie sich aber gerne die URLs für später.
# herunterladen podman pull container-registry.oracle.com/goldengate/goldengate-free:latest # umbenennen bzw. einen zusätzlichen tag anhängen podman tag container-registry.oracle.com/goldengate/goldengate-free:latest my-internal-registry.fancy.name/goldengate/goldengate-free:latest # hochladen podman push my-internal-registry.fancy.name/goldengate/goldengate-free:latest
Die “free use” Lizenz für GoldenGate free besagt, daß es auch produktiv kostenlos eingesetzt werden darf, jedoch nur für Oracle Datenbanken die nicht größer sind als 20 GB Gesamtgröße inklusive aller pluggable databases und der container database. Aber da wäre ja noch der komfortable Wizard enthalten zur Einrichtung von Oracle Datenbanken für GoldenGate! Der Wizard wird in diesem Blog Beitrag näher beschrieben.
Alternative 2: Oracle bietet offizielle Skripte an, um eigene Docker Images für GoldenGate zu erzeugen. Damit können auch Images für non-Oracle Datenbankzugriffe wie Postgres, DB2 usw. generiert werden.
Laden Sie zunächst die Container build Skripte für alle möglichen Oracle Produkte auf ein Linux-System Ihrer Wahl herunter:
git clone https://github.com/oracle/docker-images cd docker-images/OracleGoldenGate/23
Im nun aktuellen Unterverzeichnis “docker-images/OracleGoldenGate/23” finden Sie eine README.md Datei mit weiteren Instruktionen um das Image zu erzeugen und als Container in Betrieb zu nehmen. Ohne Kubernetes. Aber darum kümmern wir uns gleich.
Laden Sie zunächst die gewünschte GoldenGate Software für Linux 64bit als .zip Datei von edelivery.oracle.com herunter – je nachdem ob Sie eine Variante für Oracle, Postgres, DB2 usw haben möchten. Suchen Sie nach “GoldenGate” und wählen Sie dann Version 23.4 , Linux 64bit, und Ihr jeweiliges Datenbanksystem. GoldenGate für BigData(Kafka,MongoDB,Snowflake,…) trägt bereits Versionsnummer 24.2.1 anstelle von 23 und heißt nunmehr “GoldenGate for Distributed Applications and Analytics” ! Über den darin ebenfalls enthaltenen neuen Transaktionsmanager microTX bzw. otmm folgt noch ein weiterer Beitrag..


Die heruntergeladenen Dateien tragen Namen wie V1041909-01.zip (=GG4Postgres) , V1042871-01.zip (=GG4Oracle) , V1043063-01.zip (=GG4MySQL) und so weiter.

Belassen Sie die Dateien so wie sie sind ohne sie zu entpacken. Achten Sie bitte darauf, daß Ihre Wunschdatei im gleichen Verzeichnis liegt wie Ihr Arbeitsverzeichnis, und das sollte “docker-images/OracleGoldenGate/23” sein.
Erzeugen Sie nun das Container Image durch Angabe Ihres heruntergeladenen Wunsch-Zips als Parameter. Unser Beispiel verwendet GoldenGate 23ai auf Linux 64Bit für Oracle Datenbanken, also V1042871-01.zip:
podman build --tag=oracle/goldengate_oracle:23.4 --build-arg INSTALLER=V1042871-01.zip .
Und laden Sie nach ein paar Minuten der Software-Installation bzw. Image-Erzeugung dieses in Ihr eigenes Repository hoch, z.B. wie folgt:
podman tag oracle/goldengate_oracle:23.4 my-internal-registry.fancy.name/goldengate/goldengate_oracle:23.4 podman push my-internal-registry.fancy.name/goldengate/goldengate_oracle:23.4
Schauen Sie gerne in die “Dockerbuild” Datei hinein und in die beigefügten Skripte. Die GoldenGate Software wird innerhalb des Containers als neu angelegter Benutzer “ogg” ausgeführt, die Start-Skripte selbst jedoch als root-Benutzer um zusätzliche Prozesse wie nginx anzustoßen.
Fertig! Sie können nun eines der GoldenGate Container Images gerne lokal starten , indem Sie per Umgebungsvariablen und Volume mounts Angaben zur Konfiguration einer vollwertigen “advanced” Installation machen. Wie das geht steht im README.md in Ihrem Arbeitsverzeichnis. Aber gehen wir lieber gleich weiter in eine “richtige” Laufzeitumgebung wie Kubernetes und versuchen uns dort.
Ein Kubernetes Deployment mit persistentem Storage und Netzwerk Zugang definieren
Angaben zum Storage, Umgebungsvariablen und Netzwerk erfolgen in YAML Dateien, die Sie mittels “kubectl apply -f <Dateiname>” in Ihr Kubernetes Cluster übertragen.
Vorschlag Nummer eins wäre ein Deployment des GoldenGate Containers und nicht nur ein einzelner POD, um z.B. einen rollierenden Austausch eines laufenden Containers durch eine neuere Version zu ermöglichen. Die YAML Datei (z.B. “gg-deploy.yaml”) sähe wie folgt aus:
dsfsdfapiVersion: apps/v1 kind: Deployment metadata: labels: app: goldengate_eastcoast instance: goldengate_oracle_23.4.0 name: goldengate-oracle-eastcoast namespace: goldengate spec: replicas: 1 selector: matchLabels: app: goldengate_eastcoast instance: goldengate_oracle_23.4.0 template: metadata: labels: app: goldengate_eastcoast instance: goldengate_oracle_23.4.0 spec: containers: - env: - name: OGG_DEPLOYMENT value: EastCoastDeployment - name: OGG_ADMIN valueFrom: secretKeyRef: key: oggadmin name: ogg-admin-secret - name: OGG_ADMIN_PWD valueFrom: secretKeyRef: key: oggadminpwd name: ogg-admin-secret image: container-registry.oracle.com/goldengate/goldengate-free:latest imagePullPolicy: IfNotPresent name: app ports: - containerPort: 443 name: ggate protocol: TCP volumeMounts: - mountPath: /u01/ogg/scripts name: u01 - mountPath: /u02 name: u02 - mountPath: /u03 name: u03 volumes: - name: u01 persistentVolumeClaim: claimName: ogg-oracle-eastcoast-u01-pvc - name: u02 persistentVolumeClaim: claimName: ogg-oracle-eastcoast-u02-pvc - name: u03 persistentVolumeClaim: claimName: ogg-oracle-eastcoast-u03-pvc
Kurz erklärt bedeutet dies:
- Das Deployment erfolgt in den Namespace “goldengate”. D.h. er sollte zuerst angelegt werden bevor dieses Deployment angestoßen wird.
- Als Container Image wird das offizielle “free” Image von container-registry.oracle.com verwendet.
- Der Wunsch-Name des GoldenGate Deployments lautet “EastCoastDeployment” und wird per Umgebungsvariable an den Container übergeben.
- Der Wunsch-Benutzer und dessen Wunsch-Kennwort werden nicht direkt angegeben, sondern kommen aus einem Kubernetes “Secret”.
- Kubernetes öffnet den SSL Port 443 zum Container hin, dort lauscht übrigens der NGINX proxy. Dieser leitet intern an die laufenden GoldenGate Prozesse weiter und setzt HTTP Header nach Bedarf. NGINX terminiert den SSL Verkehr, d.h. es sind keine Zertifikate in und durch GoldenGate zu verwalten. Das machen NGINX und Kubernetes.
- Die Verzeichnisse /u01 , /u02 und /u03 werden als Volume eingebunden. Dort werden beim erstmaligen Start die Konfiguration abgelegt, Log Dateien, tnsnames.ora und sqlnet.ora bei Bedarf, und später die Trail-Dateien für den Datenbank-Sync. Ein weiteres Volume kann gerne unter /etc/nginx/cert eingebunden werden, welches auf in Kubernetes abgelegte und aktualisierte Zertifikate verweist. Im Moment arbeiten wir jedoch mit on-the-fly erzeugten self-signed Zertifikaten…
Wenn wir nun die nötigen Kommandos absetzen um den Namespace anzulegen und das Deployment anzuwerfen…
kubectl create namespace goldengate kubectl apply -f gg-deploy.yaml // und prüfen, ob sich etwas tut kubectl get pods -n goldengate
…dann merken wir, es passiert scheinbar nichts, zumindest ist kein laufender Pod vorhanden. Kubernetes wartet auf weitere Angaben, denn das per Secret einzubindende Kennwort und die angefragte Storage fehlen noch. Entsprechende Meldungen können Sie dem Event Log entnehmen: kubectl get events -n goldengate.
Das Kubernetes Secret mit Wunsch-Kennwort und Wunsch-Benutzer (einigen wir uns auf den Dateinamen ogg-secret.yaml) könnte wie folgt aussehen. Kubernetes Secrets dürfen auch auf externe Key Vault Lösungen verweisen wie der Vault Service in der Oracle Cloud , Hashicorp Vault oder andere:
apiVersion: v1 kind: Secret type: Opaque metadata: name: ogg-admin-secret namespace: goldengate stringData: oggadmin: oggadmin oggadminpwd: OGGadmin123!
Dann holen wir drei Persistent Volume Claims heran, damit Kubernetes die Volumes anlegt , bereitstellt und dem Deployment anhängt. Der Dateiname dafür könnte ogg-pvc.yaml sein:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ogg-oracle-eastcoast-u01-pvc namespace: goldengate spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: rook-ceph-block --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ogg-oracle-eastcoast-u03-pvc namespace: goldengate spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: rook-ceph-block --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ogg-oracle-eastcoast-u03-pvc namespace: goldengate spec: accessModes: - ReadWriteOnce resources: requests: storage: 50Gi storageClassName: rook-ceph-block
Über die hier verwendeten Storage Class und Größen läßt sich gerne viel disktieren. Lassen Sie die Storage Class Angabe weg, wird eine default storage Class verwendet, insofern eine vorhanden ist. In meiner Umgebung existiert eine “rook-ceph-block” Storage Class, die auf eine recht typische Storage Lösung für OnPrem Kubernetes verweist. In der Oracle Cloud wäre dies eher “oracle-bv” (Oracle Block Volume) oder es gibt in Ihrem Cluster gleich mehrere Storage Classes zur Auswahl, z.B. für langsam und günstig oder schnell und teuer.
Die Größenangaben sollten genügen. Vor allem müssen die anfallenden Logs und noch wichtiger die Trail Dateien des Datensyncs ordentlich Platz finden. Eine produktive Datenbank erzeugt gerne mehrere Gigabytes an Sync-Daten pro Stunde , die mit der gewünschten Lagerzeit der Trail Dateien (retention time, gewöhnlich mehrere Tage) zu multiplizieren ist.
Falls noch nicht geschehen ist es jetzt an der Zeit, die beiden Dateien abzusenden und Kubernetes sein Werk vollbringen zu lassen:
kubectl apply -f ogg-secret.yaml kubectl apply -f ogg-pvc.yaml kubectl get pvc -n goldengate NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE ogg-oracle-eastcoast-u01-pvc Bound pvc-0cb3936a-b782-45a8-8487-728a91b71b4d 10Gi RWO rook-ceph-block 7d1h ogg-oracle-eastcoast-u02-pvc Bound pvc-1c714fad-b6e1-49a0-9d52-3240a22a741a 10Gi RWO rook-ceph-block 7d1h ogg-oracle-eastcoast-u03-pvc Bound pvc-9315996b-2ab3-4002-baf0-a61d3cb9d059 10Gi RWO rook-ceph-block 7d1h kubectl get secret -n goldengate NAME TYPE DATA AGE ogg-admin-secret Opaque 2 7d1h kubectl get deployment -n goldengate NAME READY UP-TO-DATE AVAILABLE AGE goldengate-oracle-eastcoast 1/1 1 1 7d1h # Problem-Suche z.B. mit # kubectl get events -n goldengate # falls der Download nicht klappt oder die Volumes nicht angelegt werden
So weit, so gut. Es fehlt nur noch am Netzwerk-Zugang, denn wie kommt man mit dem Browser nun an die GoldenGate REST services heran oder an das User Interface ?
Beispiel-Methode 1:
Die brutal anmutende Methode ist, sich den aktuellen Namen des laufenden POD zu erfragen und mittels “kubectl port-forward” den Port 443 auf den lokalen Rechner zu tunneln. Gut für einen schnellen Test, mehr aber normalerweise nicht:
> kubectl get pod -n goldengate NAME READY STATUS RESTARTS AGE goldengate-oracle-eastcoast-5f9ffcd5dd-5qtds 1/1 Running 0 31h > kubectl port-forward goldengate-oracle-eastcoast-5f9ffcd5dd-5qtds -n goldengate 8443:443 & Forwarding from 127.0.0.1:8443 -> 443 Forwarding from [::1]:8443 -> 443 > curl https://127.0.0.1:8443 --insecure Handling connection for 8443 <html> <head><title>302 Found</title></head> <body> <center><h1>302 Found</h1></center> <hr><center>nginx/1.22.1</center> </body> </html>
Wenn diese Art von Output erscheint, d.h. ein von nginx innerhalb des GoldenGate Containers erzeugter Forward, dann funktioniert der Zugang prinzipiell und Sie können mit einem lokalen Browser auf dieselbe localhost-URL zugreifen. Sie werden dann an die GoldenGate Login Seite weitergeleitet.
Beispiel Methode 2:
Um die GoldenGate UI permanent per Browser zugänglich zu machen gibt es mehrere Möglichkeiten. Die Basis ist stets eine Kubernetes “Service” Ressource, die für Port-Weiterleitung zum Container und für die Namensauflösung im kubernetes-internen Netzwerk zuständig ist. Ist dieser Service vom Typ “LoadBalancer”, erhält er eine Cluster-externe IP Adresse und kann direkt von einem Browser angesprochen werden. So sähe eine entsprechende Service-Definition aus:
apiVersion: v1 kind: Service metadata: name: goldengate-oracle-eastcoast namespace: goldengate spec: ports: - port: 8888 protocol: TCP targetPort: 443 selector: app: goldengate_eastcoast instance: goldengate_oracle_23.4.0 type: LoadBalancer
Der Service öffnet den Port 8888 und leitet innerhalb des Containers an Port 443, d.h. SSL verschlüsselt weiter. Es werden die von nginx verwalteten und per Skript erzeugten Zertifikate benutzt (unter /etc/nginx/cert im container liegend). Es wäre an der Stelle “targetPort” auch Port 80 möglich, reines HTTP ohne Verschlüsselung. Der hier definierte Service bindet sich an alle Container deren Metadaten den Angaben im “selector” Feld entsprechen (unabhängig vom Host, interner IP Adresse und Zahl der Replica). Mit einem “kubectl get service” Kommando erhalten Sie die zugeteilten internen und externen IP Adressen und können direkt mit Ihrem Browser darauf zugreifen. Eventuell dauert es einige Zeit, bis eine offizielle IP Adresse zugewiesen wurde. Solange verbleibt die external-IP auf dem Status PENDING.
> kubectl get service goldengate-oracle-eastcoast -n goldengate NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE goldengate-oracle-eastcoast LoadBalancer 10.104.101.13 130.61.137.234 8888/TCP 9d
Anstelle von reinen IP Adressen werden zu Textzwecken oft gern auflösbare Names-Adressen des .nip.io Dienstes verwendet. Aus der externen IP Adresse 130.61.137.234 wird dann ein nicht ganz beliebiger aber sprechender Name wie zum Beispiel ggeast.130.61.137.234.nip.io.

Beispiel-Methode 3:
Meist wird jedoch aus mehreren guten Gründen vor den Service ein Routing-Dienst geschaltet. Eine Schleuse, die nach außen hin nur wenige IP Adressen belegt und nach Kubernetes hinein aufgrund von IP Namen und / oder URIs an jeweilige Container weiterleitet, internen Netzverkehr verschlüsselt, SSL-terminiert, Logins prüft und Identitäten einfügt, Netzwerk Monitoring ermöglicht und vieles mehr. Dazu sollten vorab Netzwerk-Ressourcen in Ihrem Cluster installiert sein wie istio, nginx oder andere die als Provider für Kubernetes Ingress Ressourcen fungieren oder ganz eigene Routing Implementationen bieten. Hier ein diskussionsfähiges aber nicht unbedingt lauffähiges Beispiel für einen ClusterIP Service, an den über ein istio Gateway weitergeleitet wird. Die Routing Konfiguration erfolgt durch das Anlegen eines istio VirtualService.
apiVersion: v1
kind: Service
metadata:
name: goldengate-oracle-eastcoast
namespace: goldengate
spec:
ports:
- port: 8888
protocol: TCP
targetPort: 80
selector:
app: goldengate_eastcoast
instance: goldengate_oracle_23.4.0
type: ClusterIP
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: goldengate-oracle-eastcoast
namespace: goldengate
spec:
gateways:
- istio-system/http-istio-gateway
hosts:
- ggeast.141.147.33.99.nip.io
http:
- match:
- uri:
prefix: /
route:
- destination:
host: goldengate-oracle-eastcoast
port:
number: 8888
Der VirtualService verläßt sich in diesem Beispiel darauf, daß das istio Gateway die externe IP Adresse 141.147.33.99 erhalten hat und verwendet diese Adresse für das Routing: alle Anfragen an den Hostnamen ggeast.141.147.33.99.nip.io werden an den GoldenGate Service weitergeleitet, der hier namentlich eingetragen wurde: goldengate-oracle-eastcoast.Tragen Sie in Ihrer Umgebung gerne die externe IP Adresse Ihres istio ingress-Gateways ein. Um diese herauszufinden genügt ein kurzer Aufruf von kubectl get service:
> kubectl get service -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-egressgateway ClusterIP 10.96.229.150 <none> 80/TCP,443/TCP,15443/TCP 188d istio-ingressgateway LoadBalancer 10.105.6.214 141.147.33.99 15021:31062/TCP,80:31127/TCP,443:32163/TCP,15012:30128/TCP,15443:30106/TCP 188d istiod ClusterIP 10.101.106.218 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 188d
Das istio Gateway selbst könnte die SSL Verschlüsselung und Terminierung übernehmen und jeglichen Netzverkehr an den unverschlüsselten Port 80 im GoldenGate Container weiterleiten. Außerdem ermöglicht istio eine transparente on-the-fly Verschlüsselung des internen Netzverkehrs, damit sich die einzelnen Container nicht selbst um Verschlüsselung kümmern müssen (istio auto-injection genannt). Die Beispiel Konfiguration eines istio Gateways mit SSL Terminierung könnte wie folgt aussehen:
kind: Gateway name: http-istio-gateway namespace: istio-system spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http number: 443 protocol: HTTPS tls: credentialName: istio-tls mode: SIMPLE
Kurz erklärt würde das istio Gateway auf alle Anfragen auf Port 443 reagieren und per HTTPS nach außen kommunizieren. Die SSL Zertifikate stammen aus einem Kubernetes “Secret” namens istio-tls und könnten von einem kubernetes Dienst wie cert-manager erzeugt und aktualisiert werden. Ohne weitere Konfiguration wie z.B. passende DestinationRules spräche dieses Gateway mit unverschlüsselten oder on-the-fly verschlüsselten Containern.
Beispiel-Methode 4:
Neuere Kubernetes Versionen bieten eine eigene Ingress-Ressource an, die ähnlich funktioniert wie ein istio VirtualService in Beispiel-Methode 3. Nur läßt sich dabei zusätzlich wählen, wer den Ingress implementiert – istio , nginx oder ein anderer Dienst. Auch hier folgt eine diskutierfähige und nicht unbedingt in Ihrer Umgebung lauffähige Beispiel-Konfiguration. Es wird der gleiche Service als Basis benutzt wie in Beispiel-Methode 3. Es wird ebenfalls eine Installation des istio-Paketes vorausgesetzt. Statt eines VirtualService wird hier eine IngressClass und ein state-of-the-art Kubernetes Ingress definiert:
apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: istio spec: controller: istio.io/ingress-controller --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress namespace: goldengate spec: ingressClassName: istio rules: - host: ggeast.141.147.33.99.nip.io http: paths: - path: / pathType: Prefix backend: service: name: goldengate-oracle-eastcoast port: number: 8888 --- apiVersion: v1 kind: Service metadata: name: goldengate-oracle-eastcoast namespace: goldengate spec: ports: - port: 8888 protocol: TCP targetPort: 80 selector: app: goldengate_eastcoast instance: goldengate_oracle_23.4.0 type: ClusterIP
Soviel zum Deployment und damit zur Anbindung von Netzwerk und Storage. Wenn Sie möchten ist hier bereits das Ende des Beitrages erreicht, denn GoldenGate sollte nun laufen und ansprechbar sein. Eine Integration von GoldenGate mit einem Identity Management System wie der Oracle Identity Cloud (oder denkbar auch mit keycloak) ist ein separates, weiterführendes Thema und wird beispielhaft in einem Blog unseres GoldenGate Product Managements beschrieben. Eine GoldenGate Mesh Installation und wie GoldenGate Container sich untereinander verbinden um Sync-Daten auszutauschen wird ebenfalls Teil eines anderen Blog Eintrages. Doch was auf jeden Fall noch zu beleuchten wäre: wie läßt sich GoldenGate in ein für Kubernetes typisches Monitoring mit Grafana, Prometheus und Co. einbinden ?
GoldenGate an ein (Kubernetes) Monitoring-System anbinden
Jede GoldenGate Installation bietet von sich aus einen Performance Metrics Dienst, eingebettet in das GoldenGate User Interface. Dieser zeigt umfassende Metriken zum Disk I/O, Speicherverbrauch, Netzwerk I/O, betroffene Tabellen, Datenoperationen, Zeitversatz (Lag) des Daten-syncs und noch einiges mehr. Allerdings lassen sich dort nur aktuelle Werte einsehen bzw. Werte seit Aufruf des User Interface – und nur so lange, bis der Hauptspeicher Ihres JavaScript-fähigen Browsers zur Neige geht oder die HTTP Session ausläuft, was auch immer zuerst geschieht.


Um alle GoldenGate Installationen in einer Monitoring Umgebung zusammenzufassen und auch einmal historische Daten der letzten Tage einzusehen ist die Einbindung einer Monitoring Umgebung vonnöten und wird seitens GoldenGate selbstverständlich unterstützt. Um alle seine Metriken an ein externes Monitoring System zu übertragen ist lediglich ein kleiner zusätzlicher Konfigurations-Eintrag notwendig.
Das Metrik-Format lautet hier “statsd“, die Metriken werden per UDP Protokoll an einen nennbaren Container versandt, der das Format beherrscht. Z.B. kommt mit “influxDB” eine Datenbank Engine mit Plugin für statsd Daten (telegraf) und Schnittstelle zum Analyse Werkzeug Grafana. Dieser Weg wird in einem Blog Eintrag unseres GoldenGate Product Management erklärt. Unser nun folgendes Beispiel geht einen sehr ähnlichen Weg, jedoch über die klassischere Variante mit einer Prometheus Datenbank, Grafana und einem automatischen Konverter vom statsd Format in das Prometheus Format (statsd-exporter, Teil des Prometheus Projektes).
Grundsätzlich kann eine GoldenGate Konfiguration mit ihren Artefakten wie Extracts, Replicats, Connections, Distribution Paths usw. über REST Service Aufrufe automatisiert und geskriptet werden. Ein solcher REST Service Aufruf ist auch notwendig, um nachträglich den Metrik Export zu aktivieren. Zunächst lesen wir die bestehende Konfiguration inklusive Metrik Behandlung aus. Je nach gewählter Netzwerkanbindung passen Sie bitte Ihre verwendete URL entsprechend an. Der Aufruf Pfad bleibt gleich inklusive des Deployment-Namens. Benutzername und Kennwort dürften sich zu Ihrer gewählten Umgebung ebenfalls unterscheiden:
> curl https://ggeast.141.147.33.99.nip.io/services/v2/deployments/EastCoastDeployment --insecure --user "oggadmin:OGGadmin123!"|jq
...
... jede Menge Output, aber auch Angaben zu Metriken wie:
"metrics": {
"servers": [
{
"protocol": "uds",
"socket": "PMSERVER.s",
"type": "pmsrvr"
}
],
"enabled": true
},
...
...
Kopieren Sie sich den Metrics-Anteil des JSON Dokumentes und erzeugen Sie ein neues Dokument, in das Sie sowohl den Namen eines noch zu installierenden Metrik Dienstes eintragen (statsd-exporter-service) als auch den curl-Aufruf ändern in eine PATCH Anweisung, um den GoldenGate Server umzukonfigurieren. Der nun abzusetzende REST Service Aufruf sieht in etwa wie folgt aus:
curl -X PATCH \
https://ggeast.141.147.33.99.nip.io/services/v2/deployments/EastCoastDeployment \
--user oggadmin:OGGadmin123! \
--insecure \
-H 'Cache-Control: no-cache' \
-d '{
"metrics": {
"servers": [
{
"protocol": "uds",
"socket": "PMSERVER.s",
"type": "pmsrvr"
},
{
"type":"statsd",
"host":"statsd-exporter-service"
}
],
"enabled": true
}
}'
Starten Sie nun den GoldenGate Container durch, indem sie den POD löschen. Kubernetes startet automatisch einen neuen POD nach.
> kubectl get pods -n goldengate NAME READY STATUS RESTARTS AGE goldengate-oracle-eastcoast-5f9ffcd5dd-5qtds 1/1 Running 1 4d6h > kubectl delete pod goldengate-oracle-eastcoast-5f9ffcd5dd-5qtds -n goldengate > kubectl get pods -n goldengate NAME READY STATUS RESTARTS AGE goldengate-oracle-eastcoast-5f9ffcd5dd-54f7t 1/1 Running 0 6s
Ohne weitere Angaben versendet GoldenGate nun seine Metriken an den Kubernetes Dienst statsd-exporter-service per UDP Protokoll auf Port 8125. Daß an dieser Adresse noch kein Container lauscht macht nichts weiter aus und erzeugt auch keine Fehler – diese Art von Toleranz ist typisch für das UDP Protokoll. Sorgen wir nun dafür, daß der statsd-exporter installiert wird und er die Metriken entgegennimmt.
Für Tests ist ein separates Kubernetes Deployment denkbar. Später ist es sinnvoller wenn der statsd-exporter als sogenanntes sidecar eingerichtet und somit ein Teil des GoldenGate POD wird.
Folgendes Deployment und zugehöriger Service sind denkbar:
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/instance: statsd-exporter app.kubernetes.io/name: statsd-exporter-prometheus name: statsd-exporter-prometheus namespace: goldengate spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: statsd-exporter app.kubernetes.io/name: statsd-exporter-prometheus template: metadata: labels: app.kubernetes.io/instance: statsd-exporter app.kubernetes.io/name: statsd-exporter-prometheus spec: containers: - image: docker.io/prom/statsd-exporter:latest imagePullPolicy: Always args: ["--statsd.mapping-config", "/config/statsd-mapping.yaml", "--log.level", "debug"] name: app ports: - containerPort: 9102 name: http protocol: TCP - containerPort: 9125 name: push protocol: UDP volumeMounts: - mountPath: /config name: config volumes: - name: config configMap: defaultMode: 420 name: statsd-mapping-config --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/instance: statsd-exporter app.kubernetes.io/name: statsd-exporter-prometheus-service app: gg23ai-east name: statsd-exporter-service namespace: goldengate spec: ports: - port: 8125 protocol: UDP targetPort: 9125 name: push - port: 9102 protocol: TCP targetPort: 9102 name: http selector: app.kubernetes.io/instance: statsd-exporter app.kubernetes.io/name: statsd-exporter-prometheus type: ClusterIP
Der standardmäßige statsd-exporter Container lauscht (intern) auf UDP Port 9125, GoldenGate sendet seine Metriken per default an Port 8125. Die Service Definition verknüpft die beiden Ports miteinander. Der angegebene debug log level Parameter kann später wieder entfernt werden. Zunächst ist es aber wichtig zu sehen, ob überhaupt Metriken von GoldenGate im Container ankommen.
Es fehlt noch eine weitere Datei (in einer sogenannten ConfigMap mit Namen statsd-mapping-config) mit normalerweise unnötigen Angaben zur Umbenennung bzw. zum Mapping der Metrik Daten in ein eigenes Wunsch-Format. Der default ist jedoch prometheus als Zielformat. Die Metriken sollten idealerweise noch genauso heißen und funktionieren wie in der GoldenGate Dokumentation für statsd Metriken aufgeführt. Geben wir dennoch eine zugegeben recht leere Konfigurationsdatei mit auf den Weg mit einigen Kommentaren als Beispiel:
apiVersion: v1 kind: ConfigMap metadata: name: statsd-mapping-config namespace: goldengate data: statsd-mapping.yaml: |+ mappings: #- match: "statistics-replicat.*" # name: "gg_statistics_replicat" # labels: # type: "$1" #- match: "receiver-service-stats.*" # name: "gg_statistics_recsrvc" # labels: # type: "$1"
Sind nun beide YAML Konfigurationen (mit Deployment, internem Service und ConfigMap) mittels “kubectl apply” Aufruf an Ihr Kubernetes Cluster übertragen worden, so läßt sich prüfen ob der Container startet und ob vielleicht auch schon Metriken ankommen:
> kubectl get pods -n goldengate NAME READY STATUS RESTARTS AGE goldengate-oracle-eastcoast-5f9ffcd5dd-5qtds 1/1 Running 1 4d7h statsd-exporter-prometheus-845d75f7df-j9hbg 1/1 Running 1 4d6h > kubectl logs statsd-exporter-prometheus-845d75f7df-j9hbg -n goldengate ... ts=2024-09-09T15:38:16.242Z caller=listener.go:97 level=debug msg="Incoming line" proto=udp line="trail-input.io-read-count,deploymentName=EastCoastDeployment,deploymentId=7a56bbeb-3db4-4242-9420-6968e18c55a0,processType=replicat,processName=HRREP,trail-name=HR,trail-path=/u02/Deployment/var/lib/data:28556|g" ts=2024-09-09T15:38:16.242Z caller=listener.go:97 level=debug msg="Incoming line" proto=udp line="trail-input.io-read-bytes,deploymentName=EastCoastDeployment,deploymentId=7a56bbeb-3db4-4242-9420-6968e18c55a0,processType=replicat,processName=HRREP,trail-name=HR,trail-path=/u02/Deployment/var/lib/data:6211|g" ts=2024-09-09T15:38:16.242Z caller=listener.go:97 level=debug msg="Incoming line" proto=udp line="trail-input.trail-read-errors,deploymentName=EastCoastDeployment,deploymentId=7a56bbeb-3db4-4242-9420-6968e18c55a0,processType=replicat,processName=HRREP,trail-name=HR,trail-path=/u02/Deployment/var/lib/data:0|g" ts=2024-09-09T15:38:16.242Z caller=listener.go:97 level=debug msg="Incoming line" proto=udp line="trail-input.trail-times-at-eof,deploymentName=EastCoastDeployment,deploymentId=7a56bbeb-3db4-4242-9420-6968e18c55a0,processType=replicat,processName=HRREP,trail-name=HR,trail-path=/u02/Deployment/var/lib/data:28551|g" ts=2024-09-09T15:38:16.242Z caller=listener.go:97 level=debug msg="Incoming line" proto=udp line="trail-input.trail-lob-bytes,deploymentName=EastCoastDeployment,deploymentId=7a56bbeb-3db4-4242-9420-6968e18c55a0,processType=replicat,processName=HRREP,trail-name=HR,trail-path=/u02/Deployment/var/lib/data:0|g" ...
Die eben gezeigten Log Einträge stammen aus einem bereits aufgesetzten, laufenden Sync Vorgang HRREP mit Trail HR. In Ihrem Log müßten zumindest CPU Informationen und Werte zu den Basisdiensten adminsrvr, distsrvr und so weiter eintreffen. Der statsd-exporter öffnet den Port 9102, um die gesammelten Metriken per HTTP Aufruf (URI Pfad /metrics) abzugeben. Das ist genau die Schnittstelle, die Prometheus für seinen Scraping Vorgang benötigt. Wenn Sie in Ihrer Umgebung Prometheus als Kubernetes Ressource eingerichtet haben so müssen sie keine Scraping-Konfigurationsdateien mit Angaben füttern, sondern es genügt eine typische ServiceMonitor Ressource mit Angaben dazu, wie das Scraping des statsd-exporter stattfinden soll. Das sähe in etwa wie folgt aus:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
app: gg23ai-east
release: prometheus
name: goldengate-east-monitor
namespace: goldengate
spec:
endpoints:
- bearerTokenSecret:
key: ''
interval: 20s
port: http
relabelings:
- action: replace
sourceLabels:
- __meta_kubernetes_endpoints_label_app
targetLabel: instance
namespaceSelector: {}
selector:
matchLabels:
app.kubernetes.io/instance: statsd-exporter
app.kubernetes.io/name: statsd-exporter-prometheus-service
Hier sind einige optionale Angaben gemacht worden, die sich zu Ihrer Umgebung unterscheiden dürften. Beispielsweise muß in der von mir gewählten Prometheus Installation jeglicher ServiceMonitor das Metadatum “release: prometheus” tragen oder er wird ignoriert. Das Scraping Intervall, d.h. wie häufig werden die Metriken von Prometheus abgefragt, liegt bei 20 Sekunden und anstatt einen Container-Namen für das abgefragte Objekt in die Prometheus Datenbank einzutragen (ein label namens instance) wird der Wert gg23ai-east aus dem Metadatum app verwendet.
Nach erfolgtem “kubectl apply” müßten die Metriken nun auch in Ihrer Prometheus Installation ankommen.
Wird der ServiceMonitor eingebunden? Ein Blick auf Prometheus – Status – Service Discovery hilft hier weiter:

Sind für GoldenGate typische Metriken erkennbar ? Eine kurze Suche per “Graph” Menü sollte Ergebnisse liefern. Zum Beispiel per Suche nach der Metrik process_performance_cpu_time:


Hat diese funktioniert, können nun beliebige Dashboards in Grafana erzeugt werden um die Metriken historisch einzusehen und beispielswiese nach Installation zu gruppieren. Es gibt keine offiziellen Grafana dashboards für GoldenGate zum Download, jedoch können Sie gerne ein kleines selbst erstelltes Dashboard für einen schnellen Test und als Beispiel in Ihre Umgebung importieren (in Grafana: Dashboards – New Button – import – upload JSON file).

Das Dashboard liegt gemeinsam mit vielen der hier erklärten YAML Dateien in einem öffentlichen github Repository.
Wenn alles funktioniert hat, bietet sich folgender oder ähnlicher Anblick wenn ein Daten-Sync einmal eingerichtet ist:

Fazit:
Nicht nur für Tests und Schulungen können GoldenGate Umgebungen in Kubernetes besonders schnell eingerichtet, konfiguriert und wieder verworfen werden. Es handelt sich bei GoldenGate im Container um eine “advanced” Installation mit nginx reverse proxy und SSL Terminierung mit Möglichkeit, auf nativem Wege in Kubernetes Zertifikate einzuflanschen, die sehr wichtigen Netzwerkzugänge beliebig einzurichten und sämtliche Deployments in einer nativen Monitoring Umgebung zu vereinen. Es bleiben weiterführende Themen offen wie die Verknüpfung der GoldenGate Installationen mit einem Single SignOn Dienst und der Verknüpfung der GoldenGate Installationen untereinander über sogenannte Distribution Paths. Dennoch können Sie von dieser Warte aus gerne unsere zahlreichen Lehrvideos und kostenlosen Kurse einsehen, um Daten-syncs für zahlreiche Szenarien aufzusetzen und zu testen wie RZ und Cloud Migrationen, Warehouse Befüllungen, Desaster Recovery und noch einiges mehr. Wir haben für Sie einige Links vorbereitet:
GoldenGate Product Management auf youtube
Oracle Learning zu GoldenGate auf youtube – z.B. getting started
Oracle LiveLabs zu GoldenGate active-active sync
GoldenGate statsd Monitoring Einbindung (inkl. Grafana Dashboard für influxdb auf github)
GoldenGate nginx reverse proxy setup
Beispiel YAMLs und Grafana Dashboard dieses Blog Beitrages
Und wie immer: viel Spaß beim Ausprobieren und Testen !