This page describes the process of using DM Convert to convert your Deployment Manager configurations to Kubernetes Resource Model (KRM) or Terraform.
Set up your environment
Set up your environment variables
Save the following environment variables, which the rest of this guide uses:
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format="value(projectNumber)")
export DM_CONVERT_IMAGE="us-central1-docker.pkg.dev/\
dm-convert-host/deployment-manager/dm-convert:public-preview"
# Enable the Cloud Build API
gcloud services enable cloudbuild.googleapis.com
# Grant Cloud Build service account permission to manage Google Cloud Storage
# bucket and DM deployments
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role=roles/storage.admin
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role=roles/deploymentmanager.editor
Set up your tools
You must have access to the following tools:
gcloud
gsutil
docker
kubectl
If you use Cloud Shell to run DM Convert, you already have access to them.
Convert your configurations
At a high level, you migrate your Deployment Manager configuration to Terraform or KRM by:
Preparing a Deployment Manager deployment for conversion.
Converting the configuration to either the HCL (HashiCorp configuration language, for Terraform) or the KRM (Kubernetes Resource Model) format.
Using Terraform or Config Connector to apply the converted configuration.
Abandoning the existing Deployment Manager deployment.
Prepare your existing deployment
DM Convert operates on Deployment Manager configuration files and templates. To provide these files and templates to DM Convert, you use a Cloud Storage bucket.
To create a Cloud Storage bucket to store your Deployment Manager
configuration at $BUCKET_URI
, run the following commands:
export BUCKET_NAME=$PROJECT_ID-dm-config
export BUCKET_URI=gs://$BUCKET_NAME
gsutil mb $BUCKET_URI
# This is where we will store DM configuration to be converted
export DM_CONFIG_URI=$BUCKET_URI/dm
You can add a configuration file directly to the Cloud Storage bucket, or acquire a configuration from a live deployment.
Convert a configuration file
You can use the following sample configuration to try out the converter. Replace
PROJECT_ID
with your Google Cloud project ID, and save
the below contents to a file called deployment.yaml
:
resources:
- name: bigquerydataset
type: bigquery.v2.dataset
properties:
datasetReference:
datasetId: bigquerydataset
projectId: PROJECT_ID
defaultTableExpirationMs: 36000000
location: us-west1
- type: bigquery.v2.table
name: bigquerytable
properties:
datasetId: bigquerydataset
labels:
data-source: external
schema-type: auto-junk
tableReference:
projectId: PROJECT_ID
tableId: bigquerytable
metadata:
dependsOn:
- bigquerydataset
After you save the file, copy it to the Cloud Storage bucket you previously created:
gsutil cp ./deployment.yaml $DM_CONFIG_URI/deployment.yaml
Grant the Identity and Access Management (IAM) role roles/bigquery.dataEditor
to your
Cloud Build service account:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role=roles/bigquery.dataEditor
Acquire a configuration from a live deployment
If you want to acquire and convert the configuration of a live deployment, you
can retrieve the expanded configuration and save it to disk by running the
following commands, replacing DEPLOYMENT_NAME
with the
name of the deployment.
Cloud Build
export DEPLOYMENT_NAME=[DEPLOYMENT_NAME]
export MANIFEST_NAME=$(gcloud deployment-manager deployments \
describe $DEPLOYMENT_NAME \
--project $PROJECT_ID --format="value(deployment.manifest)" |\
grep -oEi "manifest-[0-9]+")
gcloud deployment-manager manifests describe $MANIFEST_NAME \
--deployment $DEPLOYMENT_NAME --project $PROJECT_ID \
--format="value(expandedConfig)" > deployment.yaml
# Grant additional roles to allow the Cloud Build service account to manage the
# resources in your deployment. For a list of roles, see
# https://cloud.google.com/iam/docs/understanding-roles.
# For example:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role=roles/pubsub.editor
# Alternatively, you may grant roles/editor for testing purposes:
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role=roles/editor
Alternate
# Configure your project/deployment
DEPLOYMENT_NAME=foo
PROJECT_ID=bar
# Fetch the latest manifest for the given deployment
gcloud deployment-manager deployments describe $DEPLOYMENT_NAME \
--project $PROJECT_ID --format="value(deployment.manifest)"
https://www.googleapis.com/deploymentmanager/v2/projects/$PROJECT_ID/global/deployments/bq/manifests/manifest-1618872644848
# The manifest name is the last path segment from the URI
# in the above command output
MANIFEST_NAME="manifest-1618872644848"
# Save the expanded manifest to deployment.yaml
gcloud deployment-manager manifests describe $MANIFEST_NAME \
--deployment $DEPLOYMENT_NAME --project $PROJECT_ID \
--format="value(expandedConfig)" > deployment.yaml
After you save the file, copy it to the Cloud Storage bucket you previously created:
gsutil cp ./deployment.yaml $DM_CONFIG_URI/deployment.yaml
Convert your existing deployment
This guide uses Cloud Build for the conversion process.
The build definition reads the Deployment Manager configuration from the
Cloud Storage bucket $DM_CONFIG_URI
, converts it to KRM or Terraform
format, and saves the output in the same Cloud Storage bucket.
Copy the following contents into a file called cloudbuild_convert.yaml
:
steps:
- id: '[FETCH_DM_CONFIG]'
name: 'gcr.io/cloud-builders/gsutil'
entrypoint: 'sh'
args:
- '-c'
- |
mkdir dm
gsutil cp "${_BUCKET_URI}/dm/*" dm/.
mkdir "${_OUTPUT_FORMAT}"
- id: '[CONVERT_DM_CONFIG]'
name: '${_DM_CONVERT_IMAGE}'
args: ['--config', './dm/deployment.yaml',
'--project_id', '${PROJECT_ID}',
'--project_number', '${PROJECT_NUMBER}',
'--output_format', '${_OUTPUT_FORMAT}',
'--output_file', '${_OUTPUT_FORMAT}/${_OUTPUT_FILE}',
'--deployment_name', '${_DEPLOYMENT_NAME}']
- id: '[EXPORT_OUTPUT_TO_STORAGE_BUCKET]'
name: 'gcr.io/cloud-builders/gsutil'
entrypoint: 'sh'
args:
- '-c'
- |
gsutil cp "${_OUTPUT_FORMAT}/${_OUTPUT_FILE}" \
"${_BUCKET_URI}/output/${_OUTPUT_FILE}"
You can invoke Cloud Build from the same folder as cloudbuild_convert.yaml
by
providing the following parameters:
_BUCKET_URI
: The Cloud Storage bucket to read a Deployment Manager configuration from and save the converted output into._OUTPUT_FORMAT
: The output format for the conversion. This can be eitherKRM
for KRM orTF
for Terraform._OUTPUT_FILE
: The name of the file to which the converted output will be saved in the Cloud Storage bucket._DM_CONVERT_IMAGE
: The container image to use._DEPLOYMENT_NAME
: The name of the deployment. This is relevant if you're using templates in your Deployment Manager configuration, and are also using thedeployment
environment variable. For more information, visit Using an environment variable.
Sample conversions
KRM
To convert the configuration to the KRM format and save it to
$BUCKET_URI/output/krm_resources.yaml
, run the following command:
export KRM_RESOURCES=krm_resources.yaml
gcloud builds submit --no-source --config cloudbuild_convert.yaml \
--substitutions=_DM_CONVERT_IMAGE=$DM_CONVERT_IMAGE,_BUCKET_URI=$BUCKET_URI,\
_DEPLOYMENT_NAME=test-conversion-to-krm,\
_OUTPUT_FORMAT=KRM,_OUTPUT_FILE=$KRM_RESOURCES
# Print output file
gsutil cat $BUCKET_URI/output/$KRM_RESOURCES
Terraform
To convert the configuration to the HCL format and save it as
$BUCKET_URI/output/tf_resources.tf
, run the following command:
export TF_RESOURCES=tf_resources.tf
gcloud builds submit --no-source --config cloudbuild_convert.yaml \
--substitutions=_DM_CONVERT_IMAGE=$DM_CONVERT_IMAGE,_BUCKET_URI=$BUCKET_URI,\
_DEPLOYMENT_NAME=test-conversion-to-tf,\
_OUTPUT_FORMAT=TF,_OUTPUT_FILE=$TF_RESOURCES
# Print output file
gsutil cat $BUCKET_URI/output/$TF_RESOURCES
Apply your converted configuration
KRM
Set up Config Connector
To actuate the resources in the KRM configuration files, you need a Kubernetes cluster with Config Connector installed. To create a test cluster, refer to Installing with the GKE add-on.
In Cloud Shell, ensure that your kubectl
credentials are configured for
the GKE cluster that you want to use. Replace
GKE_CLUSTER
with the name of the cluster, and run the
following command:
gcloud container clusters get-credentials GKE_CLUSTER
Deploy your converted KRM configuration by using kubectl
To deploy your converted KRM configuration using kubectl
, run the following
commands:
# Copy the converted configuration from the storage bucket
gsutil cp $BUCKET_URI/output/$KRM_RESOURCES $KRM_RESOURCES
# Ensure that the namespace is annotated to create resources in the correct
# project/folder/organization. https://cloud.google.com/config-connector/docs/how-to/install-upgrade-uninstall#specify
kubectl apply -n CONFIG_CONNECTOR_NAMESPACE -f $KRM_RESOURCES
# Wait for the resources to become healthy
kubectl wait -n CONFIG_CONNECTOR_NAMESPACE --for=condition=Ready \
--timeout=5m -f $KRM_RESOURCES
Terraform
Set up Terraform
Use the Cloud Storage bucket you previously created to configure Terraform with your Google Cloud project:
# Configure default project cat <<EOF > echo > main.tf provider "google" { project = "$PROJECT_ID" } EOF # Configure Cloud Storage remote backend to store state in gs://$BUCKET_NAME/tfstate cat <<EOF > echo > backend.tf terraform { backend "gcs" { bucket = "$BUCKET_NAME" prefix = "tfstate" } } EOF
Deploy your converted configuration by using Terraform
Create a local file called cloudbuild_tf.yaml
in the same folder as the
main.tf
and backend.tf
files that you previously created, and copy the
following into it:
steps:
- id: '[FETCH_DM_CONFIG]'
name: 'gcr.io/cloud-builders/gsutil'
entrypoint: 'sh'
args:
- '-c'
- |
# Fetch the latest manifest for the given deployment
gsutil cp $_BUCKET_URI/output/*.tf .
- id: '[APPLY_USING_TERRAFORM]'
name: 'hashicorp/terraform'
entrypoint: 'sh'
args:
- '-c'
- |
echo "*************** TERRAFORM INIT ******************"
# NOTE: if Terraform state gets corrupted during testing,
# use init --reconfigure to reset backend
terraform init
echo "*************** TERRAFORM PLAN ******************"
terraform plan
echo "************** TERRAFORM APPLY ******************"
terraform apply --auto-approve
Import existing resources
If you're converting an existing deployment, use
terraform import RESOURCE_TYPE RESOURCE_ID
to import the existing resources instead of provisioning them again by using
terraform apply
.
For example, if your existing deployment was:
resources:
- type: pubsub.v1.topic
name: sample-pubsub-topic
properties:
topic: sample-pubsub-topic
- type: pubsub.v1.subscription
name: sample-pubsub-subscription
properties:
topic: $(ref.sample-pubsub-topic.name)
subscription: sample-pubsub-subscription
According to the
import
section of the Terraform documentation for
google_pubsub_topic
,
terraform import
can take one of the following formats:
$ terraform import google_pubsub_topic.default projects/PROJECT_NAME/topics/NAME
$ terraform import google_pubsub_topic.default PROJECT_NAME/NAME
$ terraform import google_pubsub_topic.default NAME
Make the following substitutions:
PROJECT_NAME
is your project ID.NAME
is the Deployment Manager resource name, such assample-pubsub-topic
.default
is the Terraform resource name, which is the Deployment Manager resource name with all-
characters replaced with_
. You can also find the resource name by usinggsutil cat $BUCKET_URI/output/$TF_RESOURCES
to check the converted Terraform configuration.
After you make the substitutions, your command should be similar to:
$ terraform import google_pubsub_topic.sample_pubsub_topic
$PROJECT_ID/sample-pubsub-topic
The Terraform documentation for
google_pubsub_subscription
shows the following possible formats:
$ terraform import google_pubsub_subscription.default projects/PROJECT_NAME/subscriptions/NAME
$ terraform import google_pubsub_subscription.default PROJECT_NAME/NAME
$ terraform import google_pubsub_subscription.default NAME
One possible terraform import
command is:
$ terraform import google_pubsub_subscription.sample_pubsub_subscription
$PROJECT_ID/sample-pubsub-subscription
The Cloud Build definition for this command is:
steps:
- id: '[FETCH_DM_CONFIG]'
name: 'gcr.io/cloud-builders/gsutil'
entrypoint: 'sh'
args:
- '-c'
- |
# Fetch the latest manifest for the given deployment
gsutil cp $_BUCKET_URI/output/*.tf .
- id: '[APPLY_USING_TERRAFORM]'
name: 'hashicorp/terraform'
entrypoint: 'sh'
args:
- '-c'
- |
echo "*************** TERRAFORM INIT ******************"
# NOTE: if Terraform state gets corrupted during testing,
# use init --reconfigure to reset backend
terraform init
echo "*************** TERRAFORM PLAN ******************"
terraform plan
echo "************** TERRAFORM IMPORT ******************"
terraform import google_pubsub_topic.sample_pubsub_topic $PROJECT_ID/sample-pubsub-topic
terraform import google_pubsub_subscription.sample_pubsub_subscription $PROJECT_ID/sample-pubsub-subscription
Optionally, you can use Deployment Manager to delete the deployment, and
recreate the deployment with Terraform by using terraform apply
.
You can invoke Cloud Build from the same folder as the file you previously created, by providing the following parameters:
_BUCKET_URI
: The storage bucket where you stored your converted Terraform configuration.
gcloud builds submit . --config cloudbuild_tf.yaml \
--substitutions=_BUCKET_URI=$BUCKET_URI
Clean up
Clean up the sample dataset and table
KRM
To clean up the BigQuery dataset and table from the sample configuration, run:
# If the resource was created via Config Connector:
kubectl delete -n CONFIG_CONNECTOR_NAMESPACE -f $KRM_RESOURCES
Terraform
Save the following Cloud Build definition to
cloudbuild_tf_destroy.yaml
:
# If the resource was created via Terraform, save the following Cloud Build steps into cloudbuild_tf_destroy.yaml:
steps:
- id: '[FETCH_DM_CONFIG]'
name: 'gcr.io/cloud-builders/gsutil'
entrypoint: 'sh'
args:
- '-c'
- |
# Fetch the latest manifest for the given deployment
gsutil cp $_BUCKET_URI/output/*.tf .
- id: '[DESTROY_USING_TERRAFORM]'
name: 'hashicorp/terraform'
entrypoint: 'sh'
args:
- '-c'
- |
echo "*************** TERRAFORM INIT ******************"
terraform init
# NOTE: if Terraform state gets corrupted during testing,
# use init --reconfigure to reset backend
# Remove delete protection on BigQuery table
sed -i "/resource \"google_bigquery_table\"/a deletion_protection=\"false\"" tf_resources.tf
terraform apply --auto-approve
echo "*************** TERRAFORM DESTROY ****************"
terraform destroy --auto-approve
After you save the definition, run the following command:
gcloud builds submit . --config cloudbuild_tf_destroy.yaml \
--substitutions=_BUCKET_URI=$BUCKET_URI
Clean up your deployment
To abandon a live deployment that you successfully converted to KRM or Terraform, run:
gcloud deployment-manager deployments delete DEPLOYMENT_NAME --delete-policy ABANDON
Using DM Convert locally
If you want to iterate and debug locally, you can run DM Convert locally in Docker.
KRM
To convert the configuration in deployment.yaml
to the KRM format and save it to
krm_resources.yaml
, run the following command:
docker run --rm -it --workdir=/convert \
--volume=$(pwd):/convert \
us-central1-docker.pkg.dev/dm-convert-host/deployment-manager/dm-convert:public-preview \
--output_format krm \
--config deployment.yaml \
--output_file krm_resources.yaml
Terraform
To convert the configuration in deployment.yaml
to the HCL format and save it as
output.tf
, run the following command:
docker run --rm -it --workdir=/convert \
--volume=$(pwd):/convert \
us-central1-docker.pkg.dev/dm-convert-host/deployment-manager/dm-convert:public-preview \
--output_format tf \
--config deployment.yaml \
--output_file output.tf
To get a list of supported resources, you can use the --list_supported_types
flag for a given output format specified by using --output_format
.
KRM
To list supported resources for KRM, run the following command:
docker run --rm -it \
us-central1-docker.pkg.dev/dm-convert-host/deployment-manager/dm-convert:public-preview \
--output_format krm \
--list_supported_types
Terraform
To list supported resources for Terraform, run the following command:
docker run --rm -it \
us-central1-docker.pkg.dev/dm-convert-host/deployment-manager/dm-convert:public-preview \
--output_format tf \
--list_supported_types