Service Tickets
Gain technical support
检测到您已登录华为云国际站账号,为了您更好的体验,建议您访问国际站服务网站 https://www.huaweicloud.com/intl/zh-cn
不再显示此消息
检测到您已登录华为云国际站账号,为了您更好的体验,建议您访问国际站服务网站 https://www.huaweicloud.com/intl/zh-cn
不再显示此消息
中国站
简体中文A virtual private cloud (VPC) is a virtual network dedicated to your Huawei Cloud account. It is logically isolated from other virtual networks in the Huawei Cloud. You can launch cloud resources, such as ECS instances, into your VPC.
A networking connection called a VPC peering connection allows you to route traffic between two VPCs using their respective private IPv4 or IPv6 addresses. It is possible for instances in either VPC to talk with one another as though they were on the same network.
Terraform is a robust open-source Infrastructure as Code (IaC) software tool offered by HashiCorp. Terraform facilitates the provisioning and managing your on-prem and cloud resources and automates these practices. In addition, infrastructure as code enables versioning and speeds up testing processes.
In this article, you will comprehend the following steps by using Terraform.
First of all, you need to install Terraform on your local device.
Install Terraform [https://developer.hashicorp.com/terraform/downloads]
You can find the essential commands for other operating systems from the link above.
Below you can see the required code snippets for Ubuntu/Debian. In this article, you will see how to create Huawei Cloud resources on a local device with Ubuntu installed.
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
After successful installation, you can start writing terraform code.
Terraform language is defined in terms of a syntax called HCL (Hashicorp Configuration Language). HCL is a declarative language. Terraform has different variables like resources, data, outputs, and more...
Every Terraform configuration has at least one module, known as the root module, in its main working directory. The main module can include the configurations of its resources by calling other modules. These modules are called child modules. These child modules can be used multiple times to reduce code duplication. In the following, you can see the structure of the modules.
demo
┣ external
┃ ┗ ssh_key_gen.sh
┣ modules
┃ ┣ ecs
┃ ┃ ┣ main.tf
┃ ┃ ┣ output.tf
┃ ┃ ┗ variable.tf
┃ ┣ peering
┃ ┃ ┣ main.tf
┃ ┃ ┣ output.tf
┃ ┃ ┗ variable.tf
┃ ┗ vpc
┃ ┃ ┣ main.tf
┃ ┃ ┣ output.tf
┃ ┃ ┗ variable.tf
┣ main.tf
┣ output.tf
┣ terraform.auto.tfvars
┗ variable.tf
Keypair resources were created with a bash script that creates an ssh key using Terraform's external data source.
#!/bin/bash
# generate ssh key pair file name
# with 8 digits random characters
FILE_NAME="KeyPair-$(
cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 8
echo
)"
# Check if the .ssh file is in the directory
# and create the .ssh file if it isn't.
if [[ ! -d "./external/.ssh" ]]; then
mkdir ./external/.ssh
fi
# file path
ssh_key_file="./external/.ssh/${FILE_NAME}"
# check if such a file exists in the directory
# and generate an ssh key file.
if [[ ! -f "${ssh_key_file}" ]]; then
ssh-keygen -q -t rsa -N '' -b 2048 -v -f $ssh_key_file -m PEM
fi
# add .pem extension to the file
mv ${ssh_key_file} "${ssh_key_file}.pem"
jq -n \
--arg key_file_name "$FILE_NAME" \
--arg public_key "$(cat ${ssh_key_file}.pub)" \
'{"key_file_name":$key_file_name, "public_key":$public_key}'
ecs/main.tf
data "external" "ssh_key_generator" {
program = ["bash", "${path.root}/external/ssh_key_gen.sh"]
}
resource "huaweicloud_compute_keypair" "keypair" {
name = "${data.external.ssh_key_generator.result.key_file_name}"
public_key = "${data.external.ssh_key_generator.result.public_key}"
}
Terraform must store the state of your managed infrastructure and configuration. Terraform uses this state to map real-world resources to your configuration, track information, and boost efficiency for huge infrastructures. This state is typically kept in a local file called "terraform.tfstate", but it can also be kept remotely, which is better for collaborative environments.
You will see how to keep "terraform.state" file in Object Storage Service using Terraform s3 backend.
Firstly, we create a bucket named vpcpeeringbucket in Object Storage Service.
Added terraform code containing the following backend configurations to the main.tf file representing the root module.
main.tf
terraform {
required_providers {
huaweicloud = {
source = "huaweicloud/huaweicloud"
version = ">= 1.20.0"
}
}
backend "s3" {
bucket = "vpcpeeringbucket"
key = "peering/terraform.tfstate"
region = "ap-southeast-3"
endpoint = "https://obs.ap-southeast-3.myhuaweicloud.com"
skip_region_validation = true
skip_credentials_validation = true
skip_metadata_api_check = true
}
}
The module sets up a vpc and a subnet that belongs to this vpc. Also, you can set the CIDR block type, gateway IP, and DNS list of the vpc.
vpc/variable.tf
variable "cidr_block" {}
variable "subnet_cidr_block" {}
variable "subnet_gateway_ip" {}
vpc/main.tf
resource "random_string" "this" {
length = 8
lower = true
numeric = true
special = false
}
locals {
dns_list = ["100.125.1.250", "100.125.129.250"]
}
resource "huaweicloud_vpc" "vpc" {
name = "vpc-${random_string.this.id}"
cidr = var.cidr_block
}
resource "huaweicloud_vpc_subnet" "subnet" {
vpc_id = huaweicloud_vpc.vpc.id
name = "subnet-${random_string.this.id}"
cidr = var.subnet_cidr_block
gateway_ip = var.subnet_gateway_ip
dns_list = local.dns_list
}
The module setup an ECS instance belonging to a specific subnet and opens it to the internet with EIP.
ecs/variable.tf
variable "flavor" {}
variable "subnet_id" {}
variable "os_name" {}
variable "disk_type" {}
variable "eip_publicip_type" {}
variable "eip_size" {}
variable "eip_share_type" {}
variable "eip_charge_mode" {}
variable "secg_direct" {}
variable "ethertype" {}
variable "ip_addr" {}
variable "admin_pass" {}
ecs/main.tf
resource "random_string" "this" {
length = 8
lower = true
numeric = true
special = false
}
data "huaweicloud_images_image" "os_image" {
name = var.os_name
most_recent = true
}
# Security Group that allows for every incoming request.
resource "huaweicloud_networking_secgroup" "secgroup" {
name = "secg-${random_string.this.id}"
}
resource "huaweicloud_networking_secgroup_rule" "rule" {
security_group_id = huaweicloud_networking_secgroup.secgroup.id
direction = var.secg_direct
ethertype = var.ethertype
remote_ip_prefix = var.ip_addr
}
# SSH keypair file
data "external" "ssh_key_generator" {
program = ["bash", "${path.root}/external/ssh_key_gen.sh"]
}
resource "huaweicloud_compute_keypair" "keypair" {
name = "${data.external.ssh_key_generator.result.key_file_name}"
public_key = "${data.external.ssh_key_generator.result.public_key}"
}
resource "huaweicloud_compute_instance" "ecs" {
name = "ecs-${random_string.this.id}"
image_id = data.huaweicloud_images_image.os_image.id
flavor_id = var.flavor
security_groups = [huaweicloud_networking_secgroup.secgroup.name]
key_pair = huaweicloud_compute_keypair.keypair.name
system_disk_type = var.disk_type
admin_pass = var.admin_pass
network {
uuid = var.subnet_id
}
}
# Create elastic ip address for ecs instance and associate to it
resource "huaweicloud_vpc_eip" "ecs_eip" {
publicip {
type = var.eip_publicip_type
}
bandwidth {
name = "bandwith-${random_string.this.id}"
size = var.eip_size
share_type = var.eip_share_type
charge_mode = var.eip_charge_mode
}
}
resource "huaweicloud_compute_eip_associate" "ecs_eip_associated" {
public_ip = huaweicloud_vpc_eip.ecs_eip.address
instance_id = huaweicloud_compute_instance.ecs.id
}
The module provides a peering connection between VPCs and routing to each other with CIDR blocks.
peering/variable.tf
variable "vpc" {}
variable "peer_vpc" {}
peering/main.tf
resource "random_string" "this" {
length = 8
lower = true
numeric = true
special = false
}
# Create peering connection
resource "huaweicloud_vpc_peering_connection" "peering" {
name = "peering-${var.vpc.name}_${var.peer_vpc.name}"
vpc_id = var.vpc.id
peer_vpc_id = var.peer_vpc.id
}
resource "huaweicloud_vpc_route" "route1" {
vpc_id = var.vpc.id
destination = var.peer_vpc.cidr
type = "peering"
nexthop = huaweicloud_vpc_peering_connection.peering.id
}
resource "huaweicloud_vpc_route" "route2" {
vpc_id = var.peer_vpc.id
destination = var.vpc.cidr
type = "peering"
nexthop = huaweicloud_vpc_peering_connection.peering.id
}
main.tf
Add Huawei Cloud's Terraform registry
provider "huaweicloud" {
region = local.region
access_key = var.auth_accesskey
secret_key = var.auth_secretkey
}
An expression is given a name by a local variable, allowing you to reuse the name within a module rather than repeating the expression.
locals {
region = "ap-southeast-1"
vpc = [
{
cidr_block = "10.123.0.0/22"
subnet_cidr_block = "10.123.0.0/24"
subnet_gateway_ip = "10.123.0.1"
},
{
cidr_block = "10.10.12.0/22"
subnet_cidr_block = "10.10.12.0/24"
subnet_gateway_ip = "10.10.12.1"
},
{
cidr_block = "10.57.240.0/22"
subnet_cidr_block = "10.57.240.0/24"
subnet_gateway_ip = "10.57.240.1"
}
]
}
module "vpc" {
source = "./modules/vpc"
count = length(local.vpc)
cidr_block = local.vpc[count.index].cidr_block
subnet_cidr_block = local.vpc[count.index].subnet_cidr_block
subnet_gateway_ip = local.vpc[count.index].subnet_gateway_ip
}
locals {
ecs_flavor = "s3.large.2"
ubuntu_18_04 = "Ubuntu 18.04 server 64bit"
all_ip_addr = "0.0.0.0/0"
disk_type = "SAS"
subnet_ids = module.vpc[*].subnet_id
}
module "ecs" {
source = "./modules/ecs"
count = length(local.subnet_ids)
subnet_id = local.subnet_ids[count.index]
flavor = local.ecs_flavor
os_name = local.ubuntu_18_04
disk_type = local.disk_type
eip_publicip_type = var.eip_dynamic_bgp
eip_size = var.eip_size_eight
eip_share_type = var.eip_dedicated
eip_charge_mode = var.eip_traffic
secg_direct = var.secg_ingress_direct
ethertype = var.ipv4_ethertype
ip_addr = local.all_ip_addr
admin_pass = var.admin_pass
}
locals {
peering = [
{
vpc = module.vpc[0]
peer_vpc = module.vpc[1]
},
{
vpc = module.vpc[0]
peer_vpc = module.vpc[2]
},
{
vpc = module.vpc[1]
peer_vpc = module.vpc[2]
}
]
}
module "peering" {
source = "./modules/peering"
count = length(local.peering)
vpc = local.peering[count.index].vpc
peer_vpc = local.peering[count.index].peer_vpc
}
Without changing the source code of the module, input variables allow you to tweak some features of Terraform modules. With the help of this functionality, you may exchange modules among several Terraform setups, making your module reusable and composable.
variable.tf
variable "auth_accesskey" {
description = "The access key id of the user's account"
type = string
sensitive = true
}
variable "auth_secretkey" {
description = "The secret key id of the user's account"
type = string
sensitive = true
}
variable "admin_pass" {
type = string
sensitive = true
}
variable "secg_ingress_direct" {
type = string
default = "ingress"
}
variable "ipv4_ethertype" {
type = string
default = "IPv4"
}
variable "eip_traffic" {
type = string
default = "traffic"
}
variable "eip_dedicated" {
type = string
default = "PER"
}
variable "eip_size_eight" {
type = number
default = 8
}
variable "eip_dynamic_bgp" {
type = string
default = "5_bgp"
}
Output values reveal data that other Terraform configurations can use and make information about your infrastructure available on the command line.
output.tf
output "ecs" {
value = [for ecs in module.ecs[*] : {
id = ecs.id
name = ecs.name
private_ip = ecs.fixed_ip_v4
public_ip = ecs.eip
key_file = ecs.keypair_file_name
}]
}
output "vpc" {
value = [for vpc in module.vpc[*] : {
id = vpc.id
name = vpc.name
}]
}
We can manage environment variable assignments methodically in a file with the extension .tfvars. Although there are several ways to manage variables in Terraform, tfvars files are the best and most popular way to do so due to their simplicity and efficiency.
terraform.auto.tfvars
auth_accesskey = "your-access-key"
auth_secretkey = "your-secret-key"
First, the following commands must be entered to perform the backend configuration.
export AWS_ACCESS_KEY_ID="your Huawei Cloud accesskey"
export AWS_SECRET_ACCESS_KEY="your Huawei Cloud secretkey"
terraform init
terraform plan
terraform apply
After terraform apply command, you should see the status file in the obs bucket.
terraform output ecs
ssh -i ./external/.ssh/KeyPair-456c7d29.pem root@119.8.105.201
Connected to the ecs-qM2dqrPW instance via ssh and pinged the private IP of the other two instances.
terraform destroy
REFERENCES
We use cookies to improve our site and your experience. By continuing to browse our site you accept our cookie policy. Find out more