Skip to content

Commit f6cb69a

Browse files
rishabh20yunus-qureshiabhisbyk
authored
Kubernetes support for SI DB docker images (#1877)
* added k8s folder under OracleDatabase/SingleInstance/extensions/ directory Signed-off-by: Rishabh Gupta <rishabh.y.gupta@oracle.com> * added README for the k8s extension Signed-off-by: Rishabh Gupta <rishabh.y.gupta@oracle.com> * Update extension logic in Dockerfile Signed-off-by: Yunus Qureshi <write2yunus@gmail.com> * Give execute perms to buildExtensions.sh Signed-off-by: Yunus Qureshi <write2yunus@gmail.com> * Fix conditions Signed-off-by: Yunus Qureshi <write2yunus@gmail.com> * Source the shell script extn Signed-off-by: Yunus Qureshi <write2yunus@gmail.com> * modified the k8s extension dockerfile to call runOracle.sh of each previous base image in the correct order Signed-off-by: Rishabh Gupta <rishabh.y.gupta@oracle.com> * Fixing permission issue for runOracle.sh, lock.py (for k8s extension) file Signed-off-by: abhisbyk <abhishek.by.kumar@oracle.com> * Updated the k8s extension's README Signed-off-by: abhisbyk <abhishek.by.kumar@oracle.com> Co-authored-by: Yunus Qureshi <write2yunus@gmail.com> Co-authored-by: abhisbyk <abhishek.by.kumar@oracle.com>
1 parent 3bc7dfc commit f6cb69a

File tree

11 files changed

+455
-3
lines changed

11 files changed

+455
-3
lines changed

OracleDatabase/SingleInstance/extensions/buildExtensions.sh

100644100755
File mode changed.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# LICENSE UPL 1.0
2+
#
3+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
4+
#
5+
# ORACLE DOCKERFILES PROJECT
6+
# --------------------------
7+
# This is the Dockerfile for Oracle Database with Fast Fail Over support
8+
#
9+
# REQUIREMETNS FOR THIS IMAGE
10+
# ----------------------------------
11+
# Any release of prebuilt oracle/database base docker image
12+
#
13+
# HOW TO BUILD THIS IMAGE
14+
# -----------------------
15+
#
16+
# Run:
17+
# $ docker build -t <extended_image_name> . --build-arg BASE_IMAGE=18.3.0-ee
18+
#
19+
20+
ARG BASE_IMAGE=oracle/database:19.3.0-ee
21+
FROM ${BASE_IMAGE}
22+
23+
# Extn name
24+
ARG EXTENSION_NAME=k8s
25+
26+
# Environment variables required for this build (do NOT change)
27+
# -------------------------------------------------------------
28+
ENV ORACLE_SID=ORCLCDB \
29+
STARTUP_FILE=startUp.sh \
30+
SHUT_DB_FILE=shutDown.sh \
31+
LOCKING_SCRIPT=lock.py \
32+
SWAP_LOCK_FILE=swapLocks.sh \
33+
CHECK_DB_LOCK_FILE=checkDBLockStatus.sh
34+
35+
# Turn on dnfs
36+
RUN cd $ORACLE_HOME/rdbms/lib && make -f ins_rdbms.mk dnfs_on
37+
38+
# Updated Health Check
39+
HEALTHCHECK --interval=1m --start-period=30m \
40+
CMD "$ORACLE_BASE/$CHECK_DB_LOCK_FILE" >/dev/null || exit 1
41+
42+
# backup original runOracle
43+
RUN if test -e "$ORACLE_BASE/$RUN_FILE.orig"; then EXTN='extended'; else EXTN='orig'; fi ; \
44+
mv "$ORACLE_BASE/$RUN_FILE" "$ORACLE_BASE/$RUN_FILE.$EXTN" && \
45+
ln -sf "$ORACLE_BASE/$STARTUP_FILE" /home/oracle/ && \
46+
ln -sf "$ORACLE_BASE/$SHUT_DB_FILE" /home/oracle/
47+
48+
# Copy updated scripts for k8s support
49+
COPY --chown=oracle:dba $RUN_FILE $START_FILE $STARTUP_FILE $SHUT_DB_FILE $LOCKING_SCRIPT $CHECK_DB_LOCK_FILE $ORACLE_BASE/
50+
RUN mv "$ORACLE_BASE/$RUN_FILE" "$ORACLE_BASE/$RUN_FILE.$EXTENSION_NAME"
51+
COPY --chown=oracle:dba $SWAP_LOCK_FILE $ORACLE_BASE/scripts/setup/
52+
53+
# Set perms and append a call to main runOracle
54+
RUN if test -e "$ORACLE_BASE/$RUN_FILE.extended"; then \
55+
mv "$ORACLE_BASE/$RUN_FILE.extended" "$ORACLE_BASE/$RUN_FILE" ; \
56+
else echo ". $ORACLE_BASE/$RUN_FILE.orig" > "$ORACLE_BASE/$RUN_FILE" ; fi ; \
57+
if ! grep "$RUN_FILE.$EXTENSION_NAME" "$ORACLE_BASE/$RUN_FILE"; then \
58+
sed -i "1i . $ORACLE_BASE/$RUN_FILE.$EXTENSION_NAME" "$ORACLE_BASE/$RUN_FILE"; \
59+
fi && \
60+
chmod ug+x $ORACLE_BASE/*.sh $ORACLE_BASE/*.py && sync
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Support for Deployment on K8S
2+
3+
Packages the scripts required to run multiple replicas of Oracle Single Instance Database docker image in a Kubernetes cluster.
4+
5+
More information on how to deploy the resulting image using [helm](https://helm.sh/) can be found [here](https://github.com/oracle/docker-images/blob/main/OracleDatabase/SingleInstance/helm-charts/oracle-db/README.md).
6+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
# LICENSE UPL 1.0
3+
#
4+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
5+
#
6+
# Since: Mar, 2020
7+
# Author: mohammed.qureshi@oracle.com
8+
# Description: Checks the status of Oracle Database and Locks
9+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10+
#
11+
12+
export ORACLE_SID=${ORACLE_SID^^}
13+
14+
if "$ORACLE_BASE/$LOCKING_SCRIPT" --check --file "$ORACLE_BASE/oradata/.${ORACLE_SID}.create_lck"; then
15+
exit 1 # create lock held, DB is still initializing
16+
elif ! "$ORACLE_BASE/$LOCKING_SCRIPT" --check --file "$ORACLE_BASE/oradata/.${ORACLE_SID}.exist_lck"; then
17+
exit 1 # exist lock not held, DB is still initializing
18+
elif "$ORACLE_BASE/$CHECK_DB_FILE"; then
19+
# DB health is good
20+
exit 0
21+
elif test -f "$ORACLE_BASE/oradata/.${ORACLE_SID}.nochk"; then
22+
exit 1 # Skip health check
23+
elif pgrep -f pmon; then
24+
# DB procs detected
25+
exit 1
26+
else
27+
# No DB procs detected
28+
"$ORACLE_BASE/$LOCKING_SCRIPT" --release --file "$ORACLE_BASE/oradata/.${ORACLE_SID}.exist_lck"
29+
# Kill the process that keeps the container alive
30+
pkill -9 -f "tail.*alert"
31+
fi
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#! /usr/bin/python -u
2+
# LICENSE UPL 1.0
3+
#
4+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
5+
#
6+
# Since: Mar, 2020
7+
# Author: mohammed.qureshi@oracle.com
8+
# Description: Provides file locking support
9+
#
10+
#
11+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
12+
#
13+
14+
import os
15+
import time
16+
import sys
17+
import signal
18+
import argparse
19+
import fcntl
20+
import tempfile
21+
from multiprocessing.connection import Listener, Client
22+
23+
# Multiprocess communication auth key
24+
AUTHKEY = 'vkidSQkgAHc='
25+
26+
27+
def acquire_lock(lock_file, sock_file, block):
28+
"""
29+
Acquire a lock on the passed file, block if needed
30+
:param lock_file:
31+
:param sock_file:
32+
:param block:
33+
:return:
34+
"""
35+
print('[%s]: Acquiring lock on %s' % (time.strftime('%Y:%m:%d %H:%M:%S'), lock_file))
36+
lock_handle = open(lock_file, 'w')
37+
while True:
38+
try:
39+
fcntl.flock(lock_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
40+
print('[%s]: Lock acquired on %s' % (time.strftime('%Y:%m:%d %H:%M:%S'), lock_file))
41+
break
42+
except IOError as e:
43+
if not block:
44+
print(e)
45+
return 1
46+
time.sleep(0.1)
47+
48+
if os.fork():
49+
return 0
50+
else:
51+
# Spawn a child process to hold on to the lock
52+
if os.path.exists(sock_file):
53+
os.remove(sock_file)
54+
print('[%s]: Holding on to the lock using %s' % (time.strftime('%Y:%m:%d %H:%M:%S'), sock_file))
55+
listener = Listener(address=sock_file, authkey=AUTHKEY)
56+
57+
def release(sig=None, frame=None):
58+
"""
59+
Release if the process is stopped/terminated
60+
:param sig:
61+
:param frame:
62+
:return:
63+
"""
64+
# Hold on to the lock for other container
65+
# processes to terminate first. Allow 30 secs timeout
66+
if sig:
67+
time.sleep(30)
68+
lock_handle.close()
69+
listener.close()
70+
print('[%s]: Lock released on %s' % (time.strftime('%Y:%m:%d %H:%M:%S'), lock_file))
71+
72+
signal.signal(signal.SIGTERM, release)
73+
signal.signal(signal.SIGINT, release)
74+
while True:
75+
conn = listener.accept()
76+
if conn.recv():
77+
break
78+
release()
79+
80+
81+
def check_lock(sock_file):
82+
"""
83+
Check if lock is held
84+
:param sock_file:
85+
:return:
86+
"""
87+
if not os.path.exists(sock_file):
88+
return 1
89+
print('[%s]: Connecting to the lock process %s' % (time.strftime('%Y:%m:%d %H:%M:%S'), sock_file))
90+
cl = Client(address=sock_file, authkey=AUTHKEY)
91+
cl.send(False)
92+
cl.close()
93+
print('[%s]: Lock held' % (time.strftime('%Y:%m:%d %H:%M:%S')))
94+
return 0
95+
96+
97+
def release_lock(sock_file):
98+
"""
99+
Release the lock by connecting to lock process and terminating it
100+
:param sock_file:
101+
:return:
102+
"""
103+
if not os.path.exists(sock_file):
104+
return 1
105+
print('[%s]: Connecting to the lock process %s' % (time.strftime('%Y:%m:%d %H:%M:%S'), sock_file))
106+
cl = Client(address=sock_file, authkey=AUTHKEY)
107+
cl.send(True)
108+
cl.close()
109+
return 1
110+
111+
112+
def main():
113+
"""
114+
Main function, sets up arg parsing
115+
:return:
116+
"""
117+
parser = argparse.ArgumentParser(prog=sys.argv[0])
118+
parser.add_argument('--acquire', action='store_true', dest='acquire')
119+
parser.add_argument('--check', action='store_true', dest='check')
120+
parser.add_argument('--release', action='store_true', dest='release')
121+
parser.add_argument('--file', dest='lock_file')
122+
parser.add_argument('--block', action='store_true', dest='block')
123+
args = parser.parse_args()
124+
if not args.lock_file:
125+
parser.print_help()
126+
sys.exit()
127+
# Derive sock_file name from lock_file
128+
sock_file = os.path.join(tempfile.gettempdir(), os.path.basename(args.lock_file))
129+
if args.acquire:
130+
sys.exit(acquire_lock(args.lock_file, sock_file, args.block))
131+
elif args.check:
132+
sys.exit(check_lock(sock_file))
133+
elif args.release:
134+
sys.exit(release_lock(sock_file))
135+
136+
137+
# Entry point
138+
if __name__ == '__main__':
139+
main()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
# LICENSE UPL 1.0
3+
#
4+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
5+
#
6+
# Since: Mar, 2020
7+
# Author: mohammed.qureshi@oracle.com
8+
# Description: Runs the Oracle Database inside the container
9+
#
10+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
11+
#
12+
13+
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
14+
############# MAIN ################
15+
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #
16+
###################################
17+
18+
export ORACLE_SID=${ORACLE_SID^^}
19+
20+
"$ORACLE_BASE/$LOCKING_SCRIPT" --acquire --file "$ORACLE_BASE/oradata/.${ORACLE_SID}.create_lck" --block
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/bin/bash
2+
# LICENSE UPL 1.0
3+
#
4+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
5+
#
6+
# Since: Apr, 2020
7+
# Author: mohammed.qureshi@oracle.com
8+
# Description: Shuts down the Oracle Database.
9+
# The ORACLE_HOME and the PATH has to be set.
10+
#
11+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
12+
#
13+
14+
if [ "$#" = 0 ]; then
15+
cat << EOF
16+
17+
Usage: $0 [mode]
18+
Shutdowns the DB in the specified mode. Mode can be either of normal, immediate, transactional or abort
19+
20+
LICENSE UPL 1.0
21+
22+
Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
23+
24+
EOF
25+
exit 1
26+
fi
27+
28+
# Check that ORACLE_HOME is set
29+
if [ "$ORACLE_HOME" == "" ]; then
30+
script_name=`basename "$0"`
31+
echo "$script_name: ERROR - ORACLE_HOME is not set. Please set ORACLE_HOME and PATH before invoking this script."
32+
exit 1;
33+
fi;
34+
35+
export ORACLE_SID=$(grep "$ORACLE_HOME" /etc/oratab | cut -d: -f1)
36+
option="$1"
37+
38+
if "$ORACLE_BASE/$LOCKING_SCRIPT" --check --file "$ORACLE_BASE/oradata/.${ORACLE_SID}.exist_lck" &> /dev/null; then
39+
# Exist lock held, disable exit on failed health check
40+
touch "$ORACLE_BASE/oradata/.${ORACLE_SID}.nochk" && sync
41+
fi
42+
43+
echo "Performing shutdown $option"
44+
# Now shutdown database
45+
sqlplus / as sysdba << EOF
46+
shutdown $option;
47+
exit;
48+
EOF
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/bash
2+
# LICENSE UPL 1.0
3+
#
4+
# Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
5+
#
6+
# Since: Mar, 2020
7+
# Author: mohammed.qureshi@oracle.com
8+
# Description: Starts the Listener and Oracle Database.
9+
# The ORACLE_HOME and the PATH has to be set.
10+
#
11+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
12+
#
13+
14+
# Check that ORACLE_HOME is set
15+
if [ "$ORACLE_HOME" == "" ]; then
16+
script_name=`basename "$0"`
17+
echo "$script_name: ERROR - ORACLE_HOME is not set. Please set ORACLE_HOME and PATH before invoking this script."
18+
exit 1;
19+
fi;
20+
21+
export ORACLE_SID=$(grep "$ORACLE_HOME" /etc/oratab | cut -d: -f1)
22+
23+
# Start database in nomount mode, shutdown first to abort any zombie procs on restart
24+
for i in {1..10}; do
25+
sqlplus / as sysdba << EOF
26+
shutdown abort;
27+
startup nomount;
28+
exit;
29+
EOF
30+
if pgrep -f pmon; then
31+
break
32+
fi
33+
# Sometimes DB locks of dead container are not released immediately
34+
echo "Waiting for $i sec(s) before restarting Oracle processes"
35+
sleep $i
36+
done
37+
38+
# startup can get into a wait mode here
39+
$ORACLE_BASE/scripts/setup/$SWAP_LOCK_FILE
40+
41+
# Start Listener
42+
lsnrctl start
43+
44+
condn_sql=""
45+
if ! pgrep -f pmon; then
46+
# if Oracle processes die for some reason by the time lock is acquired
47+
condn_sql="shutdown abort;
48+
startup nomount;
49+
"
50+
fi
51+
52+
# Disable exit on failed health check
53+
touch "$ORACLE_BASE/oradata/.${ORACLE_SID}.nochk" && sync
54+
55+
for i in {1..10}; do
56+
# Start database
57+
sqlplus / as sysdba << EOF
58+
$condn_sql
59+
alter database mount;
60+
alter database open;
61+
alter pluggable database all open;
62+
alter system register;
63+
exit;
64+
EOF
65+
if "$ORACLE_BASE/$CHECK_DB_FILE"; then
66+
# DB health is good
67+
echo "DB is in good health on startup"
68+
break
69+
fi
70+
# Sometimes DB locks of a dead container are not released immediately
71+
echo "Waiting for $i sec(s) before restarting Oracle processes and opening the database"
72+
sleep $i
73+
done
74+
75+
# Enable health check exit
76+
rm -f "$ORACLE_BASE/oradata/.${ORACLE_SID}.nochk"
77+

0 commit comments

Comments
 (0)