Blog

Using Terraform and Altinity.Cloud to create ClickHouse® clusters in your cloud infrastructure

Using Terraform and Altinity.Cloud to create ClickHouse® clusters in your cloud infrastructure

Altinity.Cloud is the leading managed service for ClickHouse, giving you unmatched flexibility and scalability for analytical workloads. One of the most popular ways of using Altinity.Cloud is Bring Your Own Cloud (BYOC), which lets you create ClickHouse clusters in your infrastructure. That means you have complete control over the infrastructure beneath your ClickHouse clusters, perfect for customers with data sovereignty requirements. As well as customers who enjoy the phrase “complete control.” 

Terraform is an open-source Infrastructure as Code (IaC) tool that lets you define and provision cloud resources declaratively with configuration files. In this post, we’ll look at how Altinity’s Terraform provider lets you create Altinity.Cloud environments on the four major cloud platforms (AWS, GCP, Azure, and Hetzner Cloud). Do some minor setup, run the script, enjoy a refreshing beverage, and you’ve got a new Altinity.Cloud environment, ready for your ClickHouse clusters and data. 

Prerequisites

Before getting started, make sure you have the following:

  1. Terraform Installed: Download and install Terraform from the official website.
  2. An Altinity.Cloud Account: Sign up for an Altinity.Cloud account if you haven’t already. (Sign up now, thank us later.)
  3. An Altinity.Cloud API Token: Generate an API token in Altinity.Cloud for authentication. The Altinity API Guide includes complete instructions on generating an Altinity.Cloud Anywhere API token.
  4. Cloud Provider Access: Forgive us for stating the obvious, but the cloud account you’re using must have permission to create resources. In testing we’ve often been surprised: “Hmmm. Guess I can’t create GCP projects after all.”

It’s also possible that your account with your cloud provider may not have the capacity to allocate more resources, either globally or for the particular region you specified in your Terraform script. You’ll have to work that out with the in-house administrator for your cloud provider. 

Setting Up the Terraform Configuration

Terraform uses .tf files to define infrastructure. You’ll need two files: one that tells Terraform how to find the Altinity provider, and one that has the details the Altinity provider needs to create an Altinity.Cloud environment in your cloud account. 

Define the Altinity Terraform Provider

No matter what provider you’re using, create a version.tf file so Terraform can find the Altinity provider:

terraform {
  required_providers {
    altinitycloud = {
      source = "altinity/altinitycloud"
      # https://github.com/altinity/terraform-provider-altinitycloud/blob/master/CHANGELOG.md
      version = "0.4.4"
    }
  }
}
provider "altinitycloud" {
  # `api_token` can be omitted if ALTINITYCLOUD_API_TOKEN env var is set.
  api_token = “ABCDEFGHI” 
}

