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

In this Blog I am going to show how we can quickly get an Oracle 18c Express Edition (XE) database up and running on Kubernetes for testing purposes on a laptop.

This blog post covers:

  • Configuring Minikube for Kubernetes
  • Building the Oracle 18c XE Docker image
  • Running Oracle 18x XE in Kubernetes
  • The Kubernetes Dashboard
  • Connecting from a laptop
  • Kubernetes management with Minikube

Configuring Minikube

Before we start, if you have not already have VirtualBox and Minikube installed you can get Minikube here, and VirtualBox using this link.

In this blog I will using Oracle VirtualBox 6.0.1 and Minikube version 1.11.0, you can your check your local versions with:

$ vboxmanage --version
6.0.16r135674
$ minikube version
minikube version: v1.11.0
commit: 57e2f55f47effe9ce396cea42a1e0eb4f611ebbd

Ok, let’s increase the default Minikube VM memory size from 2GB to 10GB, this is required to give my Oracle 18xe database a bit more memory, I will also set the MiniKube vm driver to use VirtualBox this can be done by changing the Minikube configuration e.g.

$ minikube config set memory 10240
$ minikube config set vm-driver virtualbox
⚠️  These changes will take effect upon a minikube delete and then a minikube start
$ minikube config view
- disk-size: 40GB
- vm-driver: virtualbox
- memory: 10240

I will also enable the minikube metrics server to provide a CPU and Memory Usage graphs.

$ minikube addons enable metrics-server

To check what add-ons are enabled use minikube addons list

$ minikube addons list
|-----------------------------|----------|--------------|
|         ADDON NAME          | PROFILE  |    STATUS    |
|-----------------------------|----------|--------------|
| ambassador                  | minikube | disabled     |
| dashboard                   | minikube | enabled ✅   |
| default-storageclass        | minikube | enabled ✅   |
| efk                         | minikube | disabled     |
| freshpod                    | minikube | disabled     |
| gvisor                      | minikube | disabled     |
| helm-tiller                 | minikube | disabled     |
| ingress                     | minikube | disabled     |
| ingress-dns                 | minikube | disabled     |
| istio                       | minikube | disabled     |
| istio-provisioner           | minikube | disabled     |
| logviewer                   | minikube | disabled     |
| metallb                     | minikube | disabled     |
| metrics-server              | minikube | enabled ✅   |
| nvidia-driver-installer     | minikube | disabled     |
| nvidia-gpu-device-plugin    | minikube | disabled     |
| olm                         | minikube | disabled     |
| registry                    | minikube | disabled     |
| registry-aliases            | minikube | disabled     |
| registry-creds              | minikube | disabled     |
| storage-provisioner         | minikube | enabled ✅   |
| storage-provisioner-gluster | minikube | disabled     |
|-----------------------------|----------|--------------|

Start Minikube

$ minikube start
😄  minikube v1.11.0 on Darwin 10.14.6
✨  Using the virtualbox driver based on user configuration
👍  Starting control plane node minikube in cluster minikube
🔥  Creating virtualbox VM (CPUs=2, Memory=10240MB, Disk=40960MB) ...
🐳  Preparing Kubernetes v1.18.3 on Docker 19.03.8 ...
🔎  Verifying Kubernetes components...
🌟  Enabled addons: dashboard, default-storageclass, metrics-server, storage-provisioner
🏄  Done! kubectl is now configured to use "minikube"

Building our Oracle Docker Image

The Oracle 18c Express Edition (XE) Docker build scripts now automatically ‘pulls’ the database RPM from OTN for you. This means you no longer any need to pre-download the Oracle 18xe image for this build.

Please Note: this still required for all other non-free versions.

Let’s start by cloning the Oracle maintained Docker files from GitHub.

$ git clone https://github.com/oracle/docker-images.git

Navigate to the SingleInstance dockerfiles directory e.g.

$ cd docker-images/OracleDatabase/SingleInstance/dockerfiles

The script installs the Oracle Database software, but it does not create and configure a database. When the build has been complete, you can verify the image has been created by listing the available Docker images.

The eval command will force the Docker image to be built in our Kubernetes minikube VM rather than on our laptop.

$ eval $(minikube docker-env)
$ ./buildDockerImage.sh -v 18.4.0 -x

If we perform a docker images command you will notice that we don’t have a database image, don’t worry that’s expected.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
oraclelinux         7-slim              7442ca158991        7 days ago          120MB

However, if we shell into our minikube VM we should see our 18c XE database image.

$ minikube ssh
                         _             _            
            _         _ ( )           ( )           
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __  
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)


