《 Terraform:代码级别的基础架构》一书

图片您好,habrozhiteli!该书适用于所有已编写代码的负责人。这适用于系统管理员,运营专家,发行版,SR,DevOps工程师,基础架构开发人员,全周期开发人员,工程团队负责人和技术总监。无论您处于什么位置,如果您涉及基础架构,部署代码,配置服务器,扩展集群,备份数据,监控应用程序并在凌晨三点钟接听电话,这本书都是适合您的。

这些责任加在一起通常被称为运营活动(或系统管理)。以前,经常会遇到知道如何编写代码但不了解系统管理的开发人员。系统管理员经常遇到没有编写代码的能力。一旦可以接受这种分离,但是在现代世界中,如果没有云计算和DevOps运动就无法想象这种分离,几乎所有开发人员都需要管理技能,并且任何系统管理员都必须能够编程。

您不仅将学习如何使用Terraform以代码形式管理基础结构,还将学习如何将其适应DevOps的整体概念。通过阅读本书,您可以回答以下问题。

  • 为什么要完全使用IaC?
  • 配置管理,业务流程,资源初始化和服务器模板之间有什么区别?
  • 我什么时候应该使用Terraform,Chef,Ansible,Puppet,Salt,CloudFormation,Docker,Packer或Kubernetes?
  • Terraform系统如何工作以及如何使用它来管理基础结构?
  • 如何创建适合重用的Terraform模块?
  • 如何为Terraform编写足够可靠的实用代码?
  • 如何测试Terraform代码?
  • 如何将Terraform纳入您的自动部署过程?
  • 在团队合作中使用Terraform的最佳方法是什么?

第二版的新功能
2017 . 2019- , ! . , .

, , , Terraform, .

  • Terraform. , Terraform 0.8. Terraform 0.12. , . , !
  • . Terraform. , , , , , , , .
  • . Terraform . , , — , .
  • . 8 , Terraform . , , , : , .
  • HCL2. Terraform 0.12 HCL HCL2. ( ${…}!), , , null, for_each for, . HCL2, 5 6.
  • . Terraform 0.9 . Terraform . Terraform 0.9 , ; 0.10 . 3.
  • Terraform. Terraform 0.10 ( AWS, GCP, Azure . .). , . terraform init , . 2 7.
  • . 2016 Terraform (AWS, GCP Azure). 100, , , 1. (, Alicloud, Oracle Cloud Infrastructure, VMware vSphere .), , (GitHub, GitLab BitBucket), (MySQL, PostreSQL InfluxDB), ( DataDog, New Relic Grafana), Kubernetes, Helm, Heroku, Rundeck Rightscale . , : , AWS , , CloudFormation!
  • Terraform. 2017 HashiCorp Terraform (registry.terraform.io) — , Terraform, . 2018 . Terraform 0.11 . « » . 153.
  • . Terraform 0.9 : , , errored.tfstate. Terraform 0.12 . , , .
  • . , (. « » . 144), « » (, « Terraform» . 242), plan apply (. « » . 64), create_before_destroy, count, (. «» . 160), , provider .

摘抄。如何测试Terraform代码


(稍后

在本书中对自动测试的问题给予更多的关注)DevOps世界充满了各种恐惧:每个人都害怕让事情正常进行,丢失数据或被黑客入侵。进行任何更改时,您总是问自己将会产生什么后果。它在所有环境中的行为都一样吗?会导致再次中断吗?而且,如果发生这种情况,您这次需要留多少时间来修复它?随着公司的发展,风险越来越大,使部署过程变得更糟,并增加了出错的风险。许多公司试图通过减少部署频率来最大程度地降低这种风险,但是结果是,每个单独的部署都会变得更大并且更容易出错。

如果以代码形式管理基础架构,则有更好的方法来最大程度地降低风险:测试。他们的目标是给您足够的信心进行更改。这里的关键词是信心:没有测试可以保证没有错误,因此您更有可能应对概率。如果您可以将所有基础结构和部署过程捕获为代码,则可以在测试环境中测试此代码。如果成功,则相同的代码很有可能在工业环境中运行。在充满恐惧和不确定性的世界中,高概率和高信心是昂贵的。

在本章中,我们将介绍测试基础结构代码(手动和自动)的过程,重点是后者。

手动测试:

  • 手动测试的基础;
  • 测试后清洁资源。

自动化测试:

  • 单元测试;
  • 整合测试;
  • 端到端测试;
  • 其他测试方法。

手动测试


考虑如何测试Terraform代码时,将测试与使用通用编程语言(例如Ruby)编写的代码进行一些比较是很有用的。想象一下,您正在web-server.rb文件中编写一个简单的Ruby Web服务器:

class WebServer < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
     case request.path
     when "/"
         response.status = 200
         response['Content-Type'] = 'text/plain'
         response.body = 'Hello, World'
     else
         response.status = 404
         response['Content-Type'] = 'text/plain'
         response.body = 'Not Found'
     end
  end
