Skip to content

Latest commit

 

History

History
322 lines (245 loc) · 10.5 KB

remote-backends.mdx

File metadata and controls

322 lines (245 loc) · 10.5 KB
page_title description
Remote Backends - CDK for Terraform
Configure a remote backend where Terraform can store infrastructure state files remotely.

Remote Backends

Terraform stores state about managed infrastructure to map real-world resources to the configuration, keep track of metadata, and improve performance. Terraform stores this state in a local file by default, but you can also use a Terraform remote backend to store state remotely.

By default, cdktf init will configure a Terraform Cloud workspace and a corresponding remote backend to store state for the new project. If you run cdktf init --local to configure your new project to use a local backend to store state, you can still migrate the state to a remote backend later.

You can configure your CDK for Terraform (CDKTF) remote backend to be Terraform Cloud, another Terraform supported backend, or a custom location.

When to Use Remote Backends

Consider using a remote backend when multiple individuals or teams need access to your infrastructure state data.

Remote state makes it easier for teams to work together because all members have access to the latest state data in the remote store. It also allows you to share output values with other configurations, allowing groups to share infrastructure resources. For example, a core infrastructure team can handle building the core machines and then expose some information that other teams can use for their own infrastructure.

Define Remote Backends

You can define a JSON configuration for a remote backend with a TerraformBackend subclass or a JSON configuration file.

The following example uses the TerraformBackend subclass CloudBackend.

import { Construct } from "constructs";
import { App, CloudBackend, TerraformStack, TerraformOutput } from "cdktf";

class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new CloudBackend(this, {
      hostname: "app.terraform.io",
      organization: "company",
      workspaces: {
        name: "my-app-prod",
      },
    });

    new TerraformOutput(this, "dns-server", {
      value: "hello-world",
    });
  }
}

const app = new App();
new Mystack(app, "hello-terraform");
import software.constructs.Construct;
import com.hashicorp.cdktf.TerraformStack;
import com.hashicorp.cdktf.App;
import com.hashicorp.cdktf.CloudBackend;
import com.hashicorp.cdktf.CloudBackendProps;
import com.hashicorp.cdktf.NamedCloudWorkspace;
import com.hashicorp.cdktf.TerraformOutput;
import com.hashicorp.cdktf.TerraformOutputConfig;

public class MainRemoteBackendDefine extends TerraformStack {

    public MainRemoteBackendDefine(Construct scope, String id) {
        super(scope, id);

        new CloudBackend(this, CloudBackendProps.builder()
                .hostname("app.terraform.io")
                .organization("company")
                .workspaces(new NamedCloudWorkspace("my-app-prod"))
                .build()
        );

        new TerraformOutput(this, "dns-server", TerraformOutputConfig.builder()
                .value("hello-world")
                .build()
        );
    }
}
from constructs import Construct
from cdktf import App, CloudBackend, NamedCloudWorkspace, TerraformStack, TerraformOutput
class RemoteBackendStack(TerraformStack):
    def __init__(self, scope: Construct, id: str):
        super().__init__(scope, id)

        CloudBackend(self,
            hostname = "app.terraform.io",
            organization = "company",
            workspaces = NamedCloudWorkspace("my-app-prod")
        )

        TerraformOutput(self, "dns-server",
            value = "hello-world"
        )

app = App()
RemoteBackendStack(app, "hello-terraform")
app.synth()

When you call cdktf synth, CDKTF generates a JSON file called remote.tf.json in the cdktf.out stack sub-directory containing the synthesized CDKTF code. For example, CDKTF creates the output for a stack called hello-terraform in cdktf.out/stacks/hello-terraform.

The following example shows the stack output directory.

tree .
.
├── cdk.tf.json
└── remote.tf.json

The following example shows the generated remote.tf.json file.

{
  "terraform": {
    "backend": {
      "remote": {
        "hostname": "app.terraform.io",
        "organization": "company",
        "workspaces": {
          "name": "my-app-prod"
        }
      }
    }
  }
}

Initialize Remote Backends

All cdktf operations perform an automatic terraform init, but you can also initialize manually.

