After deploying an application in Serverless App Engine (SAE), you can add an internet-facing Server Load Balancer (SLB) instance to expose the application to the public, or add an internal-facing SLB instance to enable communication between applications in the same Virtual Private Cloud (VPC). This topic describes how to use Terraform to associate and disassociate an internet-facing SLB instance with an SAE application.
You can run the sample code in this topic by using the following link: Run with one click
Prerequisites
-
Using the AccessKey of an Alibaba Cloud account poses a high security risk because the account has full permissions on all resources. We recommend that you create and use a RAM user for your infrastructure management. For more information, see Create a RAM user and Create an AccessKey.
-
Attach the following policy to the RAM user that you use to run Terraform commands. It grants the minimum permissions required to manage the resources in this tutorial. For more information, see Manage RAM user permissions.
This custom policy allows the RAM user to describe, create, delete, configure, and set the status of SLB instances. It also grants permissions to associate and disassociate SAE applications with SLB instances.
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": [ "slb:DescribeLoadBalancers", "slb:DescribeLoadBalancerAttribute", "slb:CreateLoadBalancer", "slb:DeleteLoadBalancer", "slb:ModifyLoadBalancerInternetSpec", "slb:CreateLoadBalancerTCPListener", "slb:CreateLoadBalancerHTTPListener", "slb:CreateLoadBalancerHTTPSListener", "slb:DeleteLoadBalancerListener", "slb:SetLoadBalancerStatus", "sae:BindSlb", "sae:UnbindSlb" ], "Resource": "*" } ] } -
Prepare a Terraform runtime environment. You can use one of the following methods:
-
Resource Orchestration Service (ROS) provides a managed Terraform hosting service. You can deploy Terraform templates directly on the ROS console. For more information, see Create a Terraform-type stack.
-
Use Terraform in Terraform Explorer: This method is ideal for quick experimentation and debugging of Terraform.
-
Quickly create resources by using Terraform: Cloud Shell comes pre-installed with Terraform and is pre-configured with your identity credentials. You can run Terraform commands directly in Cloud Shell. This method provides quick and convenient access to Terraform.
-
Install and configure Terraform locally: This method is suitable for scenarios with poor network connectivity or when you need a custom development environment.
-
Resources
-
alicloud_sae_namespace: Creates and manages SAE namespaces.
-
alicloud_security_group: Creates and manages security groups.
-
alicloud_security_group_rule: Creates and manages security group rules.
-
alicloud_sae_application: Creates and manages SAE applications.
-
alicloud_slb_load_balancer: Creates and manages SLB instances.
-
alicloud_sae_load_balancer_internet: Configures an internet-facing load balancer for an SAE application.
Create an application and bind an SLB instance
This example shows how to deploy a custom application from an image and associate it with an SLB instance in the China (Shenzhen) region.
-
Create a project folder named terraform for your Terraform files.
-
Navigate to the project directory:
cd terraform -
Create a configuration file named main.tf.
The file should contain the following configuration:
# Configure the provider provider "alicloud" { region = var.region_id } # Define variables variable "region_id" { type = string default = "cn-shenzhen" } variable "app_name" { description = "The name of the application." type = string default = "app-slb" } variable "image_url" { description = "The URL of the image." type = string default = "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-slim:0.9" } variable "namespace_id" { description = "The ID of the namespace." type = string default = "cn-shenzhen:demo" } variable "namespace_name" { description = "The name of the namespace." type = string default = "demo" } # Namespace resource "alicloud_sae_namespace" "default" { namespace_description = var.namespace_description namespace_id = var.namespace_id namespace_name = var.namespace_name } # VPC resource "alicloud_vpc" "default" { vpc_name = var.name cidr_block = "10.4.0.0/16" } # VSwitch resource "alicloud_vswitch" "default" { vswitch_name = var.name cidr_block = "10.4.0.0/24" vpc_id = alicloud_vpc.default.id zone_id = var.zone_id } # Security group resource "alicloud_security_group" "sg" { name = var.name description = var.description vpc_id = alicloud_vpc.default.id } resource "alicloud_security_group_rule" "sg_rule" { type = "ingress" ip_protocol = "tcp" nic_type = "intranet" policy = "accept" port_range = var.port_range priority = 1 security_group_id = alicloud_security_group.sg.id cidr_ip = var.cidr_ip } # Application configuration resource "alicloud_sae_application" "manual" { app_name = var.app_name app_description = var.app_description deploy = true image_url = var.image_url namespace_id = alicloud_sae_namespace.default.id vswitch_id = alicloud_vswitch.default.id vpc_id = alicloud_vpc.default.id security_group_id = alicloud_security_group.sg.id package_type = var.package_type timezone = "Asia/Beijing" replicas = var.replicas cpu = var.cpu memory = var.memory } # SLB configuration resource "alicloud_slb_load_balancer" "slb" { load_balancer_name = "prod" address_type = "internet" load_balancer_spec = "slb.s2.small" vswitch_id = alicloud_vswitch.default.id } resource "alicloud_sae_load_balancer_internet" "example" { app_id = alicloud_sae_application.manual.id internet_slb_id = alicloud_slb_load_balancer.slb.id internet { protocol = "HTTP" port = var.port target_port = 80 } } # Other variable definitions variable "namespace_description" { description = "A description for the namespace." default = "a namespace" } variable "name" { default = "tf" description = "The name for the security group rule." type = string } variable "description" { default = "A description for the security group rule." description = "The description of the security group rule." type = string } variable "port_range" { default = "1/65535" description = "The port range for the security group rule." type = string } variable "cidr_ip" { description = "The CIDR block used to create a new security group rule." type = string default = "0.0.0.0/0" } variable "zone_id" { description = "The ID of the availability zone." type = string default = "cn-shenzhen-a" } variable "app_description" { default = "A description for the application, created by Terraform." description = "The description of the application." type = string } variable "package_type" { default = "Image" description = "The package type of the application." type = string } variable "cpu" { default = "500" description = "The CPU allocation for the application, in millicores." type = string } variable "memory" { default = "1024" description = "The memory allocation for the application, in MB." type = string } variable "replicas" { default = "1" description = "The number of application instances (replicas)." type = string } variable "port" { description = "The listening port of the SLB instance." type = string default = "8000" } # Outputs output "namespace_id" { value = var.namespace_id description = "The ID of the namespace." } output "app_id" { description = "The ID of the application." value = alicloud_sae_application.manual.id } output "app_name" { description = "The name of the application." value = var.app_name } output "endpoint" { value = format("http://%s:%s", alicloud_slb_load_balancer.slb.address, var.port) } -
Run the following command to initialize your Terraform working directory.
terraform init -
Expected output:
Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary. -
Run the following commands to create the resources.
-
To deploy the application, run the following command. When prompted, type
yesand press Enter to confirm the deployment.terraform applyExpected output:
Apply complete! Resources: 4 added, 0 changed, 0 destroyed. Outputs: app_id = "8abb794f-a47b-474b-b6f5-2xxx" app_name = "app-slb" endpoint = "http://8.xxx.xxx:8000" namespace_id = "cn-shenzhen:demo"
Terraform creates the
app-slbapplication and associates it with an SLB instance. The output displays the public IP address and port of the SLB instance. -
-
Verify the result:
Run terraform show
Run the following command to view the details of the resources created by Terraform:
terraform show# alicloud_sae_application.manual: resource "alicloud_sae_application" "manual" { app_description = "A description for the application, created by Terraform." app_name = "app-slb" cpu = 500 deploy = true id = "8abb794f-a47b-474b-bxxx51" image_url = "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-slim:0.9" memory = 1024 namespace_id = "cn-shenzhen:demo" package_type = "Image" replicas = 1 security_group_id = "sg-xxx" status = "RUNNING" timezone = "Asia/Beijing" vpc_id = "vpc-xxx" vswitch_id = "vsw-xxx" } # alicloud_sae_load_balancer_internet.example: resource "alicloud_sae_load_balancer_internet" "example" { app_id = "8abb794f-a47b-474b-bxxx51" id = "8abb794f-a47b-474b-bxxx51" internet_ip = "8.xxx.xxx" internet_slb_id = "lb-xxx" internet { port = 8000 protocol = "HTTP" target_port = 80 } }Verify in a browser
Enter the IP address and port of the SLB instance into a web browser, for example,
http://121.43.XXX.XX:8000. The Nginx welcome page with the message Welcome to nginx! appears, which confirms that the application is running correctly.
Clean up resources
This topic uses the application app-slb in the China (Shenzhen) region as an example to describe how to unbind an SLB instance and delete the application.
-
To delete all created resources, run the following command in your project directory:
terraform destroy -
Expected output:
Destroy complete! Resources: 8 destroyed.This command disassociates the SLB instance, deletes the SAE application, and removes all other resources created in this tutorial.
Complete sample code
You can run the sample code in this topic by using the following link: Run with one click
# Configure the provider
provider "alicloud" {
region = var.region_id
}
# Define variables
variable "region_id" {
type = string
default = "cn-shenzhen"
}
variable "app_name" {
description = "The name of the application."
type = string
default = "app-slb"
}
variable "image_url" {
description = "The URL of the image."
type = string
default = "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-slim:0.9"
}
variable "namespace_id" {
description = "The ID of the namespace."
type = string
default = "cn-shenzhen:demo"
}
variable "namespace_name" {
description = "The name of the namespace."
type = string
default = "demo"
}
# Namespace
resource "alicloud_sae_namespace" "default" {
namespace_description = var.namespace_description
namespace_id = var.namespace_id
namespace_name = var.namespace_name
}
# VPC
resource "alicloud_vpc" "default" {
vpc_name = var.name
cidr_block = "10.4.0.0/16"
}
# VSwitch
resource "alicloud_vswitch" "default" {
vswitch_name = var.name
cidr_block = "10.4.0.0/24"
vpc_id = alicloud_vpc.default.id
zone_id = var.zone_id
}
# Security group
resource "alicloud_security_group" "sg" {
name = var.name
description = var.description
vpc_id = alicloud_vpc.default.id
}
resource "alicloud_security_group_rule" "sg_rule" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = var.port_range
priority = 1
security_group_id = alicloud_security_group.sg.id
cidr_ip = var.cidr_ip
}
# Application configuration
resource "alicloud_sae_application" "manual" {
app_name = var.app_name
app_description = var.app_description
deploy = true
image_url = var.image_url
namespace_id = alicloud_sae_namespace.default.id
vswitch_id = alicloud_vswitch.default.id
vpc_id = alicloud_vpc.default.id
security_group_id = alicloud_security_group.sg.id
package_type = var.package_type
timezone = "Asia/Beijing"
replicas = var.replicas
cpu = var.cpu
memory = var.memory
}
# SLB configuration
resource "alicloud_slb_load_balancer" "slb" {
load_balancer_name = "prod"
address_type = "internet"
load_balancer_spec = "slb.s2.small"
vswitch_id = alicloud_vswitch.default.id
}
resource "alicloud_sae_load_balancer_internet" "example" {
app_id = alicloud_sae_application.manual.id
internet_slb_id = alicloud_slb_load_balancer.slb.id
internet {
protocol = "HTTP"
port = var.port
target_port = 80
}
}
# Other variable definitions
variable "namespace_description" {
description = "A description for the namespace."
default = "a namespace"
}
variable "name" {
default = "tf"
description = "The name for the security group rule."
type = string
}
variable "description" {
default = "A description for the security group rule."
description = "The description of the security group rule."
type = string
}
variable "port_range" {
default = "1/65535"
description = "The port range for the security group rule."
type = string
}
variable "cidr_ip" {
description = "The CIDR block used to create a new security group rule."
type = string
default = "0.0.0.0/0"
}
variable "zone_id" {
description = "The ID of the availability zone."
type = string
default = "cn-shenzhen-a"
}
variable "app_description" {
default = "A description for the application, created by Terraform."
description = "The description of the application."
type = string
}
variable "package_type" {
default = "Image"
description = "The package type of the application."
type = string
}
variable "cpu" {
default = "500"
description = "The CPU allocation for the application, in millicores."
type = string
}
variable "memory" {
default = "1024"
description = "The memory allocation for the application, in MB."
type = string
}
variable "replicas" {
default = "1"
description = "The number of application instances (replicas)."
type = string
}
variable "port" {
description = "The listening port of the SLB instance."
type = string
default = "8000"
}
# Outputs
output "namespace_id" {
value = var.namespace_id
description = "The ID of the namespace."
}
output "app_id" {
description = "The ID of the application."
value = alicloud_sae_application.manual.id
}
output "app_name" {
description = "The name of the application."
value = var.app_name
}
output "endpoint" {
value = format("http://%s:%s", alicloud_slb_load_balancer.slb.address, var.port)
}
Related documents
-
For an introduction to Terraform on Alibaba Cloud, see What is Alibaba Cloud Terraform?.