Skip to main content

Command Palette

Search for a command to run...

介绍一个小工具:Terranetes

Updated
3 min read

IaC 不只是 Terraform

虽然几年前的一次讨论中,我嘲讽过某同事说,Terraform 目前最靠谱的 Provider,也就只有 Kubernetes 一个而已,相对于顾头不顾尾的 Provider 来说,Kubernetes + Operator 才是正道;然而形势比人强,目前 Terraform 的确是能帮用户踏上 IaC 旅程的方便法门。

就像 Kubernetes 之于云原生,对于 IaC 来说,Terraform 也同样有着 Day2 的问题。并且由于面对更大范围、更大成本的调度能力,Terraform 的管控也面临更大的挑战。例如工作流、合规、安全、成本等方面的考虑,以及偏差检测、模块安全等特性的应用,都是摆在管理员面前的明显问题。围绕这一工具,想要构建一个稳健的自助平台,是个颇为复杂的困难过程。

Terranetes 简介

appvia.io 是一个位于伦敦的解决方案厂商,它的开源项目 Terranetes 就尝试解决 Terraform 的 Day2 问题。这个 golang 项目在 22 年开源,到现在为止,发布了一百多个 Release,Star 数量只有 135 个,上次代码更新是在两个月前,从运作成绩来看,似乎不太成功。然而从平台工程的角度来看,这个项目提供的众多特性,却是非常值得关注和致敬的。

Terranetes 首页有这样一张图,形象地描述了这一产品的 IaC 治理思路:

工作流

图里简单地描述了一个工作流,平台团队制定规则、开发团队申请资源,控制器接收申请、引用凭据、执行规范,按照流程中设定的审批、Lint 等环节,完成资源申请过程。

他把用户明确地区分为平台和开发两种角色:

平台团队

平台用户的主要职责是为开发者用户提供自助服务的基础支持:

  • 接入资源供应商:用 CRD 的形式定义资源供应商,以此来支撑开发者使用指定供应商的资源。

  • 凭据管理:管理接入资源供应商的身份凭据,开发者无需自行管理凭据,即可获得操作资源的权限。

  • 策略管理:从成本、合规、安全等方面,提供策略支持,保障开发者对资源的有效使用。

开发团队

开发者的职责相对集中一些:引用平台团队维护的凭据、规则、模板等,按照既定工作流进行资源的申请和使用。

上手一试

官方提供了 Quick Start 文档,网络条件允许的话,几分钟就可以完成第一次资源分配。下面的例子我使用 AWS 作为资源供应商,本机的 OrbStack 提供给 Terranetes 作为控制器的 Kubernetes 运行平台。

先决条件

  • Kubernetes 集群

  • AWS 账号,有能够创建 S3 Bucket 的 AK/SK

部署

基于 Helm 的老套部署方式:

$ helm repo add appvia https://terranetes-controller.appvia.io
$ helm repo update
$ helm install -n terraform-system terranetes-controller appvia/terranetes-controller --create-namespace
...

运行后可以看到多出了 terraform-system 命名空间,其中运行了两个控制器 Pod。

CRD

看看多出了哪些 CRD:

$ kubectl api-resources | grep terraform
cloudresources                                 terraform.appvia.io/v1alpha1      true         CloudResource
configurations                                 terraform.appvia.io/v1alpha1      true         Configuration
contexts                                       terraform.appvia.io/v1alpha1      false        Context
plans                                          terraform.appvia.io/v1alpha1      false        Plan
policies                                       terraform.appvia.io/v1alpha1      false        Policy
providers                                      terraform.appvia.io/v1alpha1      false        Provider
revisions                                      terraform.appvia.io/v1alpha1      false        Revision

官网文档用下图来描述对象之间的关系:

CloudResources:这个对象用来描述 Terraform 中的云资源,CloudResources 会选择性的向用户公开属性,从而减少开发者的心智负担,并确保选项符合组织意图。

Revisions:Revision 是云资源的模板,在实际环境中,应该是经过策划和测试的版本化资产,其中会包含组织所需的默认设置,并只公开与上下文相关的功能:

  • Revision 指向 Terraform 模块。

  • 包含平台希望模块默认设置的所有默认选项,并向消费者公开部分可见选项。

  • 可以跟踪 Terraform 模块,也可独立演进。

  • 所有 CloudResources 都会引用集群中的 Revision。

  • 要升级 CloudResource 消费者,需要更新其指向的 Revision。

Configurations:另一种描述云资源的方法,相对于 CloudResource,它相对传统一些,采用了和 Module 进行一对一连接的方式。