To manually initialize a remote backend, go to the corresponding stack output directory in the cdktf.out folder and run terraform init.

$ cd cdkf.out/stacks/hello-terraform
$ terraform init

Migrate Local State Storage to Remote

After you define your remote backend, you can migrate existing local state files to the designated remote location. This requires moving Terraform state files to the CDKTF output directory.

Consider an example project called hello-terraform that is using local storage to store the Terraform state. To migrate the local stage files to the remote backend:

  1. Navigate into the main project directory.

  2. Use CloudBackend to add a new remote backend.

const stack = new MyStack(app, "hello-terraform");
new CloudBackend(stack, {
  hostname: "app.terraform.io",
  organization: "company",
  workspaces: new NamedCloudWorkspace("my-app-prod"),
});
stack = Stack(App(), "hi-terraform")
        CloudBackend(self,
            hostname = "app.terraform.io",
            organization = "company",
            workspaces = NamedCloudWorkspace("my-app-prod")
        )
  1. Run cdktf synth to generate the Terraform configuration file.

  2. Move the Terraform state file into the output directory.

    mv terraform.hello-terraform.tfstate cdktf.out/stacks/hello-terraform
  3. Navigate to cdktf.out/stacks/hello-terraform and run terraform init. CDKTF prints the following output:

    Initializing the backend...
    Do you want to copy existing state to the new backend?
      Pre-existing state was found while migrating the previous "local" backend to the
      newly configured "remote" backend. No existing state was found in the newly
      configured "remote" backend. Do you want to copy this state to the new "remote"
      backend? Enter "yes" to copy and "no" to start with an empty state.
    
      Enter a value: yes
    
      Successfully configured the backend "remote"! Terraform will automatically
      use this backend unless the backend configuration changes.
    
      Initializing provider plugins...
    
      .....
      Terraform has been successfully initialized!
    
      You may now begin working with Terraform. Try running "terraform plan" to see
      any changes that are required for your infrastructure. All Terraform commands
      should now work.
    
      If you ever set or change modules or backend configuration for Terraform,
      other cdktf cli commands will detect the change and prompt you to rerun this command if necessary.
    
    
  4. Runcdktf diff in the root hello-terraform directory to validate state migration. CDKTF prints the following output:

    Stack: hello-terraform
    
    Diff: 0 to create, 0 to update, 0 to delete.
    

    With the remote backend type in this example, a diff would indicate that the state was not migrated properly. There are no changes to the stack, which means the migration was successful. Consult the documentation for the remote backend you are using to understand how to validate state migration.

Supported Backends

In addition to Terraform Cloud, Terraform and CDKTF support the following backends.

  • local
    new LocalBackend(stack, {...});
  • azurerm
    new AzurermBackend(stack, {...});
  • consul
    new ConsulBackend(stack, {...});
  • cos
    new CosBackend(stack, {...});
  • gcs
    new GcsBackend(stack, {...});
  • http
    new HttpBackend(stack, {...});
  • oss
    new OssBackend(stack, {...});
  • pg
    new PgBackend(stack, {...});
  • s3
    new S3Backend(stack, {...});

-> Note: CDK for Terraform v0.14 deprecated the artifactory, etcd, etcdv3, manta, and swift backends. Terraform removed these backends in v1.3. For migration paths from these removed backends, refer to Upgrading to Terraform v1.3.

Escape Hatches

Escape hatches can add to or override existing resources, and you can use them for backends or backend constructs that CDKTF does not natively support. Escape hatch methods have an Override suffix (e.g., addOverride).

The following example uses an escape hatch to add an unsupported remote backend on a Stack object.

stack.addOverride("terraform.backend", {
  atlas: {
    name: "example_corp/networking-prod",
    address: "https://app.terraform.io",
  },
});
stack.addOverride("terraform.backend", new HashMap<String, HashMap>() {
    {
        put("atlas", new HashMap<String, String>() {
            {
                put("name", "example_corp/networking-prod");
                put("address", "https://app.terraform.io");
            }
        });
    }
});
stack.add_override("terraform.backend",{
    "atlas": {
        "name": "example_corp/networking-prod",
        "address": "https://app.terraform.io"
    }
})