end

这段代码将返回200 OK响应,URL为正文“ Hello,World”。对于其他任何地址,答案将为404。您将如何手动测试此代码?通常,添加更多代码以在本地运行Web服务器:

#   ,      
#  ,       
if __FILE__ == $0
  #      8000
  server = WEBrick::HTTPServer.new :Port => 8000
  server.mount '/', WebServer

  #    Ctrl+C
  trap 'INT' do server.shutdown end

  #  
  server.start
end

如果在终端中运行此文件,它将在端口8000上加载Web服务器:

$ ruby web-server.rb
[2019-05-25 14:11:52] INFO WEBrick 1.3.1
[2019-05-25 14:11:52] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]
[2019-05-25 14:11:52] INFO WEBrick::HTTPServer#start: pid=19767 port=8000

要检查此服务器的运行情况,可以使用浏览器或curl:

$ curl localhost:8000/
Hello, World

$ curl localhost:8000/invalid-path
Not Found

现在,假设我们通过向其添加一个/ api入口点(返回201 Created和一个JSON格式的主体)来更改此代码:

class WebServer < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
     case request.path
     when "/"
         response.status = 200
         response['Content-Type'] = 'text/plain'
         response.body = 'Hello, World'
     when "/api"
         response.status = 201
         response['Content-Type'] = 'application/json'
         response.body = '{"foo":"bar"}'
     else
         response.status = 404
         response['Content-Type'] = 'text/plain'
         response.body = 'Not Found'
     end
  end
end

要手动测试此更新的代码,请按Ctrl + C,然后再次运行脚本重新启动Web服务器:

$ ruby web-server.rb
[2019-05-25 14:11:52] INFO WEBrick 1.3.1
[2019-05-25 14:11:52] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]
[2019-05-25 14:11:52] INFO WEBrick::HTTPServer#start: pid=19767 port=8000
^C
[2019-05-25 14:15:54] INFO going to shutdown ...
[2019-05-25 14:15:54] INFO WEBrick::HTTPServer#start done.

$ ruby web-server.rb
[2019-05-25 14:11:52] INFO WEBrick 1.3.1
[2019-05-25 14:11:52] INFO ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]
[2019-05-25 14:11:52] INFO WEBrick::HTTPServer#start: pid=19767 port=8000

要检查新版本,可以再次使用curl命令:

$ curl localhost:8000/api
{"foo":"bar"}

手动测试基础


这种手动测试在Terraform中会是什么样?例如,在前面的章节中,您仍然具有用于部署ALB的代码。这是模块/网络/ alb / main.tf文件的片段:

resource "aws_lb" "example" {
   name                     = var.alb_name
   load_balancer_type = "application"
   subnets                  = var.subnet_ids
   security_groups      = [aws_security_group.alb.id]
}

resource "aws_lb_listener" "http" {
   load_balancer_arn = aws_lb.example.arn
   port                      = local.http_port
   protocol                = "HTTP"

   #      404
   default_action {
      type = "fixed-response"

      fixed_response {
        content_type = "text/plain"
        message_body = "404: page not found"
        status_code = 404
      }
    }
}

resource "aws_security_group" "alb" {
   name = var.alb_name
}

# (...)

如果将此清单与Ruby代码进行比较,您会看到一个明显的不同:AWS ALB,目标组,侦听器,安全组以及任何其他资源都无法部署在您自己的计算机上。

关于No.1测试的主要结论是:Terraform代码测试不能在本地进行。

这不仅适用于Terraform,而且适用于大多数IaC工具。在Terraform中进行手动测试的唯一实用方法是在实际环境中(即在AWS中)部署代码。换句话说,在阅读本书时独立启动的terraform apply和terraform destroy命令是Terraform中的手动测试。

这就是为什么在每个模块的examples文件夹中拥有易于部署的示例如此重要的原因之一(请参见第6章)。要测试alb模块,最简单的方法是使用您在examples / alb中创建的演示代码:

provider "aws" {
   region = "us-east-2"

   #     AWS  2.x
   version = "~> 2.0"
}

module "alb" {
    source = "../../modules/networking/alb"

    alb_name = "terraform-up-and-running"
    subnet_ids = data.aws_subnet_ids.default.ids
}

要部署此示例,您需要运行terraform apply命令,就像您重复做的那样:

$ terraform apply

(...)

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Outputs:

alb_dns_name = hello-world-stage-477699288.us-east-2.elb.amazonaws.com

在部署结束时,您可以使用curl等工具来确保默认情况下ALB返回404:

$ curl \
   -s \
   -o /dev/null \
   -w "%{http_code}" \
hello-world-stage-477699288.us-east-2.elb.amazonaws.com

404

基础设施检查

, HTTP, , , curl HTTP-. . , MySQL, MySQL. VPN-, VPN. , , SSH - . . , , . , .

