Managing Applications and Infrastructure with Terraform-Deploying Infrastructure with Terraform-(1)Terraform Basics and a Docker Deployment-(4)Tainting and Updating Resources

2018年10月04日


Managing Applications and Infrastructure with Terraform-Deploying Infrastructure with Terraform
1. Terraform Basics and a Docker Deployment
4. Tainting (使腐坏; 污染; 玷污,败坏(名声)) and Updating Resources

~/docker# vim main.tf

...
# Start the container, reference the above "docker_image" and "image_id"
resource "docker_container" "container_id" {
  name  = "blog"
  image = docker_image.image_id.latest
  ports {
    internal = "2368"
    external = "80"
  }
}

~/docker# terraform apply
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:

  # docker_container.container_id will be created
  + resource "docker_container" "container_id" {
      + attach           = false
      + bridge           = (known after apply)
      + command          = (known after apply)
      + container_logs   = (known after apply)
      + dns              = (known after apply)
      + dns_opts         = (known after apply)
      + entrypoint       = (known after apply)
      + exit_code        = (known after apply)
      + gateway          = (known after apply)
      + hostname         = (known after apply)
      + id               = (known after apply)
      + image            = (known after apply)
      + ip_address       = (known after apply)
      + ip_prefix_length = (known after apply)
      + ipc_mode         = (known after apply)
      + log_driver       = (known after apply)
      + log_opts         = (known after apply)
      + logs             = false
      + must_run         = true
      + name             = "blog"
      + network_data     = (known after apply)
      + read_only        = false
      + restart          = "no"
      + rm               = false
      + shm_size         = (known after apply)
      + start            = true
      + user             = (known after apply)
      + working_dir      = (known after apply)

      + ports {
          + external = 80
          + internal = 2368
          + ip       = "0.0.0.0"
          + protocol = "tcp"
        }
    }

  # docker_image.image_id will be created
  + resource "docker_image" "image_id" {
      + id     = (known after apply)
      + latest = (known after apply)
      + name   = "ghost:latest"
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

docker_image.image_id: Creating...
docker_image.image_id: Still creating... [10s elapsed]
docker_image.image_id: Still creating... [20s elapsed]
docker_image.image_id: Creation complete after 28s [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_container.container_id: Creating...
docker_container.container_id: Creation complete after 1s [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]

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

Manually marks a Terraform-managed resource as tainted, forcing it to be destroyed and recreated on the next apply.
~/docker# terraform taint docker_container.container_id
Resource instance docker_container.container_id has been marked as tainted.

~/docker# terraform plan
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.

docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_container.container_id: Refreshing state... [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # docker_container.container_id is tainted, so must be replaced
-/+ resource "docker_container" "container_id" {
        attach            = false
      + bridge            = (known after apply)
      ~ command           = [
          - "node",
          - "current/index.js",
        ] -> (known after apply)
      + container_logs    = (known after apply)
      - cpu_shares        = 0 -> null
      ~ dns               = [] -> (known after apply)
      ~ dns_opts          = [] -> (known after apply)
      - dns_search        = [] -> null
      ~ entrypoint        = [
          - "docker-entrypoint.sh",
        ] -> (known after apply)
      + exit_code         = (known after apply)
      ~ gateway           = "172.17.0.1" -> (known after apply)
      - group_add         = [] -> null
      ~ hostname          = "7e6dc048f9d1" -> (known after apply)
      ~ id                = "7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53" -> (known after apply)
        image             = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5"
      ~ ip_address        = "172.17.0.2" -> (known after apply)
      ~ ip_prefix_length  = 16 -> (known after apply)
      ~ ipc_mode          = "private" -> (known after apply)
      - links             = [] -> null
      ~ log_driver        = "json-file" -> (known after apply)
      ~ log_opts          = {} -> (known after apply)
        logs              = false
      - max_retry_count   = 0 -> null
      - memory            = 0 -> null
      - memory_swap       = 0 -> null
        must_run          = true
        name              = "blog"
      ~ network_data      = [
          - {
              - gateway          = "172.17.0.1"
              - ip_address       = "172.17.0.2"
              - ip_prefix_length = 16
              - network_name     = "bridge"
            },
        ] -> (known after apply)
      - network_mode      = "default" -> null
      - privileged        = false -> null
      - publish_all_ports = false -> null
        read_only         = false
        restart           = "no"
        rm                = false
      ~ shm_size          = 64 -> (known after apply)
        start             = true
      - sysctls           = {} -> null
      - tmpfs             = {} -> null
      + user              = (known after apply)
      ~ working_dir       = "/var/lib/ghost" -> (known after apply)

        ports {
            external = 80
            internal = 2368
            ip       = "0.0.0.0"
            protocol = "tcp"
        }
    }

Plan: 1 to add, 0 to change, 1 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.

Manually unmarks a Terraform-managed resource as tainted, restoring it as the primary instance in the state. This reverses either a manual terraform taint or the result of provisioners failing on a resource.
~/docker# terraform untaint docker_container.container_id
Resource instance docker_container.container_id has been successfully untainted.

~/docker# terraform plan
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.

docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_container.container_id: Refreshing state... [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]

------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.

Change "ghost:latest" to "ghost:alpine".
~/docker# vim main.tf
...
# Download the latest Ghost image
resource "docker_image" "image_id" {
  name = "ghost:alpine"
}
...

~/docker# terraform plan
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.

docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_container.container_id: Refreshing state... [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # docker_image.image_id will be updated in-place
  ~ resource "docker_image" "image_id" {
        id     = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest"
        latest = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5"
      ~ name   = "ghost:latest" -> "ghost:alpine"
    }

Plan: 0 to add, 1 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.

Change external = "80" to external = "8080".
~/docker# vim main.tf
...
# Start the container, reference the above "docker_image" and "image_id"
resource "docker_container" "container_id" {
  name  = "blog"
  image = docker_image.image_id.latest
  ports {
    internal = "2368"
    external = "8080"
  }
}

~/docker# terraform plan
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.

docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_container.container_id: Refreshing state... [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # docker_container.container_id must be replaced
-/+ resource "docker_container" "container_id" {
        attach            = false
      + bridge            = (known after apply)
      ~ command           = [
          - "node",
          - "current/index.js",
        ] -> (known after apply)
      + container_logs    = (known after apply)
      - cpu_shares        = 0 -> null
      ~ dns               = [] -> (known after apply)
      ~ dns_opts          = [] -> (known after apply)
      - dns_search        = [] -> null
      ~ entrypoint        = [
          - "docker-entrypoint.sh",
        ] -> (known after apply)
      + exit_code         = (known after apply)
      ~ gateway           = "172.17.0.1" -> (known after apply)
      - group_add         = [] -> null
      ~ hostname          = "7e6dc048f9d1" -> (known after apply)
      ~ id                = "7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53" -> (known after apply)
        image             = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5"
      ~ ip_address        = "172.17.0.2" -> (known after apply)
      ~ ip_prefix_length  = 16 -> (known after apply)
      ~ ipc_mode          = "private" -> (known after apply)
      - links             = [] -> null
      ~ log_driver        = "json-file" -> (known after apply)
      ~ log_opts          = {} -> (known after apply)
        logs              = false
      - max_retry_count   = 0 -> null
      - memory            = 0 -> null
      - memory_swap       = 0 -> null
        must_run          = true
        name              = "blog"
      ~ network_data      = [
          - {
              - gateway          = "172.17.0.1"
              - ip_address       = "172.17.0.2"
              - ip_prefix_length = 16
              - network_name     = "bridge"
            },
        ] -> (known after apply)
      - network_mode      = "default" -> null
      - privileged        = false -> null
      - publish_all_ports = false -> null
        read_only         = false
        restart           = "no"
        rm                = false
      ~ shm_size          = 64 -> (known after apply)
        start             = true
      - sysctls           = {} -> null
      - tmpfs             = {} -> null
      + user              = (known after apply)
      ~ working_dir       = "/var/lib/ghost" -> (known after apply)

      ~ ports {
          ~ external = 80 -> 8080 # forces replacement
            internal = 2368
            ip       = "0.0.0.0"
            protocol = "tcp"
        }
    }

  # docker_image.image_id will be updated in-place
  ~ resource "docker_image" "image_id" {
        id     = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest"
        latest = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5"
      ~ name   = "ghost:latest" -> "ghost:alpine"
    }

Plan: 1 to add, 1 to change, 1 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.

Change external = "8080" back to external = "80". Change "ghost:alpine" back to "ghost:latest".
~/docker# vim main.tf
# Download the latest Ghost image
resource "docker_image" "image_id" {
  name = "ghost:latest"
}

# Start the container, reference the above "docker_image" and "image_id"
resource "docker_container" "container_id" {
  name  = "blog"
  image = docker_image.image_id.latest
  ports {
    internal = "2368"
    external = "80"
  }
}

~/docker# terraform destroy
docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_container.container_id: Refreshing state... [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # docker_container.container_id will be destroyed
  - resource "docker_container" "container_id" {
      - attach            = false -> null
      - command           = [
          - "node",
          - "current/index.js",
        ] -> null
      - cpu_shares        = 0 -> null
      - dns               = [] -> null
      - dns_opts          = [] -> null
      - dns_search        = [] -> null
      - entrypoint        = [
          - "docker-entrypoint.sh",
        ] -> null
      - gateway           = "172.17.0.1" -> null
      - group_add         = [] -> null
      - hostname          = "7e6dc048f9d1" -> null
      - id                = "7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53" -> null
      - image             = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5" -> null
      - ip_address        = "172.17.0.2" -> null
      - ip_prefix_length  = 16 -> null
      - ipc_mode          = "private" -> null
      - links             = [] -> null
      - log_driver        = "json-file" -> null
      - log_opts          = {} -> null
      - logs              = false -> null
      - max_retry_count   = 0 -> null
      - memory            = 0 -> null
      - memory_swap       = 0 -> null
      - must_run          = true -> null
      - name              = "blog" -> null
      - network_data      = [
          - {
              - gateway          = "172.17.0.1"
              - ip_address       = "172.17.0.2"
              - ip_prefix_length = 16
              - network_name     = "bridge"
            },
        ] -> null
      - network_mode      = "default" -> null
      - privileged        = false -> null
      - publish_all_ports = false -> null
      - read_only         = false -> null
      - restart           = "no" -> null
      - rm                = false -> null
      - shm_size          = 64 -> null
      - start             = true -> null
      - sysctls           = {} -> null
      - tmpfs             = {} -> null
      - working_dir       = "/var/lib/ghost" -> null

      - ports {
          - external = 80 -> null
          - internal = 2368 -> null
          - ip       = "0.0.0.0" -> null
          - protocol = "tcp" -> null
        }
    }

  # docker_image.image_id will be destroyed
  - resource "docker_image" "image_id" {
      - id     = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest" -> null
      - latest = "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5" -> null
      - name   = "ghost:latest" -> null
    }

Plan: 0 to add, 0 to change, 2 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

docker_container.container_id: Destroying... [id=7e6dc048f9d1834a98f59106358aa325efa77d0bec289f24a341ca2794e3ea53]
docker_container.container_id: Destruction complete after 1s
docker_image.image_id: Destroying... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest]
docker_image.image_id: Destruction complete after 8s

Destroy complete! Resources: 2 destroyed.


References

Command: taint

Command: untaint

Category: orchestration Tags: public

Upvote


Downvote