Seal AppManager如何基于Terraform简化基础设施管理
阅读原文时间:2023年07月17日阅读:2

作者简介

陈灿,数澈软件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_deploymentkubernetes_service,这与我们编写 HCL 文件的资源也是相对应的,我们所创建的 resource 和 data 资源都会被记录到这个文件。

状态(State) 文件中还包含了一些元数据信息,如资源的 ID、资源的属性值等,这些信息都是 Terraform 用来管理资源的重要依据。

我们知道获取云资源状态常见的方式之一是通过各个平台自身提供的 API 服务来获取,比较 API 资源和配置文件资源的异同来决定创建或者删除资源,而 Terraform 却选择状态(State)文件来管理映射云平台的资源,而不是API 的方式来检查资源是否已经被创建,原因是什么呢?

Terraform 采取状态(State)文件的方式的好处有:

  1. Terraform 可以直接通过该文件获取创建的云资源状态。对于小型基础设施,Terraform 可以查询并同步所有资源的最新属性,这样在每次 apply 的时候只需要检查资源和状态文件的配置是否一致。如果一致则不需要做任何操作,如果不一致则需要创建、更新或者删除资源。

  2. 通过状态文件可以记录不同资源之间的关系,Terraform 可以通过依赖关系来管理创建或者销毁的顺序。

  3. 另外,对于大型基础设施,查询每个资源的耗时会较长。许多云提供商不提供同时查询多个资源的 API,每个资源的往返时间为数百毫秒。除此之外,云提供商几乎总是有 API 速率限制,因此 Terraform 在一段时间内只能请求一定数量的资源,通过 state 状态管理可以大大提升性能。

  4. 远端的 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 解决状态存储和共享的问题。