一,引言

  我们都知道在执行部署计划之后,当前目录中就产生了名叫 “” 的 Terraform 的状态文件,该文件中记录了已部署资源的状态。默认情况下,在执行部署计划后,Terraform 的状态文件会存储在本地,但是这样往往就造成一些弊端:

(1)不适用团队之间协助,就好比在数据库中对同一条数据进行操作时,就会引起异常

(2)状态文件中包含一些机密信息,会造成一定的机密泄露

(3)如果不慎将本地的状态文件删除掉的话,已执行部署计划的资源的管理将很难在通过 Terraform 进行管理

所以,Terraform 是支持在远端存储状态文件,也就是在 Azure Storage Account 中存储远端状态文件,Terraform 状态的存储是由一个称之为Backend的组件决定的,local state使用的是local backend。并且其他所有的Backend在使用之前都需要在模板中显式定义并通过 terraform init 来实现加载和配置。

二,正文

1,创建状态文件存储账户

转到Azure Portal 上,点击 “+ Create a resource”,输入 “Storage account“ 进行搜索,并且点击 ”create“

输入以下参数:

Resource group 选择:”Web_Test_TF_RG“

Storage account name:”cnbateterraformstorage“

Location:”(Asia Pacific) East Asia“

Performance:”Standard“

Account kind (账户类型)选择:”BlobStorage“

Replication (复制)选择:”Locally-redundant storage(LRS)“ (本地冗余存储(LRS))

点击 ”Review + create“ 进行创建预校验

校验完成后,点击 ”Create“ 进行创建操作

稍等片刻,等待创建完成后,点击 ”go to resource“ 跳转到资源可以查看创建的资源。

选择 “Blog service =》Containers”,点击页面上的 “+ Container” 添加存储状态文件的 Container

Name:"terraform-state"

Public access level:“Private(no anonymous access)”

点击 “Create” 进行创建。

可以看到刚刚创建容器

复制存储账户的访问密钥,稍后会有用

2,创建 Azure Key Vault(密钥保管库)

回到 Azure Portal 首页,点击 ”+ create a resource“,输入”Key Vault“ 进行搜索,点击 ”Create“ 创建

输入相关参数:

Resource group 选择:”Web_Test_TF_RG“

Key vault name:”cnbate-terraform-kv“

Region:”East Asia“

Pricing tier:”Standard“

点击 ”Review + create“ ,创建预校验。

预校验完成后,点击 ”Create“ 进行创建操作

创建完成后,可以点击 ”Go to resource“ 查看创建好的资源

选择 “Settings=》Secrets”,点击 “+ Generate/Import” 创建、或者导入机密信息

Upload options:“Manual”(手动)

Name:“terraform-stste-storage-key”

Value:复制粘贴刚刚的存储账户访问密钥

创建成功,并且可以查看到刚刚创建的机密信息

3,配置 Terraform 后端,并且测试远程 tf 状态

Terraform 需要配置后端,需要以下参数

(1)storage_account_name :Azure 存储账户名称

terraform init -backend-config="access_key=$(az keyvault secret show --name terraform-stste-storage-key --vault-name cnbate-terraform-kv --query value -o tsv)"

(2)container_name:容器名称

(3)key:存储状态文件的名称

(4)access_key:存储账户访问密钥

大家需要注意的是,我这里将 “access_key” 也就是存储账户访问密钥存放在 Azure Key Vault 中了,想要获取 “access_key” 就得通过 Azure Key Vault 获取。

以下是 Terraform 后端配置

terraform {
backend "azurerm" {
storage_account_name = "cnbateterraformstorage"
container_name = "terraform-state"
key = "cnbate.terraform.stats"
}
}

3.1,初始化 Terraform 代码

既然我们没有在 Terraform 后端配置代码块中添加 “access_key” 的信息,那么我们就得在初始化的时候对 ”access_key“ 信息赋值

