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日
~/docker# terraform apply
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
~/docker# terraform plan
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
~/docker# terraform plan
Change "ghost:latest" to "ghost:alpine".
~/docker# vim main.tf
~/docker# terraform plan
Change external = "80" to external = "8080".
~/docker# vim main.tf
~/docker# terraform plan
Change external = "8080" back to external = "80". Change "ghost:alpine" back to "ghost:latest".
~/docker# vim main.tf
~/docker# terraform destroy
References
Command: taint
Command: untaint
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