Providers:用来连接云资源提供方的定义。

Plans:无需主动创建,随 Revision 对象的定义自然产生。

Policies:对策略的引用,其中包含了 Checkov 规则的引用方法、对 Module 的限制。

Contexts:上下文提供了一种在配置之间共享通用配置的方法。集群中任何组件都可以引用该资源。

配置凭据和 Provider

接下来配置用来连接 AWS:

$ kubectl -n terraform-system create secret generic aws \
--from-literal=AWS_ACCESS_KEY_ID=${AWS_AK} \
--from-literal=AWS_SECRET_ACCESS_KEY=${AWS_SK} \
--from-literal=AWS_REGION=${AWS_AGN}
secret/aws created
$ export PROVIDER="https://raw.githubusercontent.com/appvia/terranetes-controller/master/examples/provider.yaml"
$ kubectl apply -f $PROVIDER
provider.terraform.appvia.io/aws created
provider.terraform.appvia.io/aws-irsa created

可以看到 Provider 对象的 spec 内容:

  spec:
    preload:
      cluster: wayfinder-production
      context: default
      enabled: false
      region: eu-west-2
    provider: aws
    secretRef:
      name: aws
      namespace: terraform-system
    source: secret

其中指定了 AWS 作为资源供应商,并且使用前面的 Secret 作为连接凭据。

配置 Revision

$ export REV="https://raw.githubusercontent.com/appvia/terranetes-controller/master/examples/revision.yaml"
$ kubectl apply -f ${REV}
revision.terraform.appvia.io/bucket.v1 created

打开 Revision 文件,能够大致观察到其中包含的信息:

  • configuration:其中有 Module 的地址、Context 引用、Provider 引用以及默认值

  • inputs:这里定义了用户可以控制的内容(此处只有 bucket 可写)。

  • plan:则定义了该对象所属的计划。

Revision 中定义的 Plan 也被自动创建了:

$ kubectl get plan bucket -o yaml
apiVersion: terraform.appvia.io/v1alpha1
kind: Plan
metadata:
  ...
spec:
  revisions:
  - name: bucket.v1
    revision: v0.0.1

使用 Plan->Revision 创建资源

上面两节完成了平台管理或者资源管理角色的任务,接下来要真正地申请资源了。这里需要创建如下的 CloudService 对象:

apiVersion: terraform.appvia.io/v1alpha1
kind: CloudResource
metadata:
  name: bucket
spec:
  plan:
    name: bucket
    revision: v0.0.1
  providerRef:
    name: aws
  writeConnectionSecretToRef:
    name: test
  variables:
    bucket: forever8384

执行之后,我们会看到,系统中有了一个运行成功的 Job 对象,以及一个 CloudResource 对象:

$ kubectl get jobs
NAME                  COMPLETIONS   DURATION   AGE
bucket-tgbrl-1-plan   1/1           28s        8m37s
$ kubectl get cloudresources.terraform.appvia.io
NAME     PLAN     REVISION   SECRET   CONFIGURATION   ESTIMATED     UPDATE   SYNCHRONIZED   AGE
bucket   bucket   v0.0.1     test     bucket-tgbrl    Not Enabled   None     OutOfSync      8m50s

任务已经完成,打开 AWS 控制台,也找不到我们要的 Bucket。看看 Job 对应的 Pod 日志:

kubectl logs -f bucket-tgbrl-1-plan-lj7hd
[info] Checking if required flags have been provided.
[info] Waiting 10 seconds for pod logs to be available (attempt 1/15)..
[info] waiting for the job to be scheduled
...
  # aws_s3_bucket_server_side_encryption_configuration.this[0] will be created
  + resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