In the second section, the Altinity provider uses the api_token variable to work with your Altinity.Cloud account. (The token is from prerequisite #3 above.) You can put the api_token directly in the script as we did here, but…don’t. Define it in the ALTINITYCLOUD_API_TOKEN environment variable instead. 

The main script

Next you’ll create a script named main.tf. For each provider we’ll start with a sample script from the Altinity Terraform provider’s documentation. Overall, it will look something like this: 

resource "altinitycloud_env_certificate" "this" {
  env_name = "altinity-maddie01"
}

provider "aws" {
  region = "us-west-2"
}

module "altinitycloud_connect_aws" {
  source = "altinity/connect-aws/altinitycloud"
  pem    = altinitycloud_env_certificate.this.pem
}

resource "altinitycloud_env_aws" "this" {
  name           = altinitycloud_env_certificate.this.env_name
  aws_account_id = "123456789012"
  region         = "us-west-2"
  zones          = ["us-west-2a", "us-west-2b"]
  cidr           = "10.67.0.0/21"
  load_balancers = {
    . . .
  }
  node_groups = [
    . . .
  ]
  cloud_connect = true
  depends_on = [
    module.altinitycloud_connect_aws
  ]
}

data "altinitycloud_env_aws_status" "this" {
  name                           = altinitycloud_env_aws.this.name
  wait_for_applied_spec_revision = altinitycloud_env_aws.this.spec_revision
}

This example is for AWS, but the scripts are similar for each provider. (This is obviously fake data, although readers are kindly asked to let us know if you can actually provision anything with account number 12345678012.)

All four scripts we’ll look at here end with a section like the one just above: 

data “altinitycloud_env_aws_status” “this” {
  name                           = altinitycloud_env_aws.this.name
  wait_for_applied_spec_revision = altinitycloud_env_aws.this.spec_revision
}

(Obviously aws is replaced with azure, gcp, and hcloud in the various scripts.) 

Terraform waits until the data source fully matches the environment specifications. This won’t happen until all required cloud resources are actually provisioned. Environment provisioning is asynchronous, so the fact that an environment is created doesn’t mean all of the environment’s resources are provisioned. (It’s like the difference between Kubernetes startup probes and readiness probes.)

The details

Now we’ll look at the details of using Terraform with the four major cloud providers. There are several things they have in common, all of which have values specific to each provider: 

  • A region, such as us-east-1.
  • One or more availability zones, such as us-east-1a or us-east1-b.
  • The node types used in your Altinity.Cloud environment, such as t4g.large, Standard_B2s_v2, n2d-standard-2, or cpx11.
  • A CIDR block from your private IP addresses, such as 10.67.0.0/21. At least /21 is required. 

Beyond those values, there are details specific to each provider. The following subsections show how to customize your main.tf file, starting with the sample scripts in the Altinity Terraform provider documentation. With your main.tf file customized, you’ll be ready to move on to the next section, Making the magic happen, where you’ll deploy your script. For now, jump ahead to the details for your provider: 

Creating a BYOC environment on AWS with Terraform

Before you start, you’ll need to set the environment variables AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN. With that done, create main.tf based on the AWS with public load balancer script. (The altinitycloud_env_aws documentation has other scripts; it’s possible one of the others might better suit your needs.)

At the top of the script, the env_name is the name of the Altinity.Cloud environment Terraform will create. It must start with your Altinity account name. 

resource "altinitycloud_env_certificate" "this" {
  env_name = "acme-staging"
}

The environment name is part of the certificate resource. The certificate is used by this module: 

module "altinitycloud_connect_aws" {
  source = "altinity/connect-aws/altinitycloud"
  pem    = altinitycloud_env_certificate.this.pem
}

The module creates an EC2 instance with a VPC, and that EC2 instance runs an altinitycloud-connect daemon. The instance is a proxy between Altintiy.Cloud Anywhere and your AWS account. The certificate is what allows the EC2 instance to authenticate to Altinity.Cloud Anywhere. 

You’ll need your 12-digit AWS account number here: 

resource "altinitycloud_env_aws" "this" {
  . . . 
  aws_account_id = "123456789012"
  . . . 
}

Beyond the usual parameters of region, zones, and node_group / node_type, those are the things you’ll need to set. 

The Altinity.Cloud Anywhere documentation has a section on deploying an AWS BYOC environment with Terraform if you want more details. (The documentation for the AWS Terraform provider might be useful as well.)

Jump ahead to Making the magic happen when your scripts are ready to go!

Creating a BYOC environment on Azure with Terraform

Start by logging in to your Azure account with az login. (If you haven’t already, you’ll need to install the Azure command-line tool.) With that done, create a main.tf file based on the Azure environment with public load balancer script. You’ll need the following changes:

Add your tenant_id and subscription_id to the script: 

locals {
  # Replace these values with your own Azure tenant and subscription IDs
  tenant_id       = "a1b2c3d4-e5f6-a1b2-c3d4-a1b2c3d4e5f6"
  subscription_id = "a1b2c3d4-e5f6-a1b2-c3d4-a1b2c3d4e5f6"
}

The client_id here belongs to the Altinity service account; don’t change it. 

data "azuread_service_principal" "altinity_cloud" {
  # Do not change this client_id
  client_id = "8ce5881c-ff0f-47f7-b391-931fbac6cd4b"
}

The name here is your new Altinity.Cloud environment. It must start with your Altinity account name. 

resource "altinitycloud_env_azure" "azure" {
  name            = "acme-staging"
  . . . 
}

Beyond the usual parameters of region, zones, and node_group / node_type, those are the only things specific to your new environment that you’ll need to set. 

For more information, there is a section on provisioning resources in Azure with Terraform in the Altinity.Cloud Anywhere docs. Documentation on the Azure Terraform provider itself is also available if you need it. 

Ready to go? Jump ahead to Making the magic happen.

Creating a BYOC environment on GCP with Terraform

Start by logging in to your GCP account with gcloud auth login at the command line. (See the gcloud install instructions if you don’t have the tool already.) From there, create a main.tf file based on the sample Terraform script for creating a GCP environment with a public load balancer. We’ll look at the parameters you need to specify.

To start, you need the project_id and name of the GCP project Terraform should create. (Obviously you have to have permissions to create a project.) 

resource "google_project" "this" {
  project_id          = "gcp-20241209"
  name                = "maddie-07"
}

Depending on your GCP account and how you set up your credentials, you may also need the folder_id where the project should be created and your account’s billing_account number. See the Altinity.Cloud Anywhere Terraform / GCP documentation for details on these parameters. 

The IAM section defines a number of roles that should be given to the Altinity service account that will create and manage resources in your environment. Don’t change the member field here; it should be group:anywhere-admin@altinity.com.

resource "google_project_iam_member" "this" {
  . . .
  member  = "group:anywhere-admin@altinity.com"
}

In the section that defines all the GCP resources your BYOC environment needs, the name field is the name of the Altinity.Cloud environment you’re creating. It has to start with your Altinity account name. 

resource "altinitycloud_env_gcp" "this" {
  name           = "acme-staging"
  . . . 
}

You also need to define the region, zones, and the node_type for each node_group. See the GCP documentation for the Terraform provider for complete details of all of the Altinity-specific parameters and options. You may need the Google Terraform provider documentation as well.

With everything set up, jump ahead to Making the magic happen.

Creating a BYOC environment on Hetzner Cloud with Terraform

Before you create a BYOC environment in the Hetzner cloud, you need to do the following two things: 

  1. Create a new project in your Hetzner account
  2. Create an API key with read/write permissions in that project

Assign the key to the environment variable TF_VAR_hcloud_token. The key has all of the authentication information Hetzner needs. We will encrypt this key and save it as part of the environment specification.

Now create a main.tf file based on the sample Terraform script for creating a Hetzner Cloud environment with a public load balancer. Customize it like this: 

Give your new Altinity.Cloud environment a name. The env_name must start with your Altinity account name. 

You’ll also need a network_zone and locations, similar to the region and zones of the other providers. Details on network zones and locations are on the Hetzner site. 

resource "altinitycloud_env_hcloud" "this" {
  name             = "acme-staging"
  network_zone     = "us-west"
  locations        = ["hil"]
  . . . 
}

For the node_groups, you’ll need to define the node_name, node_type, and locations. (Using the node_type as the node_name is recommended but not required.)

You can find the details of all the parameters in the documentation for the Altinity Terraform provider. Finally, jump ahead to Making the magic happen when your scripts are ready to go. (It’s a short jump.)

Making the magic happen

Once you’ve configured your scripts with the information Terraform needs to provision everything, it’s time to sit back and let Terraform do the work.

Apply the configuration

To initialize and apply the Terraform configuration, run these two commands in the directory where your version.tf and main.tf files are:

# Initialize Terraform and download providers
terraform init

# Apply the configuration
terraform apply

Terraform will provision the BYOC environment and output the status of the created resources. Depending on the resources you’re provisioning, the terraform apply command will probably take a while. But when it’s done, you’ll have a complete BYOC environment in your Altinity.Cloud account. 

As we discussed above, the data source at the end of the script ensures that Terraform waits until your cloud provider has provisioned all of the resources requested for your new environment. 

Verifying the Deployment

Once the Terraform script completes, log in to your Altinity.Cloud account and verify that the BYOC environment is listed under your environments. Go to your environment and click the Clusters tab; you won’t have any clusters, but the Altinity Cloud Manager makes it easy to create and manage them. Read on…

Creating ClickHouse clusters in your BYOC environment 

You’re ready to create a ClickHouse cluster, so click the LAUNCH CLUSTER button to start the Launch Cluster Wizard: 

The wizard takes you through panels that let you define the characteristics of your new ClickHouse cluster. For example, here’s step 4, which defines the connectivity of your cluster: 

Simply select the options you want on each panel. At a minimum, give your cluster a name and a password, select the type of nodes it should run on, and take the defaults everywhere else. When you’re ready, click the CREATE button on the last panel. In a few minutes, you’ll have a running ClickHouse cluster in your new environment. 

See the documentation for complete details on complete details on the Launch Cluster Wizard. If you’d like to know even more, the Altinity docs also include a high-level overview of the BYOC architecture

Advantages of using Terraform to create Altinity.Cloud BYOC environments

There’s a reason Terraform is so popular; it makes it easy to provision infrastructure. With the scripts we’ve looked at here, there are several benefits:

  • Simplicity – Let Terraform handle the details of creating and provisioning the resources you need.  
  • Reproducibility – Maintain consistent infrastructure definitions for testing and production environments.
  • Automation – Reduce manual configuration efforts by leveraging Terraform’s declarative syntax. 
  • Scalability – Easily adjust resource definitions to accommodate workload changes.

Conclusion

Using Terraform to provision BYOC environments in Altinity.Cloud simplifies the setup and configuration process. Once your environment is up and running, creating and managing ClickHouse clusters is straightforward. We encourage you to provision a new environment with Terraform in your Altinity.Cloud account today. (And we re-encourage you to sign up for a free trial account if you don’t have one already.) Enjoy!

Share

ClickHouse® is a registered trademark of ClickHouse, Inc.; Altinity is not affiliated with or associated with ClickHouse, Inc.

Table of Contents:

Related: