1. Terraform Vs Kubernetes
基础架构即代码(Iac) 基于不可变的基础架构,使用编排工具将基础架构文本化,允许像管理代码一样管理基础设施。2018 年,我在从事 SaaS 开发,使用 Kubernetes 平台进行部署,这一年 Terraform 很火。2019 年,我开始从事 Kubernetes 的二次开发,才听说 Terraform 。现在网上 Terraform 相关的文档增量已经很少,更多是 Kubernetes 。为什么我开始关注 Terraform ?因为测试 Kubernetes 经常需要创建大量集群。手工在 IaaS 的 GUI 创建 VM ,登陆部署是最低效的方式。我也尝试过使用 Jenkins 流水线部署 Kubernetes ,这得维护一台可靠的服务器。最后就关注到了 Terraform 。Terraform 承载的是平台,而 Kubernetes 承载的是应用。存储平台、监控平台、PaaS 平台、依赖于 Kubernetes 的平台、DevOps 平台等,需要考虑使用 VM 进行部署,减少架构上的复杂度,而用户服务的负载可以直接使用 Kubernetes 进行部署。目前,使用和运维 Kubernetes 的门槛并没有很低,强行 All in Kubernetes 而运维能力没有跟上,会导致更棘手的问题。以前服务只是慢,现在服务打不开 。
2. Terraform 的运行机制
编排工具的核心是定义一种 DSL 语言,用户使用 Outer DSL 语言描述流程,而编排工具实现 Inner DSL 对其解析,转换为具体执行动作。如下图:
Terraform 的 Outer DSL 是提供给用户编写的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| provider "cloud" {
secret_id = ""
secret_key = ""
region = ""
}
data "cloud_image" "myimage" {
os_name = "centos"
...
}
resource "cloud_instance" "my_app" {
instance_name = "app1"
...
}
|
Terraform 的 Inner DSL 是开发者使用 Golang 实现的,由两部分组成,Core 和 Plugins 。Core 通过 RPC 与 Plugins 进行通信。Plugins 插件负责领域实现,提供 Provider 。Core 负责解析 Outer DSL 、管理资源、管理构建、执行 plan。如下图:
3. 如何发布 Provider
Provider 主要是对领域的封装,直白点就是实现对 IaaS API 的封装。基于 Terraform 提供的 schema.Provider
实现鉴权、基于 schema.Resource
实现对 IaaS 资源的 CRUD 即可。https://registry.terraform.io/ 提供了类似 DockerHub 的托管功能,在页面上可以找到相关基础设施的 Provider 和 Modules 。Provider 通常就是 IaaS ,Modules 就是基于 Provider 的一个组件、应用等。
- 首先需要将 Provider 发布到 Github Release 。
主要分为如下几个步骤:
安装 goreleaser ,配置 .goreleaser.yml直接拷贝 terraform-provider-scaffolding 中的 .goreleaser.yml
文件到项目根目录下。goreleaser 用于项目的发布,可以同时编译多个系统版本,并发布到 GitHub 上。
配置 GPG_FINGERPRINT没有配置 GPG 的可以参考这篇文档,GPG 验证提交 。查看环境中的 GPG 全部秘钥:
1
2
3
| gpg --list-keys
xxx(YOUR_GPG_ID)
|
设置环境变量:
1
| export GPG_FINGERPRINT=xxx(YOUR_GPG_ID)
|
GPG_FINGERPRINT
指向了你所使用的某条 GPG 秘钥,也是下面需要在注册页面上输入的内容。
设置 GITHUB_TOKEN打开 Github 的个人 配置页面 页面,勾选 public_repo
权限,生成 Token 之后:
1
| export GITHUB_TOKEN=xxx
|
仓库打标签 发布 Release 版本1
| goreleaser release --rm-dist
|
最后在 Github 页面上看到是这样的效果:
如果使用 Github Action 自动进行发布,可以增加一个文件 `` :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| name: goreleaser
on:
push:
tags:
- 'v*'
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/[email protected]
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/[email protected]
with:
go-version: 1.14
-
name: Import GPG key
id: import_gpg
uses: crazy-max/[email protected]
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
-
name: Run GoReleaser
uses: goreleaser/[email protected]
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }}
|
RELEASE_TOKEN
就是上面的 GITHUB_TOKEN
值,而 GPG_PRIVATE_KEY
为下面命令的输出值:
1
2
3
| gpg --list-keys
xxx(YOUR_GPG_ID)
|
gpg --export-secret-keys --armor xxx(YOUR_GPG_ID)
- 然后准备好 GPG 秘钥,在 https://registry.terraform.io/ 页面上,使用 Github 账户登陆,选择 Provider 仓库,发布一个 Provider 。发布之后的效果如下:

4. 如何使用 Provider Iac 应用
在目录下新增三个文件,var.tf 、platform.tf 、install.sh 。内容大致如下:var.tf , 定义 provider 和全局变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| terraform {
required_providers {
qingcloud = {
source = "shaowenchen/qingcloud"
version = "1.2.6"
}
}
}
variable "access_key" {
default = "yourID"
}
variable "secret_key" {
default = "yourSecret"
}
variable "zone" {
default = "pek3a"
}
provider "qingcloud" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
zone = "${var.zone}"
}
|
platform.tf ,定义 IaaS 相关的资源。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| resource "qingcloud_eip" ...
resource "qingcloud_security_group" ...
resource "qingcloud_security_group_rule" ...
resource "qingcloud_keypair" ...
resource "qingcloud_instance" ...
resource "null_resource" "install_platform" {
provisioner "file" {
destination = "./install.sh"
source = "./install.sh"
connection {
type = "ssh"
user = "root"
host = "${qingcloud_eip.init.addr}"
private_key = "${file("~/.ssh/id_rsa")}"
port = "22"
}
}
provisioner "remote-exec" {
inline = [
"sh install.sh"
]
connection {
type = "ssh"
user = "root"
host = "${qingcloud_eip.init.addr}"
private_key = "${file("~/.ssh/id_rsa")}"
port = "22"
}
}
|
install.sh ,在指定的 IaaS 上安装平台应用。也可以将其封装成 module ,会更加清晰。
1
2
| #!/usr/bin/env bash
# install your application
|
这些基础设施相关的配置文件,都需要使用 Git 进行存储和管理。每次需要创建时,只需要克隆下来,进入目录:
1
2
| terraform init
terraform apply
|
即可创建对应的平台应用。而执行 terraform destroy
即可销毁创建的全部资源。
5. 参考
- https://github.com/shaowenchen/terraform-provider-qingcloud