尝试使用适用于 ARM 的 Terraform 来配置虚拟机

尝试使用支持ARM的Terraform来虚拟化ARM虚拟机。

由于HashiCorp的Terraform发布了Azure Resource Manager的提供程序,因此我想与第一次接触Terraform的人分享如何使用Terraform来进行虚拟机的配置。

13120348_1163615393678277_896436150_o.jpg

Terraform在编写代码来配置基础架构时非常方便,包括虚拟机等。对于使用Azure的人来说,通常使用Azure Resource Manager(ARM)已经足够了。但对于熟悉Terraform或需要支持多个云环境的人来说,统一使用Terraform可能会很方便。此外,Terraform是用Go语言编写的,可以在Linux / Mac / Windows上运行,并且安装也非常简单,这一点很棒。

我想將常見的用例—VM的配置和安裝Chef—進行程式化。

1. 安装

安装Terraform非常简单。

下载火星

从该页面上下载适合自己环境的二进制文件,并将其添加到路径中,然后就完成了。不需要任何其他东西。

使用する必要があります。

微软Azure:软件开发工具包

请根据您的操作系统,从这个页面的命令行工具部分下载安装程序会更好。虽然本次是在Windows上执行,但我认为在Mac上也可以使用相同的步骤。

2. 用于服务主体认证的设置

在使用Azure ARM时,您可以将真壁先生编写的Terraform认证步骤设置为最简便的方式。(在此过程中,我们将使用先前提及的Azure CLI)

让我们将说明留给真壁先生的条目,只分享具体的设置步骤。具体而言,就是在Azure的Active Directory中注册应用程序,并授予其访问权限。

2.1. 登录

进行Azure登录。

> azure login
info:    Executing command login
|info:    To sign in, use a web browser to open the page https://aka.ms/devicelogin. Enter the code <Some Code> to authenticate.

请在命令行中打开https://aka.ms.devicelogin页面,并在浏览器中输入处显示的代码,然后使用您自己的Azure帐户登录。登录完成后,我们需要切换Azure CLI的模式。Azure有两个模式,一个是旧版的Azure Service Manager,另一个是新版的Azure Resource Manager,我们需要将模式切换到新版。

> azure config mode arm

将应用程序注册到Active Directory 2.2。

服务原则刚开始可能会感觉有些麻烦,但一旦进行了下一步操作,就会真正轻松愉快!只需第一次,所以让我们享受其中吧。

通过以下命令,在Azure的Active Directory中注册您的Terraform,以进行身份验证。

主页和标识符URI可以是您拥有的某个博客或其他URL。只要与其他人不重复即可。

我知道主页和注册之类的东西可能让人有点困惑,但在服务凭据认证中,我们需要“注册应用程序”的意思,所以在这种情况下确实是必要的。这次我们只是想在Azure上用Terraform访问,所以只需要将其作为必填项填写即可,而不需要太多理解。当执行此命令时,

> azure ad app create --name "My Terraform" --home-page "http://simplearchitect.hatenablog.com/" --identifier-uris "http://simplearchitect.hatenablog.com/" --password <Your Password>
info:    Executing command ad app create
+ Creating application My Terraform
data:    AppId:                   <Some AppId>
data:    ObjectId:                <Some App ObjectId>
data:    DisplayName:             My Terraform
data:    IdentifierUris:          0=http://simplearchitect.hatenablog.com/
data:    ReplyUrls:
data:    AvailableToOtherTenants:  False
info:    ad app create command OK

使用在这里生成的,现在我们将创建服务主体。在Active Directory中,可以进行身份验证的实体均表示为主体。用户和应用程序也是主体。为了使应用程序可以访问目标服务,将使用服务主体。我们将创建一个适用于Terraform的服务主体,以访问Azure。我们将使用之前注册应用程序时获取到的应用程序ID。现在服务主体已经创建完成。

> azure ad sp create <Some AppId>
info:    Executing command ad sp create
+ Creating service principal for application <Some AppId>
data:    Object Id:               <Some Principle Object Id>
data:    Display Name:            My Terraform
data:    Service Principal Names:
data:                             <Some AppId>
data:                             http://simplearchitect.hatenablog.com/
info:    ad sp create command OK

