作为DBA运维人员
数据库真的可以运行在容器里面吗?
容器本身会不会存在安全隐患?
会不会丢失数据?
那就是丢了饭碗了啊!!!
但是公司业务发展的速度实在太快,来了一个厂商或者应用就要求我们上线一个RDS实例,并且要求实例具备高可用、可扩展能力,随时上线或者下线,领导又要求提高物理硬件资源利用率。业务部门整天催着我们快速提供数据库服务,数据库实例多了后,运维难度和复杂度直线上升。公司IT发展战略朝着微服务和互联网化全面改造,DevOps建设又旨在打通运维和开发部门壁垒,作为DBA运维人员该如何适应这种转型?
传统DBA运维管理方式无法满足当前需求
笔者同是MySQL 运维DBA过来人,目前在乙方公司转型做RDS相关产品工作。同甲方DBA运维或开发部门打交道过程中,非常能够感同身受在当前云计算、容器化、微服务等大浪中,DBA运维人员的痛点和难点。
通常DBA运维人员,研发能力比较弱,没有工程化项目经验。当然自动化运维、shell或者python脚本辅助工具等,对于小规模的RDS集群(10~20)的运维管理已经够用。但是随着公司规模的扩大应用场景的丰富,企业通常不会只有一种数据库实例,可能并存着MySQL、Oracle、SQL Server、 PostgreSQL等。
那么企业用人方要求DBA掌握多种数据库的特性能力,或者招聘每种DBA从业人员。其实关系型数据库在横向使用场景上存在共性如:高可用、RDS集群规模可扩展、计算/存储可变更、备份恢复、监控告警等等。
不要让RDS服务质量成了最后的短板
研发和运维之间确实存在壁垒,我们经常看到研发人员发布软件应用上线后,需要由运维人员提供硬件和网络环境进行部署,通常运维人员并不关心你软件运行的“好坏”或者“快慢”,只关心物理服务和网络等监控指标。
DBA运维人员除了需要关心这些指标外,还需要关心数据库软件本身的“好坏”和“快慢”。比如应用的表是否创建了合理的索引、物理机存储空间大小、SQL语句是否非法如使用了select * From table1、table2...等导致存储介质的IO被打满等等。当企业开始微服务和DevOps建设后,对服务敏捷和快速交付能力提出了要求。而关系型数据库又是一类比较特别的应用场景,一些大规模的企业更是专门设置了DBA部门来负责数据库实例的运维和开发工作。随着企业业务对产品研发速度和快速适应市场的要求,数据库实例交付速度和能力逐渐成为瓶颈。
容器化是必经之道
研发人员为什么喜欢容器?因为容器技术打包了程序所需运行时的上下文并且拥有优秀的跨平台能力,通过定义简单的流程,可以协助企业开发和运维人员快速发布和部署应用。当然也有部分DBA运维人员对容器数据库不感冒,我认为是没有合适的场景。上文提到DBA运维人员可以通过自动化运维、shell或者python脚本辅助工具等,对于小规模的RDS集群(10~20)的运维管理已经足够。
那么什么场景是合适数据库运行在容器内?笔者接触到的客户场景,通常是企业开始建设自己的DevOps需要快速交付RDS服务或是企业DBA人员 VS 负责数据库实例数量达到1:50 以上的规模比例。
浅谈容器数据库价值
所谓容器只不过是一个普通进程,这个进程的特殊之处在于:1)它可能是位于不同命名空间(ns)的,使用clone/unshare/setns系统调用将容器进程加入不同的命名空间 2)它对资源的使用(cpu,memory,diskio等)可能受到CGroup资源控制的限制。
通过使用容器graphdriver的特性,DBA在单机运行多个实例的场景下,同样版本的数据库实例本身需要运行的库文件共享了base image,大大节省了物理机器的存储空间。
容器内数据的“安全”问题
DBA最关心的基础问题是数据完整性和安全性,上文提到容器只不过是普通的一个进程,利用了Linux kernel的特性“伪装”成一个虚拟的OS运行环境,graphdriver通过CoW机制,解决镜像文件共享问题。
运行关系型数据库容器,我们需要通过另外的“接口”,不通过graphdriver来持久化数据。容器本身提供持久化数据的能力。例如:运行容器化MySQL实例,将OS的目录/opt挂载到容器的/var/lib/mysql目录,容器内MySQL实例所产生的数据都写到宿主机的/opt目录下。
代码语言:javascript复制docker run --name mysql -v /opt:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=somepassword -d mysql/mysql-server:5.7
我们通过docker inspect docker-id命令,查看该容器数据库的运行spec信息。截取部分关键信息。
代码语言:javascript复制"Mounts": [ { "Type": "volume", "Name": "b13109e14d1fd5c2d9957689a2d509b90ca8eafd4080a92de636eeb97090c0fd", "Source":"/var/lib/docker/volumes/b13109e14d1fd5c2d9957689a2d509b90ca8eafd4080a92de636eeb97090c0fd/_data", "Destination": "/var/lib/mysql",
我们看到,docker通过type为volume的方式,映射OS目录到容器内进行绑定,我们完全可以通过OS的文件系统如ext4和XFS,或者利用分布式存储的卷来保证容器数据库的数据安全。
kubernetes是容器化数据库集群最佳实践
以上非常粗浅的谈到运维DBA通常对容器数据库的质疑,当然如果要大规模部署容器数据库集群,离不开好的架构设计。
"kubernetes is eating the Container world"这句话一点都不夸张,云原生,微服务,PaaS,IoT,DevOps等等,以容器为技术栈的架构几乎都将k8s做为首选。笔者所负责的产品,同样将k8s作为容器数据库编排的框架提供多类RDS服务,目前单集群最大支持RDS规模达到1000 。kubernets架构可以让企业通过扩展自定义的资源类型来部署容器化数据库,当然还需要根据自身的业务场景来解决容器数据库的数据持久化问题,容器数据库的编排调度策略,网络方案及服务暴露方式等等。
当企业将k8s作为IT架构将数据库容器化后,给运维DBA带来的收益将是完全匹配业务快速发展的需要以及对RDS服务质量的要求,但同时也对运维DBA带来了全新的挑战,运维DBA需要充分理解k8s架构设计体系,能够通过k8s自带的Cli组件或者自定义yaml来管理资源任务。