使用Terraform为SAE应用绑定SLB

Serverless 应用引擎 SAE(Serverless App Engine)上部署应用后,可以通过添加公网SLB(Server Load Balancer,负载均衡)实现公网访问,也可以添加私网SLB实现同VPC内所有应用间互相访问。本文介绍如何通过TerraformSAE应用绑定和解绑公网SLB。

说明

本教程所含示例代码支持一键运行,您可以直接运行代码。一键运行

前提条件

  • 由于阿里云账号(主账号)具有资源的所有权限,一旦发生泄露将面临重大风险。建议您使用RAM用户,并为该RAM用户创建AccessKey,具体操作方式请参见创建RAM用户创建AccessKey

  • 为运行Terraform命令的RAM用户绑定以下最小权限策略,以获取管理本示例所涉及资源的权限。更多信息,请参见RAM用户授权

    该自定义权限策略允许RAM用户对SLB的描述、创建、删除、配置及状态设置等操作的权限,同时允许对SAE应用执行绑定和解绑SLB的操作

    {
      "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": "*"
        }
      ]
    }
  • 准备Terraform运行环境,您可以选择以下任一方式来使用Terraform。

    • ROS提供了Terraform托管服务,因此您可以直接在ROS控制台部署Terraform模板。详细操作,请参见创建Terraform类型资源栈

    • Terraform Explorer中使用Terraform:阿里云提供了Terraform的在线运行环境,您无需安装Terraform,登录后即可在线使用和体验Terraform。适用于零成本、快速、便捷地体验和调试Terraform的场景。

    • Cloud Shell:阿里云Cloud Shell中预装了Terraform的组件,并已配置好身份凭证,您可直接在Cloud Shell中运行Terraform的命令。适用于低成本、快速、便捷地访问和使用Terraform的场景。

    • 在本地安装和配置Terraform:适用于网络连接较差或需要自定义开发环境的场景。

使用的资源

创建应用并绑定SLB

本示例以在华南1(深圳)地域下为应用绑定SLB为例,介绍如何通过镜像方式自定义部署应用,并同时为应用绑定SLB。

  1. 创建一个用于存放Terraform资源的项目文件夹,命名为terraform

  2. 执行以下命令,进入项目目录。

    cd terraform
  3. 创建名为main.tf的配置文件。

    内容如下:

    # 提供商配置
    provider "alicloud" {
      region = var.region_id
    }
    
    # 变量定义
    variable "region_id" {
      type    = string
      default = "cn-shenzhen"
    }
    
    variable "app_name" {
      description = "应用名称"
      type        = string
      default     = "app-slb"
    }
    
    variable "image_url" {
      description = "镜像地址"
      type        = string
      default     = "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-slim:0.9"
    }
    
    variable "namespace_id" {
      description = "命名空间ID"
      type        = string
      default     = "cn-shenzhen:demo"
    }
    
    variable "namespace_name" {
      description = "命名空间名称"
      type        = string
      default     = "demo"
    }
    
    # 命名空间
    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
    }
    
    # 安全组
    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
    }
    
    # 应用配置
    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配置
    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
      }
    }
    
    # 其他变量定义
    variable "namespace_description" {
      description = "Namespace Description"
      default     = "a namespace"
    }
    
    variable "name" {
      default     = "tf"
      description = "The name of the security group rule"
      type        = string
    }
    
    variable "description" {
      default     = "The description of the security group rule"
      description = "The description of the security group rule"
      type        = string
    }
    
    variable "port_range" {
      default     = "1/65535"
      description = "The port range of the security group rule"
      type        = string
    }
    
    variable "cidr_ip" {
      description = "cidr blocks used to create a new security group rule"
      type        = string
      default     = "0.0.0.0/0"
    }
    
    variable "zone_id" {
      description = "Availability Zone ID"
      type        = string
      default     = "cn-shenzhen-a"
    }
    
    variable "app_description" {
      default     = "description 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 of the application, in unit of millicore"
      type        = string
    }
    
    variable "memory" {
      default     = "1024"
      description = "The memory of the application, in unit of MB"
      type        = string
    }
    
    variable "replicas" {
      default     = "1"
      description = "The replicas of the application"
      type        = string
    }
    
    variable "port" {
      description = "The port of SLB"
      type        = string
      default     = "8000"
    }
    
    # 输出
    output "namespace_id" {
      value       = var.namespace_id
      description = "Namespace ID"
    }
    
    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)
    }
  4. 执行以下命令,初始化配置。

    terraform init
  5. 预期结果:image

  6. 依次执行以下命令,创建应用。

    1. 执行以下命令,部署应用。在执行过程中,根据提示输入yes并按下Enter键,等待命令执行完成,若出现以下信息,则表示授权完成。

      terraform apply

      预期结果:image

    已成功创建绑定了SLB的应用app-slb,并输出了SLBIP地址和端口。

  7. 验证结果

    执行terraform show命令

    您可以使用以下命令查询Terraform已创建的资源详细信息:

    terraform show

    image

    浏览器访问截图

    在浏览器中输入SLBIP地址和端口,例如http://121.43.XXX.XX:8000,回车进入应用首页。image

解绑SLB并删除应用

本示例以在华南1(深圳)地域下的应用app-slb为例,介绍如何解绑SLB并删除应用。

  1. 在目标项目目录内执行以下命令,运行配置文件。

    terraform destroy
  2. 预期结果:image

    已成功解绑SLB并删除应用app-slb

完整示例

说明

当前示例代码支持一键运行,您可以直接运行代码。一键运行

# 提供商配置
provider "alicloud" {
  region = var.region_id
}

# 变量定义
variable "region_id" {
  type    = string
  default = "cn-shenzhen"
}

variable "app_name" {
  description = "应用名称"
  type        = string
  default     = "app-slb"
}

variable "image_url" {
  description = "镜像地址"
  type        = string
  default     = "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-slim:0.9"
}

variable "namespace_id" {
  description = "命名空间ID"
  type        = string
  default     = "cn-shenzhen:demo"
}

variable "namespace_name" {
  description = "命名空间名称"
  type        = string
  default     = "demo"
}

# 命名空间
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
}

# 安全组
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
}

# 应用配置
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配置
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
  }
}

# 其他变量定义
variable "namespace_description" {
  description = "Namespace Description"
  default     = "a namespace"
}

variable "name" {
  default     = "tf"
  description = "The name of the security group rule"
  type        = string
}

variable "description" {
  default     = "The description of the security group rule"
  description = "The description of the security group rule"
  type        = string
}

variable "port_range" {
  default     = "1/65535"
  description = "The port range of the security group rule"
  type        = string
}

variable "cidr_ip" {
  description = "cidr blocks used to create a new security group rule"
  type        = string
  default     = "0.0.0.0/0"
}

variable "zone_id" {
  description = "Availability Zone ID"
  type        = string
  default     = "cn-shenzhen-a"
}

variable "app_description" {
  default     = "description 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 of the application, in unit of millicore"
  type        = string
}

variable "memory" {
  default     = "1024"
  description = "The memory of the application, in unit of MB"
  type        = string
}

variable "replicas" {
  default     = "1"
  description = "The replicas of the application"
  type        = string
}

variable "port" {
  description = "The port of SLB"
  type        = string
  default     = "8000"
}

# 输出
output "namespace_id" {
  value       = var.namespace_id
  description = "Namespace ID"
}

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)
}

相关文档