「DevOps系列]为啥我们使用Terraform 而不使用Puppet, Ansible

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「DevOps系列]为啥我们使用Terraform 而不使用Puppet, Ansible相关的知识,希望对你有一定的参考价值。

参考技术A

本篇文章是深入理解Terraform系列的第一部分。在介绍文章中,我们讨论了为什么每家互联网软件公司都应该使用基础设施即代码(IAC)。那么本篇,我们打算讨论下为什么我们选择Terraform 作为我们的IAC 工具。

如果你在网上搜索“instrastructure-as-code”,很容易看到很多受欢迎的工具:

筛选出它们中你应该使用哪个不是很容易。所有这些上述工具都可以用于基础设施即代码。它们都是开源的,背靠庞大的贡献者社区,可以很好配合各种不同的云服务商。它们都提供商业支持,提供良好的文档——在官方文档和社区资源方面(比如博客文章和StackOverflow问答)。

本篇文章,我们会分成几个特定原因来解释为什么我们会选择Terraform作为IAC工具。与所有技术决策一样,这是一个权衡和优先级的问题,虽然您的特定优先级可能与我们的不同,但我们希望分享我们的思维过程将帮助您做出自己的决定。以下是我们考虑的主要权衡因素:

Chef, Puppet, Ansible, and SaltStack 都是配置管理工具,这意味着它们设计初衷都是在现有的服务器上安装和管理软件。CloudFormation 和 Terraform 是配置(provisioning)工具,这意味这它们的设计初衷是配置服务器本身的(以及基础设施的其他部分,比如负载均衡器,数据库,网络配置等),将配置这些服务器的工作留给其他工具。这两类工具互相不排斥的。因为大多数配置管理工具可以在某种程度上多一些配置工作而大多数配置工具也可以在某种程度上做配置管理的工作。但是聚焦于配置管理或者配置意味着,这些工具对于特定类型的任务会更加合适。

想Chef,Puppt,Ansible 这样的配置管理工具默认针对一种可变的基础设施范例。比如,如果你告诉Chef 安装一个新版本的OpenSSL,它就会在你现有的服务器上运行软件更新并且就地生效。随着时间推移,你会更新的更多,每台服务器都会构建一个唯一的修改 历史 。这通常会导致称为配置漂移或者误差的现象,其中每个服务器与所有其他服务器略有不同,导致难以诊断且几乎不可能再现的细微配置错误。

如果你正在使用像Terraform这样的配置工具来部署由Docker 或者 Packer创建的镜像,那么每次"修改"事实上都是一次新服务器的部署(就像是函数式编程中每次变量的修改事实上会返回新的变量)。比如,当我们部署一个新版本的OpenSSL,你会用装有新版本OpenSSL的Packer或者Docker来创建镜像,然后在整组新服务器中部署那个镜像,同时卸载老的镜像。这种方法减少了配置偏差问题的可能性,使得了解服务器上运行了哪些软件变得更加容易,同时可以让你任何时候都可以轻松部署任何版本的软件。当然,也可以强制配置管理工具来做不可变部署。但是对这些工具来说,这不是惯用的方式。不管怎样,使用配置工具都是一种更加自然的方式。

Chef和Ansible鼓励一种程序风格,您可以编写代码,逐步指定如何实现预期状态。 Terraform,CloudFormation,SaltStack和Puppet都鼓励更具说明性的风格,您可以编写指定所需最终状态的代码,IAC工具本身负责确定如何实现该状态。

例如,假设您要部署10台服务器(AWS术语中的“EC2 Instances”)来运行应用程序的v1版本。以下是使用过程方法执行此操作的Ansible模板的简化示例:

表面上看,这两种方法可能看起来相似,当您最初使用Ansible或Terraform执行它们时,它们将产生类似的结果。有趣的是,当您想要进行更改时会发生什么。

例如,假设流量增加,并且您希望将服务器数量增加到15。使用Ansible,您之前编写的过程代码就没法使用了;如果您刚刚将服务器数量更新为15并重新启动该代码,那么它将部署15台新服务器,总共25台服务器!因此,您必须了解已部署的内容并编写一个全新的过程脚本来添加5台新服务器:

