Originally published on the Consensus Enterprises blog.
For our cloud computing, we typically use an OpenStack provider because of its open-source nature: There’s no vendor lock-in, and the IaaS code is peer-reviewed unlike providers such as AWS, Azure, GCP, etc. (Shout out to Vexxhost for having great support!) As such, we’ve been using OpenStack’s Swift object storage service for storing Terraform’s state, which allows Terraform to track all of the resources it manages for automating infrastructure.
Recently, however, support for the Swift backend has been removed. If you’re still using Swift for this purpose, you’ll need to migrate your Terraform state files to another backend. Because the official migration documentation is sparse, I’ll describe how to migrate from Swift to GitLab-managed Terraform state. GitLab is a fantastic option because it can be used to manage so many other aspects of your project that you need anyway: Git repository hosting, issue tracking, CI/CD, etc. We use GitLab for all of our projects so it’s a great fit for us.
The actual step of migrating the data is well supported, but there’s some required set-up before and after.
When you change backends, Terraform gives you the option to migrate your state to the new backend. This lets you adopt backends without losing any existing state.
Prerequisities
- Downgrade to the latest pre-1.3 Terraform version.
- e.g.
sudo apt install terraform=1.2.9
- e.g.
- Navigate to your Terraform directory.
cd /path/to/git/repository/terraform
- Move your local state files out of the way as they could be set up for a different environment.
mv .terraform /tmp
- Set up your environment variables to connect to use your existing state backend.
- e.g.
source ../openstackrc/vexxhost-...-staging-ca-ymq-1.openrc.sh
- e.g.
- Initialize Terraform from the remote state.
terraform init
- Back up your current state.
cp .terraform/terraform.tfstate terraform.tfstate.backup-staging
- In your Terraform code, in your
backend
stanza, replaceswift
withhttp
. - Unset the old state environment variables.
export TF_CLI_ARGS_init=
- Fetch one of your Gitlab personal access tokens with the
api
permission. If you don’t have any that aren’t expired, create a new one in your settings.
Setting variables in your local environment
To actually migrate the data, the GitLab documentation says to set a single environment variable, and then manually run terraform init
with many options. Given that this is error-prone and not easily repeatable, I’d recommend using a shell script (or similar) instead.
Create a file named setup-terraform-variables
, and populate it like so:
|
|
You can set other Terraform variables in here as well, and include it in other deployment-environment-specific shell scripts that you run to set up each one. For example, if you’re using OpenStack generally, these would be your openstackrc
files, which contain your credentials for accessing the API.
For a further optimization, you can write the GitLab credentials to a local file so as not to have to enter them every time, but I’ll leave this as an exercise to the reader. (If I get a chance, I’ll come back here and update it.)
Changing the backend type
In your Terraform configuration files, it’s necessary to change the backend type from Swift to HTTP.
|
|
If you’re wondering why we need to use TF_CLI_ARGS_init
, and can’t use Terraform variables in the stanza, see my earlier article Setting Deployment Environments’ Terraform State Backends with Environment Variables .
Migrating the data
You can now run:
terraform init
You should now see something like this, which requires your confirmation part-way through.
|
|
Resetting your local environment to use the new state storage
This will purge your old state, and set it up to match the new remote state.
- Move your local state files out of the way as they reflect the old state backend.
mv .terraform /tmp
- Upgrade Terraform to the latest version.
- e.g.
sudo apt install terraform
- e.g.
- Set up your environment variables again, using the updated code, to connect to your desired cloud environment. This script must include
setup-terraform-variables
as discussed above.source ../openstackrc/vexxhost-...-staging-ca-ymq-1.openrc.sh
- Initialize Terraform from the remote state.
terraform init
Confirming the presense of the remote state files
You can now see any of your state files in the GitLab Web UI on your Gitlab project’s page. Simply navigate to Infrastructure
-> Terraform
, and they’ll be listed.