基础设施即代码--Terraform安装与示例

Terraform 是一种安全有效地构建、更改和版本控制基础设施的工具(基础架构自动化的编排工具)。它的目标是 "Write, Plan, and create Infrastructure as Code", 基础架构即代码。

Terraform 几乎可以支持所有市面上能见到的云服务。具体的说就是可以用代码(其实就是配置文件定义)来管理维护 IT 资源,把之前需要手动操作的一部分任务通过程序来自动化的完成,这样的做的结果非常明显:高效、不易出错。

用法与k8s容器平台的helm有点类似,都是声明式资源管理,并对版本有较好的管理,配合git食用更佳。

下文将练习通过Terraform在Azure云上创建资源组、vnet、虚拟机。

其实Azure本身提供了ARM模板配合变量配置文件,也是以声明式创建和管理资源。
但我更好奇Terraform到底有什么魔力,让各大云厂商在官方文档里进行推介,容我一探究竟。

安装 terraform

支持 MAC,Win,Linux
https://developer.hashicorp.com/terraform/tutorials/azure-get-started/install-cli

Centos/RHEL

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

检查版本

[root@centos8 azure-terraform]# terraform version
Terraform v1.3.9
on linux_amd64
+ provider registry.terraform.io/hashicorp/azurerm v3.44.1

开启命令自动补全,执行完重新进入下bas窗口

 touch ~/.bashrc
terraform -install-autocomplete

安装 Azure CLI 及登录认证

https://learn.microsoft.com/zh-cn/cli/azure/install-azure-cli

Azure CLI 的 RPM 包依赖于 python3 包。Centos7 可能会遇到些问题,Centos8没问题。我此处用的Centos8.5

sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo dnf install -y https://packages.microsoft.com/config/rhel/8/packages-microsoft-prod.rpm
sudo dnf install azure-cli

# 查看版本
[root@centos8 azure-terraform]# az version
{
  "azure-cli": "2.45.0",
  "azure-cli-core": "2.45.0",
  "azure-cli-telemetry": "1.0.8",
  "extensions": {}
}

使用Terraform创建资源组

先尝试实现一个最简单场景,了解下大概的使用流程。

创建配置文件

新建一个空目录,并在其中创建一个 main.tf 文件

mkdir azure-terraform
cd azure-terraform/

编辑 main.tf 配置文件

[root@centos8 azure-terraform]# cat main.tf
# We strongly recommend using the required_providers block to set the
# Azure Provider source and version being used
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.44.1"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {}
}

# Create a resource group
resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "West Europe"
}

文件的上半部分 terraform/provider 定义了将要使用什么云,及插件的版本,在以下连接的右上角“USE PROVIDER”查看。 resource 部分表示要创建的资源,此处是创建一个资源组,在以下连接的右上角“Documentation”,有所有支持的资源定义解读。
https://registry.terraform.io/providers/hashicorp/azurerm/latest

Azure 权限认证

在通过 Terraform 创建之前,需要先配置权限认证,才能去创建或配置资源。

https://learn.microsoft.com/zh-cn/azure/developer/terraform/authenticate-to-azure?tabs=bash

主要两种方式:

  1. 通过powershell 或者 az cli 进行认证
  2. 通过服务主体。服务主体创建后,可以在环境变量指定ID和密码。也可以配置在main.tf(明文,不安全)

此处就通过最简单的方式,执行 az login
注意如果是国内azure云,也就是21世纪互联运营的那个,需要切到中国区 az cloud set --name AzureCloud

az login
# 查看订阅
az account show
# 切换订阅
az account set --subscription "<subscription_id_or_subscription_name>"

初始化插件

执行 terraform init。 terraform init 会分析 xxx.tf 代码中所使用到的Provider,并尝试下载Provider插件到本地
如果网络连不上多执行几次,国内网络老大难。。。

成功后会看到提示 "Terraform has been successfully initialized!"

可以看到新增了两个隐藏文件,目录下就有 azure privider 的插件

[root@centos8 azure-terraform]# tree
.
└── main.tf

0 directories, 1 file
[root@centos8 azure-terraform]# tree -a
.
├── main.tf
├── .terraform
│   └── providers
│       └── registry.terraform.io
│           └── hashicorp
│               └── azurerm
│                   └── 3.44.1
│                       └── linux_amd64
│                           └── terraform-provider-azurerm_v3.44.1_x5
└── .terraform.lock.hcl

7 directories, 3 files

格式化和校验配置文件(可选操作)

执行 terraform fmt 格式化配置文件,比如对齐。如果自动修改了文件,会列出修改的内容。同时对错误的格式也会指出,建议执行。

terraform validate 验证配置文件,和上面命令有点类似,但是不会去修改文件

terraform plan 预览变更

执行 terraform plan 可以预览一下代码即将产生的变更:

[root@centos8 azure-terraform]# terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.example will be created
  + resource "azurerm_resource_group" "example" {
      + id       = (known after apply)
      + location = "westeurope"
      + name     = "example-resources"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

───────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these
actions if you run "terraform apply" now.

terraform apply 执行变更

运行terraform apply 时,Terraform会首先重新计算一下变更计划,并且像刚才执行plan命令那样把变更计划打印给我们,要求我们人工确认。让我们输入yes,然后回车

[root@centos8 azure-terraform]# terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.example will be created
  + resource "azurerm_resource_group" "example" {
      + id       = (known after apply)
      + location = "westeurope"
      + name     = "example-resources"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.example: Creating...
azurerm_resource_group.example: Creation complete after 6s [id=/subscriptions/3c398848-b31e-427a-aa4e-3b87b2ae6064/resourceGroups/example-resources]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

terraform show 查看当前部署

查看当前部署资源属性和元数据,可以用这些值来配置其他资源

[root@centos8 azure-terraform]# terraform show
# azurerm_resource_group.example:
resource "azurerm_resource_group" "example" {
    id       = "/subscriptions/3c398848-b31e-427a-aa4e-3b87b2ae6064/resourceGroups/example-resources"
    location = "westeurope"
    name     = "example-resources"
}

# terraform state list  命令可以列出创建的资源列表
[root@centos8 azure-terraform]# terraform state list
azurerm_resource_group.example

apply 完成后将变更操作时的状态信息保存在一个状态文件中,默认情况下会保存在当前工作目录下的terraform.tfstate文件里。不要手动修改这个文件。 再次执行 apply 的时候会检查 tfstate 文件,如果没有这个文件,会认为是第一次创建。 同时下一步 destroy 删除资源的时候也依赖这个文件。
同时 tfstate 中的密码都是明文的,存储需注意安全。

[root@centos8 azure-terraform]# cat terraform.tfstate
{
  "version": 4,
  "terraform_version": "1.3.9",
  "serial": 1,
  "lineage": "27786e94-4a19-71cc-43e4-e2d1dfa1f851",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "azurerm_resource_group",
      "name": "example",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "id": "/subscriptions/3c398848-b31e-427a-aa4e-3b87b2ae6064/resourceGroups/example-resources",
            "location": "westeurope",
            "name": "example-resources",
            "tags": null,
            "timeouts": null
          },
          "sensitive_attributes": [],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo1NDAwMDAwMDAwMDAwLCJkZWxldGUiOjU0MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjo1NDAwMDAwMDAwMDAwfX0="
        }
      ]
    }
  ],
  "check_results": null
}

terraform destroy 清理资源

会列出要清理的对象进行确认,清理之后会自动把 tfstate 文件备份 terraform.tfstate.backup 。原文件 terraform.tfstate 中 resource 部分会被清空了。

创建 vnet 和虚拟机

main.tf 增加vnet,sub,vm 等配置文件。注意下变量的引用,vnet 会引用RG名称,网卡引用subnet id

[root@centos8 azure-terraform]# cat main.tf
# We strongly recommend using the required_providers block to set the
# Azure Provider source and version being used
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.44.1"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "main" {
  name     = "${var.prefix}-resources"
  location = var.location
}

resource "azurerm_virtual_network" "main" {
  name                = "${var.prefix}-network"
  address_space       = ["10.0.0.0/22"]
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
}

resource "azurerm_subnet" "internal" {
  name                 = "internal"
  resource_group_name  = azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = ["10.0.2.0/24"]
}

resource "azurerm_network_interface" "main" {
  name                = "${var.prefix}-nic"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.internal.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_linux_virtual_machine" "main" {
  name                            = "${var.prefix}-vm"
  resource_group_name             = azurerm_resource_group.main.name
  location                        = azurerm_resource_group.main.location
  size                            = "Standard_D2s_v3"
  admin_username                  = "${var.username}"
  admin_password                  = "${var.password}"
  disable_password_authentication = false
  network_interface_ids = [
    azurerm_network_interface.main.id,
  ]

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }

  os_disk {
    storage_account_type = "Standard_LRS"
    caching              = "ReadWrite"
  }
}

variables.tf 定义资源名称前缀,地区,vm的用户名密码

[root@centos8 azure-terraform]# cat variables.tf
variable "prefix" {
  description = "The prefix which should be used for all resources in this example"
  type    = string
  default = "demo"
}

variable "location" {
  description = "The Azure Region in which all resources in this example should be created."
  type    = string
  default = "eastus"
}

variable "username" {
  description = "The virtual machine username."
  type    = string
  default = "caifeng"
}

variable "password" {
  description = "The virtual machine password."
  type    = string
  default = "abcdef@123"
}

terraform apply 更新变更,可以在portal 上查看RG,VM信息。 state list 查看资源列表。

[root@centos8 azure-terraform]# terraform apply

[root@centos8 azure-terraform]# terraform state list
azurerm_linux_virtual_machine.main
azurerm_network_interface.main
azurerm_resource_group.main
azurerm_subnet.internal
azurerm_virtual_network.main

参考文档

https://developer.hashicorp.com/terraform/cloud-docs/workspaces/dynamic-provider-credentials/azure-configuration
https://registry.terraform.io/providers/hashicorp/azurerm/latest
https://lonegunmanb.github.io/introduction-terraform/

关注我的github,后续更新会同步上去

https://github.com/cai11745/hybrid-cloud

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容