Bruce Blog Bruce Blog
首页
  • CentOS
  • Ubuntu-Debian
  • 系统网络
  • 系统辅助工具
  • MySQL
  • Redis
  • Mongodb
  • Docker基础
  • Container基础
  • Kubernetes

    • Kubernetes基础
    • Kubernetes辅助
  • Container-Network
  • Jenkins
  • Gitlab
  • ArgoCD
  • Ansible
  • Terraform
  • AWS
  • MQ
  • NGINX
  • JumpServer
  • 基础
  • 函数模块
  • 框架
  • 基础

    • Golang环境
    • 语法
    • 数据类型与运算符
    • 分支语句
    • 循环语句
    • 数组
    • 切片
    • Map
    • String
    • 函数
    • 包的管理
    • 指针
    • 结构体
    • Go语言中的OOP
    • 方法和接口
    • 错误处理
  • Go进阶

    • Go进阶
  • Go框架

    • Go框架
  • Golang辅助

    • Golang辅助
  • CSS
  • HTML
  • JavaScript
  • 前端辅助
  • 常用命令
  • 性能监控工具
  • Windows下Docker使用
  • 日常学习
  • 其他导航

Bruce Tao

运维界的该溜子
首页
  • CentOS
  • Ubuntu-Debian
  • 系统网络
  • 系统辅助工具
  • MySQL
  • Redis
  • Mongodb
  • Docker基础
  • Container基础
  • Kubernetes

    • Kubernetes基础
    • Kubernetes辅助
  • Container-Network
  • Jenkins
  • Gitlab
  • ArgoCD
  • Ansible
  • Terraform
  • AWS
  • MQ
  • NGINX
  • JumpServer
  • 基础
  • 函数模块
  • 框架
  • 基础

    • Golang环境
    • 语法
    • 数据类型与运算符
    • 分支语句
    • 循环语句
    • 数组
    • 切片
    • Map
    • String
    • 函数
    • 包的管理
    • 指针
    • 结构体
    • Go语言中的OOP
    • 方法和接口
    • 错误处理
  • Go进阶

    • Go进阶
  • Go框架

    • Go框架
  • Golang辅助

    • Golang辅助
  • CSS
  • HTML
  • JavaScript
  • 前端辅助
  • 常用命令
  • 性能监控工具
  • Windows下Docker使用
  • 日常学习
  • 其他导航
  • Ansible

  • Terraform

    • terraform命令使用
    • terraform概述
    • terraform基础
    • terraform语法
    • Backend配置
    • 阿里云实践
    • 腾讯云实践
    • 华为云实践
    • Docker实践
    • AWS实践
    • Terraform扩展
      • Azure实践
      • K8S实践
    • AWS

    • Cloud
    • Terraform
    Bruce
    2022-10-27
    目录

    Terraform扩展

    # 一、Terrform元参数

    # Meta-Arguments 元参数
    • count 创建相似的资源
    • for_each 创建相似的资源
    • depends_on 定义资源或者模块的依赖
    • provider 定义provider选项
    • lifecycle 资源的生命周期行为

    # 二、Count创建资源副本

    • count = num数值类型,可以通过length()计算数量
    • count.index 索引

    count适合没有区别的资源创建时候使用

    # 示例: 创建三条DNS记录
    • server1.chsaos.com
    • server2.chsaos.com
    • server3.chsaos.com
    locals {
    	zone = "chsaos.com"
    	records = ["server1","server2","server3"]
    }
    
    resource "alicloud_dns_record" "record" {
    	count = length{local.records}
    	name = local.zone
    	host_record = local.records[count.index]
    	type = "A"
    	value = "192.168.1.1"
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    项目目录"terraform-extend/count"

    $ cd terraform-extend/count
    $  tree ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 2 files
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 会发生事项?
    • 此时移除一条记录
    • 移除server2.chsaos.com
    • server2.chsaos.com销毁?
    $ vim main.tf
    locals {
      zone    = "chsaos.com"
      # records = ["server1", "server2", "server3"]
      records = ["server1", "server3"]
    }
    
    resource "alicloud_dns_record" "record" {
      count       = length(local.records)
      name        = local.zone
      host_record = local.records[count.index]
      type        = "A"
      value       = "192.168.1.1"
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 更新后发生的问题

    image-20220922130434195

    $ terraform plan
    alicloud_dns_record.record[2]: Refreshing state... [id=786406789912754176]
    alicloud_dns_record.record[0]: Refreshing state... [id=786406789925343232]
    alicloud_dns_record.record[1]: Refreshing state... [id=786406789923228672]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      ~ update in-place
      - destroy
    
    Terraform will perform the following actions:
    
      # alicloud_dns_record.record[1] will be updated in-place
      ~ resource "alicloud_dns_record" "record" {
          ~ host_record = "server2" -> "server3"
            id          = "786406789923228672"
            name        = "chsaos.com"
            # (7 unchanged attributes hidden)
        }
    
      # alicloud_dns_record.record[2] will be destroyed
      # (because index [2] is out of range for count)
      - resource "alicloud_dns_record" "record" {
          - host_record = "server3" -> null
          - id          = "786406789912754176" -> null
          - locked      = false -> null
          - name        = "chsaos.com" -> null
          - priority    = 0 -> null
          - routing     = "default" -> null
          - status      = "ENABLE" -> null
          - ttl         = 600 -> null
          - type        = "A" -> null
          - value       = "192.168.1.1" -> null
        }
    
    Plan: 0 to add, 1 to change, 1 to destroy.
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36

    # 三、for_each出国念资源副本

    • 可以过滤set类型和map类型

    • for_each = set(string) map(string)

    • 它能用于set(string) 或者map(string)

    • set(string)

    • each.key = each.value

    • map(string)

    • each.key = key

    • each.value = value

    $ vim main.tf
    locals {
      zone = "chsaos.com"
      records = ["server1", "server2", "server3"]
    
    }
    
    resource "alicloud_dns_record" "record" {
      for_each    = toset(local.records)
      name        = local.zone
      host_record = each.value
      type        = "A"
      value       = "192.168.1.1"
    }
    
    
    # 列表发生变化
    $ vim main.tf
    locals {
      zone    = "chsaos.com"
      # records = ["server1", "server2", "server3"]
      records = ["server1", "server3"]
    }
    
    resource "alicloud_dns_record" "record" {
      for_each    = toset(local.records)
      name        = local.zone
      host_record = each.value
      type        = "A"
      value       = "192.168.1.1"
    }
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    
    # 变更的结果(这里只是destroy了server2)
    $ terraform apply -auto-approve
    alicloud_dns_record.record["server2"]: Refreshing state... [id=786408864035945472]
    alicloud_dns_record.record["server1"]: Refreshing state... [id=786408864033819648]
    alicloud_dns_record.record["server3"]: Refreshing state... [id=786408864042206208]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
    symbols:
      - destroy
    
    Terraform will perform the following actions:
    
      # alicloud_dns_record.record["server2"] will be destroyed
      # (because key ["server2"] is not in for_each map)
      - resource "alicloud_dns_record" "record" {
          - host_record = "server2" -> null
          - id          = "786408864035945472" -> null
          - locked      = false -> null
          - name        = "chsaos.com" -> null
          - priority    = 0 -> null
          - routing     = "default" -> null
          - status      = "ENABLE" -> null
          - ttl         = 600 -> null
          - type        = "A" -> null
          - value       = "192.168.1.1" -> null
        }
    
    Plan: 0 to add, 0 to change, 1 to destroy.
    alicloud_dns_record.record["server2"]: Destroying... [id=786408864035945472]
    alicloud_dns_record.record["server2"]: Destruction complete after 0s
    
    Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79

    for_each适用于创建不相同的资源

    # 四、dynamic动态内联块

    • dynamic: 定义动态资源块,后面是label,默认为生成的语句块名称
    • for_each: 要进行迭代循环的对象(map、set、list)
    • iterator(迭代器): 临时的变量名称,如果未定义则使用label即"ports"
    • content: 要生成的语句块的内容部分

    image-20220922134401763

    示例:

    • terraform调用docker api创建container
    $ cd terraform-extend/dynamic
    $ vim main.tf
    provider "docker" {
      host = "tcp://172.31.228.152:2375"
    }
    
    resource "docker_image" "jenkins" {
      name         = "jenkins/jenkins:2.332.2-centos7-jdk8"
      keep_locally = true //销毁时不删除本地镜像
    }
    
    locals {
      jenkins_ports = [
        {
          internal = 8080
          external = 8080
        },
        {
          internal = 50000
          external = 50000
        }
      ]
    }
    
    resource "docker_container" "jenkins" {
      image = docker_image.jenkins.name
      name  = "jenkins123"
    
      dynamic "ports" {
        for_each = local.jenkins_ports
        content {
          internal = ports.value.internal
          external = ports.value.external
          ip       = "0.0.0.0"
          protocol = "tcp"
        }
      }
      #   ports {
      #     internal = 8080
      #     external = 8080
      #     ip = "0.0.0.0"
      #     protocol = "tcp"
      #   }
      #   ports {
      #     internal = 50000
      #     external = 50000
      #     ip = "0.0.0.0"
      #     protocol = "tcp"
      #   }
    
      user = "root"
      volumes {
        container_path = "/var/jenkins_home"
        host_path      = "/data/jenkins/jenkins_home"
      }
    }
    
    
    $ vim versions.tf
    terraform {
      required_providers {
        docker = {
          source  = "kreuzwerker/docker"
          version = "~> 2.13.0"
        }
      }
    }
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    $ terraform destroy 或 terraform destroy -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75

    # 五、depends_on依赖关系

    • 处理 资源或模块之间的依赖关系

    • 这里还是以上面使用的docker 创建container示例

    $ cd terraform-extend/dynamic
    $ vim main.tf
    # 在docker本机的话下面的docker API连接可以不用配置
    provider "docker" {
      host = "tcp://172.31.228.152:2375"
    }
    
    resource "docker_image" "jenkins" {
      name         = "jenkins/jenkins:2.332.2-centos7-jdk8"
      keep_locally = true //销毁时不删除本地镜像
    }
    
    locals {
      jenkins_ports = [
        {
          internal = 8080
          external = 8080
        },
        {
          internal = 50000
          external = 50000
        }
      ]
    }
    
    resource "docker_container" "jenkins" {
      image = docker_image.jenkins.name
      name  = "jenkins123"
    
      dynamic "ports" {
        for_each = local.jenkins_ports
        content {
          internal = ports.value.internal
          external = ports.value.external
          ip       = "0.0.0.0"
          protocol = "tcp"
        }
      }
      #   ports {
      #     internal = 8080
      #     external = 8080
      #     ip = "0.0.0.0"
      #     protocol = "tcp"
      #   }
      #   ports {
      #     internal = 50000
      #     external = 50000
      #     ip = "0.0.0.0"
      #     protocol = "tcp"
      #   }
    
      user = "root"
      volumes {
        container_path = "/var/jenkins_home"
        host_path      = "/data/jenkins/jenkins_home"
      }
    
      # 这里添加当前container依赖的资源为docker_image
      depends_on = [
        docker_image.jenkins
      ]
    }
    
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    $ terraform destroy 或 terraform destroy -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    # 六、provider自定义供应商

    # resource
    • 覆盖资源中的provider
    • 例如: 分别在cn-beijing和cn-shanghai区域分别创建1个实例
    provider "alicloud" {
    	alias = "north"
    	region = "cn-beijing"
    	access_key = "xxxxxx"
    	secret_key = "xxxxxx"
    }
    
    provider "alicloud" {
    	region = "cn-shanghai"
    	access_key = "xxxxxx"
    	secret_key = "xxxxxx"
    }
    
    resource "alicloud_instance" "ecs_demo_north" {
    	provider = alicloud north
    	......
    }
    
    resource "alicloud_instance" "ecs_demo" {
    	......
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    示例

    $ cd terraform-extend/provider
    $ tree .
    .
    ├── main.tf
    └── versions.tf
    
    0 directories, 2 files
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    • 控制台查看VPC创建结果

    image-20220922142944168

    image-20220922143004819

    # module
    • 默认子模块继承根模块provider
    • provider = map()
    • key: provider名称
    • value: .
    provider "alicloud" {
    	alias = "north"
    	region = "cn-beijing"
    }
    
    provider "alicloud" {
    	region = "cn-shanghai"
    }
    
    module "example" {
    	source = "./example"
    	provider = {
    		alicloud = alicloud north
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    示例

    这里依赖modules下面的vpc模块调用"terraform-extend/modules/vpc"

    $ cd terraform-extend/provider-module
    tree ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 2 files
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    # 七、生命周期

    # lifecycle
    • 标记资源不被删除或者销毁前创建新的资源
    • create_before_destroy 先创建新的对象,再销毁旧的对象
    • prevent_destroy 防止资源被销毁
    • ignore_changes 忽略资源的差异
    • replace_triggered_by 当指定的资源修改后替换当前资源
    • precondition postcondition 条件检查
    # 生命周期之销毁之前创建新资源

    示例

    $ cd terraform-extend/lifecycle/create_before_destroy
    $ tree  ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 4 files
    
    $ cat main.tf
    provider "alicloud" {
      region = "cn-shanghai"
    }
    
    locals {
      region = "cn-shanghai-a"
      # 这里的vsw所在区域为`cn-shanghai-a`
      vsw_id        = "vsw-uf6ct0jpe5ujmgh7my7np"
      secgroup_id   = "sg-uf6fy0y9i7j1t4dif549"
      instance_name = "myecsserver1"
      instance_type = "ecs.sn2ne.large"
    }
    
    data "alicloud_images" "images_ds" {
      owners       = "system"
      name_regex   = "^centos_7_9"
      architecture = "x86_64"
      status       = "Available"
      os_type      = "linux"
      # output_file  = "./outputs.json"
    }
    
    # output "image_id" {
    #   value = data.alicloud_images.images_ds.images[2].id
    # }
    
    resource "alicloud_instance" "myecs2" {
      availability_zone          = local.region
      security_groups            = [local.secgroup_id]
      instance_type              = local.instance_type
      system_disk_category       = "cloud_efficiency"
      system_disk_name           = "tf_system_disk_name"
      system_disk_description    = "tf_system_disk_description"
      image_id                   = data.alicloud_images.images_ds.images[2].id
      instance_name              = local.instance_name
      vswitch_id                 = local.vsw_id
      internet_max_bandwidth_out = 0
      internet_charge_type       = "PayByTraffic"
      password                   = "root@1234"
    
      # 开启先创建替换的资源,再去销毁需要被删除的资源
      lifecycle {
        create_before_destroy = true
      }
    }
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68

    注意

    • terraform默认的行为是,先销毁一个资源再去创建一个资源
    $ terraform plan
    ......
     # alicloud_instance.myecs4 will be destroyed
      # (because alicloud_instance.myecs4 is not in configuration)
      - resource "alicloud_instance" "myecs4" {
    	......
          - spot_price_limit                   = 0 -> null
          - spot_strategy                      = "NoSpot" -> null
          - status                             = "Running" -> null
          - subnet_id                          = "vsw-uf6ct0jpe5ujmgh7my7np" -> null
          - system_disk_category               = "cloud_efficiency" -> null
          - system_disk_description            = "tf_system_disk_description" -> null
          - system_disk_name                   = "tf_system_disk_name" -> null
          - system_disk_size                   = 40 -> null
          - tags                               = {
              - "env"   = "dev"
              - "owner" = "bruce"
            } -> null
          - volume_tags                        = {
              - "env"   = "dev"
              - "owner" = "bruce"
            } -> null
          - vswitch_id                         = "vsw-uf6ct0jpe5ujmgh7my7np" -> null
        }
    
    Plan: 1 to add, 0 to change, 1 to destroy.
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    • 加上"lifecycle"之后控制台查看目前正在创建一个新的资源来替换原有资源

    image-20220922154605495

    # 生命周期之销毁之避免销毁

    示例

    $ cd terraform-extend/lifecycle/create_before_destroy
    $ tree  ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 4 files
    
    $ cat main.tf
    provider "alicloud" {
      region = "cn-shanghai"
    }
    
    locals {
      region = "cn-shanghai-a"
      # 这里的vsw所在区域为`cn-shanghai-a`
      vsw_id        = "vsw-uf6ct0jpe5ujmgh7my7np"
      secgroup_id   = "sg-uf6fy0y9i7j1t4dif549"
      instance_name = "myecsserver1"
      instance_type = "ecs.sn2ne.large"
    }
    
    data "alicloud_images" "images_ds" {
      owners       = "system"
      name_regex   = "^centos_7_9"
      architecture = "x86_64"
      status       = "Available"
      os_type      = "linux"
      # output_file  = "./outputs.json"
    }
    
    # output "image_id" {
    #   value = data.alicloud_images.images_ds.images[2].id
    # }
    
    resource "alicloud_instance" "myecs2" {
      availability_zone          = local.region
      security_groups            = [local.secgroup_id]
      instance_type              = local.instance_type
      system_disk_category       = "cloud_efficiency"
      system_disk_name           = "tf_system_disk_name"
      system_disk_description    = "tf_system_disk_description"
      image_id                   = data.alicloud_images.images_ds.images[2].id
      instance_name              = local.instance_name
      vswitch_id                 = local.vsw_id
      internet_max_bandwidth_out = 0
      internet_charge_type       = "PayByTraffic"
      password                   = "root@1234"
    
      # 开启先创建替换的资源,再去销毁需要被删除的资源
      lifecycle {
        create_before_destroy = true
        # 开启防止销毁保护
        prevent_destroy       = true
      }
    }
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70

    注意:

    • 销毁时候的错误提示
    $ terraform destroy -auto-approve
    data.alicloud_images.images_ds: Reading...
    data.alicloud_images.images_ds: Read complete after 3s [id=1253956010]
    alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
    ╷
    │ Error: Instance cannot be destroyed
    │ 
    │   on main.tf line 34:
    │   34: resource "alicloud_instance" "myecs2" {
    │ 
    │ Resource alicloud_instance.myecs2 has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To
    │ avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the
    │ -target flag.
    ╵
    
    #  销毁提示生命周期中添加了防止销毁参数`lifecycle.prevent_destroy`
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 生命周期之忽略远程变更

    示例

    $ cd terraform-extend/lifecycle/create_before_destroy
    $ tree  ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 4 files
    
    $ cat main.tf
    provider "alicloud" {
      region = "cn-shanghai"
    }
    
    locals {
      region = "cn-shanghai-a"
      # 这里的vsw所在区域为`cn-shanghai-a`
      vsw_id        = "vsw-uf6ct0jpe5ujmgh7my7np"
      secgroup_id   = "sg-uf6fy0y9i7j1t4dif549"
      instance_name = "myecsserver1"
      instance_type = "ecs.sn2ne.large"
    }
    
    data "alicloud_images" "images_ds" {
      owners       = "system"
      name_regex   = "^centos_7_9"
      architecture = "x86_64"
      status       = "Available"
      os_type      = "linux"
      # output_file  = "./outputs.json"
    }
    
    # output "image_id" {
    #   value = data.alicloud_images.images_ds.images[2].id
    # }
    
    resource "alicloud_instance" "myecs2" {
      availability_zone          = local.region
      security_groups            = [local.secgroup_id]
      instance_type              = local.instance_type
      system_disk_category       = "cloud_efficiency"
      system_disk_name           = "tf_system_disk_name"
      system_disk_description    = "tf_system_disk_description"
      image_id                   = data.alicloud_images.images_ds.images[2].id
      instance_name              = local.instance_name
      vswitch_id                 = local.vsw_id
      internet_max_bandwidth_out = 0
      internet_charge_type       = "PayByTraffic"
      password                   = "root@1234"
    
    # 这里新增加了tags
      tags = {
        env   = "dev"
        owner = "bruce"
      }
    
      # 开启先创建替换的资源,再去销毁需要被删除的资源
      lifecycle {
        create_before_destroy = true
        # 开启防止销毁保护
        prevent_destroy       = true
      }
    }
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76

    注意:

    • 远程信息变更
    $ terraform apply -auto-approve
    data.alicloud_images.images_ds: Reading...
    data.alicloud_images.images_ds: Read complete after 2s [id=1253956010]
    alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
    symbols:
      ~ update in-place
    
    Terraform will perform the following actions:
    
      # alicloud_instance.myecs2 will be updated in-place
      ~ resource "alicloud_instance" "myecs2" {
            id                                 = "i-uf6gx7hn08wwq8v5vfeu"
          ~ tags                               = {
              + "env"   = "dev"
              + "owner" = "bruce"
            }
            # (26 unchanged attributes hidden)
        }
    
    Plan: 0 to add, 1 to change, 0 to destroy.
    alicloud_instance.myecs2: Modifying... [id=i-uf6gx7hn08wwq8v5vfeu]
    alicloud_instance.myecs2: Modifications complete after 1s [id=i-uf6gx7hn08wwq8v5vfeu]
    
    Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    image-20220922155834608

    • 控制台编辑了tags,导致tags发生了表更

      • 解决方法

        1.在terraform文件中注释被修改的地方

        2.在lifecycle中添加ignore_changes,在ignore_changes中如果有多个值的话用","做隔离

    $ rraform plan
    data.alicloud_images.images_ds: Reading...
    data.alicloud_images.images_ds: Read complete after 2s [id=1253956010]
    alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
    symbols:
      ~ update in-place
    
    Terraform will perform the following actions:
    
      # alicloud_instance.myecs2 will be updated in-place
      ~ resource "alicloud_instance" "myecs2" {
            id                                 = "i-uf6gx7hn08wwq8v5vfeu"
          ~ tags                               = {
              + "owner" = "bruce"
                # (1 unchanged element hidden)
            }
            # (26 unchanged attributes hidden)
        }
    
    Plan: 0 to add, 1 to change, 0 to destroy.
    
    $ vim main.tf
    ......
      lifecycle {
        ignore_changes = [
          tags,
          instance_name
        ]
      }
      
    # 这里再次查看没有任何变更信息
    $ terraform plan
    data.alicloud_images.images_ds: Reading...
    data.alicloud_images.images_ds: Read complete after 1s [id=1253956010]
    alicloud_instance.myecs2: Refreshing state... [id=i-uf6gx7hn08wwq8v5vfeu]
    
    No changes. Your infrastructure matches the configuration.
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39

    image-20220922160435153

    # 生命周期之触发资源替换
    • replace_triggered_by 当指定的资源修改后替换当前资源(此功能是在terraform 1.2.0后新增的)

    示例

    $ cd terraform-extend/lifecycle/create_before_destroy
    $ tree  ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 4 files
    
    $ cat main.tf
    provider "alicloud" {
      region = "cn-shanghai"
    }
    
    locals {
      region = "cn-shanghai-a"
      # 这里的vsw所在区域为`cn-shanghai-a`
      vsw_id        = "vsw-uf6ct0jpe5ujmgh7my7np"
      secgroup_id   = "sg-uf6fy0y9i7j1t4dif549"
      instance_name = "myecsserver1"
      instance_type = "ecs.sn2ne.large"
    }
    
    data "alicloud_images" "images_ds" {
      owners       = "system"
      name_regex   = "^centos_7_9"
      architecture = "x86_64"
      status       = "Available"
      os_type      = "linux"
      # output_file  = "./outputs.json"
    }
    
    # output "image_id" {
    #   value = data.alicloud_images.images_ds.images[2].id
    # }
    
    # 这里新增加了VPC
    resource "alicloud_vpc" "vpc" {
      vpc_name   = "myvpc"
      cidr_block = "172.20.0.0/16"
    }
    
    resource "alicloud_instance" "myecs2" {
      availability_zone          = local.region
      security_groups            = [local.secgroup_id]
      instance_type              = local.instance_type
      system_disk_category       = "cloud_efficiency"
      system_disk_name           = "tf_system_disk_name"
      system_disk_description    = "tf_system_disk_description"
      image_id                   = data.alicloud_images.images_ds.images[2].id
      instance_name              = local.instance_name
      vswitch_id                 = local.vsw_id
      internet_max_bandwidth_out = 0
      internet_charge_type       = "PayByTraffic"
      password                   = "root@1234"
    
        lifecycle {
          # 这里增加了替换的VPC资源
          replace_triggered_by = [
            alicloud_vpc.vpc.vpc_name
          ]
        }
    }
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    • 新增加VPC资源

    image-20220922162314276

    $ vim main.tf
    provider "alicloud" {
      region = "cn-shanghai"
    }
    
    locals {
      region = "cn-shanghai-a"
      # 这里的vsw所在区域为`cn-shanghai-a`
      vsw_id        = "vsw-uf6ct0jpe5ujmgh7my7np"
      secgroup_id   = "sg-uf6fy0y9i7j1t4dif549"
      instance_name = "myecsserver1"
      instance_type = "ecs.sn2ne.large"
    }
    
    data "alicloud_images" "images_ds" {
      owners       = "system"
      name_regex   = "^centos_7_9"
      architecture = "x86_64"
      status       = "Available"
      os_type      = "linux"
      # output_file  = "./outputs.json"
    }
    
    ......
    
        lifecycle {
          create_before_destroy = true
          # 这里增加了替换的VPC资源
          replace_triggered_by = [
            alicloud_vpc.vpc.vpc_name
          ]
        }
    }
    
    # 查看terraform执行计划
    $ terraform plan
    data.alicloud_images.images_ds: Reading...
    alicloud_vpc.vpc: Refreshing state... [id=vpc-uf62ypar80mrwhfoxuqw6]
    data.alicloud_images.images_ds: Read complete after 1s [id=1253956010]
    alicloud_instance.myecs2: Refreshing state... [id=i-uf6hcv5xjlfqccjdbjqy]
    
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
    symbols:
      ~ update in-place
    +/- create replacement and then destroy
    
    Terraform will perform the following actions:
    
      # alicloud_instance.myecs2 will be replaced due to changes in replace_triggered_by  # 这里被触发的替换提示
    +/- resource "alicloud_instance" "myecs2" {
          + credit_specification               = (known after apply)
          + deployment_set_group_no            = (known after apply)
          ~ host_name                          = "iZuf6hcv5xjlfqccjdbjqyZ" -> (known after apply)
          ~ id                                 = "i-uf6hcv5xjlfqccjdbjqy" -> (known after apply)
          - internet_charge_type               = "PayByTraffic" -> null
          ~ internet_max_bandwidth_in          = -1 -> (known after apply)
          + key_name                           = (known after apply)
          ~ private_ip                         = "172.19.17.55" -> (known after apply)
          + public_ip                          = (known after apply)
          + role_name                          = (known after apply)
          ~ secondary_private_ip_address_count = 0 -> (known after apply)
          ~ secondary_private_ips              = [] -> (known after apply)
          - spot_price_limit                   = 0 -> null
          ~ subnet_id                          = "vsw-uf6ct0jpe5ujmgh7my7np" -> (known after apply)
          + system_disk_performance_level      = (known after apply)
            tags                               = {
                "env"   = "dev"
                "owner" = "bruce"
            }
          ~ volume_tags                        = {
              - "env"   = "dev"
              - "owner" = "bruce"
            } -> (known after apply)
            # (17 unchanged attributes hidden)
        }
    
      # alicloud_vpc.vpc will be updated in-place
      ~ resource "alicloud_vpc" "vpc" {
            id                    = "vpc-uf62ypar80mrwhfoxuqw6"
            name                  = "myvpc"
          ~ vpc_name              = "myvpc" -> "myvpc1"
            # (8 unchanged attributes hidden)
        }
    
    Plan: 1 to add, 1 to change, 1 to destroy.
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    # 生命周期之条件检查
    • precondition postcondition 条件检查

    https://www.terraform.io/language/expressions/custom-conditions

    示例

    $ cd terraform-extend/lifecycle/create_before_destroy
    $ tree  ./
    ./
    ├── main.tf
    └── versions.tf
    
    0 directories, 4 files
    
    $ cat main.tf
    provider "alicloud" {
      region = "cn-shanghai"
    }
    
    locals {
      region = "cn-shanghai-a"
      # 这里的vsw所在区域为`cn-shanghai-a`
      vsw_id        = "vsw-uf6ct0jpe5ujmgh7my7np"
      secgroup_id   = "sg-uf6fy0y9i7j1t4dif549"
      instance_name = "myecsserver1"
      instance_type = "ecs.sn2ne.large"
    }
    
    data "alicloud_images" "images_ds" {
      owners       = "system"
      name_regex   = "^centos_7_9"
      architecture = "x86_64"
      status       = "Available"
      os_type      = "linux"
      # output_file  = "./outputs.json"
    }
    
    # output "image_id" {
    #   value = data.alicloud_images.images_ds.images[2].id
    # }
    
    # 这里新增加了VPC
    resource "alicloud_vpc" "vpc" {
      vpc_name   = "myvpc"
      cidr_block = "172.20.0.0/16"
    }
    
    resource "alicloud_instance" "myecs2" {
      availability_zone          = local.region
      security_groups            = [local.secgroup_id]
      instance_type              = local.instance_type
      system_disk_category       = "cloud_efficiency"
      system_disk_name           = "tf_system_disk_name"
      system_disk_description    = "tf_system_disk_description"
      image_id                   = data.alicloud_images.images_ds.images[2].id
      instance_name              = local.instance_name
      vswitch_id                 = local.vsw_id
      internet_max_bandwidth_out = 0
      internet_charge_type       = "PayByTraffic"
      password                   = "root@1234"
    
      lifecycle {
        create_before_destroy = true
        # prevent_destroy       = true
    
        # 检测系统的ami必须包含"x86_64"
        precondition {
          condition = data.alicloud_images.images_ds.architecture == "x86_64"
          error_message = "The selected AMI must be for the x86_64 architecture."
        }
    
        # 检测tags中的"env"必须等于"dev"
        postcondition {
          condition     = self.tags["env"] == "dev"
          error_message = "tags error!"
        }
    
      }
    }
    
    
    # 声明环境变量
    export ALICLOUD_ACCESS_KEY="xxxxxx"
    export ALICLOUD_SECRET_KEY="xxxxxx"
    export ALICLOUD_REGION="cn-shanghai"
    export TF_CLI_CONFIG_FILE=/home/terraform/youdianzhishi-terraform/terraform-extend/.terraformrc
    
    # 执行terraform命令
    $ terraform init 
    $ terraform fmt 或 terraform init -recursive
    $ terraform validate
    $ terraform plan
    $ terraform apply 或 terraform apply -auto-approve
    
    
    # 查看参数是否有问题
    $ terraform  validate
    Success! The configuration is valid.
    
    $ terraform apply 
    data.alicloud_images.images_ds: Reading...
    alicloud_vpc.vpc: Refreshing state... [id=vpc-uf62ypar80mrwhfoxuqw6]
    data.alicloud_images.images_ds: Read complete after 1s [id=1253956010]
    alicloud_instance.myecs2: Refreshing state... [id=i-uf6c2xw8vbvz167ze6dm]
    
    No changes. Your infrastructure matches the configuration.
    
    Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
    
    Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    上次更新: 2024/04/09, 16:48:42
    AWS实践
    Azure实践

    ← AWS实践 Azure实践→

    最近更新
    01
    AWS NAT-NetWork-Firwalld配置(一)
    04-09
    02
    AWS NAT-NetWork-Firwalld配置(二)
    04-09
    03
    kubernetes部署minio对象存储
    01-18
    更多文章>
    Theme by Vdoing | Copyright © 2019-2024 Bruce Tao Blog Space | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式