2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

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:202217
用户头像

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

关注

评论 1 条评论

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

下一站,冠军|走进2022 OceanBase数据库大赛12强

OceanBase 数据库

数据库 oceanbase

软件测试/测试开发 | 测试平台开发-前端开发之Vue.js 框架的使用

测试人

重磅通知!OpenAI又放大招:官宣开放API接口-3.5版本 需求大涨,机遇与挑战并存,谁能拔得头筹?

加入高科技仿生人

人工智能 开源 openai ChatGPT

what量化合约系统开发&源码丨clear合约量化系统开发技术(Demo案例)

I8O28578624

软件测试/测试开发 | 一步一步学测试平台开发-Vue restful请求

测试人

软件测试 自动化测试 测试开发 测试平台

瓴羊Quick BI与Power BI之争:数据大屏优势明显

对不起该用户已成仙‖

软件测试/测试开发 | 测试平台开发-前端开发之Vue router路由设计

测试人

软件测试 测试开发 测试平台

微服务引擎 MSE 企业版全新升级

阿里巴巴中间件

阿里云 微服务 云原生

小程序容器作为软件中间件技术不可忽视的价值

FinFish

小程序容器 小程序技术 软件中间件

隐私计算技术路线介绍及对比

隐语SecretFlow

隐私计算

OpenKruise 开发者不容错过的带薪实习机会!马上加入 LFX Mentorship 计划

阿里巴巴中间件

阿里云 开源 云原生 OpenKruise

新思科技为三星SDS公司开源使用和风险管理提供自动治理解决方案

InfoQ_434670063458

开源 软件开发 新思科技 软件安全

首批!阿里云容器服务 ACK 顺利通过信通院云原生混部项目评估

阿里巴巴中间件

阿里云 容器 云原生

开源项目的演进会遇到哪些“坑”?KubeVela 从发起到晋级 CNCF 孵化的全程回顾

阿里巴巴云原生

阿里云 开源 云原生 KubeVela

基于Python+UIautomation的WindowsGUI自动化测试实战(二)-计算器

Python 自动化测试 GUI UIaotumation

ChatGPT潜能很大,问题也是

引迈信息

人工智能 低代码开发 应用开发 ChatGPT JNPF

为企业全方位解决进销存管理难题的ERP套件

力软低代码开发平台

ICLR 2023 | 网易伏羲3篇论文入选,含强化学习、自然语言处理等领域

网易伏羲

Soul 云原生网关最佳实践

阿里巴巴中间件

阿里云 云原生 实践 云原生网关

数据库革新拐点已来——MatrixOne Beta Program Recap

MatrixOrigin

云原生 分布式数据库 MatrixOrigin MatrixOne

详细剖析|袋鼠云数栈前端框架Antd 3.x 升级 4.x 的踩坑之路

袋鼠云数栈

前端‘’

【云图说】 | 第268期 初识开天企业工作台MSSE

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 3 月 PK 榜

使用metrics-server监控k8s的资源指标

tiandizhiguai

DevOps 微服务 云原生 k8s

基于Python+UIautomation的WindowsGUI自动化测试实战(一)-记事本

自动化测试 GUI UIaotumation

ChatGPT辅助编程

鲸品堂

ChatGPT 企业号 3 月 PK 榜

2022 IoTDB Summit:阿里白渐《迈向物联网时代大数据计算平台——MaxCompute 基于IoTDB构建解决方案》

Apache IoTDB

大数据 时序数据库 IoTDB

Apache IoTDB v0.13.4 发布|优化监控功能

Apache IoTDB

IoTDB

Apache IoTDB v1.0.1 发布|修复分区计算,优化集群启停流程

Apache IoTDB

IoTDB

新思科技发布《2023年开源安全和风险分析》报告

InfoQ_434670063458

开源 新思科技 软件安全

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