Using Terraform to Deploy Cloud Block Store in Azure
This KB is updated for Terrafrom-provider-cbs v0.7.0
Introduction
This document demonstrates the steps required to deploy Pure Cloud Block Store (CBS) in Azure using Terraform.
Requirements
CBS Prerequisites
A number of mandatory resources have to be checked and configured prior to deployment, please refer to the Cloud Block Store Deployment and Configuration Guide for Azure for more details on the following high-level steps:
- Region selected is supported by CBS.
- Have an Azure Active Directory Premium 2 license.
- Set the appropriate User IAM roles and permissions.
- Networking - VNet and Subnets.
- Networking – Outbound Internet access using NAT GW or Azure Firewall.
- Networking – service endpoint (CosmosDB and KeyVault) attached to the designated subnet.
- Cloud Block Store license key.
For POC purposes, there is a Quick Launch Terraform module that would create all the CBS prerequisites and also deploy CBS with a Jump Host. Refer to this link: cloudblockstore-quicklaunch github repo
Terraform Prerequisites
The following are infrastructure and resources are mandatory for successful Terraform deployment:
Local or Virtual Machine
The machine running Terraform code whether its local machine or an Azure VMIt has to have two characteristics:
- Has connectivity to CBS Azure VNet network mentioned in the previous section.
- Can authenticate to Azure using one of the methods listed below: Azure CLI or Azure Service Principle.
The recommended method for connectivity is to have an Azure VM to run the Terraform code, Then peer the VM VNet with the CBS VNet.
Example for Azure Portal, Azure CLI, and PowerShell can be found here Create a peering
Install Terraform
Download and install the appropriate Terraform package for your operating system and hardware architecture via the link below:
Download CBS Terraform provider files 
Create a new directory for the Terraform deployment, and copy or download Terraform provider sample for CBS Azure (Three files shown on the screenshot)from the below link:
https://github.com/PureStorage-OpenConnect/terraform-provider-cbs/tree/main/examples/azure_array
Authenticate to Azure
There are two ways to authenticate to an Azure account:
1. Azure CLI
Download and install the latest version of the Azure CLI tool via the link below:
https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
For authentication, log in to the Azure CLI:
az login
And list the Subscriptions associated with the account:
az account list
if the user logging in has more than one Subscription. Specify the Subscription to be the default:
az account set --subscription="SUBSCRIPTION_ID"
2.Azure Service Principal
Terraform can be authenticated with a Service Principal in the provider configuration under main.tf file by adding the following:
provider "cbs" { azure { client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" client_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } }
For step-by-step on how to create Azure Service Principle, follow this link: Creating a Service Principal in the Azure Portal
Key Vault
Along with the infrastructure components defined in the CBS Prerequisite, an Azure Key Vault is required to deploy Cloud Block Store in Azure using Terraform. An existing Key Vault may be used, or a new one can be created for the array. Multiple arrays may reuse the same Key Vault.
Any Azure account that wishes to use Terraform to perform management operations on the array must be granted Get
, Set
, Delete
, List
, and Recover
permissions on secrets within the Key Vault. All secrets created or accessed by the CBS Terraform Provider will use a cbs-
prefix.
An example Key Vault creation using the azurerm_key_vault
resource from the azurerm provider is shown below.
## Add This snippet to main.tf data "azurerm_client_config" "client_config" {} // Key Vault name must be globally unique resource "random_id" "vault_id" { byte_length = 8 } resource "azurerm_key_vault" "cbs_key_vault" { name = "cbs-${random_id.vault_id.hex}" location = "location_xxxx" resource_group_name = "resource_yyyy" tenant_id = data.azurerm_client_config.client_config.tenant_id sku_name = "standard" access_policy { tenant_id = data.azurerm_client_config.client_config.tenant_id object_id = data.azurerm_client_config.client_config.object_id secret_permissions = ["Get", "Set", "Delete", "List", "Recover"] } } resource "cbs_array_azure" "azure_instance" { array_name = "terraform-example-instance" location = "location_xxxx" resource_group_name = "resource_xxxx" license_key = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx" log_sender_domain = "example-company.org" alert_recipients = ["admin1@example-company.org", "admin2@example-company.org"] array_model = "V10MUR1" zone = 1 key_vault_id = azurerm_key_vault.cbs_key_vault.id pureuser_private_key_path = "/path/to/private_key" virtual_network_id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx/resourceGroups/mock_resource_group_name/providers/Microsoft.Network/virtualNetworks/xxxxxxxx", management_subnet = "SN-xxxxxxxxxxxxxx" system_subnet = "SN-xxxxxxxxxxxxxx" iscsi_subnet = "SN-xxxxxxxxxxxxxx" replication_subnet = "SN-xxxxxxxxxxxxxx" jit_approval_group_object_ids = ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"] }
Private Key
In order to set up long term management of new arrays, the provider must obtain access to the array during deployment in order to obtain management credentials. In order to accomplish this, the provider must be supplied a private SSH key, either a file path to the key with the pureuser_private_key_path
parameter or the key text itself with the pureuser_private_key
parameter. The management credentials are stored in the Azure Key Vault that is specified by the key_vault_id
parameter. To retrieve the credentials, the provider requires access to the management port of the array, and therefore the machine running Terraform must be able to access the management subnet used for the array.
Deployment
By navigating to the downloaded Terraform sample, use any text editor to edit the terraform.tfvars file and fill the prerequisites. An example screenshot is provided below for additional guidance.
Variables Reference:
array_name
(Required) - Name of the array, and the name of the managed application.location
(Required) - Azure location in which to deploy the array.resource_group_name
(Required) - Name of the resource group in which to deploy the managed application.license_key
(Required) - Pure Storage-provided license key.
- For Evaluation Mode Trial License use this key: CBS-TRIAL-LICENSElog_sender_domain
(Required) - Domain name used to determine how CBS logs are parsed and treated by Pure Storage Support and Escalations.alert_recipients
(Optional) - List of email addresses to receive alerts.array_model
(Required) - CBS array size to launch. The possible values areV10MUR1
orV20MUR1
.zone
(Required) - The Availability Zone within the deployment location.virtual_network_id
(Required) - Virtual network id that contains the network interfaces of the array.key_vault_id
(Required) - Key Vault where provider stores sensitive information
- Do not include this on terraform.tfvars nor variable.tf if you would like to use the Terraform code from Key Vault section.management_subnet
(Required) - Subnet containing the management interfaces on the array.system_subnet
(Required) - Subnet for the system interface of the Array.iscsi_subnet
(Required) - Subnet containing the iSCSI interfaces on the array.replication_subnet
(Required) - Subnet containing the replication interfaces on the array.jit-groups-ids
(Required) - A list of Azure Active Directory groups that enable their users to approve JIT access requests.plan_name
(Required) - Specifies the name of the plan from the marketplace.plan_product
(Required) - Specifies the product of the plan from the marketplace.plan_publisher
(Required) - Specifies the publisher of the plan.pureuser_private_key_path
(Required) - File path of the private key to enable SSH access to the controllers. You must specify onepureuser_private_key_path
or onepureuser_private_key
.pureuser_private_key
(Required) - Text content of the private key to enable SSH access to the controllers. You must specify onepureuser_private_key_path
or onepureuser_private_key
.tags
(Optional) - A list of tags to apply to all resources in the managed application.
Save the changes to the file, and open a terminal window and navigate to the Terraform deployment directory that has been created, and Run terraform init command to initialize the working directory.
Next, Run the terraform plan command to create the execution plan.
Finally, Run the terraform apply command to execute the plan and start deploying.
The Cloud Block Store deployment process takes around 10 to 15 minutes. Go to Azure Managed Applications, A new managed application should be created and in the deployment state.
Once the terraform apply command is complete, Run terraform show command to list the output information of the CBS deployment stack. This includes the management IP address that is used to log into the CBS.
More information can be found by logging to Azure console and navigating to Managed Application, then under the tab Parameters and Output. The Management IP address used to log in CBS is addressed as FloatingManagementIP.
Use the Management IP address to log into GUI Management Console via any browser. To access the CBS instance via CLI, refer to Logging onto CBS via CLI section in the Deployment and Configuration Guide.
Do not use the terraform destroy command to destroy Cloud Block Store instance deployed via Terraform. Please refer to Removing Cloud Block Store section in the Deployment and Configuration Guide and follow the instructions.
Troubleshoot
Marketplace Offer Terms are not Accepted
╷ │ Error: failed to create Managed Application "tf-adam-fusion-cbs-EASTUS-CBS" (Resource Group "tf-adam-fusion-cbs-EASTUS"): managedapplications.ApplicationsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="ResourcePurchaseValidationFailed" Message="User failed validation to purchase resources. Error message: 'You have not accepted the legal terms on this subscription: '81cefe76-78c0-4df5-a564-e900f1ae2ba0' for this plan. Before the subscription can be used, you need to accept the legal terms of the image. To read and accept legal terms, use the Azure CLI commands described at https://go.microsoft.com/fwlink/?linkid=2110637 or the PowerShell commands available at https://go.microsoft.com/fwlink/?linkid=862451. Alternatively, deploying via the Azure portal provides a UI experience for reading and accepting the legal terms. Offer details: publisher='purestoragemarketplaceadmin' offer = 'pure_storage_cloud_block_store_deployment', sku = 'cbs_azure_6_4_5', Correlation Id: 'a13685de-a008-48a8-8ff8-ecfcfd00e043'.'" │ │ with cbs_array_azure.azure_cbs, │ on main.tf line 200, in resource "cbs_array_azure" "azure_cbs": │ 200: resource "cbs_array_azure" "azure_cbs" {
To resolve this, you can choose to accept the offer via Azure CLI or Azure PowerShell SDK.
CLI
az vm image terms accept [--offer] [--plan] [--publisher]
Example (Parameters from the error above):
az vm image terms accept --offer "pure_storage_cloud_block_store_deployment" --plan "cbs_azure_6_4_5" --publisher "purestoragemarketplaceadmin"
PowerShell
Get-AzMarketplaceTerms -Publisher '<publisher name>'-Product '<product name>' -Name '<plan name>' | Set-AzMarketplaceTerms -Accept
Example (Parameters from the error above):
Get-AzMarketplaceTerms -Publisher 'purestoragemarketplaceadmin' -Product 'pure_storage_cloud_block_store_deployment' -Name 'cbs_azure_6_4_5' | Set-AzMarketplaceTerms -Accept
Marketplace Plan already Exists
If you have already deployed the same version of Cloud Block Store (ex: 6.4.2) in the same subscription. You might get the below error after applying the code.
azurerm_key_vault.cbs_key_vault: Creation complete after 2m34s [id=/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/
cbs-tf-poc-EASTUS/providers/Microsoft.KeyVault/vaults/CBS-5f131be82ec77ade]
╷
│ Error: A resource with the ID "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.MarketplaceOrdering/agreements/
purestoragemarketplaceadmin/offers/pure_storage_cloud_block_store_deployment/plans/cbs_azure_6_4_2"
already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_marketplace_agreement" for more information.
│
│ with azurerm_marketplace_agreement.plan,
│ on main.tf line 27, in resource "azurerm_marketplace_agreement" "plan":
│ 27: resource "azurerm_marketplace_agreement" "plan" {
│
To resolve this, you would need to import the plan to Terraform state
terraform import azurerm_marketplace_agreement.plan /subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.MarketplaceOrdering/agreements/purestoragemarketplaceadmin/offers/pure_storage_cloud_block_store_deployment/plans/cbs_azure_6_4_2