How to deploy an Oracle 19c database on Kubernetes with Portworx storage using Helm

Background

Over the last few years I have shared a number of posts showing how we can deliver Oracle databases on Kubernetes using deployments and statefulsets, on-premises and in the Oracle Cloud.

I have also recently posted about the use of the new Oracle Database Kubernetes Operator (OraOperator), however another simple method is with Helm.

What is Helm

Helm is a Kubernetes package manager which can be used to simplify Kubernetes deployments, think yum or apt for Linux. Helm charts are the method of packaging Kubernetes application for installation and upgrades.

Prerequisites

Before we start we need to confirm we have a Kubernetes version high than 1.12, Helm version of 2.x or 3.x and a Kubernetes secret to access the Oracle Container Registry.

Kubernetes

Use kubectl version to confirm Kubernetes version is higher than 1.12, for example

# kubectl version --short | awk -Fv '/Server Version: / {print $3}'
1.21.3

Helm

And check Helm version, using helm version, thus.

# helm version
version.BuildInfo{Version:"v3.7.1", GitCommit:"1d11fcb5d3f3bf00dbe6fe31b8412839a96b3dc4", GitTreeState:"clean", GoVersion:"go1.16.9"}

Oracle Container Registry

Create Kubernetes secret for Oracle Container Registry using Oracle SSO credentials, for example.

# kubectl create secret docker-registry regcred --docker-server=container-registry.oracle.com --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

Alternatively, logon to the Oracle Container Registry (OCR) using SSO credentials

# docker login container-registry.oracle.com
Username: <SSO email>
Password: <SSO password>
Login Succeeded

And then create a Kubernetes secret using the ~/.docker/config.json file.

# kubectl create secret generic regcred --from-file=.dockerconfigjson=$HOME/.docker/config.json  --type=kubernetes.io/dockerconfigjson -n oracle-namespace
secret/regcred created

Default Kubernetes Namespace

To avoid having to specify our namespace with -n each time use the set-context to specify a default namespaces for example oracle-namespace.

# kubectl config set-context --current --namespace=oracle-namespace

Oracle database Helm package

The Oracle 19c database Helm chart creates a multi-tenant, single pdb Oracle Database 19c running on Oracle Linux 7.

Start by cloning the Oracle GitHub repo

# git clone https://github.com/oracle/docker-images.git
Cloning into 'docker-images'...
remote: Enumerating objects: 15267, done.
remote: Counting objects: 100% (129/129), done.
remote: Compressing objects: 100% (96/96), done.
remote: Total 15267 (delta 48), reused 73 (delta 23), pack-reused 15138
Receiving objects: 100% (15267/15267), 10.23 MiB | 4.70 MiB/s, done.
Resolving deltas: 100% (8973/8973), done.

The Helm chart can be found in the docker-images/OracleDatabase/SingleInstance/helm-charts/oracle-db directory.

Use helm package to generate oracle-db-1.0.0.tgz

# helm package docker-images/OracleDatabase/SingleInstance/helm-charts/oracle-db
Successfully packaged chart and saved it to: /root/oracle-db-1.0.0.tgz

Create Portworx Storage Class

The Oracle Helm chart supports a number of customisation, including providing a Kubernetes Storage Class, for this post I will be using a Portworx Storage Class.

The Portworx storage class is configured to use an io_profile of db_remote, priority_io of high, and to allow volume expansions, I have also selected a replication factor of 3 as the majority of OCI regions provide 3 Availability Domains.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: px-ora-sc
provisioner: kubernetes.io/portworx-volume
parameters:
  repl: "3"
  io_profile: "db_remote"
  priority_io: "high"
allowVolumeExpansion: true
# kubectl apply -f px-ora-sc.yaml
storageclass.storage.k8s.io/px-ora-sc created

Installing Chart

Before we install the chart preform a dry-run to validate configuration

# helm install db19c -f values.yaml oracle-db-1.0.0.tgz --dry-run

If all ok, now install using helm install and a configuration yaml file.

# helm install db19c -f values.yaml oracle-db-1.0.0.tgz

Output from helm install

NAME: db19c
LAST DEPLOYED: Thu Feb 10 12:36:00 2022
NAMESPACE: oracle-namespace
STATUS: deployed
REVISION: 1
NOTES:
#
# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
#

# ===========================================================================
# == Add below entries to your tnsnames.ora to access this database server ==  
# ====================== from external host =================================  
ORCLCDB=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<ip-address>)(PORT=<port>))
    (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=<ORACLE_SID>)))
ORCLPDB1=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<ip-address>)(PORT=<port>))
    (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=<ORACLE_PDB>)))
#                                                                              
#ip-address : IP address of any of the Kubernetes nodes
#port       : Service Port that is mapped to the port 1521 of the container.
#

Application details
====================
IP and port can be found using the following:
export NODE_PORT=$(kubectl get --namespace oracle-namespace -o jsonpath="{.spec.ports[0].nodePort}" services db19c-oracle-db)
export NODE_XDB_PORT=$(kubectl get --namespace oracle-namespace -o jsonpath="{.spec.ports[1].nodePort}" services db19c-oracle-db)
export NODE_IP=$(kubectl get nodes --namespace oracle-namespace -o jsonpath="{.items[0].status.addresses[0].address}")
echo listener at $NODE_IP:$NODE_PORT
echo XDB at $NODE_IP:$NODE_XDB_PORT

Oracle Databases SID, PDB name can be figured out by :

ORACLE_SID=$(kubectl get  -o jsonpath="{.spec.template.spec.containers[?(.name == 'oracle-db')].env[?(.name == 'ORACLE_SID')].value }" deploy db19c-oracle-db)
ORACLE_PDB=$(kubectl get  -o jsonpath="{.spec.template.spec.containers[?(.name == 'oracle-db')].env[?(.name == 'ORACLE_PDB')].value }" deploy db19c-oracle-db)

List Charts

# helm list
NAME 	NAMESPACE       	REVISION	UPDATED                              	STATUS  	CHART          	APP VERSION
db19c	oracle-namespace	1       	2022-02-10 12:36:00.0585055 +0000 UTC	deployed	oracle-db-1.0.0	   

Kubernetes Deployment

Using the details provide in from helm install output, we can check the $ORACLE_SID, for example

# ORACLE_SID=$(kubectl get  -o jsonpath="{.spec.template.spec.containers[?(.name == 'oracle-db')].env[?(.name == 'ORACLE_SID')].value }" deploy db19c-oracle-db)

# echo $ORACLE_SID
PSTGCDB

# ORACLE_PDB=$(kubectl get  -o jsonpath="{.spec.template.spec.containers[?(.name == 'oracle-db')].env[?(.name == 'ORACLE_PDB')].value }" deploy db19c-oracle-db)

# echo $ORACLE_PDB
PSTGPDB1

Deployments

# kubectl get deployments
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
db19c-oracle-db   0/1     1            0           4m11s

Pods

# kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
db19c-oracle-db-57478b775-ngnr8   0/1     Running   0          4m2s

Pod Logs

# kubectl logs pods/db19c-oracle-db-57478b775-ngnr8
[2022:02:10 12:36:06]: Acquiring lock .PSTGCDB.create_lck with heartbeat 30 secs
[2022:02:10 12:36:06]: Lock acquired
[2022:02:10 12:36:06]: Starting heartbeat
[2022:02:10 12:36:06]: Lock held .PSTGCDB.create_lck
ORACLE EDITION: ENTERPRISE
LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 10-FEB-2022 12:36:06
Copyright (c) 1991, 2019, Oracle.  All rights reserved.
Starting /opt/oracle/product/19c/dbhome_1/bin/tnslsnr: please wait...
TNSLSNR for Linux: Version 19.0.0.0.0 - Production
System parameter file is /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/db19c-oracle-db-57478b775-ngnr8/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0 - Production
Start Date                10-FEB-2022 12:36:07
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/19c/dbhome_1/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/db19c-oracle-db-57478b775-ngnr8/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully
Prepare for db operation
8% complete
Copying database files
31% complete
Creating and starting Oracle instance
32% complete
36% complete
40% complete
43% complete
46% complete
Completing Database Creation
51% complete
54% complete
Creating Pluggable Databases
58% complete
77% complete
Executing Post Configuration Actions
100% complete
Database creation complete. For details check the logfiles at:
 /opt/oracle/cfgtoollogs/dbca/PSTGCDB.
Database Information:
Global Database Name:PSTGCDB
System Identifier(SID):PSTGCDB
Look at the log file "/opt/oracle/cfgtoollogs/dbca/PSTGCDB/PSTGCDB.log" for further details.
SQL*Plus: Release 19.0.0.0.0 - Production on Thu Feb 10 12:59:54 2022
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle.  All rights reserved.
...
The Oracle base remains unchanged with value /opt/oracle
#########################
DATABASE IS READY TO USE!
#########################
...

Persistent Volume Claims

# kubectl get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
db19c-oracle-db   Bound    pvc-329c205a-42ea-4d68-bb3a-3a0de59fb262   20Gi       RWX            px-ora-sc      2m2s

Services

# kubectl get svc 
NAME              TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                         AGE
db19c-oracle-db   NodePort   10.105.52.239   <none>        1521:30067/TCP,5500:30396/TCP   8m27s

Test Connection

Using the above details and SQLplus we can connect to our pdb.

% sqlplus system/Kube#2020@10.225.115.150:30067/PSTGPDB1 @database_details

SQL*Plus: Release 19.0.0.0.0 - Production on Thu Feb 10 14:30:07 2022
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.

Last Successful login time: Thu Feb 10 2022 14:29:59 +00:00

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

Current Time   : 10/02/22 14:30:08

Database Details
===============================================
Hostname       : db19c-oracle-db-57478b775-ngnr8
Database Name  : PSTGCDB
Date Created   : 10/02/22 12:38:47
Date Started   : 10/02/22 12:59:10
Resetlogs Date : 10/02/22 12:38:49
DB Status      : OPEN
Space Allocated:	 .69 GB
Space Used     :	 .56 GB

SQL> show con_name;
PSTGPDB1

SQL> select banner_full from v$version;
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

Uninstalling the Chart

To delete the dbc19c deployment, use helm uninstall, for example

# helm uninstall db19c
release "db19c" uninstalled 

The helm uninstall command removes all the Kubernetes components associated with the chart, including the Persistent Volume Claim (PVC) and deletes the release.

If we repeat helm list we can see that the package has been removed.

# helm list
NAME	NAMESPACE	REVISION	UPDATED	STATUS	CHART	APP VERSION

Summary

In this post I have shared how we can use a Helm chart to deploy an Oracle 19c database on Kubernetes, configure the chart to use a StorageClass, connect remotely and tidy-up the deployment.

[twitter-follow screen_name=’RonEkins’ show_count=’yes’]

Leave a Reply

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: