一,引言

  我们都知道在执行部署计划之后,当前目录中就产生了名叫 “” 的 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. Springboot — 用更优雅的方式发HTTP请求:RestTemplate

    RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率. 我之前的HTTP开发是用ap ...

  2. Java集合源码分析(七)——TreeMap

    简介 TreeMap 是一个有序的key-value集合,它的内部是通过红黑树实现的. TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合. TreeMap ...

  3. stringbuilder和stringbuffer速度比较

    同样的代码,只改了类型,分别为stringbuilder和stringbuffer,只比较一下,执行引擎为hive. 当数据量为100000条,string builder耗时280秒,stringb ...

  4. gulp-sourcemaps的用法

    1.项目文件夹中,安装gulp-sourcemaps插件 npm install --save gulp-sourcemaps 2.gulpfile.js文件,导入要用到的插件. 如: // 引入gu ...

  5. C++异常之二 基本语法

    2. 异常处理的基本语法 下面是一个基本的代码例子,说明 throw.try.catch的基本用法,与 catch 的类型自动匹配: 1 #include <iostream> 2 #in ...

  6. 纯HTML + CSS制作个人资料卡

    总体预览: 材料:背景图与头像.jpg IDE:VS Code 外部链接:CDN加速的font-awesome图标 <link rel="stylesheet" href=& ...

  7. screw一键生成数据库文档

    1. 简介   在项目开发和交付阶段,数据库文档是必不可少的.对于大型项目多个数据库几百甚至几千张表来说,手写数据库文档必然是耗时且痛苦的.因此需要一个插件自动生成文档.   screw提供了多种文件 ...

  8. Kubernetes【K8S】(三):资源清单

    K8S中的资源 K8S中所有的内容都抽象为资源,资源实例化之后叫做对象.一般使用yaml格式的文件来创建符合我们预期的pod,这样的yaml文件我们一般成为资源清单. 名称空间级资源 工作负载型资源( ...

  9. CDH集群spark-shell执行过程分析

    目的 刚入门spark,安装的是CDH的版本,版本号spark-core_2.11-2.4.0-cdh6.2.1,部署了cdh客户端(非集群节点),本文主要以spark-shell为例子,对在cdh客 ...

  10. 容器编排系统之ReplicaSet和Deployment控制器

    前文我们了解了k8s上的Pod资源的生命周期.健康状态和就绪状态探测以及资源限制相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/14143610.htm ...