terraform init -backend-config="access_key=$(az keyvault secret show --name terraform-stste-storage-key --vault-name cnbate-terraform-kv --query value -o tsv)"

然后,我们可以看到执行初始化命令之后的日志输出

同时会在存储账户的容器中生成 Blob 块

并且可以看到当前blob 块的详细信息

LEASE STATUS:解锁状态

LEASE STATE:可用状态

3.2,生成执行计划

terraform plan

以下是执行后输入的日志信息

从中不难看到,在生成执行计划之前,先获取状态锁。(注意,生成执行计划。不会将该执行计划持久化到远程状态存储)

PS D:\Core\Terraform\Azure\terraform_cnbate_traffic manager> terraform plan
Acquiring state lock. This may take a few moments...
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage. data.azurerm_resource_group.cnbate_resource_group: Refreshing state... ------------------------------------------------------------------------ An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create Terraform will perform the following actions: # azurerm_app_service.cnbate_app_service01 will be created
+ resource "azurerm_app_service" "cnbate_app_service01" {
+ app_service_plan_id = (known after apply)
+ app_settings = {
+ "ASPNETCORE_ENVIRONMENT" = "Production"
}
+ client_affinity_enabled = false
+ client_cert_enabled = false
+ custom_domain_verification_id = (known after apply)
+ default_site_hostname = (known after apply)
+ enabled = true
+ https_only = false
+ id = (known after apply)
+ location = "eastasia"
+ name = "CnBateBlogWeb01"
+ outbound_ip_address_list = (known after apply)
+ outbound_ip_addresses = (known after apply)
+ possible_outbound_ip_address_list = (known after apply)
+ possible_outbound_ip_addresses = (known after apply)
+ resource_group_name = "Web_Test_TF_RG"
+ site_credential = (known after apply) + auth_settings {
+ additional_login_params = (known after apply)
+ allowed_external_redirect_urls = (known after apply)
+ default_provider = (known after apply)
+ enabled = (known after apply)
+ issuer = (known after apply)
+ runtime_version = (known after apply)
+ token_refresh_extension_hours = (known after apply)
+ token_store_enabled = (known after apply)
+ unauthenticated_client_action = (known after apply) + active_directory {
+ allowed_audiences = (known after apply)
+ client_id = (known after apply)
+ client_secret = (sensitive value)
} + facebook {
+ app_id = (known after apply)
+ app_secret = (sensitive value)
+ oauth_scopes = (known after apply)
} + google {
+ client_id = (known after apply)
+ client_secret = (sensitive value)
+ oauth_scopes = (known after apply)
} + microsoft {
+ client_id = (known after apply)
+ client_secret = (sensitive value)
+ oauth_scopes = (known after apply)
} + twitter {
+ consumer_key = (known after apply)
+ consumer_secret = (sensitive value)
}
} + connection_string {
+ name = (known after apply)
+ type = (known after apply)
+ value = (sensitive value)
} + identity {
+ identity_ids = (known after apply)
+ principal_id = (known after apply)
+ tenant_id = (known after apply)
+ type = (known after apply)
} + logs {
+ detailed_error_messages_enabled = (known after apply)
+ failed_request_tracing_enabled = (known after apply) + application_logs {
+ file_system_level = (known after apply) + azure_blob_storage {
+ level = (known after apply)
+ retention_in_days = (known after apply)
+ sas_url = (sensitive value)
}
} + http_logs {
+ azure_blob_storage {
+ retention_in_days = (known after apply)
+ sas_url = (sensitive value)
} + file_system {
+ retention_in_days = (known after apply)
+ retention_in_mb = (known after apply)
}
}
} + site_config {
+ always_on = (known after apply)
+ app_command_line = (known after apply)
+ auto_swap_slot_name = (known after apply)
+ default_documents = (known after apply)
+ dotnet_framework_version = (known after apply)
+ ftps_state = (known after apply)
+ health_check_path = (known after apply)
+ http2_enabled = (known after apply)
+ ip_restriction = (known after apply)
+ java_container = (known after apply)
+ java_container_version = (known after apply)
+ java_version = (known after apply)
+ linux_fx_version = (known after apply)
+ local_mysql_enabled = (known after apply)
+ managed_pipeline_mode = (known after apply)
+ min_tls_version = (known after apply)
+ php_version = (known after apply)
+ python_version = (known after apply)
+ remote_debugging_enabled = (known after apply)
+ remote_debugging_version = (known after apply)
+ scm_ip_restriction = (known after apply)
+ scm_type = (known after apply)
+ scm_use_main_ip_restriction = (known after apply)
+ use_32_bit_worker_process = (known after apply)
+ websockets_enabled = (known after apply)
+ windows_fx_version = (known after apply) + cors {
+ allowed_origins = (known after apply)
+ support_credentials = (known after apply)
}
} + source_control {
+ branch = (known after apply)
+ manual_integration = (known after apply)
+ repo_url = (known after apply)
+ rollback_enabled = (known after apply)
+ use_mercurial = (known after apply)
} + storage_account {
+ access_key = (sensitive value)
+ account_name = (known after apply)
+ mount_path = (known after apply)
+ name = (known after apply)
+ share_name = (known after apply)
+ type = (known after apply)
}
} # azurerm_app_service.cnbate_app_service02 will be created
+ resource "azurerm_app_service" "cnbate_app_service02" {
+ app_service_plan_id = (known after apply)
+ app_settings = {
+ "ASPNETCORE_ENVIRONMENT" = "Production"
}
+ client_affinity_enabled = false
+ client_cert_enabled = false
+ custom_domain_verification_id = (known after apply)
+ default_site_hostname = (known after apply)
+ enabled = true
+ https_only = false
+ id = (known after apply)
+ location = "southeastasia"
+ name = "CnBateBlogWeb02"
+ outbound_ip_address_list = (known after apply)
+ outbound_ip_addresses = (known after apply)
+ possible_outbound_ip_address_list = (known after apply)
+ possible_outbound_ip_addresses = (known after apply)
+ resource_group_name = "Web_Test_TF_RG"
+ site_credential = (known after apply) + auth_settings {
+ additional_login_params = (known after apply)
+ allowed_external_redirect_urls = (known after apply)
+ default_provider = (known after apply)
+ enabled = (known after apply)
+ issuer = (known after apply)
+ runtime_version = (known after apply)
+ token_refresh_extension_hours = (known after apply)
+ token_store_enabled = (known after apply)
+ unauthenticated_client_action = (known after apply) + active_directory {
+ allowed_audiences = (known after apply)
+ client_id = (known after apply)
+ client_secret = (sensitive value)
} + facebook {
+ app_id = (known after apply)
+ app_secret = (sensitive value)
+ oauth_scopes = (known after apply)
} + google {
+ client_id = (known after apply)
+ client_secret = (sensitive value)
+ oauth_scopes = (known after apply)
} + microsoft {
+ client_id = (known after apply)
+ client_secret = (sensitive value)
+ oauth_scopes = (known after apply)
} + twitter {
+ consumer_key = (known after apply)
+ consumer_secret = (sensitive value)
}
} + connection_string {
+ name = (known after apply)
+ type = (known after apply)
+ value = (sensitive value)
} + identity {
+ identity_ids = (known after apply)
+ principal_id = (known after apply)
+ tenant_id = (known after apply)
+ type = (known after apply)
} + logs {
+ detailed_error_messages_enabled = (known after apply)
+ failed_request_tracing_enabled = (known after apply) + application_logs {
+ file_system_level = (known after apply) + azure_blob_storage {
+ level = (known after apply)
+ retention_in_days = (known after apply)
+ sas_url = (sensitive value)
}
} + http_logs {
+ azure_blob_storage {
+ retention_in_days = (known after apply)
+ sas_url = (sensitive value)
} + file_system {
+ retention_in_days = (known after apply)
+ retention_in_mb = (known after apply)
}
}
} + site_config {
+ always_on = (known after apply)
+ app_command_line = (known after apply)
+ auto_swap_slot_name = (known after apply)
+ default_documents = (known after apply)
+ dotnet_framework_version = (known after apply)
+ ftps_state = (known after apply)
+ health_check_path = (known after apply)
+ http2_enabled = (known after apply)
+ ip_restriction = (known after apply)
+ java_container = (known after apply)
+ java_container_version = (known after apply)
+ java_version = (known after apply)
+ linux_fx_version = (known after apply)
+ local_mysql_enabled = (known after apply)
+ managed_pipeline_mode = (known after apply)
+ min_tls_version = (known after apply)
+ php_version = (known after apply)
+ python_version = (known after apply)
+ remote_debugging_enabled = (known after apply)
+ remote_debugging_version = (known after apply)
+ scm_ip_restriction = (known after apply)
+ scm_type = (known after apply)
+ scm_use_main_ip_restriction = (known after apply)
+ use_32_bit_worker_process = (known after apply)
+ websockets_enabled = (known after apply)
+ windows_fx_version = (known after apply) + cors {
+ allowed_origins = (known after apply)
+ support_credentials = (known after apply)
}
} + source_control {
+ branch = (known after apply)
+ manual_integration = (known after apply)
+ repo_url = (known after apply)
+ rollback_enabled = (known after apply)
+ use_mercurial = (known after apply)
} + storage_account {
+ access_key = (sensitive value)
+ account_name = (known after apply)
+ mount_path = (known after apply)
+ name = (known after apply)
+ share_name = (known after apply)
+ type = (known after apply)
}
} # azurerm_app_service_plan.cnbate_app_service_plan01 will be created
+ resource "azurerm_app_service_plan" "cnbate_app_service_plan01" {
+ id = (known after apply)
+ kind = "Windows"
+ location = "eastasia"
+ maximum_elastic_worker_count = (known after apply)
+ maximum_number_of_workers = (known after apply)
+ name = "cnbate_appserviceplan01"
+ resource_group_name = "Web_Test_TF_RG" + sku {
+ capacity = (known after apply)
+ size = "S1"
+ tier = "Standard"
}
} # azurerm_app_service_plan.cnbate_app_service_plan02 will be created
+ resource "azurerm_app_service_plan" "cnbate_app_service_plan02" {
+ id = (known after apply)
+ kind = "Windows"
+ location = "southeastasia"
+ maximum_elastic_worker_count = (known after apply)
+ maximum_number_of_workers = (known after apply)
+ name = "cnbate_appserviceplan02"
+ resource_group_name = "Web_Test_TF_RG" + sku {
+ capacity = (known after apply)
+ size = "S1"
+ tier = "Standard"
}
} # azurerm_traffic_manager_endpoint.cnbate_traffic_manager_endpoint01 will be created
+ resource "azurerm_traffic_manager_endpoint" "cnbate_traffic_manager_endpoint01" {
+ endpoint_location = (known after apply)
+ endpoint_monitor_status = (known after apply)
+ endpoint_status = (known after apply)
+ geo_mappings = [
+ "CN",
]
+ id = (known after apply)
+ name = "cnbateblogweb_webapp01_performance"
+ priority = (known after apply)
+ profile_name = "cnbateblogweb"
+ resource_group_name = "Web_Test_TF_RG"
+ target = (known after apply)
+ target_resource_id = (known after apply)
+ type = "azureEndpoints"
+ weight = (known after apply)
} # azurerm_traffic_manager_endpoint.cnbate_traffic_manager_endpoint02 will be created
+ resource "azurerm_traffic_manager_endpoint" "cnbate_traffic_manager_endpoint02" {
+ endpoint_location = (known after apply)
+ endpoint_monitor_status = (known after apply)
+ endpoint_status = (known after apply)
+ geo_mappings = [
+ "SG",
]
+ id = (known after apply)
+ name = "cnbateblogweb_webapp02_performance"
+ priority = (known after apply)
+ profile_name = "cnbateblogweb"
+ resource_group_name = "Web_Test_TF_RG"
+ target = (known after apply)
+ target_resource_id = (known after apply)
+ type = "azureEndpoints"
+ weight = (known after apply)
} # azurerm_traffic_manager_profile.cnbate_traffic_manager_profile will be created
+ resource "azurerm_traffic_manager_profile" "cnbate_traffic_manager_profile" {
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "cnbateblogweb"
+ profile_status = (known after apply)
+ resource_group_name = "Web_Test_TF_RG"
+ tags = {
+ "Environment" = "Production"
}
+ traffic_routing_method = "Geographic" + dns_config {
+ relative_name = "cnbateblogweb"
+ ttl = 60
} + monitor_config {
+ interval_in_seconds = 30
+ path = "/"
+ port = 80
+ protocol = "http"
+ timeout_in_seconds = 10
+ tolerated_number_of_failures = 3
}
} Plan: 7 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run. PS D:\Core\Terraform\Azure\terraform_cnbate_traffic manager>

