QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

MySQL 是如何做容器测试的?

  • 2018-09-27
  • 本文字数:8909 字

    阅读完需:约 29 分钟

传统的基础设施管理是一项手动任务,由系统管理员管理静态服务器。现代云平台的自动化能力改变了这种工作方式:基础设施通常被描述为“代码”,基础设施管理系统会对基础设施自动做出变更。因此,基础设施的变得更加动态,周转时间也要短得多。

基础设施测试框架通常被用于验证机器镜像的状态(Amazon Machine Images、Google Compute Images 或 Oracle OCI Images)。随着容器基础设施的出现,容器基础设施的测试变得与机器镜像的测试一样重要。

在 MySQL,我们有很多基础设施,我们越来越多地使用容器来代替真实(虚拟)机器。此外,越来越多的核心基础设施运行在 Oracle 的云基础设施(OCI)上。这要求我们实现多个级别的自动化,并且可以利用基础设施测试来验证我们的服务器(或虚拟机、容器)的状态。基础设施测试还用于验证我们发布的一些工件的状态。

在这篇博文中,我们将重点介绍如何使用自动化基础设施测试来验证 MySQL Server Docker 镜像。我们将比较三个可用于进行容器测试的框架,并给出示例代码。

自动化基础设施测试

基础设施测试用于测试基础设施的状态:Apache 服务器是否在监听 80 端口?是否正确配置了 DNS 服务器,这些设置是否正确反映在 resolv.conf 文件中?要安装的二进制文件是否都已经存在于机器镜像中?

这类测试可以作为 bash 脚本的一部分,因此通常被用于配置任务,或者在(手动)创建实例后进行手动验证。自动化基础设施测试更进一步,它假设需要对很多基础设施和脚本的正确性做出验证,以及动态的现代云环境有很多东西需要通过手动的方式处理。

基础设施测试工具通常与 Ansible、Puppet 或 Chef 等配置工具结合使用。配置工具在机器上安装软件,测试框架则确保它们能够正常运行。然后,任何东西都可以通过代码来表示,并使用工具进行自动化。

我们的重点是测试 Docker 镜像,对我们来说,这些工作有点偏向底层。由于我们所有的 Docker 镜像主要是由经过测试并发布的 yum 软件包层组成,这些层位于非常可靠的 OS 层之上,我们主要想要验证软件包的版本是否正确,以及这些二进制文件的功能是否正常。在镜像构建期间,可能会发生网络故障,出现软件包安装不完整的情况,我们想要通过自动化测试来捕捉它们。

在评估测试工具时,需要考虑到以下两个方面的问题:

  • 配置语言,即想要测试的内容(可用包、必要的文件等)
  • 测试执行,即如何运行测试(local/ssh/container)

对于以下的工具,我们将关注这两个方面的问题。这个领域最常见的工具包括:

  • InSpec/Serverspec
  • Goss
  • Container Structure Test

接下来,我们将逐个简要介绍它们。

InSpec

InSpec 基于 RSpec(Ruby)测试框架,并借鉴了 Serverspec(也是基于 RSpec 构建,并被广泛采用)的经验。它是 Chef 生态系统的一部分,用于配置和测试基础设施。它的配置保存在一个 ruby 文件中。

可以通过 resources 指定多种配置语言

通过 targets(local/ssh/docker)来测试执行

Goss

Goss 是 Serverspec 的一个快速而简单的替代品,是使用 Go 语言开发的一个服务器测试和验证框架。它的配置保存在一个 yaml 文件中,这个文件可以很方便地从当前系统状态生成。

支持多种配置语言

支持在本地和 Docker 容器中执行测试(通过 dgoss 脚本)

Container Structure Test

Container Structure Test 是一个用于验证容器镜像结构的框架。与 Goss 一样,它也是用 Go 语言编写,并使用了 yaml 配置文件。该项目于今年早些时候发布,它的应用范围相对较窄(只支持容器),但它提供了足够的功能来测试镜像。

  • 支持的配置语言较少
  • 测试执行仅限于本地容器

示例:MySQL Server Images

接下来,我们将演示如何安装所需工具,解释各个配置文件,并在本地运行测试。我们针对最新的 MySQL Server 容器(latest 或 8.0 标签)运行测试。为了方便起见,我们跳过构建步骤,从公共注册表下载容器并在本地运行测试。在我们的构建管道中,我们首先构建容器,运行测试,在运行成功之后才会推送到公共注册表。可以通过输入以下命令来获取最新版本的 mysql-server 镜像:

复制代码
docker pull mysql/mysql-server

总的来说,我们想测试两个东西:

  • 容器是否存在主机上,并包含正确的元数据
  • 容器是否包含所有的包和二进制文件

先决条件

除了可用的 Docker 环境之外,运行该示例还需要在本地安装 InSpec、Goss 和 Container Structure Test。

InSpec 的说明可以在这里找到: https://downloads.chef.io/inspec 。在 Linux 平台上,可以通过运行以下命令安装 Goss 和 Container Structure Test 二进制文件:

复制代码
curl -L https://github.com/aelsabbahy/goss/releases/download/v0.3.6/goss-linux-amd64 -o goss && chmod +x goss
curl -L https://raw.githubusercontent.com/aelsabbahy/goss/master/extras/dgoss/dgoss -o dgoss && chmod +x dgoss
curl -L https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 -o container-structure-test && chmod +x container-structure-test

安装好所有二进制文件并将它们添加到系统路径中,然后就可以通过 shell 脚本运行测试。

测试配置

为了比较配置和测试执行过程的不同之处,我们提供了用于测试这三个框架的 MySQL Server Docker 镜像的示例文件: https://github.com/neumayer/mysql-server-image-tests

可以通过以下命令来克隆它:

复制代码
git clone https://github.com/neumayer/mysql-server-image-tests.git

存储库中包含的配置文件:

  • mysql-server-inspec.rb
  • goss.yaml
  • mysql-server-container-structure-test.yml

让我们来依次查看这些文件,先从 InSpec 配置文件开始:

复制代码
control 'container' do
impact 0.5
describe docker_container('mysql-server') do
it { should exist }
it { should be_running }
its('repo') { should eq 'mysql/mysql-server' }
its('ports') { should eq '3306/tcp, 33060/tcp' }
its('command') { should match '/entrypoint.sh mysqld' }
end
end
control 'server-package' do
impact 0.5
describe package('mysql-community-server-minimal') do
it { should be_installed }
its ('version') { should match '8.0.12.*' }
end
end
control 'shell-package' do
impact 0.5
describe package('mysql-shell') do
it { should be_installed }
its ('version') { should match '8.0.12.*' }
end
end

InSpec 通过 profile 和 control 来组织测试用例,其中 control 是较小的单元,是与给定主题相关的一组测试。第一个 control 叫“container”,针对宿主机器运行,与运行在 localhost 上的 Docker 守护进程通信,验证容器是否正在运行。另外两个 control 检查容器内的包。这种区别很重要,因为后两个 control 可以针对 localhost、ssh 主机或 Docker 容器运行。在我们的例子中,我们让它们针对容器运行,这样可以带来非常好的可重用性和灵活性。虽然我们在示例中只使用了 Docker 和包资源,但实际上 control 可以使用任何现有的 InSpec 资源。

下面是运行流程:

  • 启动容器
  • 针对 localhost 运行 “container” control
  • 针对容器运行剩余的 control

脚本看起来是这样的:

复制代码
docker run -d --name mysql-server mysql/mysql-server
inspec exec mysql-server-inspec.rb --controls container
inspec exec mysql-server-inspec.rb -t docker://mysql-server --controls server-package

如果运行成功,InSpec 将输出以下内容:

复制代码
Profile: tests from mysql-server-inspec.rb (tests from mysql-server-inspec.rb)
Version: (not specified)
Target: local://
✔ container: Docker Container mysql-server
✔ Docker Container mysql-server should exist
✔ Docker Container mysql-server should be running
✔ Docker Container mysql-server repo should eq "mysql/mysql-server"
✔ Docker Container mysql-server ports should eq "3306/tcp, 33060/tcp"
✔ Docker Container mysql-server command should match "/entrypoint.sh mysqld"
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 5 successful, 0 failures, 0 skipped
Profile: tests from mysql-server-inspec.rb (tests from mysql-server-inspec.rb)
Version: (not specified)
Target: docker://d06da2588b80a4ee9b839b55c2f719ab9e860904eeb831b71488704f50f8b994
server-package: System Package mysql-community-server-minimal
System Package mysql-community-server-minimal should be installed
System Package mysql-community-server-minimal version should match "8.0.12.*"
Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 2 successful, 0 failures, 0 skipped

Goss 的配置文件如下所示:

复制代码
file:
/usr/sbin/mysqld:
exists: true
contains: []
package:
mysql-community-server-minimal:
installed: true
mysql-shell:
installed: true
port:
tcp6:3306:
listening: true
ip: []
tcp6:33060:
listening: true
ip: []
user:
mysql:
exists: true
process:
mysqld:
running: true