如果你执行了这个模板,Terraform会意识到它已经创建了10个服务器,因此它需要做的只是创建5个新服务器。实际上,在运行此模板之前,您可以使用Terraform的 plan 命令来预览它将进行的更改:

显然,上述例子是简化的。 Ansible允许您在部署新的EC2实例之前使用标签来搜索现有的EC2实例(例如,使用instance_tags和count_tag参数),但是必须根据每个资源的情况为Ansible管理的每个资源手动找出这种逻辑。 过去的 历史 ,可能会令人惊讶地复杂化(例如,不仅通过标签,还可以通过图像版本,可用区域等查找现有实例)。 这突出了程序IAC工具的两个主要问题:

默认情况下,Chef,Puppet和SaltStack都要求您运行主服务器以存储基础设施的状态并分发更新。 每次要更新基础设施中的某些内容时,都使用客户端(例如,命令行工具)向主服务器发出新命令,主服务器将更新推送到所有其他服务器或那些服务器定期从主服务器中提取最新的更新。

主服务器提供了一些优点。 首先,它是一个单一的中心位置,您可以在其中查看和管理基础设施的状态。 许多配置管理工具甚至为主服务器提供Web界面(例如,Chef Console,Puppet Enterprise Console),以便更容易查看正在发生的事情。 其次,一些主服务器可以在后台连续运行,并强制执行您的配置。 这样,如果有人在服务器上进行手动更改,主服务器可以还原该更改以防止配置偏移。

但是,必须运行主服务器有一些严重的缺点:

Chef,Puppet和SaltStack对无主模式有不同程度的支持,您只需在每个服务器上运行代理软件,通常在一定周期内(例如,每5分钟运行一次的cron作业),并使用它从版本控制(而不是从主服务器)下拉最新更新。 这显着减少了变动的次数,但是,如下一节所述,这仍然留下了许多未答复的问题,尤其是关于如何配置服务器以及首先在其上安装代理软件的问题。

Ansible,CloudFormation,Heat和Terraform默认都是无主的。 或者,更准确一些,它们中的一些可能依赖于主服务器,但它已经是您正在使用的基础设施的一部分,而不是您必须管理的额外部分。 例如,Terraform使用云提供商的API与云提供商进行通信,因此在某种意义上,API服务器是主服务器,除了它们不需要任何额外的基础设施或任何额外的认证机制(即,只使用您的API密钥)。 Ansible的工作方式是通过SSH直接连接到每个服务器,因此,您不必再运行任何额外的基础结构或管理额外的身份验证机制(即只使用SSH密钥)。

Chef,Puppet和SaltStack都要求您在要配置的每台服务器上安装代理软件(例如,Chef Client,Puppet Agent,Salt Minion)。 代理通常在每个服务器的后台运行并负责

安装最新的配置管理更新。

这有一些缺点:

再强调一次,Chef,Puppet和SaltStack都对无代理模式(例如,salt-ssh)有不同程度的支持,但是这些通常感觉它们是作为事后的想法加入的,并不总是支持完整的配置管理工具的功能集。这就是为什么Chef,Puppet和SaltStack的默认或惯用配置几乎总是包含一个代理,通常也包含一个master。

所有这些额外的动态部分都会在您的基础架构中引入大量新的故障模式。 每次凌晨3点收到错误报告时,您都必须弄清楚它是否是应用程序代码,IAC代码,配置管理客户端,主服务器或者服务器中的错误。 客户端与主服务器通信,或者其他服务器与主服务器通信的方式,或者......

Ansible,CloudFormation,Heat和Terraform不要求您安装任何额外的代理。 或者,更准确一些,它们中的一些需要代理,但这些代理通常已作为您正在使用的基础结构的一部分安装。 例如,AWS,Azure,Google Cloud和所有其他云提供商负责在每台物理服务器上安装,管理和验证代理软件。 作为Terraform的用户,您不必担心任何问题:您只需发出命令然后云服务商会在所有你的服务器上为你执行它们。 使用Ansible,您的服务器需要运行SSH守护程序,不管怎么样,这都会普遍运行在大多数服务器上的。

选择任何技术时要考虑的另一个关键因素是成熟度。 下表显示了每个IAC工具的初始发布日期和当前版本号(截至2019年5月)。

