Ubuntu 18.04下使用AWS OpsWorks部署时mysql_client安装失败如何解决
问题根因
整个报错的触发链路是两层兼容性问题叠加导致的:
- 系统升级过程中,AWS OpsWorks自动将内置Chef运行时从原有的12.13.37升级到12.18.31,该版本收紧了自定义资源的属性校验规则;同时当前使用的mysql cookbook是早期为Ubuntu 16.04环境适配的版本,和Ubuntu18.04的包结构未做兼容。
- Cookbook加载阶段,
mysql/libraries/mysql_base.rb中定义的version属性仅声明接受String类型,默认值设为nil,触发Chef的CHEF-5属性校验规则告警。 - 执行部署动作时,cookbook自动探测系统中mysql客户端包版本的逻辑未适配Ubuntu18.04的包结构,探测结果返回nil;后续代码直接对nil值调用
split方法,触发NoMethodError导致安装流程中断。
对应解决方法
快速临时修复
不需要修改cookbook源码,直接在业务调用代码中显式传入合法的版本值,绕开自动探测逻辑:
mysql_client 'default' do # Ubuntu 18.04 官方源默认提供的mysql客户端包版本为5.7 version '5.7' action :create end
这种方式可以直接跳过内部版本探测流程,不会拿到nil值触发空方法调用报错,可快速恢复部署。
本地补丁修复(不升级cookbook版本的前提下)
如果不想改动业务层的资源调用逻辑,可以直接在本地cookbook仓库修改两处代码适配新环境:
- 第一处:修改
mysql_base.rb中version属性的校验规则,允许nil值作为合法输入,消除属性校验告警。将原有属性定义
调整为property :version, String, default: nilproperty :version, [String, nil], default: nil - 第二处:定位cookbook中对版本值调用
split的代码段,增加nil值判断保护,避免空值调用方法报错。比如原有逻辑node['mysql']['pkg_version'].split('.').first,增加判空分支:pkg_version = node['mysql']['pkg_version'] return if pkg_version.nil? major_version = pkg_version.split('.').first
长期稳定方案
将当前使用的老旧版本mysql cookbook升级到适配Chef 12.18、Ubuntu 18.04的稳定8.x系列版本,该版本已经内置了Ubuntu18.04的包探测逻辑、对齐了新版Chef的属性校验规则,升级完成后原有业务调用代码不需要任何改动即可正常运行,从根源上避免后续同类环境升级带来的兼容问题。
内容的提问来源于stack exchange,提问作者Paul Warren
相关产品推荐
相关产品推荐

