Managing Applications and Infrastructure with Terraform-Deploying Infrastructure with Terraform-(1)Terraform Basics and a Docker Deployment-(13)Terraform Workspaces
2018年10月04日
~/docker# terraform apply
~/docker# ls
~/docker# cat terraform.tfstate
~/docker# terraform destroy
Manage workspaces.
Workspaces are managed with the terraform workspace set of commands. To create a new workspace and switch to it, you can use terraform workspace new; to switch workspaces you can use terraform workspace select; etc.
~/docker# terraform workspace new dev
~/docker# terraform workspace new prod
~/docker# terraform workspace select dev
The persistent data stored in the backend belongs to a workspace. Initially the backend has only one workspace, called "default", and thus there is only one Terraform state associated with that configuration.
Terraform starts with a single workspace named "default". This workspace is special both because it is the default and also because it cannot ever be deleted. If you've never explicitly used workspaces, then you've only ever worked on the "default" workspace.
~/docker# terraform workspace select default
~/docker# terraform workspace select dev
~/docker# terraform apply
~/docker# terraform workspace select prod
~/docker# terraform apply
Access http://[PublicIP] and http://[PublicIP]:8080
Both URL could be successfully accessed.
~/docker# ls
~/docker# cd terraform.tfstate.d
Each Terraform configuration has an associated backend that defines how operations are executed and where persistent data such as the Terraform state are stored.
~/docker/terraform.tfstate.d# ls
~/docker/terraform.tfstate.d# cd ..
References
Command: workspace
Workspaces
*
Managing Applications and Infrastructure with Terraform-Deploying Infrastructure with Terraform
1. Terraform Basics and a Docker Deployment
13. Terraform Workspaces
~/docker# terraform apply
var.env env: dev or prod Enter a value: dev 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: # module.container.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 = "dev_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 = 8080 + internal = 2368 + ip = "0.0.0.0" + protocol = "tcp" } } # module.image.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. Changes to Outputs: + IP_Address = (known after apply) + container_name = "dev_blog" 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 module.image.docker_image.image_id: Creating... module.image.docker_image.image_id: Still creating... [10s elapsed] module.image.docker_image.image_id: Still creating... [20s elapsed] module.image.docker_image.image_id: Creation complete after 29s [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest] module.container.docker_container.container_id: Creating... module.container.docker_container.container_id: Creation complete after 1s [id=b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: IP_Address = 172.17.0.2 container_name = dev_blog
~/docker# terraform apply
var.env env: dev or prod Enter a value: prod module.image.docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest] module.container.docker_container.container_id: Refreshing state... [id=b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd] 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: # module.container.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 = "b1fa2d496c2b" -> (known after apply) ~ id = "b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd" -> (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 = "dev_blog" -> "prod_blog" # forces replacement ~ 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 = 8080 -> 80 # forces replacement internal = 2368 ip = "0.0.0.0" protocol = "tcp" } } # module.image.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. Changes to Outputs: ~ IP_Address = "172.17.0.2" -> (known after apply) ~ container_name = "dev_blog" -> "prod_blog" Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: no Apply cancelled.
~/docker# ls
container image main.tf outputs.tf terraform.tfstate terraform.tfstate.backup variables.tf
~/docker# cat terraform.tfstate
{ "version": 4, "terraform_version": "0.13.4", "serial": 74, "lineage": "709353e2-1832-8aef-af95-42e941eeb58a", "outputs": { "IP_Address": { "value": "172.17.0.2", "type": "string" }, "container_name": { "value": "dev_blog", "type": "string" } }, "resources": [ { "module": "module.container", "mode": "managed", "type": "docker_container", "name": "container_id", "provider": "provider[\"registry.terraform.io/terraform-providers/docker\"]", "instances": [ { "schema_version": 2, "attributes": { "attach": false, "bridge": "", "capabilities": [], "command": [ "node", "current/index.js" ], "container_logs": null, "cpu_set": "", "cpu_shares": 0, "destroy_grace_seconds": null, "devices": [], "dns": [], "dns_opts": [], "dns_search": null, "domainname": "", "entrypoint": [ "docker-entrypoint.sh" ], "env": null, "exit_code": null, "gateway": "172.17.0.1", "group_add": null, "healthcheck": [], "host": [], "hostname": "b1fa2d496c2b", "id": "b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd", "image": "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5", "ip_address": "172.17.0.2", "ip_prefix_length": 16, "ipc_mode": "private", "labels": [], "links": null, "log_driver": "json-file", "log_opts": {}, "logs": false, "max_retry_count": 0, "memory": 0, "memory_swap": 0, "mounts": [], "must_run": true, "name": "dev_blog", "network_alias": null, "network_data": [ { "gateway": "172.17.0.1", "ip_address": "172.17.0.2", "ip_prefix_length": 16, "network_name": "bridge" } ], "network_mode": "default", "networks": null, "networks_advanced": [], "pid_mode": "", "ports": [ { "external": 8080, "internal": 2368, "ip": "0.0.0.0", "protocol": "tcp" } ], "privileged": false, "publish_all_ports": false, "read_only": false, "restart": "no", "rm": false, "shm_size": 64, "start": true, "sysctls": null, "tmpfs": null, "ulimit": [], "upload": [], "user": "", "userns_mode": "", "volumes": [], "working_dir": "/var/lib/ghost" }, "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjIifQ==", "dependencies": [ "module.image.docker_image.image_id" ] } ] }, { "module": "module.image", "mode": "managed", "type": "docker_image", "name": "image_id", "provider": "provider[\"registry.terraform.io/terraform-providers/docker\"]", "instances": [ { "schema_version": 0, "attributes": { "id": "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest", "keep_locally": null, "latest": "sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5", "name": "ghost:latest", "pull_trigger": null, "pull_triggers": null }, "private": "bnVsbA==" } ] } ] }
~/docker# terraform destroy
var.env env: dev or prod Enter a value: dev module.image.docker_image.image_id: Refreshing state... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest] module.container.docker_container.container_id: Refreshing state... [id=b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd] 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: # module.container.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 = "b1fa2d496c2b" -> null - id = "b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd" -> 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 = "dev_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 = 8080 -> null - internal = 2368 -> null - ip = "0.0.0.0" -> null - protocol = "tcp" -> null } } # module.image.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. Changes to Outputs: - IP_Address = "172.17.0.2" -> null - container_name = "dev_blog" -> null 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 module.container.docker_container.container_id: Destroying... [id=b1fa2d496c2bfa811fa71640b067fcdb60ad8d04be2c4fe118941687b48911fd] module.container.docker_container.container_id: Destruction complete after 1s module.image.docker_image.image_id: Destroying... [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest] module.image.docker_image.image_id: Destruction complete after 10s Destroy complete! Resources: 2 destroyed.
Manage workspaces.
Workspaces are managed with the terraform workspace set of commands. To create a new workspace and switch to it, you can use terraform workspace new; to switch workspaces you can use terraform workspace select; etc.
~/docker# terraform workspace new dev
Created and switched to workspace "dev"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration.
~/docker# terraform workspace new prod
Created and switched to workspace "prod"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration.
~/docker# terraform workspace select dev
Switched to workspace "dev".
The persistent data stored in the backend belongs to a workspace. Initially the backend has only one workspace, called "default", and thus there is only one Terraform state associated with that configuration.
Terraform starts with a single workspace named "default". This workspace is special both because it is the default and also because it cannot ever be deleted. If you've never explicitly used workspaces, then you've only ever worked on the "default" workspace.
~/docker# terraform workspace select default
Switched to workspace "default".
~/docker# terraform workspace select dev
Switched to workspace "dev".
~/docker# terraform apply
var.env env: dev or prod Enter a value: dev 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: # module.container.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 = "dev_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 = 8080 + internal = 2368 + ip = "0.0.0.0" + protocol = "tcp" } } # module.image.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 in workspace "dev"? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes module.image.docker_image.image_id: Creating... module.image.docker_image.image_id: Still creating... [10s elapsed] module.image.docker_image.image_id: Still creating... [20s elapsed] module.image.docker_image.image_id: Creation complete after 29s [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest] module.container.docker_container.container_id: Creating... module.container.docker_container.container_id: Creation complete after 2s [id=2c856cff5dc5316f16572c088d92bf38df8a0af7519d630cd6d12413ea33b34e] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: IP_Address = 172.17.0.2 container_name = dev_blog
~/docker# terraform workspace select prod
Switched to workspace "prod".
~/docker# terraform apply
var.env env: dev or prod Enter a value: prod 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: # module.container.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 = "prod_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" } } # module.image.docker_image.image_id will be created + resource "docker_image" "image_id" { + id = (known after apply) + latest = (known after apply) + name = "ghost:alpine" } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions in workspace "prod"? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes module.image.docker_image.image_id: Creating... module.image.docker_image.image_id: Still creating... [10s elapsed] module.image.docker_image.image_id: Still creating... [20s elapsed] module.image.docker_image.image_id: Creation complete after 26s [id=sha256:a7d409c8a8af50ce6df5cc5cb94600b657acc9cfd82216d89a83730467bdd439ghost:alpine] module.container.docker_container.container_id: Creating... module.container.docker_container.container_id: Creation complete after 2s [id=311610e3b765e81f3d2ad545198218f8768c2441eddcb62f82e7a1928eaf1621] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: IP_Address = 172.17.0.3 container_name = prod_blog
Access http://[PublicIP] and http://[PublicIP]:8080
Both URL could be successfully accessed.
~/docker# ls
container image main.tf outputs.tf terraform.tfstate terraform.tfstate.backup terraform.tfstate.d variables.tf
~/docker# cd terraform.tfstate.d
Each Terraform configuration has an associated backend that defines how operations are executed and where persistent data such as the Terraform state are stored.
~/docker/terraform.tfstate.d# ls
dev prod
~/docker/terraform.tfstate.d# cd ..
References
Command: workspace
Workspaces