通过这样做,已经创建了用于访问Azure的服务主体。接下来,为了设置权限,将分配角色。
在这里,我们给予了对Azure订阅的Contributor权限。请在中填写您的Azure订阅。顺便一提,您可以通过Azure CLI的”azure account list”命令查找到您当前使用的订阅ID。

> azure role assignment create --objectId <Some Principle Object Id> -o Contributor -c /subscriptions/<Your Subscription Id>  
info:    Executing command role assignment create
+ Finding role with specified name
-data:    RoleAssignmentId     : /subscriptions/<Your subscription Id>/providers/Microsoft.Authorization/roleAssignments/<Your role assignment Id>
data:    RoleDefinitionName   : Contributor
data:    RoleDefinitionId     : <Your role defininition Id>
data:    Scope                : /subscriptions/<Your subscription Id>
data:    Display Name         : My Terraform
data:    SignInName           :
data:    ObjectId             : <Some Principle Object Id>
data:    ObjectType           : ServicePrincipal
data:
+
info:    role assignment create command OK

完成设置后,请执行以下命令以获取所需的tenant_id。之后,TenantId将显示在您的订阅ID位置上。租户是指拥有某物的人。

> azure  account list --json
[
  {
    "id": "<Your subsctiption Id>",
    "name": "<Your subsctiption name>",
    "user": {
      "name": "<Your e-mail address>",
      "type": "user"
    },
    "tenantId": "<Your tenantId>",
    "state": "Enabled",
    "isDefault": true,
    "registeredProviders": [],
    "environmentName": "AzureCloud"
  }
   :

3. 创建Terraform配置文件

接下来,我们要创建Terraform的配置文件,也就是所谓的基础设施即代码。

我已经在Gist上上传了整个代码。Azure ARM模板的Terraform配置文件(链接:https://gist.github.com/TsuyoshiUshio/6abf201db0ab23dde83acd0c86636b12)。

将此文件保存为 terraform.tf 或类似的名称。然后创建一个名为 terraform.tfvar 的文件,内容如下。

顺便提一下,client_secret 是在创建2.2版的Azure AD应用程序时指定的密码。而在这种情况下是指Ubuntu,这是sudo用户的默认名称。密码也是一样的噢。

terraform.tfvars 地貌配置文件

default_user = "<OS User Name>"
default_password = "<OS User password>"
subscription_id = "<Your subscription Id>"
client_id       = "<Some AppId>"
client_secret   = "<Your Password>"
tenant_id       = "<Your tenantId>"

我认为,如果阅读AZURERM_VIRTUAL_MACHINE附近的内容,就可以理解terraform.tf文件的说明。实际上,它与Azure Resource Manager是一样的,因此如果先对Azure Resource Manager有一定的了解,理解会更加深入。

作为Azure资源管理器的解释,我最喜欢的是安纳先生博客中的这篇文章,因为它非常易懂。

创建资源模板-超基础编。

4. 使用Terraform进行配置管理

请确认.tf文件和.tfvars文件都已准备就绪。请注意,tfvars文件名必须为terraform.tfvars。

>dir
 :
2016/04/30  12:41               667 terraform.tf
2016/04/30  12:40                58 terraform.tfvars

使用`terraform plan`命令将创建terraform执行计划,显示了构建此基础架构的信息。执行命令后,将创建一个名为`terraform.tfstate`的文件。

> terraform plan

在实际进行配置之后,只要执行terraform apply命令,就会在Azure上创建一个安装了Chef的Ubuntu虚拟机。值得一提的是,如果想要连续进行配置,请参考以下的提示。由于存在一些容易出错的地方,我已经整理好了。

> terraform apply
 :
azurerm_virtual_machine.test (remote-exec): Thank you for installing Chef!
azurerm_virtual_machine.test: Creation complete

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

C:\Users\tsushi\Codes\Terraform>

5. 使用Azure ARM进行Terraform的技巧

我会给你一些关于使用 Azure ARM 进行 Terraform 的提示。还有一些需要注意的地方,请小心。

5.1. 如果需要进行两次或更多次的配置,可以更改存储账户的名称。

这是一个非常关键的问题。如果想要尝试不同的Terraform配置,并且需要多次进行预配时,一旦删除资源组并重新执行terraform apply,就不能再创建存储账户了。会出现这样的提示并无法继续。

azurerm_storage_account.test: Still creating... (10s elapsed)
azurerm_storage_account.test: Still creating... (20s elapsed)
azurerm_storage_account.test: Still creating... (30s elapsed)
azurerm_storage_account.test: Still creating... (40s elapsed)
azurerm_storage_account.test: Still creating... (51s elapsed)
azurerm_storage_account.test: Still creating... (1m1s elapsed)
azurerm_storage_account.test: Still creating... (1m11s elapsed)
azurerm_storage_account.test: Still creating... (1m21s elapsed)
azurerm_storage_account.test: Still creating... (1m31s elapsed)
azurerm_storage_account.test: Still creating... (1m41s elapsed)
azurerm_storage_account.test: Still creating... (1m51s elapsed)
   : 

我只需要一个选项:

这可能只是个猜测,但在ARM时代,存储帐户名称似乎不能在资源组级别重复,而是在Azure中应该是唯一的。

并且,一旦删除了它,这个名字看起来会持续一段时间。(可能之后会批量删除)因此,有些情况下,删除的存储账户在第二天可能会被使用,有些情况下可能不能使用……是这样的感觉(根据我的实验)。所以,如果想要删除并重新创建存储账户的话,最好将其改成一个不同的名字。

因此,我认为 Azure Resource Manager 的模板中使用了名为 uniqueString 的函数来定义存储帐户的名称,这已经成为标准做法。关于这个问题,我已将其报告给了 Terraform 的 GitHub Issue。

第二次创建Azure ARM存储账户失败 #6412

这个问题师傅也给出了评论,我来分享一下!

@tmak_tw 不过当我试着用destroy时,似乎不起作用。可能是有什么不同吧。—TsuyoshiUshio (@sandayuu) 2016年4月30日

当Terraform命令无法正常运行时,您可以删除terraform.tfstate文件和备份。

在执行terraform命令时可能会出现无法正常运行的情况。这可能是由于ARM供应商功能尚不完善所致。
但是,在这种情况下,只需删除terraform plan和terraform apply能够创建的以下文件,它将恢复正常运行。

2016/04/30  12:13            12,268 terraform.tfstate
2016/04/30  12:11               197 terraform.tfstate.backup

5.3. 在创建虚拟机时,无法访问虚拟机的资源。

就Virtual Machine资源而言,希望在os_profile和connection的部分同时指定相同的用户和密码。最初尝试通过在connection部分使用类似`${self.os_profile.*.admin_password}`的方式共享数据,但无法成功。可能是因为虚拟机在创建完成之后才能进行此类引用,而在当前阶段中虚拟机正在创建过程中,所以这些值无法被引用。因此,在接下来的部分中将使用var机制来进行描述,可以让代码更加清晰明了。

resource "azurerm_virtual_machine" "test" {
    name = "TerraformVM01"
    location = "Japan East"
    resource_group_name = "${azurerm_resource_group.test.name}"
    network_interface_ids = ["${azurerm_network_interface.test.id}"]
    vm_size = "Standard_A0"

    storage_image_reference {
    publisher = "Canonical"
    offer = "UbuntuServer"
    sku = "14.04.2-LTS"
    version = "latest"
    }

    storage_os_disk {
        name = "myosdisk1"
        vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd"
        caching = "ReadWrite"
        create_option = "FromImage"
    }

    os_profile {
    computer_name = "TerraformTest"
    admin_username = "${var.default_user}"
    admin_password = "${var.default_password}"
    }

    os_profile_linux_config {
    disable_password_authentication = false
    }

    provisioner "remote-exec" {
    connection {
        type = "ssh"
        user = "${var.default_user}"
        password = "${var.default_password}"
        host = "${azurerm_public_ip.test.ip_address}"
    }
      inline = [
      "sudo sh -c 'curl -L https://omnitruck.chef.io/install.sh | bash'"
      ]
    }
}

5.4. 集中管理订阅和密码,并进行外部处理。

密码和订阅之类的信息,我们都不想将其写在公开的文件中对吧?在这种情况下,使用下面的variables机制会很方便。
外部文件的名称应固定为terraform.tfvars,请不要更改为其他名称!tf文件可以使用不同的名称。

以下是terraform.tf的定义和使用示例。顺便提一下,如果没有准备terraform.tfvars文件,则会在执行terraform plan命令时需要输入参数。

variable "default_user" {}
variable "default_password" {}
variable "subscription_id" {}
variable "client_id" {}
variable "client_secret" {}
variable "tenant_id" {}

provider "azurerm" {
  subscription_id = "${var.subscription_id}"
  client_id       = "${var.client_id}"
  client_secret   = "${var.client_secret}"
  tenant_id       = "${var.tenant_id}"
}

terraform.tfvars 可以进行翻译为:terraform设置变量.tfvars

default_user = "<OS User Name>"
default_password = "<OS User password>"
subscription_id = "<Your subscription Id>"
client_id       = "<Some AppId>"
client_secret   = "<Your Password>"
tenant_id       = "<Your tenantId>"

5.5. 如果在虚拟机启动后想要进行一些配置,可以使用远程执行等方法。

以下是关于此部分的内容。这个命令是远程执行shell命令的方式。在这个例子中,我们使用一行命令来安装chef。还有其他各种不同的配置管理工具,请参考。

提供者

    provisioner "remote-exec" {
    connection {
        type = "ssh"
        user = "${var.default_user}"
        password = "${var.default_password}"
        host = "${azurerm_public_ip.test.ip_address}"
    }
      inline = [
      "sudo sh -c 'curl -L https://omnitruck.chef.io/install.sh | bash'"
      ]
    }

在控制台的黑色间隙中实际上隐藏着文字。

当执行terraform apply命令并查看命令提示符时,会呈现出如下的样式。奇怪的是,显示的行之间存在间隔。

2016-04-30 (3).png

如果将此间隔部分复制并粘贴,实际上会输出一些字符,只是因为它们是看不见的黑色。

azurerm_virtual_machine.test: Creating...
  availability_set_id:                                                "" => "<computed>"
  license_type:                                                       "" => "<computed>"
  location:                                                           "" => "japanwest"
  name:                                                               "" => "TerraformVM01w"
  network_interface_ids.#:                                            "" => "1"
  network_interface_ids.3726743223:                                   "" => "/subscriptions/<Your subscription id and more>"
  os_profile.#:                                                       "" => "1"
  os_profile.3526563767.admin_password:                               "" => "<Your password>"
  os_profile.3526563767.admin_username:                               "" => "azureuser"
  os_profile.3526563767.computer_name:                                "" => "TerraformTestw"
  os_profile.3526563767.custom_data:                                  "" => "<computed>"
  os_profile_linux_config.#:                                          "" => "1"
  os_profile_linux_config.2972667452.disable_password_authentication: "" => "0"
  os_profile_linux_config.2972667452.ssh_keys.#:                      "" => "0"
  plan.#:                                                             "" => "<computed>"

补充:我的HashiCorp导师已经评论了。

在Windows的终端中运行terraform命令时,建议使用”-no-color”选项。

使用Visual Studio Code来编辑tf文件非常方便。

最近我非常喜欢使用Visual Studio Code。作为一名同时使用Mac和Windows的开发者,能运行在两个平台上让我非常开心。此外,它不仅轻便,还可以保存代码。实际上,在使用它编写tf文件时,它能给我提供自动补全功能,非常方便。:)

hokan.png

最后

这次我尝试使用Terraform的Azure Resource Manager提供程序来启动虚拟机并进行一些供应的用例。虽然资源仍然有限的问题,但DSL写起来很容易,而且还可以部署ARM模板,感觉相当不错。

目前来看,如果只使用Azure,我认为在方便性方面,Azure资源管理器模板是首选。但我认为它将越来越便捷,所以需要关注。此外,在Windows、Mac和Linux上都能稳定运行,这真是太棒了!

这就是以上的内容。祝大家愉快地体验HashiCorp与Azure的生活。

bannerAds