问题的现象
当我们在Docker容器中安装和创建oracle11g数据库时,可以成功安装软件、成功配置网络服务监听,但是在执行dbca建库程序时会在执行到76%左右的时候报错挂起。虽然反复换了多个环境,包括把基础镜像系统从centos7换到centos6,最终问题的现象是一致的,即卡在进度条76%的地方就僵死掉了。
我们使用的oracle版本是11.2.0.30。以相同的方式和环境条件安装oracle12c时,均可以成功完成安装和配置,并不会有类似问题。
问题的分析
参考资料
关于该问题在网上的资料并不多,最终找到以下两篇技术资料,可以有效地讲清问题的原因,且解决掉问题。
- https://zhangjoto.github.io/li-yong-dockerjian-li-oracle-11gshi-yan-huan-jing.html#dockerfile
- https://www.cnblogs.com/diffx/p/11005799.html
问题分析
在遇到以上问题时,请先查看oracle数据库的安装日志:
$ORACLE_BASE/cfgtoollogs/dbca/$ORACLE_SID/postDBCreation.log
从该安装日志中,可以得到一个有效的错误信息提示,如下所示:
ERROR at line 1:
ORA-29516: Aurora assertion failure: Assertion failure at joez.c:3422
Bulk load of method java/lang/Object.<init> failed; insufficient shm-object space
ORA-06512: at line 3
- 显示oracle需要使用的shm-object共享内存空间不足!
一般来说,这个/dev/shm共享内存空间是直接挂载使用的操作系统tmpfs空间,tmpfs在redhat中默认大小为物理内存的一半。Oracle 中的Automatic Memory Management特性就使用了/dev/shm。
我们检查一下Docker容器实际上给运行中的容器分配了多大的/dev/shm空间:
$ grep /dev/shm /etc/fstab
tmpfs /dev/shm tmpfs defaults 0 0
单独查看/etc/fstab中的静态挂载参数时,还没有发现什么问题。
继续查看下分区的动态挂载结果:
$ grep /dev/shm /etc/mtab
shm /dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=65536k 0 0
可以看到最终的挂载参数中多出一个 size=65536k
的选项 ,把容器实例可用的/dev/shm
空间大小限制为65MB
。
这便是造成我们在容器中创建oracle11g库实例失败的直接原因。而oracle12c可能是针对容器资源的这一使用限制做出了适配处理,故虽然软件版本更新,却不会在建库时报错。
问题的解决
Docker容器的解决办法
在创建容器时,需要指定 --privileged
选项,以允许容器修改/dev/shm
空间的挂载参数。
在容器中修改 /etc/fstab
文件,将/dev/shm
的挂载参数更新为 tmpfs /dev/shm tmpfs defaults,size=1g 0 0
。
在容器中,使用dbca建库之前,执行 # mount -o remount /dev/shm 命令,重新挂载下 /dev/shm 空间。
Kubernetes中的解决办法
在k8s中,是一个容器集群的概念,我们不便为某一个容器开后门。所以,参照网上的资料,最终采用的是下面这样的解决方案。
在创建Pod容器时,为其定义一个emptyDir
类型的存储卷,而该存储卷的medium
类型定义为 Memory
,将该存储卷挂到容器的/dev/shm
路径下。
以下是两个相关的yaml代码版本段:
1)存储卷挂载路径的定义
volumeMounts:
- mountPath: /dev/shm
name: dshm
2)存储卷的定义
volumes:
- name: dshm
emptyDir:
medium: Memory
采用以上解决办法,即可成功在Docker/k8s中安装出oracle 11g数据库了。