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