除了 mysqld 文件,我们还要检查所需的软件包是否已安装、公开端口是否正确以及所需的进程是否在运行。Goss 将为我们启动容器:

复制代码
GOSS_SLEEP=10 dgoss run -p 3306:3306 mysql/mysql-server

因为设置了 GOSS_SLEEP,所以我们的服务器有足够时间完成初始化,其余参数被传给 docker run。输出如下:

复制代码
INFO: Starting docker container
INFO: Container ID: 75bc8869
INFO: Sleeping for 10
INFO: Running Tests
File: /usr/sbin/mysqld: exists: matches expectation: [true]
User: mysql: exists: matches expectation: [true]
Process: mysqld: running: matches expectation: [true]
Port: tcp6:33060: listening: matches expectation: [true]
Port: tcp6:33060: ip: matches expectation: [[]]
Port: tcp6:3306: listening: matches expectation: [true]
Port: tcp6:3306: ip: matches expectation: [[]]
Package: mysql-shell: installed: matches expectation: [true]
Package: mysql-community-server-minimal: installed: matches expectation: [true]
Total Duration: 0.038s
Count: 9, Failed: 0, Skipped: 0
INFO: Deleting container

Container Structure Test 的 yaml 配置片段如下:

复制代码
schemaVersion: "2.0.0"
metadataTest:
exposedPorts: [ "3306", "33060" ]
entrypoint: [ "/entrypoint.sh" ]
cmd: [ "mysqld" ]
volumes: [ "/var/lib/mysql" ]
commandTests:
- name: "mysqlsh"
command: "mysqld"
args:
- "--version"
expectedOutput:
- "8.0.12"
- name: "mysqlsh"
command: "mysqlsh"
args:
- "--version"
expectedOutput:
- "8.0.12"
fileExistenceTests:
- name: "mysqld"
path: "/usr/sbin/mysqld"

此外,我们还要检查公开的端口是否正确,然后直接运行二进制文件(而不是像其他工具那样使用内部包装器)以验证它们是否已就位。

复制代码
container-structure-test --image mysql/mysql-server test --config mysql-server-container-structure-test.yml

与 Goss 类似,调用起来很简单,只需要提供镜像名称和配置文件。

复制代码
==================================================================
====== Test file: mysql-server-container-structure-test.yml ======
==================================================================
INFO: stdout: /usr/sbin/mysqld Ver 8.0.12 for Linux on x86_64 (MySQL Community Server - GPL)
=== RUN: Command Test: mysqlsh
--- PASS
stdout: /usr/sbin/mysqld Ver 8.0.12 for Linux on x86_64 (MySQL Community Server - GPL)
INFO: stdout: mysqlsh Ver 8.0.12 for Linux on x86_64 - for MySQL 8.0.12 (MySQL Community Server (GPL))
=== RUN: Command Test: mysqlsh
--- PASS
stdout: mysqlsh Ver 8.0.12 for Linux on x86_64 - for MySQL 8.0.12 (MySQL Community Server (GPL))
INFO: File Existence Test: mysqld
=== RUN: File Existence Test: mysqld
--- PASS
=== RUN: Metadata Test
--- PASS
===================================================================
============================= RESULTS =============================
===================================================================
Passes: 4
Failures: 0
Total tests: 4
PASS

Container Structure Test 运行速度快,易于调用,只不过只能用于容器。在大多数情况下,它可以确保容器的行为是正确的。

可以在存储库的根目录运行以下脚本来执行上述的测试:

  • ./inspec.sh
  • ./goss.sh
  • ./container-structure-test.sh

MySQL 的容器测试

我们已经开始使用 InSpec 测试所有的 Docker 镜像。从下一个 MySQL 版本(8.0.13)开始,基本的 InSpec 测试将成为 MySQL Server、MySQL Cluster 和 MySQL Router Docker 镜像自动发布流程的一部分。我们主要基于以下几点做出这样的决定:

  • 它拥有最大的作用域(ssh/local/docker),可进一步在内部使用;
  • 广泛的资源;
  • 依赖机制;
  • 由于它与 Chef 生态系统的关系以及与 Serverspec 的相似性而被广泛采用。

存在的不足:

  • 因为是 ruby 调用,运行速度感觉比 Go 语言的替代品慢(但我们认为这不是关键问题);
  • InSpec 更通用,但需要做出权衡,用更多的脚本来运行测试。