...
  # aws_s3_bucket_versioning.this[0] will be created
  + resource "aws_s3_bucket_versioning" "this" {
...
Plan: 6 to add, 0 to change, 0 to destroy.

搞 Terraform 的读者会看得出来,他似乎只做了 Plan,没有做实际的 Apply。

文档解释说,默认情况下,资源的创建是需要被批准的,除非是使用了注解:terraform.appvia.io/apply=true,所以我们现在加入这个:

$ kubectl annotate cloudresources bucket "terraform.appvia.io/apply"=true --overwrite
cloudresource.terraform.appvia.io/bucket annotated

接下来会看到一个新的 Job 在运行,类似 bucket-l6jkf-1-apply-xp45d 这样的名称。这个 Pod 运行成功之后,会看到 S3 桶已经创建。

客户端

Terranetes 还有个叫 tnctl 的命令行客户端软件,提供了任务跟踪、审批等能力,避免大量使用 kubectl 来完成这些任务。

其他

偏差检测

CloudResource 有个字段 spec.enableDriftDetection,设置为 True 就可以启动偏差检测。例如上面的 CloudResource,我们修改这个字段为 True 之后,删除对应的桶,一段时间之后,这个资源就会变成 OutOfSync 状态。

监控

Controller 自带了 Prometheus 的指标抓取端口,提供了请求数、延迟时间等简单的指标。

除了这些基本功能之外,Terranetes 还能对接 Infracost 进行成本数据采集和预测,不过这是个商业产品,就没有进一步尝试了。

总之,Terranetes 提供了一个相对全面的框架,其中展示的工作流、策略、分权等设计,都是很好的范本,很值得工具平台、IaC 相关方案的设计者们参考和学习。

More from this blog

龙虾恐慌:AIOps 又要改名了?

ChatGPT 开始,把 AI 拉近到普罗大众的面前,让无数人感受到 AI 的亲民魅力。而龙虾,则把大模型驱动的自动化能力,突然间变得水灵灵、活泼泼地走进千家万户。它不只是“风口上的猪”,而是风口本身。热度高到让 Mac mini 一度断货,不知道这在不在库克的预料之内。 每代人都有每代人的鸡蛋,春节期间,我就领了我的鸡蛋。翻出古老的 MacBook Air M1,充值各种大模型。当然了,这个工具

Mar 9, 20261 min read

再见 2025

我猜不少人以为这个号废了吧?并没有,只是今年变化有点大,一直有种抄起键盘,无从说起的感觉,所以一直偷懒到今天,2025 的最后一天。 今年是我的第四个本命年,去年末一期播客里,大内说本命年不是灾年,是变化年,有危也有机。可是讲真啊,只看到危,没看到机。 各种因缘际会,从鹅厂跳槽到前东家,已经接近四年,第一个合同期已经进入尾声。除了前两年还在云原生领域嗷嗷叫,后两年基本都是些鸡零狗碎的东西了,用老东家的术语说是——偏离主航道,可谓是前景暗淡了。 一旦确定要滚蛋,反倒心思轻松起来,每天骑着我的小红车...

Jan 5, 20261 min read

辅助编程?dora 说:我知道你很急可是请你别急

从 OpenGPT 把大模型的火烧旺了之后,这三年来,相信很多组织或摩拳擦掌、或躬身入局,希望借助聪明能干的大模型,或想偿还技术宅,或想降本增效,或想弯道超车。一时间,沉寂许久的 AIxx 又活过来了,LLM Ops、Vibe Coding、中医大模型、GPT 算命等等,全都老树发新芽,焕发了勃勃生机。那么视角拉回从业者最关注的饭碗相关的领域之一——AI 辅助开发,产生了什么触动,应该如何拥抱呢? DORA 的年度报告中给出了很有意思的结论——强者恒强。 执行摘要部分总结了几个有趣的点: 问题...

Oct 6, 20251 min read

[译]dora:ai 辅助软件开发状态报告

执行摘要 在 2025 年,科技领导者面临的核心问题已不再是“是否要采用 AI”,而是“如何实现其价值”。 DORA 的研究基于超过 100 小时的定性访谈和来自全球近 5,000 名技术专业人士的问卷调查。研究揭示了一个关键事实:AI 在软件开发中的主要角色是“放大器”。它会放大高效能组织的优势,也会凸显组织的缺陷。 关键结论:AI 是放大器 AI 投资的最大回报并非来自工具本身,而是来自组织底层系统的战略性建设: 高质量的内部平台 清晰的工作流 团队的协同能力 缺少这些基础,AI ...

Oct 2, 202514 min read

僭越了,有人在用 Rust 写 Kubernetes

一个新语言问世,最爱做的事情之一,就是重写存量软件了。 云原生喝酒 SIG 重点扶持项目——rk8s(https://github.com/rk8s-dev/rk8s) 也可以归在这个范畴里,只不过这个项目重写的东西比较大,是 Kubernetes。 从 2025 年 1 月第一个 Commit 开始,到现在有了 200 多次 Commit,十几万行代码。当然距离 Kubernetes 的几百万行代码还差得远——老马就是喜欢整这种大无畏项目。 另外该项目也是国内第一个脱离 Cargo 转向使用 ...

Sep 27, 20253 min read

【伪】架构师

342 posts