3.3,执行部署计划

terraform apply

以下是正在执行部署计划输入日志

同样,也是先获取状态锁

PS D:\Core\Terraform\Azure\terraform_cnbate_traffic manager> terraform plan
Acquiring state lock. This may take a few moments...
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage. data.azurerm_resource_group.cnbate_resource_group: Refreshing state...

在执行的过程中,我们再次登录Azure Portal 中,查看存储账容器中的 Blob 块的状态

LEASE STATUS:已锁定

LEASE STATE:已租用(其实可以理解为 “不可用”)

等待部署计划执行完毕之后,Blob 块的状态又恢复到 “已解锁,可用”

同时,点击图中的 “Edit” 可以看到由 terraform 管理的各自资源状态信息全部写到了当前 Blob 块中

ok,今天的内容就先到此。重要提醒:大家做完测试后,别忘记执行 terraform destroy (销毁部署计划)

*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。φ(゜▽゜*)♪是

三,结尾

  将状态文件进行远端存到Azure Storage Account 中,Blob 中存储的数据会在保存前进行加密处理,并且一旦配置远端存储模式后,状态文件永远不会存储在本地,这样更加方面团队之间的协作。并且远端存储带来的好处是实现了与资源定义模板管理的解耦,可以让 Terraform 状态脱离本地磁盘而存储,提升了资源状态的安全性。