同样,这不是一个同类的比较,因为不同的工具有不同的版本控制方案,但一些趋势是明确的。 到目前为止,Terraform是此比较中最年轻的IAC工具。 它仍然是处于1.0.0版本之前,因此无法保证稳定或向后兼容的API,并且错误相对常见(尽管大多数都是次要的)。 这是Terraform最大的弱点:虽然它在短时间内变得非常受欢迎,但使用这种新的尖端工具所付出的代价是它不像其他一些IAC选项那样成熟。

虽然我一直在比较整个博客文章中的IAC工具,但事实是您可能需要使用多种工具来构建您的基础设施。 您看到的每个工具都有优点和缺点,因此您需要为正确的工作选择合适的工具。

以下是我见过的三种常见组合在很多公司都很好用:

配置 + 配置管理

示例:Terraform和Ansible。 您可以使用Terraform部署所有底层基础设施,包括网络拓扑(即VPC,子网,路由表),数据存储(例如,mysql,Redis),负载均衡器和服务器。 然后,您使用Ansible在这些服务器之上部署您的应用程序。

这是一个简单的方法,因为没有运行额外的基础设施(Terraform和Ansible都是客户端应用程序),并且有很多方法可以使Ansible和Terraform一起工作(例如,Terraform为您的服务器添加特殊标签然后Ansible使用这些标签来查找服务器并对其进行配置。 主要缺点是使用Ansible通常意味着您编写了大量程序式代码,使用可变服务器,因此随着代码库,基础架构和团队的增长,维护可能会变得更加困难。

配置 + 服务器模板

示例:Terraform和Packer。您使用Packer将应用程序打包为虚拟机镜像。然后使用Terraform部署(a)具有这些虚拟机镜像的服务器和(b)基础架构的其余部分,包括网络拓扑(即VPC,子网,路由表),数据存储(例如,MySQL,Redis),和负载均衡器。

这也是一种简单的方法,因为没有运行额外的基础设施(Terraform和Packer都是仅客户端应用程序)。此外,这是一种不可变的基础架构方法,这将使维护更容易。但是,有两个主要缺点。首先,虚拟机可能需要很长时间才能构建和部署,这会降低迭代速度。其次,您可以使用Terraform实施的部署策略是有限的(例如,您无法在Terraform中本地实施蓝绿色部署),因此您要么最终编写大量复杂的部署脚本,要么转向编排工具,如下所述。

配置 + 服务器模板 + 编排

示例:Terraform,Packer,Docker和Kubernetes。 您使用Packer创建安装了Docker和Kubernetes的虚拟机映像。 然后使用Terraform部署(a)服务器集群,每个服务器运行此虚拟机镜像,以及(b)基础架构的其余部分,包括网络拓扑(即VPC,子网,路由表),数据存储( 例如,MySQL,Redis)和负载均衡器。 最后,当服务器集群启动时,它形成一个Kubernetes集群,用于运行和管理Dockerized应用程序。

这种方法的优点是Docker镜像构建相当快,您可以在本地计算机上运行和测试它们,并且您可以利用Kubernetes的所有内置功能,包括各种部署策略,自动修复,自动缩放, 等等。 缺点是增加了复杂性,无论是在运行额外的基础设施方面(Kubernetes集群都很难部署和运营,尽管大多数主要的云提供商现在提供托管的Kubernetes服务,可以减轻部分工作),还是学习、管理和debug额外的抽象层(Kubernetes,Docker,Packer)方面。

Terraform系列一腾讯云CVM相关简单创建

背景:

记得2019左右就看到过Terraform系列的文章和书籍,当时所有的业务都上云了管理也很是方便,看了一眼就没有作过多的研究。但本着对技术发展的前瞻敏锐性, 还是觉得这个东西是会火起来的。正巧最近泽阳大佬devops训练营https://www.yuque.com/devopsvip穿插上了Terraform!个人又开始下体验一把了…Terraform!个人又开始体验了一把…

一、安装Terraform

1. 包管理器 or 二进制

打开terraform官方下载页面https://www.terraform.io/downloads。选择安装方式**包管理器 **or 二进制方式

2. Terraform Cloud

当然了还有托管方式Terraform Cloud…毕竟现在是一个到处cloud的时代,忽略,这里只演示包管理器的安装方式!

3. rocky install terraform

个人的工作环境是一台rocky linux ,选择了centos8/rhel 的yum 安装的方式:

[root@zhangpeng ~]# sudo yum install -y yum-utils
[root@zhangpeng ~]# sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
[root@zhangpeng ~]# sudo yum -y install terraform



查看Terraform当前安装版本:

[root@zhangpeng ~]# terraform -version
Terraform v1.1.7
on linux_amd64

二、使用Terraform管理腾讯云

参照:

1. 创建帐号并授权:

登陆访问管理-用户-用户列表-新建用户,按照自己的方式选择创建用户,我选择了快速构建


给了AdministratorAccess权限限…测试吧,本来其实我先开一个子项目然后授权?但是这眼花缭乱的权限配置,无从下手…点击创建用户,生成密钥:


注:生产环境应该尽量合理设置帐号权限边界!

2. 配置provider文件 and terraform init

创建一个terraform的文件夹并配置id 密钥,参照:https://cloud.tencent.com/developer/article/1473713

[root@zhangpeng ~]# mkdir terraform 
[root@zhangpeng ~]# cd terraform/
[root@zhangpeng terraform]# vim provider.tf
[root@zhangpeng terraform]# cat provider.tf 
provider "tencentcloud" 
    secret_id  = "xxxxxxxxxxxxxxxxxxxx"
    secret_key = "xxxxxxxxxxxxxxxxxxx"
    region     = "ap-beijing"




what 开始没有仔细看报错,凭直觉以为是被墙…科学上网还是如此。google搜索:

Could not retrieve the list of available versions for provider hashicorp/tencentcloud: provider registry registry.terraform.io │ does not have a provider named registry.terraform.io/hashicorp/tencentcloud


https://registry.terraform.io/providers/tencentcloudstack/tencentcloud/latest/docs

不建议将凭据硬编码到任何 Terraform 配置中,如果此文件曾经提交给公共版本控制系统,则存在秘密泄露的风险。…那还是使用系统变量吧!
按照提示:

[root@zhangpeng terraform]# export TENCENTCLOUD_SECRET_ID="xxxxxxxx"
[root@zhangpeng terraform]# export TENCENTCLOUD_SECRET_KEY="xxxxxx"
[root@zhangpeng terraform]# export TENCENTCLOUD_REGION="ap-beijing"
[root@zhangpeng terraform]# terraform plan


还是没有搞起来有点怀疑人生了…
谷歌搜了一下最新的terraform 腾讯云关键词搜索到聂伟星的博客:聂伟星https://www.niewx.cn/2021/09/11/Terraform-orchestrates-Tencent-Cloud-resources/。按照流程走一下:

[root@zhangpeng terraform]# cat provider.tf 
terraform 
  required_providers 
    tencentcloud = 
      source = "tencentcloudstack/tencentcloud"
    
  

provider "tencentcloud" 
    secret_id  = "xxxxxxxxxxx"
    secret_key = "xxxxxxxxxxx"
    region     = "ap-beijing"


[root@zhangpeng terraform]# terraform init


ok,int成功

3.编排部署文件

就参照:https://cloud.tencent.com/developer/article/1473713

1. 首先创建一个vpc

cat vpc.ft

resource "tencentcloud_vpc" "vpc_bj" 
    name = "vpc_bj"
    cidr_block = "10.0.0.0/16"
    is_multicast = false


2. 创建一个路由

cat route_table.tf

resource "tencentcloud_route_table" "rtb_vpc_bj" 
  vpc_id = tencentcloud_vpc.vpc_bj.id
  name   = "rtb-vpc-bj"


注:后之后觉 route其实可以不创建的…毕竟有默认的default…

3. 创建子网

创建子网subset,我这里之间创建了4个子网…偷懒了,个人习惯而已…
cat subnet.tf

resource "tencentcloud_subnet" "subnet_bj_01" 
    name = "bj-01"
    cidr_block = "10.0.1.0/24"
    availability_zone = "ap-beijing-1" 
    vpc_id = "$tencentcloud_vpc.vpc_bj.id"
    route_table_id = "$tencentcloud_route_table.rtb_vpc_bj.id"

resource "tencentcloud_subnet" "subnet_bj_02" 
    name = "bj-02"
    cidr_block = "10.0.2.0/24"
    availability_zone = "ap-beijing-2"
    vpc_id = "$tencentcloud_vpc.vpc_bj.id"
    route_table_id = "$tencentcloud_route_table.rtb_vpc_bj.id"

resource "tencentcloud_subnet" "subnet_bj_03" 
    name = "bj-03"
    cidr_block = "10.0.3.0/24"
    availability_zone = "ap-beijing-3"
    vpc_id = "$tencentcloud_vpc.vpc_bj.id"
    route_table_id = "$tencentcloud_route_table.rtb_vpc_bj.id"

resource "tencentcloud_subnet" "subnet_bj_04" 
    name = "bj-04"
    cidr_block = "10.0.4.0/24"
    availability_zone = "ap-beijing-4"
    vpc_id = "$tencentcloud_vpc.vpc_bj.id"
    route_table_id = "$tencentcloud_route_table.rtb_vpc_bj.id"


4. 创建安全组

cat security_group.tf

resource "tencentcloud_security_group" "sg_bj" 
    name = "sg-bj"    


resource "tencentcloud_security_group_rule" "sg_bj_1" 
    security_group_id = "$tencentcloud_security_group.sg_bj.id"
    type = "ingress"
    cidr_ip = "0.0.0.0/0"
    ip_protocol = "tcp"
    port_range = "22,80"
    policy = "accept"

5. 创建cvm

cat cvm.tf

resource "tencentcloud_instance" "cvm_almalinux" 
  instance_name = "cvm-almalinux"
  availability_zone = "ap-beijing-2"
  image_id = "img-q95tlc25"
  instance_type = "S2.MEDIUM2"
  system_disk_type = "CLOUD_PREMIUM"
      
  security_groups = [
    "$tencentcloud_security_group.sg_bj.id"
  ]

  vpc_id = "$tencentcloud_vpc.vpc_bj.id"
  subnet_id = "$tencentcloud_subnet.subnet_bj_02.id"
  internet_max_bandwidth_out = 10
  count = 1


当然了区域镜像都可以自己选择了 …我img-q95tlc25是一个almalinux的镜像。早先找腾讯云团队问能不能早点上rocky 跟almalinux的镜像。给我分享了一下正好测试一下!

6 . terraform plan

执行** terraform plan **预览部署计划,

[root@zhangpeng terraform]# terraform plan




7. terraform apply

terraform apply 进行资源部署

[root@zhangpeng terraform]# terraform apply


enter a value输入yes 确认。等待资源创建!

4.验证资源的部署

登陆腾讯云后台似有网络管理页面:https://console.cloud.tencent.com/vpc/vpc选择北京区域。查看新建的vpc创建成功

点开对应vpc route发现route也创建成功,默认是有default路由的,所以我这里是不是可以不创建路由?

点击子网查看创建的四个subset子网:

点击上图bj-02子网中的cvm查看示例名 镜像id 规格与配置文件相对应!

后续:

  1. 给cvm绑定公网ip
  2. 调整硬盘大小,添加数据盘
  3. 给cvm绑定ssh-key

以上都是针对cvm的管理,其他的想更进一步体验一下其他服务的管理。比如 数据库 负载均衡 tke等其他的相关基础服务!
对了删除服务我也体验过了…开始创建有问题删除重新创建的:

terraform show
terraform destroy

另外感觉个人对帐号的权限管理玩的不太好。想深入研究一下腾讯云的cam访问控制
特别鸣谢:

  1. 聂伟星的博客
  2. 腾讯云生态产品团队:腾讯云Terraform应用指南(一)(比较早的文章了,有点老)
  3. 官方文档:https://registry.terraform.io/providers/tencentcloudstack/tencentcloud/latest/docs/

以上是关于「DevOps系列]为啥我们使用Terraform 而不使用Puppet, Ansible的主要内容,如果未能解决你的问题,请参考以下文章

Terraform系列一腾讯云CVM相关简单创建

Terraform系列一腾讯云CVM相关简单创建

terraform-远程状态存储

如何使用 Azure Devops 将 powershell 列表变量传输到 terraform?

在 azure 后端存储中使用状态文件将 terraform 的输出传递到 Azure Devops Pipeline

在现有且正在运行的 Azure DevOps 代理池中更改目标 VM ScaleSet?