使用Terraform为SAE应用绑定SLB

更新时间:
复制 MD 格式

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的场景。

    • 使用Terraform快速创建资源:阿里云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. 预期结果:

    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.
  6. 依次执行以下命令,创建应用。

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

      terraform apply

      预期结果:

      Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
      Outputs:
      app_id = "8abb794f-a47b-474b-b6f5-2xxx"
      app_name = "app-s1b"
      endpoint = "http://8.xxx.xxx:8000"
      namespace_id = "cn-shenzhen:demo"

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

  7. 验证结果

    执行terraform show命令

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

    terraform show
    # alicloud_sae_application.manual:
    resource "alicloud_sae_application" "manual" {
        app_description            = "description created by Terraform"
        app_name                   = "app-slb"
        batch_wait_time            = 10
        command_args_v2            = []
        config_map_mount_desc      = jsonencode([])
        cpu                        = 500
        custom_host_alias          = jsonencode([])
        deploy                     = true
        enable_ahas                = "false"
        enable_grey_tag_route      = false
        envs                       = jsonencode([])
        id                         = "8abb794f-a47b-474b-bxxx51"
        image_url                  = "registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-slim:0.9"
        memory                     = 1024
        min_ready_instance_ratio   = -1
        min_ready_instances        = -1
        namespace_id               = "cn-shenzhen:demo"
        package_type               = "Image"
        package_version            = "1732255950"
        replicas                   = 1
        security_group_id          = "sg-xxx"
        status                     = "RUNNING"
        termination_grace_period_seconds = 30
        vpc_id                     = "vpc-xxx"
        vswitch_id                 = "vsw-xxx"
    }
    
    # alicloud_sae_load_balancer_internet.manual:
    resource "alicloud_sae_load_balancer_internet" "manual" {
        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    = "TCP"
            target_port = 80
        }
    }
        termination_grace_period_seconds = 30
        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         = "xxx"
        id             = "xxx"
        internet_ip    = "xxx"
        internet_slb_id = "lb-wz98ts8jnxxx"
    }

    浏览器访问截图

    在浏览器中输入SLBIP地址和端口,例如http://121.43.XXX.XX:8000,回车进入应用首页。在浏览器中访问服务器的 8000 端口,页面显示 Nginx 默认欢迎页 Welcome to nginx!,表明 Nginx 已成功安装并正常运行。

解绑SLB并删除应用

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

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

    terraform destroy
  2. 预期结果:

    Destroy complete! Resources: 8 destroyed.

    已成功解绑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)
}

相关文档