前言

持续部署(CD)流水线,已经成为新软件构建和测试时的必备利器。这其中也包括测试环境建立、测试执行验证和销毁测试环境,以可重复的方式不断持续进行。通常我们会添加自动化测试工具,进行功能测试、负载测试、集成测试和其他非功能性测试,并在推送到生产之前和之后都会验证产品的质量。

现在借助混沌工程,我们就可以把故障注入测试添加到已有的自动化测试套件中。CI/CD流水线中,也应添加混沌实验运行的新步骤,确保所有代码更改在到达用户之前都是可靠的。因此,在持续部署流水线中,我们使用“自动故障注入”的方式来测试可靠性,以便及早发现问题并减少生产事件。

本文中,我们将在Jenkins流水线中创建新的Stage,以使用Gremlin将受控数量的故障注入到测试系统。通过本文,你将学习到:

  • 如何使用Docker部署Jenkins实例。
  • 如何在Gremlin中创建API密钥。
  • 如何使用Gremlin API发起攻击。

一、先决条件

在开始本教程之前,以下是必备的先决条件:

Docker,用于从容器镜像轻松部署Jenkins。

Gremlin部署在运行混沌实验的主机上。这可以是与Jenkins相同的主机,但理想情况下,它应该是应用部署的主机,以便进行测试。

Gremlin帐户(在下面注册)。

image.png

1.1 启动并运行Jenkins

在这一步中,使用官方Docker镜像建立一个Jenkins实例。如果已经有一个Jenkins环境,请跳到1.3创建混沌部署流水线。

在命令行中,输入以下内容,使用Docker初始化Jenkins实例。

docker run --publish 8080:8080 --publish 50000:50000 --name jenkins jenkins/jenkins:lts-alpine

在浏览器上打开http://localhost:8080,确认Jenkins正在运行。

如果这是第一次设置 Jenkins,需要输入管理员密码和选择安装的软件包。默认设置将正常工作。然后,添加一个管理员用户并登录该帐户。

image.png

1.2 添加Gremlin API到Jenkins

在此步骤中,在Jenkins实例中输入Gremlin API密钥和团队ID。

Gremlin API密钥与Gremlin用户帐户相关联,并允许Jenkins向Gremlin进行身份验证,而无需用户名或密码。

团队ID与Gremlin团队相关联,并允许Jenkins在Gremlin团队中运行攻击、定位主机和执行其他操作。

要获取团队 ID,请登录Gremlin Web应用。单击右上角的用户图标,然后单击团队设置。单击配置选项卡,查看团队ID:

image.png

复制团队ID,因为在下一步中需要它。

接下来,我们将创建一个API密钥。单击右上角的用户图标,然后单击帐户设置。单击API Keys选项卡,然后单击New API Key。输入密钥的名称(例如“Jenkins”)和可选的描述,然后单击保存。从出现的窗口中复制密钥。

image.png

现在我们有了团队ID和API密钥,将它们输入到Jenkins 中:

http://localhost:8080/credentials/store/system/domain/_/newCredentials

或者打开Jenkins仪表板,在Manage Jenkins > Manage Credentials > Global。单击添加凭据。将 Kind选择为Secret text, Scope 设置Global,如下所示。将Gremlin API密钥粘贴到 Secret字段中,然后输入gremlin-api-key作为 ID。单击确定保存。

image.png

为团队ID重复此步骤。选择Secret text,将ID粘贴到该Secret字段中,然后输入gremlin-team-id字段。单击确定保存。

image.png

1.3 创建混沌部署流水线

在这一步中,我们将创建一个Jenkins流水线。该流水线将运行CPU攻击,在一定时间内消耗目标主机上的CPU容量。攻击的目标是我们安装好Gremlin的一台主机。

在典型的CI/CD流水线中,流水线代码会包含以下步骤:

  • 提供测试环境
  • 部署应用程序
  • 将 Gremlin 代理部署到该环境
  • 运行攻击

这里,我们将跳过前三个步骤,仅展示如何使用Gremlin API运行攻击。

在运行自动化测试时,我们建议从开发/测试环境开始,然后逐渐将它们应用到生产环境中。在生产部署上运行自动化实验,可助力捕获生产特有的可靠性问题。

在Jenkins主界面上,单击“New Item”。输入一个名称,例如“Chaos Pipeline”,选择 Pipeline,然后单击 OK。向下滚动到 Pipeline 部分,然后输入以下代码:

pipeline {
    agent none
    environment {
        ATTACK_ID = ''
        GREMLIN_API_KEY = credentials('gremlin-api-key')
        GREMLIN_TEAM_ID = credentials('gremlin-team-id')
    }
    parameters {
        string(name: 'TARGET_IDENTIFIER', defaultValue: 'gremlin-demo-lab-host', description: 'Host to target')
        string(name: 'CPU_LENGTH', defaultValue: '30', description: 'Duration of CPU attack')
        string(name: 'CPU_CORE', defaultValue: '1', description: 'Number of cores to impact')
        string(name: 'CPU_CAPACITY', defaultValue: '100', description: 'The percentage of total CPU capacity to consume')
    }
    stages {
        stage('Initialize test environment') {
            steps{
                echo "[Add commands to create a test environment.]"
            }
        }
        stage('Install application to test environment') {
            steps{
                echo "[Add commands to deploy your application to your test environment.]"
            }
        }
        stage('Run chaos experiment') {
            agent any
            steps {
                script {
                    ATTACK_ID = sh (
                        script: "curl -s -H 'Content-Type: application/json;charset=utf-8' -H 'Authorization: Key ${GREMLIN_API_KEY}' https://api.gremlin.com/v1/attacks/new?teamId=${GREMLIN_TEAM_ID} --data '{ \"command\": { \"type\": \"cpu\", \"args\": [\"-c\", \"$CPU_CORE\", \"-l\", \"$CPU_LENGTH\", \"-p\", \"$CPU_CAPACITY\"] },\"target\": { \"type\": \"Exact\", \"hosts\" : { \"ids\": [\"$TARGET_IDENTIFIER\"] } } }' --compressed",
                        returnStdout: true
                    ).trim()
                echo "View your experiment at https://app.gremlin.com/attacks/${ATTACK_ID}"
                }
            }
        }
    }
}

让我们仔细看看这个脚本。

首先,在environment部分,获取Gremlin API密钥和团队ID。在parameters中,我们定义了攻击的参数。TARGET_IDENTIFIER是攻击对象的主机名,例如这里我们使用gremlin-demo-lab-host。可以通过单击“Clients” > “Hosts”,在Gremlin Web应用中找到主机列表:

image.png

接下来是Stage的部分。前两个Stage是添加提供和设置测试环境的步骤。第三个Stage,“运行混沌实验”,调用Gremlin API开始攻击。请注意该script字段,其中包含对Gremlin API的完整调用。

使用选定的任何Gremlin API调用替换此字段,无论是调用不同类型的攻击(Attack)、运行场景(Scenario)、攻击Kubernetes资源(Resource)还是攻击服务(Service)。

现在,将默认值替换为TARGET_IDENTIFIER,即攻击对象的主机名。有时候,我们也会调整CPU攻击的参数CPU_LENGTHCPU_CORECPU_CAPACITY。其中

  • CPU_LENGTH是攻击将运行多长时间(秒)
  • CPU_CORE是受影响的CPU核数
  • CPU_CAPACITY是要消耗的CPU百分比

image.png

接下来,通过选择“Build with Parameters”,然后选择“Build”来运行演示脚本。Jenkins将快速完成前两个Stage,然后调用Gremlin API并发起攻击。

Stage视图长这个样子:

image.png

注意:如果构建失败,会收到groovy.lang.MissingPropertyException: No such property: CPU\_CORE for class: groovy.lang.Binding,请尝试重新构建。

通过单击构建版本号,打开控制台输出,将看到以下内容:

Started by user Admin
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] withCredentials
Masking supported pattern matches of $GREMLIN_API_KEY
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Initialize test environment)
[Pipeline] echo
[Add commands to create a test environment.]
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Install application to test environment)
[Pipeline] echo
[Add commands to deploy your application to your test environment.]
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Run chaos experiment)
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/Chaos Pipeline
[Pipeline] {
[Pipeline] script
[Pipeline] {
[Pipeline] sh
Warning: A secret was passed to "sh" using Groovy String interpolation, which is insecure.
         Affected argument(s) used the following variable(s): [GREMLIN_API_KEY]
         See https://jenkins.io/redirect/groovy-string-interpolation for details.
+ curl -s -H 'Content-Type: application/json' -H 'Authorization: Key ****' https://api.gremlin.com/v1/attacks/new --data '{ "command": { "type": "cpu", "args": ["-c", "1", "-l", "30", "-p", "100"] },"target": { "type": "Exact", "hosts" : { "ids": ["gremlin-demo-lab-host"] } } }' --compressed
[Pipeline] echo
View your experiment at https://app.gremlin.com/attacks/User requires privilege for target team: TEAM_DEFAULT
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // node
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] End of Pipeline
Finished: SUCCESS

恭喜!现在已将混沌实验集成到CI/CD流水线中!

结束语

本文只是CI/CD流水线中启用混沌工程的第一步。

未来我们可通过运行场景(Scenario)而不是攻击(Attack)来进一步扩展混沌工程实践,并验证实验的完成情况,使用状态检查在系统不稳定时自动停止实验,或者在集成或负载测试中同时运行实验。如果有自动化负载或功能测试,请将它们与混沌实验一起运行,以确保系统能够在压力下可靠运行。

这些相同的原则也可应用于其他持续部署工具,例如Spinnaker、GitLab或CircleCI等等。

来源:混沌工程实践

作者:阮如安

声明:文章获得作者授权在IDCF社区公众号(devopshub)转发。优质内容共享给思否平台的技术同伴,如原作者有其他考虑请联系小编删除,致谢。

6月每周四晚8点,【冬哥有话说】开心一“夏”。公众号留言“回放”可获取视频会看地址

  • 0603 无敌哥 《IDCF人才成长地图与5P》(《端到端DevOps持续交付(5P)精品课》第1课)
  • 0610 冬哥 《带你玩转创新设计思维》
  • 0617 无敌哥 《敏捷项目管理到底是个啥》
  • 0624 冬哥 《VUCA时代的敏捷领导力》

用户bPcN1SC
149 声望55 粉丝