参考资料:Terraform 官方azurerm 文档

Terraform_Cnbate_Traffic_Manager github:https://github.com/yunqian44/Terraform_Cnbate_Traffic_Manager

作者:Allen

版权:转载请在文章明显位置注明作者及出处。如发现错误,欢迎批评指正。

Azure Terraform(四)状态文件存储的更多相关文章

  1. Azure Terraform(七)利用Azure DevOps 实现自动化部署基础资源(补充)

    一,引言 之前一篇文章有讲解到利用 利用Azure DevOps 实现自动化部署基础资源,当时 TF 代码没有针对 Azure 各个资源的封装,所有的资源代码全部写在一个 main.tf 文件中.然后 ...

  2. Azure Terraform(五)利用Azure DevOps 实现自动化部署基础资源

    一,引言 上一篇我们结合学习 Azure Traffic Manger 的内容,做了一个负载均衡的基础设施架构.通过 Terraform 部署执行计划,将整个 Azure Traffic Manage ...

  3. Azure Terraform(六)Common Module

    一,引言 之前我们在使用 Terraform 构筑一下 Azure 云资源的时候,直接将所以需要创建的资源全面写在 main.tf 这个文件中,这样写主要是为了演示使用,但是在实际的 Terrafor ...

  4. Azure Terraform(八)利用Azure DevOps 实现Infra资源和.NET CORE Web 应用程序的持续集成、持续部署

    一,引言 上一篇讲解到利用 Azure DevOps 将整个 Azure Web App,Azure Traffic Manager profile,Azure Storage Account,Azu ...

  5. Azure Terraform(九)利用 Azure DevOps Pipeline 的审批来控制流程发布

    一,引言 Azure Pipeline 管道是一个自动化过程:但是往往我们由于某种原因,需要在多个阶段之前获得批准之后再继续下一步流程,所以我们可以向Azure Pipeline 管道添加审批!批准流 ...

  6. Azure Terraform(十)利用 Azure DevOps 的条件语句选择发布环境

    一,引言 之前我讲过的所有的案例中,都是将整个Azure Resource 部署到同一个订阅下,没有做到灵活的在 Azure Pipeline 在运行前选择需要部署的环境.在实际的项目开发中,我们也会 ...

  7. Azure Terraform(十一)Azure DevOps Pipeline 内的动态临时变量的使用

    思路浅析 在我们分析的 Azure Terraform 系列文中有介绍到关于 Terraform 的状态文件远程存储的问题,我们在  Azure DevOps Pipeline 的 Task Job ...

  8. Azure Terraform(二)语法详解

    一,引言 上篇文章开始,我们简单介绍了以下通过基础设施管理工具----- Terraform,通过它来统一管理复杂的云基础设施资源.作为入门演示,使用Terraform 部署Azure 资源组的方式直 ...

  9. [ Android 五种数据存储方式之二 ] —— 文件存储数据

    关于文件存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的. 文件可用来存放大量数据,如文本.图片.音 ...

