作者简介
陈灿,数澈软件Seal 后端研发工程师,曾在腾讯负责敏捷研发体系建设以及 DevOps 解决方案的敏捷实践。在敏捷研发和产品效能提升有着丰富的经验,致力于构建一站式研发友好的平台工程解决方案。现在是 Seal 平台工程团队核心研发人员。
平台工程(Platform Engineering)是近几年大火的技术概念,指专注于通过减少现代软件交付的复杂性和不确定性来提高开发人员的生产力的一种软件工程方法。内部开发平台则是平台工程的具体实现之一。本文将结合平台工程的理念介绍 Terraform 的基本概念和使用方法,包括在使用 Terraform 的过程中所面临的一些挑战以及 Seal AppManager 是如何解决这些问题的。
内部开发平台, Internal Development Platform(IDP),是建立在工程团队现有技术工具之上的一个自助服务层。IDP 是一个由平台团队开发的平台,使开发人员能够轻松地配置、部署和启动应用基础设施,无需依赖运维团队。IDP 有助于进一步自动化运维工作流程,并通过简化应用程序配置和基础设施管理来弥补和提升工作效率。同时,IDP 让开发人员拥有更多的自主权,使开发人员从编写代码到软件交付,都能够处理自如。
在传统的基础设施部署和管理中,通常会使用手动配置和管理的方式。这意味着管理员需要手动操作服务器、网络设备和存储等基础设施组件,安装和配置软件,以及处理各种依赖关系和环境变化。这种方式需要花费大量的时间和精力,并且容易出现配置错误和不一致性。
平台工程的首要任务之一是降低开发人员使用基础设施的难度。因为绝大多数的开发人员并不关心底层服务的复杂概念和创建方式,比如开发需要用存储服务,但不关心它们是如何创建的,再如一些专有名词如对象存储、磁盘阵列等,也不属于开发人员的关心范畴。
在大多数的业务场景中,开发人员只关注如何使用这些服务、数据是否可以持久化地保存在指定目录中。因此,平台工程完全可以提供一个适应大多数场景的存储服务,开发人员只需要选择自己所需要的服务类型,利用平台工程的能力创建服务,获取服务的地址,即可使用该服务。
平台工程通过抽象定义,在服务的基础上抽象出应用这一概念,多个应用可以组合成一个业务场景,应用之间存在显式或者隐式的关系。彼此之间通过这种关系有机地组合成一个完整的业务整体,并对外提供服务。
Terraform 是一个基础设施即代码(IaC)工具,它允许你安全、高效地构建、改变和更新基础设施。这包括低级别的组件,如计算实例、存储和网络,以及高级别的组件,如 DNS 条目、SaaS 功能等。
在 Terraform 诞生之前,基础设施的管理是一个非常繁琐的工作,需要人工操作,而且易出错,而 Terraform 的出现,让基础设施的管理变得简单、高效、可靠。Terraform 特别适合云环境:AWS、GCP、Azure、阿里云等, 通过丰富的 Provider 管理不同类型的资源,一切都像插件一样,可以轻松地扩展。
Terraform 采用 HCL 代码管理和维护基础设施资源,并且在运行之前可以通过terraform plan命令可以看到资源的变化,而这些变化是通过 Terraform 的状态文件来管理的。
Terraform 的 State(状态)是一个关键概念,用于记录当前基础设施的状态和配置。使用 Terraform 进行部署时,它会跟踪已创建的资源和其配置状态,并将其存储在本地的.tfstate文件中或使用远程存储(如AWS S3、Azure Blob存储)进行管理。
State 文件记录了资源的状态,当资源发生变化时,配置状态也会变化。因此,Terraform 支持在部署前预览资源变化而不需要真正的执行。Terrafrom 的配置状态文件可以保存在本地,也支持保存在远程的存储中,如:S3、Consul、gcs、kubernetes 或者其他自定义的 HTTP Backend 中。
macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
Linux Ubuntu
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
Linux CentOS
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform
Linux 二进制安装
Linux 用户也可以通过二进制的方式安装 Terraform,从官方下载对应的版本。
https://www.terraform.io/downloads.html
通过二进制安装 1.4.6 版本的 Terraform:
curl -sfL https://releases.hashicorp.com/terraform/1.4.6/terraform_1.4.6_linux_amd64.zip -o /tmp/terraform.zip
unzip /tmp/terraform.zip -d /usr/bin/
rm -f /tmp/terraform.zip
Windows
windows 用户可以通过 Chocolatey 来安装 Terraform, Chocolatey 是一个 Windows 的包管理器,类似于 Linux 的 yum 或者 apt-get,它可以帮助你快速的安装和卸载软件。
choco install terraform
或者去 Terraform 官网下载对应的版本,然后解压后配置 PATH 环境变量。最后,通过terraform version
命令来验证是否安装成功。
配置 Kubernetes Provider,通过后~/.kube/config文件来管理 Kubernetes 资源,这里也可以使用其他的 kubeconfig 文件。
provider "kubernetes" {
config_path = "~/.kube/config"
}
创建一个 Kubernetes Deployment
resource "kubernetes_deployment" "nginx" {
metadata {
name = "nginx"
labels = {
app = "nginx"
}
}
spec {
replicas = 1
selector {
match_labels = {
app = "nginx"
}
}
template {
metadata {
labels = {
app = "nginx"
}
}
spec {
container {
image = "nginx:latest"
name = "nginx"
port {
container_port = 80
}
}
}
}
}
}
Kubernetes Deployment 服务
resource "kubernetes_service" "nginx" {
metadata {
name = "nginx"
}
spec {
selector = {
app = kubernetes_deployment.nginx.metadata[0].labels.app
}
type = "NodePort"
port {
port = 80
target_port = 80
node_port = 30080
}
}
}
将上面的配置复制并在目标目录如~/terraform-demo
mkdir ~/terraform-demo && cd ~/terraform-demo
创建 main.tf 文件,将上述配置复制到 main.tf 并保存,完整的文件配置如下:
打开终端,进入到目标目录,初始化 Terraform 环境
cd ~/terraform-demo && terraform init
执行terraform plan
来预览资源的变化
执行terraform apply
来创建资源
最后在浏览器中访问http://localhost:30080
即可看到 nginx 的欢迎页面。
如果想要删除资源,可以执行terraform destroy
命令来删除资源。
通过上述例子,我们可以看到 Terraform 的管理 Kubernetes 资源非常简单,只需要通过 HCL 语言来描述资源的配置,然后通过terraform apply
来创建资源。此外 Terraform 还支持通过terraform import
来导入已经存在的资源,这样就可以将已经存在的资源纳入到 Terraform 的中进行管理。
Terraform 通过 HCL 描绘了资源的配置,但它如何知道资源是否已经被创建了呢?资源的新增、修改和删除是如何决定的?它怎样管理资源之间的依赖关系呢?要了解这些问题,就得依赖 Terraform 的状态管理机制了。
Terraform 将每次执行基础设施变更操作时的状态信息保存在一个状态(State)文件中,默认情况下会保存在当前工作目录下的terraform.tfstate
文件里,依托于状态文件来决定执行资源的变更方式。
在上述示例中,可以看到生成的状态(State) 文件中包含所创建的资源,如kubernetes_deployment
和kubernetes_service
,这与我们编写 HCL 文件的资源也是相对应的,我们所创建的 resource 和 data 资源都会被记录到这个文件。
状态(State) 文件中还包含了一些元数据信息,如资源的 ID、资源的属性值等,这些信息都是 Terraform 用来管理资源的重要依据。
我们知道获取云资源状态常见的方式之一是通过各个平台自身提供的 API 服务来获取,比较 API 资源和配置文件资源的异同来决定创建或者删除资源,而 Terraform 却选择状态(State)文件来管理映射云平台的资源,而不是API 的方式来检查资源是否已经被创建,原因是什么呢?
Terraform 采取状态(State)文件的方式的好处有:
Terraform 可以直接通过该文件获取创建的云资源状态。对于小型基础设施,Terraform 可以查询并同步所有资源的最新属性,这样在每次 apply 的时候只需要检查资源和状态文件的配置是否一致。如果一致则不需要做任何操作,如果不一致则需要创建、更新或者删除资源。
通过状态文件可以记录不同资源之间的关系,Terraform 可以通过依赖关系来管理创建或者销毁的顺序。
另外,对于大型基础设施,查询每个资源的耗时会较长。许多云提供商不提供同时查询多个资源的 API,每个资源的往返时间为数百毫秒。除此之外,云提供商几乎总是有 API 速率限制,因此 Terraform 在一段时间内只能请求一定数量的资源,通过 state 状态管理可以大大提升性能。
远端的 Backend 可以管理状态文件,这样可以实现多人协作,多人共享同一个状态文件。
然而,采用这种方式管理资源并非十全十美,当执行terraform apply
时,Terraform 会直接读取 State 文件来判断是否需要创建、更新或者删除资源。如果我们手动删除这个文件,再次执行terraform apply
时,Terraform 会认为这是一个全新的环境,从而会重新创建所有的资源,进而导致资源的管控混乱——原先创建的资源就再也没法通过terraform destroy
来删除了。因此妥善保管好这个状态文件非常重要,任何时候都不要手动修改或者删除这个文件。
细心的你可能会发现,状态(State)文件中的所有信息都是明文的,这意味着如果这个文件泄露,里面包含密码等关键信息都会被泄露,这将会对你的基础设施造成巨大的安全风险。除此之外,如果因设备损坏或者其他因素导致文件损坏,那么 tfstate 所记录的资源信息也会丢失,这样也会导致资源的泄露、管控混乱。
因此,Terraform 还提供了一种 Backend 的状态管理方案。这样就可以将状态文件保存在远程的存储中,比如 AWS S3、GCS、HTTP 等,这样就可以避免状态文件被泄露的风险。团队成员之间可以利用 Backend 解决文件存储和共享的问题。
通过上面的示例,我们可以看到 Terraform 管理 Kubernetes 资源非常简单,但是正如前文中提到过的 Terraform 也存在一些问题,这些问题可能会影响到我们对资源管理的使用体验。比如:
使用 HCL 语言来描述资源的配置,意味着开发人员需要学习一门新的语言,而且如果想要使用 Terraform 来管理其他资源,比如 AWS、GCP 等,那么就需要学习这些资源的 Provider 的配置,导致学习成本增加。另外一些语法问题也会增加使用的难度。
状态管理问题,Terraform 通过状态文件来管理资源,而状态文件所记录的资源都是明文的。如果状态文件遭受泄露、损坏等情况,会对资源的管控造成巨大的风险。
基础设施资源管理者需要拥有对资源的知识经验,这样才能够正确的配置资源,否则就会导致资源的配置错误导致资源的创建失败,或者资源的配置不符合预期。
大量的资源管控需要编写大量的 HCL 文件,资源的使用者需要花费大量的时间来查找资源和配置文件,管理资源的成本也会随着资源的增加而增加。
资源的状态不能实时获取,如 Kubernetes 的资源状态,查看日志和执行终端等等,这些需要通过其他的方式管理。
Seal AppManager 是一款基于平台工程理念的应用部署管理平台,底层基于 Terraform 技术构建,上周刚刚发布新版本。它可以帮助开发人员和运维快速地搭建一个生产或者测试环境,同时也可以帮助运维人员快速地管理这些环境,通过平台工程的能力解决上述问题。
Seal AppManager 可以将资源抽象成服务,利用应用来控制这些服务,进而将资源的底层配置和实际使用分离开,简化基础设施的管理。
通过管理多个环境和配置的方法,确保开发、测试和生产环境的一致性,降低错误和不一致的风险,并确保应用程序始终准确运行。
由于平台提供控制和治理功能,开发人员还可以确保所使用的环境是安全的,并且符合最佳实践和安全标准。资源的使用者只需要关注资源的使用,而不需要关注资源的底层原理及配置。
通过定义的资源模版,开发人员无需再关注 HCL 语言的语法,Terraform Provider 参数该如何配置以及基础设施的底层实现是什么原理,只需要通过平台提供的 UI 界面,通过定义好的模块填写参数就可以自助使用资源。这大大降低了开发人员使用资源的难度,提升了整体的开发效率。
除此之外,Terraform 的状态管理的不便之处也得到了解决。Seal AppManager 平台通过将状态文件保存在 HTTP Backend 远端,这样就可以避免状态文件被泄露的风险。不同的服务之间会自动管理所属的状态,这样团队成员之间可以利用 Backend 解决状态存储和共享的问题。
Seal AppManager 定义了资源上层的一系列抽象来帮助简化应用服务的管理难度,通过项目(Project)、环境(Environment)、连接器(Connector)、服务(Service)以及资源(Resource)的概念来管理业务服务的生命周期。
在内部主要通过 App Manager、Deployer 和 Operator 三大组件来管理资源,其中 App Manager 负责管理资源,Deployer 负责部署资源,Operator 处理资源的状态。在管理部署应用资源之前,需要先创建连接器,利用连接器用来连接资源的提供者,如 Kubernetes、AWS、阿里云等,还可以自定义其他连接器来实现不同的云资源的管理。
AppManager 管理服务的生命周期,包括创建、更新、删除服务,同时管控应用实例的版本,包括创建、更新、删除应用实例的版本。
Deployer 可以自动根据应用的配置来自动生成资源的配置文件,然后通过 Terraform 来部署资源。Deployer 会自动识别模版定义的 Provider 根据环境中的 Connector 配置来生成资源的配置文件。通过 Deployer 可以实现资源的部署创建,更新,删除,回滚等操作。
Operator 可以管理资源的状态,包括查看资源的状态、查看资源的日志、执行资源的终端等等。Operator 定义了一系列的资源操作,通过不同的资源类型与对应服务商的 API Server 来实现资源的操作。如 Kubernetes 资源的操作,Operator 通过 Kubernetes API Server 可以实现资源的状态查看、日志查看、终端执行等等。目前 Seal App Manager 支持 Kubernetes、AWS、阿里云资源的操作,后续会支持更多云厂商的资源操作。
在创建服务之前,需要先创建连接器。可以在连接器管理界面创建一个 Kubernetes 的连接器,并把这个连接器分配到default环境中。
示例中选取 default 项目,在default 项目中创建default环境,就可以在该环境中创建 K8s 相关的服务了,你也可以创建其他类型的连接器如AWS、阿里云类型的连接器创建相关的云服务。Seal AppManager 也支持多环境,可以根据业务场景创建不同的环境,如dev、prod等,在不同环境中管理不同的资源,这样就可以实现不同环境的资源管理。
配置好环境之后,就可以创建服务了。服务所使用的模块可以选择系统内置的模板,也可以在模块管理中根据业务需求自定义模板创建服务。在创建服务的时候,需要选择服务的模块和版本,配置好模板参数,这样就可以创建一个服务了。
下面演示利用内置的webservice
和mysql
模块创建一个 web 应用。
在default
环境中先创建database
服务, 填写模块相应的配置并保存。
等待database
服务创建完成后,接着在default环境中创建web服务,可以通过环境变量的形式,将数据库服务database的信息注入web服务的环境变量中 ,业务相关的程序通过环境变量即可访问到database服务的数据库。
创建好的实例会自动根据应用的配置管理和通过 Deployer 自动部署资源。在部署完成之后,Operator 会自动同步资源的状态,其他资源的操作如查看日志,执行终端都可以很方便的在实例详情页操作。
环境中的资源可以通过资源的服务列表页查看资源的情况,同时 Seal AppManager 提供了服务级别和环境级别依赖图,通过顶层的环境视角帮助开发更好的理解业务架构。在依赖图中可以清晰的看到不同服务之间的依赖关系,以及它们所部署的资源,在依赖图上也可以执行日志和终端,以帮助开发人员更便捷的查看服务日志和执行业务相关的一些命令,提升研发效率。
Seal AppManager 也支持快速创建服务,如批量克隆服务到不同环境。在之前的示例基础上,我们可以创建一个新的dev环境,将database和web服务快速的克隆到dev环境上。克隆服务的同时也会将其依赖管理保留克隆到新的环境中,这样可以为团队中其他的研发或者测试快速的创建一个开发或者测试环境。
可以看到,在 Seal AppManager 中,业务系统的资源管理和部署变得非常简单,没有运维经验的开发人员甚至是测试也可以快速通过 Seal AppManager 来管理和部署资源。
除了本文中的示例之外,Seal AppManager还支持其他资源类型,如 AWS、阿里云等,这些资源的支持可以通过定义对应的连接器来实现管控,只需要配置好连接器, 在运维中心创建对应的模块,如内置的 aws-rds、alicloud-rds。创建服务的时候选择对应的模块,即可完成对应云资源的部署和管理。另外,Seal AppManager 还提供了 AIGC 的能力来帮助平台工程师快速编写基础设施模块。
依托于 Terraform 的强大生态,Seal AppManager可以支持更多的资源类型,平台工程师可以在系统中定义不同的模块,即可实现为不同业务系统提供一致的资源管理和部署体验。
在云原生时代,应用的部署和管理变得越来越复杂,传统的运维方式已经无法满足业务的快速迭代,如何提高研发团队的生产力,降低运维成本,是每个企业都需要面对的问题。Terraform 作为一个开源的基础设施即代码工具,可以帮助企业实现基础设施的自动化管理,但是 Terraform 作为一个基础设施即代码的工具不是一个完整的解决方案,需要配合其他的工具来实现资源规范的管理和部署。
而 Seal AppManager 就是一个基于 Terraform 的资源管理和部署平台,它可以帮助企业实现资源的自动化管理和部署,提高研发团队的生产力,降低运维成本。开发人员通过 Seal AppManager 的支持,可以从运维的繁琐工作中解放出来,将精力放在所开发的业务上。