$ docker images
REPOSITORY                          TAG            IMAGE ID          CREATED              SIZE
oracle/database                      18.4.0-xe     e1df47b35fce      2 minutes ago      5.87GB
oraclelinux                             7-slim     7442ca158991      7 days ago          120MB
k8s.gcr.io/kube-proxy                  v1.18.3     3439b7546f29      4 weeks ago         117MB
k8s.gcr.io/kube-controller-manager     v1.18.3     da26705ccb4b      4 weeks ago         162MB
k8s.gcr.io/kube-apiserver              v1.18.3     7e28efa976bd      4 weeks ago         173MB
k8s.gcr.io/kube-scheduler              v1.18.3     76216c34ed0c      4 weeks ago         95.3MB
kubernetesui/dashboard                  v2.0.0     8b32422733b3      8 weeks ago         222MB
k8s.gcr.io/pause                           3.2     80d28bedfe5d      4 months ago        683kB
k8s.gcr.io/coredns                       1.6.7     67da37a9a360      4 months ago        43.8MB
k8s.gcr.io/etcd                        3.4.3-0     303ce5db0e90      7 months ago        288MB
kubernetesui/metrics-scraper            v1.0.2     3b08661dc379      7 months ago        40.1MB
gcr.io/k8s-minikube/storage-provisioner v1.8.1     4689081edb10      2 years ago         80.8MB

Getting Started with Kubernetes

Kubernetes Namespace

For this blog I use a new Kubernetes namespace called oracle-namespace.

I can create a new namespace with kubectl create namespace.

$ kubectl create namespace oracle-namespace
namespace/oracle-namespace created

Or if you prefer via a YAML file.

$ cat namespace.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: oracle-namespace

$ kubectl apply -f namespace.yaml

Either way we should be able to use the kubectl get namespace to return the status.

$ kubectl get namespace oracle-namespace
NAME               STATUS   AGE
oracle-namespace   Active   34s

Kubernetes ConfigMap

For my Kubernetes build I will be using a ConfigMap to pass variables to my Oracle 18c Express Edition (XE) deployment.

I have created a file called oracle.properties which I will be used to create the configmap, this common file will be used to support multiple versions of Oracle so includes variable not needed for Oracle 18c XE.

$ kubectl create configmap oradb --from-env-file=oracle.properties -n oracle-namespace
configmap/oradb created

We can check the key pair vales using kubectl get configmaps with an output of yaml, our Oracle 18c XE database will only use ORACLE_CHARACTER_SET & ORACLE_PWD.

$ kubectl get configmaps/oradb -o yaml -n oracle-namespace
apiVersion: v1
data:
  DB_BUNDLE: basic
  DB_DOMAIN: localdomain
  DB_MEMORY: 4g
  DB_PASSWD: Kube#2020
  DB_PDB: PSTGPDB1
  DB_SID: PSTG
  ORACLE_CHARACTERSET: AL32UTF8
  ORACLE_PDB: ORCLPDB1
  ORACLE_PWD: Kube#2020
  ORACLE_SID: ORCL
kind: ConfigMap
metadata:
  creationTimestamp: "2020-06-18T10:07:57Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:DB_BUNDLE: {}
        f:DB_DOMAIN: {}
        f:DB_MEMORY: {}
        f:DB_PASSWD: {}
        f:DB_PDB: {}
        f:DB_SID: {}
        f:ORACLE_CHARACTERSET: {}
        f:ORACLE_PDB: {}
        f:ORACLE_PWD: {}
        f:ORACLE_SID: {}
    manager: kubectl
    operation: Update
    time: "2020-06-18T10:07:57Z"
  name: oradb
  namespace: oracle-namespace
  resourceVersion: "2630"
  selfLink: /api/v1/namespaces/oracle-namespace/configmaps/oradb
  uid: 1910d0c2-1de3-4a23-9462-0785ca3bd3f4

Running Oracle18c XE

We can create our Oracle 18xe database Kubernetes pod with kubectl apply

$ kubectl apply -f database_18xe.yaml -n oracle-namespace
deployment.apps/oracle18xe created
service/oracle18xe created

Use kubectl get(s) to check status e.g.

$ kubectl get deployments -n oracle-namespace
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
oracle18xe   1/1     1            1           27s
$ kubectl get pods -n oracle-namespace
NAME                          READY   STATUS    RESTARTS   AGE
oracle18xe-5d565cbfdf-cns6s   1/1     Running   0          15s

Now we know the pod name we can view the log output during the build.

