{"id":7580,"date":"2019-10-31T22:52:50","date_gmt":"2019-10-31T22:52:50","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=7580"},"modified":"2021-11-15T11:19:15","modified_gmt":"2021-11-15T11:19:15","slug":"terraform-workspace-explained","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/terraform-workspace-explained\/","title":{"rendered":"Terraform workspace explained!!!"},"content":{"rendered":"\n<p><strong>What is Terraform workspace?<\/strong><\/p>\n\n\n\n<p>Have you worked with terraform workflow? such as terraform init\/plan\/apply\/destroy with terraform configuration file? If Yes, you already have worked with Terraform workspace. YES. Thats a default workspace which you always been working with.<\/p>\n\n\n\n<p>It allows you to create different and independent states on the same configuration. And as it\u2019s compatible with remote backend this workspaces are shared with your team.<\/p>\n\n\n\n<p>Each Terraform configuration has an associated backend that defines how operations are executed and where persistent data such as the Terraform state are stored.<\/p>\n\n\n\n<p>The persistent data stored in the backend belongs to a workspace. Initially the backend has only one workspace, called &#8220;default&#8221;, and thus there is only one Terraform state associated with that configuration.<\/p>\n\n\n\n<p>Certain backends support multiple named workspaces, allowing multiple states to be associated with a single configuration. <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"442\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-1024x442.png\" alt=\"\" class=\"wp-image-7583\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-1024x442.png 1024w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-300x130.png 300w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-768x332.png 768w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace.png 1600w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"blob:https:\/\/www.devopsschool.com\/94e6db13-7e7c-45be-8f89-78e45b7a70eb\" alt=\"\"\/><\/figure>\n\n\n\n<p><strong>Multiple workspaces are currently supported by the following backends:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>AzureRM<\/li><li>Consul<\/li><li>GCS<\/li><li>Local<\/li><li>Manta<\/li><li>Postgres<\/li><li>Remote<\/li><li>S3<\/li><\/ul>\n\n\n\n<p>In the 0.9 line of Terraform releases, this concept was known as &#8220;environment&#8221;. It was renamed in 0.10 based on feedback to workspace.<\/p>\n\n\n\n<p>Terraform starts with a single workspace named &#8220;default&#8221;. This workspace is special both because it is the default and also because it cannot ever be deleted. If you&#8217;ve never explicitly used workspaces, then you&#8217;ve only ever worked on the &#8220;default&#8221; workspace<\/p>\n\n\n\n<p><strong>There are a couple of advantages to using Workspaces:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>They are defined by Hashicorp, so it&#8217;s possible that improved features could be developed in the future<\/li><li>They reduce the usage of code<\/li><\/ul>\n\n\n\n<p><strong>However, Workspaces also present a couple of challenges:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>They are still an early implementation<\/li><li>They are not yet supported by all backends<\/li><li>It is not clear at the time of deployment (terraform apply) which workspace will be used (terraform workspace show)<\/li><\/ul>\n\n\n\n<p><strong>Working with Terraform workspace?<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">\n$ terraform -help workspace\nUsage: terraform workspace\n\n  <span class=\"hljs-keyword\">New<\/span>, <span class=\"hljs-keyword\">list<\/span>, show, select <span class=\"hljs-keyword\">and<\/span> delete Terraform workspaces.\n\nSubcommands:\n    delete    Delete a workspace\n    <span class=\"hljs-keyword\">list<\/span>      <span class=\"hljs-keyword\">List<\/span> Workspaces\n    <span class=\"hljs-keyword\">new<\/span>       Create a <span class=\"hljs-keyword\">new<\/span> workspace\n    select    Select a workspace\n    show      Show the name of the current workspace<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Demo Code &#8211; <\/strong>https:\/\/github.com\/devopsschool-sample-projects\/terraform\/tree\/master\/demo.3<\/p>\n\n\n\n<p>So lets create a new dev workspace by running terraform workspace new dev and then run terraform apply. As we can see below instead of creating a terraform.tfstate file in the working folder Terraform created a new folder called <strong>terraform.tfstate.d\/dev<\/strong> and places the state file within that.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">deploy_website<\/span><span class=\"hljs-selector-class\">.sh<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">instance<\/span><span class=\"hljs-selector-class\">.tf<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">provider<\/span><span class=\"hljs-selector-class\">.tf<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfstate<\/span><span class=\"hljs-selector-class\">.d<\/span>\n\u2502   \u2514\u2500\u2500 <span class=\"hljs-selector-tag\">dev<\/span>\n\u2502       \u2514\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfstate<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfvars<\/span>\n\u2514\u2500\u2500 <span class=\"hljs-selector-tag\">vars<\/span><span class=\"hljs-selector-class\">.tf<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ok so our webserver is now up and we are happy with the results, lets create and switch to a prod workspace. So we run terraform workspace new prod. This automatically places us in the prod workspace.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">\n$ terraform workspace <span class=\"hljs-keyword\">list<\/span>\n<span class=\"hljs-keyword\">default<\/span>\ndev\n* prod<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now lets run terraform apply again. Note if we were not using a different workspace Terraform would say no changes were needed as the remote and local state would match.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">deploy_website<\/span><span class=\"hljs-selector-class\">.sh<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">instance<\/span><span class=\"hljs-selector-class\">.tf<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">provider<\/span><span class=\"hljs-selector-class\">.tf<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfstate<\/span><span class=\"hljs-selector-class\">.d<\/span>\n\u2502   \u251c\u2500\u2500 <span class=\"hljs-selector-tag\">dev<\/span>\n\u2502   \u2502   \u2514\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfstate<\/span>\n\u2502   \u2514\u2500\u2500 <span class=\"hljs-selector-tag\">prod<\/span>\n\u2502       \u2514\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfstate<\/span>\n\u251c\u2500\u2500 <span class=\"hljs-selector-tag\">terraform<\/span><span class=\"hljs-selector-class\">.tfvars<\/span>\n\u2514\u2500\u2500 <span class=\"hljs-selector-tag\">vars<\/span><span class=\"hljs-selector-class\">.tf<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And now we have a prod folder with a new state file. So as we can see above we can use Terraform workspaces to manage differences between development, staging, and production.<\/p>\n\n\n\n<p><strong>You can also backup the remote state of each workspace to S3<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"455\" height=\"291\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-code-1.png\" alt=\"\" class=\"wp-image-7582\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-code-1.png 455w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2019\/10\/terraform-workspace-code-1-300x192.png 300w\" sizes=\"auto, (max-width: 455px) 100vw, 455px\" \/><\/figure>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">\nbackend.tf:\n\n<span class=\"hljs-comment\"># Backend configuration is loaded early so we can't use variables<\/span>\nterraform {\n  backend <span class=\"hljs-string\">\"s3\"<\/span> {\n    region = <span class=\"hljs-string\">\"eu-central-1\"<\/span>\n    bucket = <span class=\"hljs-string\">\"devopsschool.com\"<\/span>\n    key = <span class=\"hljs-string\">\"state.tfstate\"<\/span>\n    encrypt = <span class=\"hljs-keyword\">true<\/span>    <span class=\"hljs-comment\">#AES-256 encryption<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Create workspaces:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">\n$ terraform workspace <span class=\"hljs-keyword\">new<\/span> dev\nCreated and switched to workspace <span class=\"hljs-string\">'dev'<\/span>\n$ terraform workspace <span class=\"hljs-keyword\">new<\/span> preprod\nCreated and switched to workspace <span class=\"hljs-string\">'preprod'<\/span>\n$ terraform workspace <span class=\"hljs-keyword\">new<\/span> prod\nCreated and switched to workspace <span class=\"hljs-string\">'prod'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Select the dev workspace:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\n$ terraform workspace select dev\n<\/code><\/span><\/pre>\n\n\n<p><strong>List workspaces:<\/strong><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">\n$ terraform workspace <span class=\"hljs-keyword\">list<\/span>\n<span class=\"hljs-keyword\">default<\/span>\n* dev\npreprod\nprod\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>With this workspace configuration, when a  terraform apply  is successfully executed, your tfstate will be now stored in the good environment folder in the s3 bucket:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">\ndevopsschool.com\nenv:\/\n    dev\/\n       state.tfstate    \n    preprod\/\n        state.tfstate    \n    prod\/\n        state.tfstate<\/code><\/span><\/pre>\n\n<div class=\"epyt-gallery\" data-currpage=\"1\" id=\"epyt_gallery_22080\"><figure class=\"wp-block-embed wp-block-embed-youtube is-type-video is-provider-youtube epyt-figure\"><div class=\"wp-block-embed__wrapper\"><iframe loading=\"lazy\"  id=\"_ytid_38965\"  width=\"760\" height=\"427\"  data-origwidth=\"760\" data-origheight=\"427\" src=\"https:\/\/www.youtube.com\/embed\/?enablejsapi=1&#038;autoplay=0&#038;cc_load_policy=0&#038;cc_lang_pref=&#038;iv_load_policy=1&#038;loop=0&#038;rel=1&#038;fs=1&#038;playsinline=0&#038;autohide=2&#038;theme=dark&#038;color=red&#038;controls=1&#038;disablekb=0&#038;\" class=\"__youtube_prefs__  no-lazyload\" title=\"YouTube player\"  data-epytgalleryid=\"epyt_gallery_22080\"  allow=\"fullscreen; accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen data-no-lazy=\"1\" data-skipgform_ajax_framebjll=\"\"><\/iframe><\/div><\/figure><div class=\"epyt-gallery-list\"><div>Sorry, there was a YouTube error.<\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>What is Terraform workspace? Have you worked with terraform workflow? such as terraform init\/plan\/apply\/destroy with terraform configuration file? If Yes, you already have worked with Terraform workspace. YES. Thats a default workspace which you always been working with. It allows you to create different and independent states on the same configuration. And as it\u2019s compatible&#8230;<\/p>\n","protected":false},"author":1,"featured_media":7782,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_joinchat":[],"footnotes":""},"categories":[5129],"tags":[5449,5130,5500],"class_list":["post-7580","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-terraform","tag-devopsschool","tag-terraform","tag-wokspace"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/7580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=7580"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/7580\/revisions"}],"predecessor-version":[{"id":25329,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/7580\/revisions\/25329"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/7782"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=7580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=7580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=7580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}