让我提醒您:由于配置中不存在其他侦听器规则,因此ALB返回404,并且alb模块中的默认操作的响应为404:

resource "aws_lb_listener" "http" {
   load_balancer_arn = aws_lb.example.arn
   port                      = local.http_port
   protocol                = "HTTP"

   #      404
   default_action {
      type = "fixed-response"

      fixed_response {
       content_type = "text/plain"
       message_body = "404: page not found"
       status_code = 404
      }
   }
}

因此,您已经知道如何运行和测试代码。现在您可以开始进行更改了。每次更改某项(例如,默认操作返回401)时,都需要使用terraform apply命令来部署新代码:

$ terraform apply

(...)

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:

alb_dns_name = hello-world-stage-477699288.us-east-2.elb.amazonaws.com

要检查新版本,可以重新启动curl:

$ curl \
   -s \
   -o /dev/null \
   -w "%{http_code}" \
   hello-world-stage-477699288.us-east-2.elb.amazonaws.com
401

完成后,运行terraform destroy命令以删除资源:

$ terraform destroy

(...)

Apply complete! Resources: 0 added, 0 changed, 5 destroyed.

换句话说,在使用Terraform时,每个开发人员都需要良好的代码示例进行测试以及真实的开发环境(例如AWS账户),该环境相当于本地计算机并用于运行测试。在手动测试过程中,您很可能必须创建和删除大量基础结构组件,这可能导致许多错误。在这方面,应将环境与用于最终测试,尤其是工业应用的更稳定的环境完全隔离。

鉴于以上所述,我强烈建议每个开发团队准备一个隔离的环境,在其中您可以创建和删除任何基础结构而不会产生任何后果。为了最大程度地减少不同开发人员之间发生冲突的可能性(假设两个开发人员试图创建一个具有相同名称的负载平衡器),理想的解决方案是为每个团队成员提供一个单独的,完全隔离的环境。例如,如果将Terraform与AWS结合使用,则每个开发人员理想情况下都应该拥有自己的帐户,他们可以在其中测试所需的一切。

测试后资源清理


为了提高开发人员的生产力,必须存在许多隔离的环境,但是如果您不谨慎操作,则可能会积累许多额外的资源,这些资源会使您的所有环境杂乱无章,并花费大量资金。
为了控制成本,请定期清洁隔离的介质。这是测试2号关键结论

至少,在测试后,当开发人员使用terraform destroy命令删除部署的所有内容时,您应该在团队中创建这种文化。可能会找到用于清理可以定期运行的多余或旧资源的工具(例如,使用cron)。以下是针对不同部署环境的一些示例。

  • cloud-nuke (http://bit.ly/2OIgM9r). , . AWS ( Amazon EC2 Instances, ASG, ELB . .). (Google Cloud, Azure) . — , . , cloud-nuke cron, . , , , :

    $ cloud-nuke aws --older-than 48h
  • Janitor Monkey (http://bit.ly/2M4GoLB). , AWS , ( — ). , , , . Netflix Simian Army, Chaos Monkey . , Simian Army , : , Janitor Monkey Swabbie (http://bit.ly/2OLrOLb).
  • aws-nuke(http://bit.ly/2ZB8lOe)。这是一个删除AWS账户所有内容的开源工具。在配置文件中以YAML格式指定要删除的帐户和资源:

    #   
    regions:
    - us-east-2
    
    #    
    accounts:
       "111111111111": {}
    
    #    
    resource-types:
       targets:
       - S3Object
       - S3Bucket
       - IAMRole

    Aws-nuke开始如下:

    $ aws-nuke -5c config.yml

自动化测试


自动测试的概念是编写测试来测试实际代码的行为。在第8章中,您将学习使用CI服务器,可以在每次单独提交后运行这些测试。如果未完成,则可以立即撤消或更正固定。因此,您的代码将始终可操作。

共有三种类型的自动化测试。

  • . — . , . (, , - ) mock-. (, mock- , ) , .
  • . . , . mock-: , , , , , , , mock-.
  • . (, , , ) . : , Selenium . - mock-, ( , ).

每种类型的测试都有其自己的目的,在它们的帮助下,您可以识别各种错误,因此应将它们一起使用。单元测试速度很快,可让您立即了解所做的更改并检查各种组合。这使您确信代码的基本组件(单个模块)的行为符合预期。但是,模块单独正确工作的事实并不意味着它们可以一起工作,因此,为了确保基本组件兼容,需要进行集成测试。另一方面,系统不同部分的正确行为并不能保证该系统在工业环境中部署后能够正常工作,因此需要通过测试来在接近实际条件下测试您的代码。

»关于这本书的更多信息上可以找到出版商的网站
» 目录
» 摘录

的优惠券Khabrozhiteley 25%的折扣- Terraform

在缴付书的纸质版本,电子书是通过电子邮件发送。

All Articles