$ kubectl logs oracle18xe-5d565cbfdf-cns6s -n oracle-namespace
Setup Oracle Database
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-5d565cbfdf-cns6s/XEPDB1
     Multitenant container database: oracle18xe-5d565cbfdf-cns6s
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!
#########################

We can use kubectl describe(s) to provide detailed information e.g.

$ kubectl describe deployments -n oracle-namespace
$ kubectl describe pods -n oracle-namespace
$ kubectl describe secrets -n oracle-namespace
$ kubectl describe services -n oracle-namespace

MiniKube Dashboard

The MiniKube dashboard provides a GUI interface to manage your Kubernetes environment, this can be started using the minikube dashboard command, this will start a browser tab ready and your ready to go.

$ minikube dashboard
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
🎉  Opening http://127.0.0.1:50795/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser.
Kubernetes Dashboard – Oracle 18.4.0-xe

From the MiniKube Dashboard we can navigate to the Pod logs and see what database logging has been written to the standard output, we can also see our database has been renamed as per our configmap.

Review log output from our Pod e.g. Workloads > Pods > POD > Logs

Minikube also provides a Shell into our Pod e.g. Workloads > Pods > POD > Shell

Connection from Laptop

To connect to our newly created Oracle database from our laptop we need to first identify the exposed IP address and port, we can do this with minikube ip & kubectl get service

$ minikube ip
192.168.99.104
$ kubectl get services -n oracle-namespace
NAME       TYPE     CLUSTER-IP  EXTERNAL-IP PORT(S)                       AGE
oracle18xe NodePort 10.99.225.175 <none>    1521:32255/TCP,5500:31620/TCP 2m42s

We can also see the ports using minkube service

$ minikube service oracle18xe -n oracle-namespace --url
http://192.168.99.104:32255
http://192.168.99.104:31620

As I have sqlplus installed on my laptop I will use that to connect using the detail above.

$ sqlplus system/Kube#2020@192.168.99.104:32255/XEPDB1

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Jun 19 09:53:11 2020
Version 19.3.0.0.0

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

Last Successful login time: Fri Jun 19 2020 09:52:56 +01:00

Connected to:
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0

SQL> show con_name;

CON_NAME
------------------------------
XEPDB1

SQL> col INSTANCE_NAME heading 'Instance Name' format a8
SQL> col HOST_NAME heading 'Host Name' format a30
SQL> col VERSION heading 'Version' format a25
SQL> select INSTANCE_NAME, HOST_NAME, VERSION from v$instance;

Instance Host Name                      Version
-------- ------------------------------ -------------------------
XE       oracle18xe-5d565cbfdf-cns6s    18.0.0.0.0

As you can above, my Oracle database is reporting the host name is the same as the Kubernetes Pod name.

Using Oracle SQL Developer

Now we have IP & Port details we can also use these to connect with Oracle SQL Developer.

Oracle SQL Developer: Oracle 18c XE
Using SQL Developer

Kubernetes management with Minikube

Minikube status

$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Stop local Minikube Cluster

This will stop our VirtualBox minikube VM.

Please note as our database is not using persistent storage we will loose all data and our database will be rebuilt.

$ minikube stop
✋  Stopping "minikube" in virtualbox ...
🛑  Node "minikube" stopped.

Start local Minikube Cluster

$ minikube start
😄  minikube v1.11.0 on Darwin 10.14.6
✨  Using the virtualbox driver based on existing profile
👍  Starting control plane node minikube in cluster minikube
🔄  Restarting existing virtualbox VM for "minikube" ...
🐳  Preparing Kubernetes v1.18.3 on Docker 19.03.8 ...
🔎  Verifying Kubernetes components...
🌟  Enabled addons: dashboard, default-storageclass, metrics-server, storage-provisioner
🏄  Done! kubectl is now configured to use "minikube"

Pause namespace

$ minikube pause -n oracle-namespace
⏯️  Paused kubelet and 2 containers in: oracle-namespace

Unpause Namespace

$ minikube unpause -n oracle-namespace
⏸️  Unpaused kubelet and 2 containers in: oracle-namespace

Delete local Minikube Cluster

This will delete the VirtualBox minikube VM and all our data.

$ minikube delete
🔥  Deleting "minikube" in virtualbox ...
💀  Removed all traces of the "minikube" cluster.

If you want to try and recreate any of the above, I have uploaded all code above to my GitHub repo.

However if you require your database to be persistent you may want to check-out the following blog posts:

The the blog posts above introduce the Kubernetes Container Storage Interface (CSI) and discuss running Oracle 19c on a multi-node Kubernetes Cluster.

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