当前位置: 首页 > 科技观察

如何使用Terratest测试基础设施即代码

时间:2023-03-17 11:32:28 科技观察

译者|布加迪评论|孙书娟手动搭建基础设施是一个费时费力的过程。这时候,我们可以使用基础设施即代码(IaC)工具来自动管理基础设施。IaC自动化可以用于任何类型的基础设施:虚拟机和存储等。随着越来越多的基础设施变成代码,需要对IaC进行单元测试和集成测试。本文简要讨论IaC是什么以及测试基础设施代码意味着什么,然后深入探讨如何使用Terratest进行IaC测试。1.InfrastructureasCode(IaC)InfrastructureasCode是通过代码配置和设置环境的过程,而不是通过GUI手动创建所需的基础设施和支持系统。例如,配置虚拟机、设置虚拟机以及为它们创建监控机制。Terraform、Packer和Ansible是典型的IaC。借助基础架构即代码,您还可以将基础架构跟踪到Git等版本控制系统中,对其进行模块化和模板化,以便您可以跨多个环境和区域重用相同的代码。灾难恢复是从基础设施即代码中获得的重要好处之一。借助IaC,您可以尽快在其他区域或环境中复制您的基础架构。2.测试基础设施代码IaC测试可以分为多个阶段:1.健全性或静态分析2.单元测试3.集成测试健全性或静态分析这是测试基础设施代码的初始阶段。在静态分析中,我们确保代码具有正确的语法。它还有助于确保我们的代码符合行业标准并遵循最佳实践。Linter就属于这一类。几种典型的健全性测试工具包括Chef的foodcritic、Docker的hadolint和Terraform的tflint。单元测试通过单元测试,我们可以在不实际配置基础设施的情况下评估代码。例如,可以限制容器以非root用户身份运行,或者云网络安全组应该只有TCP协议。一些典型的单元测试是Terraform的Conftest和ChefCookbooks的Chefspecs。以非root用户身份执行的Conftest示例:packagemaindeny[msg]{input.kind=="Deployment"notinput.spec.template.spec.securityContext.runAsNonRootmsg:="Containersmustnotrunasroot"}integrationtest在集成测试中,我们希望通过将IaC实际部署到所需环境中来对其进行测试。假设您部署了一个虚拟机并在该机器的端口80上托管了一个Nginx服务器。因此,您将在部署后检查端口80是否正在侦听。下面是使用ServerSpec执行此操作的示例:describeport(80)doit{shouldbe_listening}end在本文中,我们介绍了使用Terratest对基础设施代码进行集成测试。3.什么是地测?我们可以用它做什么?Terratest是由Gruntwork开发的Go库,可帮助您为使用Terraform或Packer编写的基础设施即代码创建和自动化测试。它为您提供各种任务所需的功能和模式,例如:测试Docker映像、Helm图表和Packer模板。允许与各种云提供商API兼容,例如AWS和Azure。Terratest对基础设施代码执行完整性和功能测试。使用Terratest,您可以轻松识别当前基础架构代码中的问题并尽快修复它们。我们还可以利用Terratest对基础设施进行合规性测试,例如为通过IaC创建的任何新S3存储桶启用版本控制和加密。4.安装Terratest所需的二进制文件Terratest主要需要Terraform和Go来执行。我们在这篇博文中使用了Terraform版本1.0.0和Go版本1.17.6进行测试。安装Terraform按照Terraform网站(https://www.terraform.io/downloads)的下载部分在您的计算机上安装Terraform,您可以使用您的包管理器或下载二进制文件并使其在您的PATH中可用。安装后,通过运行以下命令验证它是否已正确安装:terraformversionGo&test依赖项安装可以通过以下步骤完成:安装Go您可以使用Linux发行版的包管理器安装Go,或者按照Go的安装文档(https//go.dev/doc/install)。Go测试需要gcc来执行测试gotest命令可能需要gcc,您可以使用发行版的包管理器安装它。例如在CentOS/AmazonLinux2上,您可以使用yuminstall-ygcc。五、Terratest在行动现在,我们将使用Terratest执行一些集成测试。安装步骤完成后,克隆terratest-sample存储库以开始执行Terratest。我们将从使用Go编写测试并执行它们开始。需要提前说明的重要事项:1.您的测试文件名应包含_test,例如sample_test.go。这就是Go查找测试文件的方式。2.你的测试函数名应该以Test开头,T大写。比如说,TestFunction没问题,但是testFunction给出错误“没有要运行的测试”。设置AWS身份验证配置我们需要AWS凭证来设置AWS中的基础设施,这可以使用环境变量或共享凭证文件进行配置。基础设施的Terraform代码可以在组件的相应文件夹中找到。如果是ec2,则位于ec2_instance下,如果是API网关,则位于api_gateway文件夹下。Terratest将Terraform的output.tf的输出作为测试的输入。下面的代码片段用于测试我们在使用的ec2实例上是否有相同的ssh密钥。包terratesimport(“测试”“github.com/stretcr/testify/assert”“github.com/gruntwork-io/terratest/modules/terraform”)funcTestEc2SshKey(t*testing.T){terraformOptions:=terraform.WithDefaultRetryableErrors(t,&terraform.Options{TerraformDir:"../terraform",})deferterraform.Destroy(t,terraformOptions)terraform.InitAndApply(t,terraformOptions)ec2SshKey:=terraform.Output(t,terraformOptions,"instance_ssh_key")断言.Equal(t,"terratest",ec2SshKey)}我们将它分解成不同的部分来理解:首先,我们定义一个名为Terratest的Go包,然后我们导入测试执行所需的不同包。packageterratesimport("testing""github.com/stretcr/testify/assert""github.com/gruntwork-io/terratest/modules/terraform")将创建一个函数来执行实际测试,一旦我们满足所有先决条件:funcTestEc2SshKey(t*testing.T){terraformOptions:=terraform.WithDefaultRetryableErrors(t,&terraform.Options{TerraformDir:"../terraform",})deferterraform.Destroy(t,terraformOptions)terraform.InitAndApply(t,terraformOptions)ec2SshKey:=terraform.Output(t,terraformOptions,"instance_ssh_key")assert.Equal(t,"terratest",ec2SshKey)}在下一节的帮助下,我们定义Terratest应该在哪里寻找Terraform清单文件(即main.tf和output.tf)以创建基础设施。terraformOptions:=terraform.WithDefaultRetryableErrors(t,&terraform.Options{TerraformDir:"../terraform",})在Go中,我们使用defer方法执行清理任务,应该是terraformdestroy。我们使用以下代码片段对其进行定义:deferterraform.Destroy(t,terraformOptions)现在我们可以继续执行实际操作:使用terraform.InitAndApply,我们调用Terraform函数terraforminit并应用通常用于Terraform执行:terraform。InitAndApply(t,terraformOptions)如前所述,Terratest查看output.tf的输出以查找变量定义。在以下代码片段中,我们从Terraform输出中获取ssh密钥并与定义的ssh密钥名称进行匹配:ec2SshKey:=terraform.Output(t,terraformOptions,"instance_ssh_key")assert.Equal(t,"terratest",ec2SshKey)第六,执行测试将目录更改为克隆存储库的位置。转到测试文件所在的位置。初始化Go模块,并下载依赖项。查看Terratest文档的“设置项目”部分以获取更多详细信息。gomodinitec2_instancegomodtidy最后执行测试:$gotest–v---PASS:TestEc2SshKey(98.72s)PASSokcommand-line-arguments98.735s7.不妨继续使用Terratest上一节我们使用Terratest执行一些基本测试。我们现在将通过部署一个以Lambda和ALB作为后端的API网关来执行高级测试。高级功能API网关的GET请求会被ALB处理,任何方法都会通过API网关被Lambda处理。部署后,我们将对网关部署URL执行HTTPGET请求,并检查它是否返回成功代码。注意:我们在我们的实现中没有使用任何API_KEY进行身份验证,但您应该使用它来重现API网关的更真实的使用。Terraformoutput.tfoutput"lb_address"{value=aws_lb.load-balancer.dns_namedescription="负载均衡器的DNS"}output"api_id"{description="RESTAPIid"value=aws_api_gateway_rest_api.api.id}output"deployment_invoke_url"{description="Deploymentinvokeurl"value="${aws_api_gateway_stage.test.invoke_url}/resource"}用于测试执行的代码片段在第一个场景中,我们已经解释了基本语法,因此我们将直接进入测试功能。funcTestApiGateway(t*testing.T){//awsRegion:="eu-west-2"terraformOptions:=terraform.WithDefaultRetryableErrors(t,&terraform.Options{TerraformDir:"../",})deferterraform.Destroy(t,terraformOptions)terraform.InitAndApply(t,terraformOptions)stageUrl:=terraform.Output(t,terraformOptions,"deployment_invoke_url")time.Sleep(30*time.Second)statusCode:=DoGetRequest(t,stageUrl)assert.Equal(t,200,statusCode)}funcDoGetRequest(tterra_test.TestingT,apistring)int{resp,err:=http.Get(api)iferr!=nil{log.Fatalln(err)}//我们读取响应下面一行的status.returnresp.StatusCode}在上面的代码片段中,我们定义了函数DoGetRequest来运行HTTPGET测试。然后,我们使用此函数的输出作为TestApiGateway函数的输入。测试执行和输出TestApiGateway2022-03-01T06:56:18Zlogger.go:66:deployment_invoke_url="https://iuabeqgmj2.execute-api.eu-west-1.amazonaws.com/test/resource"TestApiGateway2022-03-01T06:56:18Zlogger.go:66:lb_address="my-demo-load-balancer-376285754.eu-west-1.elb.amazonaws.com"TestApiGateway2022-03-01T06:56:18Z重试。go:91:terraform[output-no-color-jsondeployment_invoke_url]TestApiGateway2022-03-01T06:56:18Zlogger.go:66:runningcommandterraformwithargs[output–no-color-jsondeployment_invoke_url]TestApiGateway2022-03-01T06:56:19Zlogger.go:66:“https://iuabeqgmj2.execute-api.eu-west-1.amazonaws.com/test/resource”---通过:TestApiGateway(42.34s)PASSok命令-line-arguments42.347s可以看到,它执行了测试函数TestApiGateway,在这里它对API网关的deployment_invoke_url进行TTPGET测试,返回测试状态。8.使用Terratest进行Terratest模块的可扩展性和合规性测试我们也可以使用Terratest进行合规性测试。一些示例包括:检查是否在您的SQS队列或S3存储桶上启用了加密。验证您是否为API网关设置了特定限制。我们为API网关开发了Terratest检查机制。在此示例中,我们验证授权方是否已添加到您的API网关。目前,Terratest在其AWS模块中没有API网关模块。您可以在TerratestAWS模块目录中找到可用的AWS模块。可以在Terratest模块目录中找到其他Terratest模块,例如Docker、Packer或Helm。我们使用Terratest和AWSGoSDK方法为Authorizer创建了我们自己的测试函数。九。结论企业及其客户希望更快地交付产品。基础设施即代码加速了基础设施的供应,这恰好满足了这一要求。随着越来越多的基础设施变成代码,用户对测试的需求也在增加。在本文中,我们讨论了像Terratest这样的工具如何帮助您在将代码部署到生产环境之前验证您的代码。我们介绍了Terratest的工作原理,甚至执行了测试用例来展示它是如何完成的。Terratest的优势之一是它的可扩展性,我们可以通过使用本文提到的模块来实现这一点。原文链接:https://www.cncf.io/blog/2022/07/18/testing-your-infrastructure-as-code-using-terratest/