一,引言

  我们都知道在执行部署计划之后,当前目录中就产生了名叫 “” 的 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. CF1327F AND Segments

    链接 Description 要求构造满足下列条件的长度为 \(n\) 的序列 \(a\) 的个数: 每个数值域在 \([0, 2 ^ k)\) \(m\) 个限制条件 \(l, r, x\),需要满 ...

  2. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

  3. protobuf 协议浅析

    目录 Protobuf 协议浅析 1. Protobuf 介绍 1.1 Protobuf 基本概念 1.2 Protobuf 的优点 1.3 Protobuf, JSON, XML 的区别 2. Pr ...

  4. (原创)nginx反向代理上网,使docker可以拉取镜像

    转载请注明出处:饭饭博客:https://www.cnblogs.com/zzf0305/p/9602107.html 摘语:参考了N多大侠的资料,终于将自己的环境配置起来了.站在众多巨人的肩膀进行总 ...

  5. Docker安装rocketmq踩坑指南

    Docker 网络 Docker容器运行的时候有host.bridge.none三种网络可供配置. 默认是bridge,即桥接网络,以桥接模式连接到宿主机:host是宿主网络,即与宿主机共用网络:no ...

  6. uni-app全局属性和方法

    全局变量和全局方法是软件开发中常用的技术点! 实现方式大致分为: 1.vuex实现,值变动灵活 2.建立js文件,页面内引用 3.挂载vue实例后使用 4.小程序中的globalData 5.本地存储 ...

  7. vs2015常用快捷键大全

    1.回到上一个光标位置/前进到下一个光标位置 1)回到上一个光标位置:使用组合键"Ctrl + -"; 2)前进到下一个光标位置:"Ctrl + Shift + - &q ...

  8. antDesign中排序sorter的坑

    antd中sorter是写在columns中的一个配置,结果为一个回调函数 如图,这是我项目中使用sorter的小例子,参数a,b分别为列表第0项数据和第1项数据.回调函数中return一个值,按照什 ...

  9. Spark-1-调优基本原则

    1基本概念和原则 每一台host上面可以并行N个worker,每一个worker下面可以并行M个executor,task们会被分配到executor上面去执行.Stage指的是一组并行运行的task ...

  10. 多任务-python实现-继承Thread类,单独编写一个类(2.1.2)

    @ 目录 1.thread类 1.thread类 threding代码实现 import threading import time class MyThread(threading.Thread): ...