我们将 InSpec 作为自动发布管道的一部分,如果测试失败,将不会生成任何工件。我们的 QA 流程包含很多其他步骤,例如之前对 MySQL Docker 镜像中的 rpm 包进行的单独测试。

相关链接:

https://cloud.oracle.com/cloud-infrastructure

https://www.chef.io

https://www.inspec.io/docs/reference/resources/

https://www.inspec.io/docs/reference/inspec_and_friends/

https://goss.rocks/

https://github.com/GoogleContainerTools/container-structure-test

https://hub.docker.com/r/mysql/mysql-server/

英文原文: https://mysqlrelease.com/2018/09/container-testing-for-mysql-server/

感谢张婵对本文的审校。

2018-09-27 11:201750
用户头像

发布了 731 篇内容, 共 455.0 次阅读, 收获喜欢 2003 次。

关注

评论 1 条评论

发布
暂无评论
发现更多内容

解锁 PDF 文件:使用 JavaScript 和 Canvas 渲染 PDF 内容

yuanyxh

前端 js PDF

tair性能挑战赛攻略心得-Zzzzz

阿里云天池

谷歌云推出全新区块链RPC服务:简化Web3开发

区块链软件开发推广运营

交易所开发 dapp开发 区块链开发 公链开发 代币开发

C++中对象的延迟构造

快乐非自愿限量之名

Java c++

Multitouch for Mac(多点触控手势增强神器)

Mac相关知识分享

TikTok怎么开直播?TikTok直播专线是什么?

Ogcloud

海外直播专线 tiktok直播 tiktok直播专线 海外直播网络 tiktok直播网络

fetch --nohooks webrtc 失败

webrtc developer

Flink垃圾图片分类优胜奖比赛攻略_贪吃的小香猪-148队

阿里云天池

关于深度学习量化的操作

芯动大师

深度学习 gpu 模型化

Mint Expedition Season 3 拉开帷幕:登顶高峰的时刻到了

NFT Research

blockchain web3 空投

阿里巴巴API助力电商:商品详情获取与数据驱动的完美结合

技术冰糖葫芦

API Gateway API 接口 API 测试 pinduoduo API

什么是任务管理工具

高端章鱼哥

BBEdit for Mac(HTML文本编辑器)

Mac相关知识分享

VLDB 2024 圆桌会议回顾:展望物联网与 AI 时代的时序数据库

Apache IoTDB

工业物联网PaaS平台的商业模式研究

不在线第一只蜗牛

云原生 物联网 PaaS

2024中国算力大会,河南如何绘写算力长卷?

脑极体

AI

四类取整方式

不在线第一只蜗牛

c++ C#

TikTok直播专线服务商推荐

Ogcloud

海外直播专线 tiktok直播 tiktok直播专线 tiktok直播网络 TikTok跨境直播

茶思屋直播|TinyEngine+AI:聚焦主航道,在实践中探索低代码技术黑土地

OpenTiny社区

低代码 OpenTiny TinyEngine

离散制造 vs 流程制造:锚定精准制造未来,从装配线到化学反应,实时数据集成在制造业案例中的多维应用

tapdata

数据库

智能财务推动企业数字化转型的研究及实践

快乐非自愿限量之名

低代码

借助Python和搜狐视频联盟API自动推荐热门视频

幂简集成

视频 API

Java获取Object中Value的方法

快乐非自愿限量之名

Java

TON基金会与Curve Finance合作:推出基于TON的新型稳定币互换项目

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 NFT开发 公链开发

万界星空科技MES系统:食品加工安全的实时监控与智能管理

万界星空科技

mes 万界星空科技 食品MES 食品行业 食品

干货满满!第二期流程挖掘实践训练营圆满落幕~

望繁信科技

流程挖掘 流程资产 流程智能 数字北极星 望繁信科技

试用完几十款ETL工具后的经验总结,ETL工具用这三款就足够了

RestCloud

kettle ETL DataX ETL数据集成

低代码开发:数据分析如何快速响应企业需求

EquatorCoco

低代码

VLDB 2024 圆桌会议回顾:展望物联网与 AI 时代的时序数据库

Apache IoTDB

mac苹果电脑办公套件全家桶下载:Office2019 for Mac 下载

你的猪会飞吗

Microsoft Office 2019 office 2019 mac破解软件下载

开发一个 PicGo 插件

yuanyxh

前端 PicGo js

MySQL是如何做容器测试的?_软件工程_Robert Neumayer_InfoQ精选文章