随机推荐

  1. Codeforces Edu Round 64 A-D

    A. Inscribed Figures 分类讨论打表即可. PS:这道题翻译有歧义. 这样稍微翻转一下,就可以是\(7\)个交点呀...(大概是我没看英文题干导致的惨案) #include < ...

  2. git使用-merge request开发操作步骤

    0. 如果当前不在develop分支,则切换到develop分支 git checkout develop 1. 获取develop分支最新代码 git pull 注意:这一步正常来说应该是一个Fas ...

  3. uni-app中组件的使用

    组件基本知识点: uniapp中:每个页面可以理解为一个单页面组件,这些单页面组件注册在pages.json里,在组件关系中可以看作父组件. 自定义可复用的组件,其结构与单页面组件类似,通常在需要的页 ...

  4. 前端js实现九宫格模式抽奖(多宫格抽奖)

    介绍: 前端九宫格是一种常见的抽奖方式,js实现如下,掌握其原理,不论多少宫格,都可以轻松应对.(代码可复制直接运行看效果). 该案例以四宫格入门,可扩展多宫格,奖品模块的布局可自由设置. <! ...

  5. JavaSE基础面试题

    1. Java语言有哪些特点(1)简单易学.有丰富的类库(2)面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高)(3)与平台无关性(JVM是Java跨平台使用的根本)(4)可靠安全(5)支 ...

  6. Linux相关介绍和安装

    目录 前言 第一章 linux介绍 1.1 linux简介 第二章 Linux起源 2.1 Unix的历史 2.2 Unix操作系统的革命 2.3 Linux系统的诞生 2.4 Linux系统的发展史 ...

  7. 推荐系统实践 0x0f AutoRec

    从这一篇开始,我们开始学习深度学习推荐模型,与传统的机器学习相比,深度学习模型的表达能力更强,并且更能够挖掘出数据中潜藏的模式.另外.深度学习模型结构也非常灵活,能够根据业务场景和数据结构进行调整.还 ...

  8. .net core WebAPI性能监控-MiniProfiler与Swagger集成

    ------------恢复内容开始------------ 安装Nuget Install-Package MiniProfiler.AspNetCore.Mvc Install-Package M ...

  9. 用Python实现童年的回忆:俄罗斯方块!别说还挺好玩

    在那个电子产品比较匮乏的年代,小游戏机

  10. webform中配置服务器控件的样式

    前台 Style <asp:Label ID="Label1" runat="server" Text="Label" Style=& ...