Getting started with Oracle 18c Express Edition (XE) on Kubernetes

In this post I will share how you can get started with containerising Oracle databases and how to use a Kubernetes Container Storage Interface (CSI) driver to provision dynamic persistent storage to the container.

For this post I will use Oracle 18c Express Edition (XE) the ‘Free Database for Everyone’ and Portworx Essentials Forever Free edition.

Docker Build scripts

Let’s start by logging onto a private registry server and pulling the latest Oracle container build script from GitHub.

# git clone https://github.com/oracle/docker-images.git
Cloning into 'docker-images'...
remote: Enumerating objects: 14145, done.
remote: Counting objects: 100% (159/159), done.
remote: Compressing objects: 100% (122/122), done.
remote: Total 14145 (delta 56), reused 91 (delta 28), pack-reused 13986
Receiving objects: 100% (14145/14145), 9.92 MiB | 1.46 MiB/s, done.
Resolving deltas: 100% (8326/8326), done.

Note: the build script requires a minimum docker version of 17.09, so before we begin it’s best to check the Docker version, for example:

# docker version --format '{{.Server.Version | printf "%.5s" }}'
20.10

Oracle 18c XE Docker image

Navigate to the container build script just downloaded and execute the buildContainerImage script.

# cd docker-images/OracleDatabase/SingleInstance/dockerfiles

Note: if version 18.4.0 is specified the build script automatically downloads the free Oracle 18c Express Edition rpm. https://download.oracle.com/otn-pub/otn_software/db-express/oracle-database-xe-18c-1.0-1.x86_64.rpm

# ./buildContainerImage.sh -v 18.4.0 -x
...
Successfully built 78adacd54ec5
Successfully tagged oracle/database:18.4.0-xe


  Oracle Database container image for 'xe' version 18.4.0 is ready to be extended: 
    
    --> oracle/database:18.4.0-xe

  Build completed in 828 seconds.

The build script automates the creation of a container, however depending upon your network you may need to be patient as the download is ~5.5GB.

# docker images oracle/database:18.4.0-xe
REPOSITORY        TAG         IMAGE ID       CREATED          SIZE
oracle/database   18.4.0-xe   78adacd54ec5   5 minutes ago   5.89GB

List repositories

To assist with the sharing of the image I have set-up a private registry, as you can see from the below it’s currently empty.

# curl -X GET http://10.225.115.68:5000/v2/_catalog
{"repositories":[]}

Tag the image

Before we can push the image to the repository we need to tag it.

# docker tag 78adacd54ec5 10.225.115.68:5000/oracledb:18.4.0-xe

Now push the image into the private registry

# docker push 10.225.115.68.:5000/oracledb:18.4.0-xe
The push refers to repository [10.225.115.68:5000/oracledb]
d8873d52115d: Pushed 
6c6f43805655: Pushed 
59759852752f: Pushed 
18.4.0-xe: digest: sha256:a0bcdaf2afbd03dd2560ad84d4d3d9cd5600a0608530136eeccade61a9f1d10f size: 951

Confirm registry

Before moving on let’s confirm that the Kubernetes master can access the repository.

[root@master-1 Oracle-on-Kubernetes]# curl -X GET http://10.225.115.68:5000/v2/_catalog
{"repositories":["oracledb"]}
[root@master-1 Oracle-on-Kubernetes]# curl -X GET http://10.225.115.68:5000/v2/oracledb/tags/list
{"name":"oracledb","tags":["18.4.0-xe"]}

We can also use curl to review detailed information about the image, including variables, mount points, directory structures and scripts used with the image.

[root@master-1 Oracle-on-Kubernetes]# curl -X GET http://10.225.115.68:5000/v2/oracledb/manifests/18.4.0-xe
{
   "schemaVersion": 1,
   "name": "oracledb",
   "tag": "18.4.0-xe",
   "architecture": "amd64",
   "fsLayers": [
...

Oracle 18c XE database

Pull manifest files.

If you want to follow this post or just interested in the Kubernetes manifest files you can find them here.

[root@master-1 Oracle-on-Kubernetes]# git clone https://github.com/PureStorage-OpenConnect/Oracle-on-Kubernetes.git
Cloning into 'Oracle-on-Kubernetes'...
remote: Enumerating objects: 67, done.
remote: Counting objects: 100% (67/67), done.
remote: Compressing objects: 100% (60/60), done.
remote: Total 67 (delta 36), reused 13 (delta 6), pack-reused 0
Unpacking objects: 100% (67/67), done.
[root@master-1 Oracle-on-Kubernetes]# cd Oracle-on-Kubernetes

Create dedicated namespace

If you don’t already have an oracle namespace, time to create one.

[root@master-1 Oracle-on-Kubernetes]# kubectl apply -f oracle-namepace.yaml 
namespace/oracle-namespace created

Create configmap

And again, create the common configmap if you have not previously followed my posts.

[root@master-1 Oracle-on-Kubernetes]# kubectl create configmap oradb --from-env-file=oracle.properties -n oracle-namespace
configmap/oradb created

Dynamic Persistent Volume Claims

Before we create our database let’s look at how we can tell Kubernetes to dynamically create the required persistent volumes.

The Oracle 18x XE container supports three mount points oradata, setup and startup.

Dynamic Persistent Volume Claims

In the picture above you can see a POD with the three VolumeMounts and corresponding Volumes.

Volume Mounts

For ease of reading we will focus on the oradata volume only, as the setup is the same for setup and startup.

Our Oracle datafiles will be stored in a mountPath of /opt/oracle/oradata this has a name of ora-data184.

volumeMounts:
  - name: ora-data184
    mountPath: "/opt/oracle/oradata"

Volumes

The volumes references the persistent volume claim name, for example ora-data184-claim

volumes:
   - name: ora-data184
     persistentVolumeClaim:
       claimName: ora-data184-claim

Persistent Volume Claim

The persistent volume claim requests storage from the storage class.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: ora-data184-claim
  labels:
    app: database
    version: 18.4.0.1
spec:
  storageClassName: px-ora-csi-sc
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

From the above we can see that the persistent volume claim ora-data-184-claim is using a storageClassName of px-ora-cs-cs

StorageClass

The Portworx CSI storage class dynamically provisions the physical storage.

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
    name: px-ora-csi-sc
provisioner: pxd.portworx.com
parameters:
   repl: "1"
allowVolumeExpansion: true
reclaimPolicy: Delete

Oracle 18c XE database

We are now ready to create a containerised Oracle 18c XE database.

[root@master-1 Oracle-on-Kubernetes]# kubectl apply -f 18xe_deployment_PX-CSI.yaml 
storageclass.storage.k8s.io/px-ora-csi-sc created
deployment.apps/oracle18xe created
persistentvolumeclaim/ora-data184-claim created
persistentvolumeclaim/ora-setup184-claim created
persistentvolumeclaim/ora-startup184-claim created
service/oracle18xe created

Deployment

Use kubectl get deployment or deploy to list deployment and check image, for example.

[root@master-1 Oracle-on-Kubernetes]# kubectl get deploy -o wide
NAME         READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                                  SELECTOR
oracle18xe   1/1     1            1           66s   oracle18xe   10.225.115.68:5000/oracledb:18.4.0-xe   app=database,version=18.4.0.1
[root@master-1 Oracle-on-Kubernetes]# kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES
oracle18xe-bc86774b6-dvtv7   1/1     Running   0          2m35s   10.244.1.24   node-1-2   <none>           <none>

Docker Image

We can also check the correct image has been pulled by logging onto the worker node and confirming the image id.

[root@node-1-2 ~]# docker images 10.225.115.68:5000/oracledb
REPOSITORY                        TAG         IMAGE ID       CREATED      SIZE
10.225.115.68:5000/oracledb       18.4.0-xe   78adacd54ec5   2 days ago   5.89 GB

Build Log

Use kubectl logs to check progress, the –follow option provides a useful way of watching the build.

The 18c XE image does not support database or pluggable name parameters, and creates a database called XE and PDB XEPDB1.

[root@master-1 Oracle-on-Kubernetes]# kubectl logs pods/oracle18xe-bc86774b6-dvtv7
ORACLE PASSWORD FOR SYS AND SYSTEM: Kube#2020
Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts:
Confirm the password:
Configuring Oracle Listener.
Listener configuration succeeded.
Configuring Oracle Database XE.
Enter SYS user password: 
******** 
Enter SYSTEM user password: 
***********
Enter PDBADMIN User Password: 
**********
Prepare for db operation
7% complete
Copying database files
29% complete
Creating and starting Oracle instance
30% complete
31% complete
34% complete
38% complete
41% complete
43% complete
Completing Database Creation
47% complete
50% complete
Creating Pluggable Databases
54% complete
71% complete
Executing Post Configuration Actions
93% complete
Running Custom Scripts
100% complete
Database creation complete. For details check the logfiles at:
 /opt/oracle/cfgtoollogs/dbca/XE.
Database Information:
Global Database Name:XE
System Identifier(SID):XE
Look at the log file "/opt/oracle/cfgtoollogs/dbca/XE/XE.log" for further details.
Connect to Oracle Database using one of the connect strings:
     Pluggable database: oracle18xe-bc86774b6-dvtv7/XEPDB1
     Multitenant container database: oracle18xe-bc86774b6-dvtv7
Use https://localhost:5500/em to access Oracle Enterprise Manager for Oracle Database XE
The Oracle base remains unchanged with value /opt/oracle
#########################
DATABASE IS READY TO USE!
#########################
The following output is now a tail of the alert.log:
2021-07-05T11:42:11.428709+00:00
XEPDB1(3):Resize operation completed for file# 10, old size 358400K, new size 368640K
2021-07-05T11:42:14.274158+00:00
XEPDB1(3):CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE  '/opt/oracle/oradata/XE/XEPDB1/users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL  SEGMENT SPACE MANAGEMENT  AUTO
XEPDB1(3):Completed: CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE  '/opt/oracle/oradata/XE/XEPDB1/users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL  SEGMENT SPACE MANAGEMENT  AUTO
XEPDB1(3):ALTER DATABASE DEFAULT TABLESPACE "USERS"
XEPDB1(3):Completed: ALTER DATABASE DEFAULT TABLESPACE "USERS"
2021-07-05T11:42:15.659094+00:00
ALTER PLUGGABLE DATABASE XEPDB1 SAVE STATE
Completed: ALTER PLUGGABLE DATABASE XEPDB1 SAVE STATE

Database Container

If you’re interested to see what our Oracle container looks like, we can shell into our database container using kubectl pods/<pod name> exec -it — /bin/bash we can see the persistent volumes presented to the container.

bash-4.2# df -Th
Filesystem                      Type     Size  Used Avail Use% Mounted on
overlay                         overlay   49G   14G   36G  27% /
tmpfs                           tmpfs    3.9G     0  3.9G   0% /dev
tmpfs                           tmpfs    3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs                           tmpfs    3.9G     0  3.9G   0% /dev/shm
/dev/sda2                       xfs       49G   14G   36G  27% /etc/hosts
/dev/pxd/pxd830774027675457210  ext4     9.8G  2.6G  6.7G  28% /opt/oracle/oradata
/dev/pxd/pxd1087869865371744604 ext4     976M  2.5M  907M   1% /opt/oracle/scripts/startup
/dev/pxd/pxd730447982461238045  ext4     976M  2.5M  907M   1% /opt/oracle/scripts/setup
tmpfs                           tmpfs    3.9G   12K  3.9G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                           tmpfs    3.9G     0  3.9G   0% /proc/acpi
tmpfs                           tmpfs    3.9G     0  3.9G   0% /proc/scsi
tmpfs                           tmpfs    3.9G     0  3.9G   0% /sys/firmware

Persistent Volume Claims

Use kubectl get persistentvolumeclaims or pvc to list the volumes used.

To limit the number of persistent volumes returned consider using filtering with labels -l, for example.

[root@master-1 Oracle-on-Kubernetes]# kubectl get pvc -l version=18.4.0.1   
NAME                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
ora-data184-claim      Bound    pvc-bae9dc20-6444-4b40-b703-d97c9d08b552   10Gi       RWO            px-ora-csi-sc   81s
ora-setup184-claim     Bound    pvc-eff35d27-87af-4543-9150-fc29cbe4b9b9   1Gi        RWO            px-ora-csi-sc   81s
ora-startup184-claim   Bound    pvc-ed8a0061-6830-45e6-97fe-73fb8debf7c1   1Gi        RWO            px-ora-csi-sc   81s   

Portworx Volumes

We can also see the three Portworx-managed volumes by using pxctl volume list with -v for volumes and -l to filter returned rows, for example.

[root@master-1 Oracle-on-Kubernetes]# pxctl volume list -v -l version=18.4.0.1
Defaulting container name to portworx.
Use 'kubectl describe pod/px-deploy-1-g2rnm -n kube-system' to see all of the containers in this pod.
ID			NAME						SIZE	HA	SHARED	ENCRYPTED	PROXY-VOLUME	IO_PRIORITY	STATUS		SNAP-ENABLED	
830774027675457210	pvc-bae9dc20-6444-4b40-b703-d97c9d08b552	10 GiB	1	no	no		no		HIGH		up - attached on 10.225.115.69	no
730447982461238045	pvc-ed8a0061-6830-45e6-97fe-73fb8debf7c1	1 GiB	1	no	no		no		HIGH		up - attached on 10.225.115.69	no
1087869865371744604	pvc-eff35d27-87af-4543-9150-fc29cbe4b9b9	1 GiB	1	no	no		no		HIGH		up - attached on 10.225.115.69	no

By using pxctl volume inspect <volume> we can see the Device Path visible from within the container, the pod using the volume as well as mount and usage details.

[root@master-1 Oracle-on-Kubernetes]# pxctl volume inspect pvc-bae9dc20-6444-4b40-b703-d97c9d08b552
Defaulting container name to portworx.
Use 'kubectl describe pod/px-deploy-1-g2rnm -n kube-system' to see all of the containers in this pod.
	Volume          	 :  830774027675457210
	Name            	 :  pvc-bae9dc20-6444-4b40-b703-d97c9d08b552
	Size            	 :  10 GiB
	Format          	 :  ext4
	HA              	 :  1
	IO Priority     	 :  HIGH
	Creation time   	 :  Jul 5 13:39:33 UTC 2021
	Shared          	 :  no
	Status          	 :  up
	State           	 :  Attached: f9f9a668-499f-432a-966a-01c36ec7858c (10.225.115.80)
	Last Attached   	 :  Jul 5 13:55:35 UTC 2021
	Device Path     	 :  /dev/pxd/pxd830774027675457210
	Labels          	 :  app=database,namespace=oracle-namespace,pvc=ora-data184-claim,repl=1,version=18.4.0.1
	Mount Options          	 :  discard
	Reads           	 :  6629
	Reads MS        	 :  59970
	Bytes Read      	 :  523563008
	Writes          	 :  12893
	Writes MS       	 :  73831
	Bytes Written   	 :  142086144
	IOs in progress 	 :  0
	Bytes used      	 :  3.4 GiB
	Replica sets on nodes:
		Set 0
		  Node 		 : 10.225.115.81 (Pool 111493ba-d0ea-45bc-84be-23d694a8fadd )
	Replication Status	 :  Up
	Volume consumers	 : 
		- Name           : oracle18xe-fc75dff95-92kq4 (0b7fc853-7334-4c4d-b69e-aa084897f96e) (Pod)
		  Namespace      : oracle-namespace
		  Running on     : node-1-4
		  Controlled by  : oracle18xe-fc75dff95 (ReplicaSet)

Summary

In this blog post I have shared how we can download, build and deploy an Oracle 18c Express Edition (XE) database on Kubernetes using the Portworx Container Storage Interface (CSI) driver to deliver dynamic persistent storage.

The Container Storage Interface can do more than just provision storage, in my next posts I will share how we can also take snapshots and perform clones.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: