使用Terraform管理SAE应用

Serverless 应用引擎 SAE(Serverless App Engine)是面向应用的Serverless PaaS平台,向上抽象了应用的概念。将应用部署至SAE后,您无需管理和维护集群与服务器,可以专注于设计和构建应用程序,将其部署在SAE。除通过控制台、API、插件、CI/CD部署外,您还可以通过Terraform来部署SAE应用。本文介绍如何通过Terraform自动创建、自定义创建以及删除SAE应用。

前提条件

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

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

    此自定义权限策略允许用户管理和操作SAE中的应用程序和服务,包括描述、创建、更新、删除、部署、启动和停止应用程序,以及创建、更新、删除、绑定和解绑服务。

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "sae:DescribeApplications",
            "sae:DescribeApplication",
            "sae:DescribeInstances",
            "sae:DescribeInstance",
            "sae:DescribeServices",
            "sae:DescribeService"
          ],
          "Resource": "*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "sae:CreateApplication",
            "sae:UpdateApplication",
            "sae:DeleteApplication",
            "sae:DeployApplication",
            "sae:StartApplication",
            "sae:StopApplication"
          ],
          "Resource": "acs:sae:*:*:application/*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "sae:CreateService",
            "sae:UpdateService",
            "sae:DeleteService",
            "sae:BindService",
            "sae:UnbindService"
          ],
          "Resource": "acs:sae:*:*:service/*"
        }
      ]
    }
  • 准备Terraform运行环境,您可以选择以下任一方式来使用Terraform。

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

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

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

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

使用的资源

  • alicloud_sae_application:用于管理和创建阿里云 Serverless 应用引擎(SAE)应用的资源。

  • alicloud_vpc:通过 VPC,用户可以完全控制自己的网络配置,包括子网划分、路由表和网络安全设置等。

  • alicloud_vswitch:是VPC内的子网,用于将VPC划分为多个子网,每个子网可以有自己的IP地址范围和路由表。通过VSwitch,用户可以在不同的子网中部署不同的应用和服务。

  • alicloud_security_group:是阿里云的安全组服务,用于管理VPC内的网络访问控制。

创建应用

SAE支持镜像部署和代码包部署。其中代码包支持JAR包、WAR包和PHP ZIP包。创建应用时,您可以按需选择以下方式配置专有网络:

  • 自动配置:SAE将自动帮您配置命名空间、VPC、vSwitch及安全组等。命名空间为默认命名空间。

  • 自定义配置:您需要为创建的应用配置所需的命名空间、VPC、vSwitch及安全组等。

自动配置

本示例以在华东2(北京)地域下创建应用为例,介绍如何通过镜像方式自动部署应用。

  1. 创建一个用于存放Terraform资源的项目文件夹,命名为terraform
  2. 执行以下命令,进入项目目录。
    cd terraform
  3. 创建名为main.tf的配置文件。内容如下。

    provider "alicloud" {
      region = var.region
    }
    
    variable "region" {
      default = "cn-beijing"
    }
    
    variable "name" {
      default = "serverless-example"
    }
    
    resource "random_integer" "default" {
      max = 99999
      min = 10000
    }
    
    data "alicloud_regions" "default" {
      current = true
    }
    
    data "alicloud_zones" "default" {
      available_resource_creation = "VSwitch"
    }
    
    resource "alicloud_vpc" "default" {
      vpc_name   = var.name
      cidr_block = "10.4.0.0/16"
    }
    
    resource "alicloud_vswitch" "default" {
      vswitch_name = var.name
      cidr_block   = "10.4.0.0/24"
      vpc_id       = alicloud_vpc.default.id
      zone_id      = data.alicloud_zones.default.zones.0.id
    }
    
    resource "alicloud_security_group" "default" {
      vpc_id = alicloud_vpc.default.id
    }
    
    resource "alicloud_sae_namespace" "default" {
      namespace_id              = "${data.alicloud_regions.default.regions.0.id}:example${random_integer.default.result}"
      namespace_name            = var.name
      namespace_description     = var.name
      enable_micro_registration = false
    }
    
    resource "alicloud_sae_application" "default" {
      app_description   = var.name
      app_name          = "${var.name}-${random_integer.default.result}"
      namespace_id      = alicloud_sae_namespace.default.id
      image_url         = "registry-vpc.${data.alicloud_regions.default.regions.0.id}.aliyuncs.com/sae-demo-image/consumer:1.0"
      package_type      = "Image"
      security_group_id = alicloud_security_group.default.id
      vpc_id            = alicloud_vpc.default.id
      vswitch_id        = alicloud_vswitch.default.id
      timezone          = "Asia/Beijing"
      replicas          = "1"
      cpu               = "500"
      memory            = "2048"
    }

    您可以登录容器镜像服务控制台,在目标实例仓库的基本信息页面查看镜像地址。格式如下

    registry.<regionId>.aliyuncs.com/<命令空间名称><镜像仓库名称>:<镜像版本号>
  4. 执行以下命令,初始化配置。
    terraform init
  1. 预期输出:

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

  • 执行以下命令,执行配置文件。在执行过程中,根据提示输入yes并按下Enter键,等待命令执行完成,若出现以下信息,则表示授权完成。

terraform apply
  1. 预期输出:

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
  1. 验证结果

执行terraform show命令

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

terraform show

image

Serverless应用引擎SAE控制台截图

登录Serverless应用引擎SAE控制台,查看创建应用列表。

image

说明

以下操作步骤示例代码支持一键运行,您可以直接运行代码。一键运行

自定义配置:镜像部署

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

  1. 创建一个用于存放Terraform资源的项目文件夹,命名为terraform
  2. 执行以下命令,进入项目目录。
    cd terraform
  3. 创建名为main.tf的配置文件。内容如下。

    provider "alicloud" {
      region = var.region_id
    }
    
    # 区域ID
    variable "region_id" {
      type    = string
      default = "cn-shenzhen"
    }
    
    # 应用名称
    variable "app_name" {
      description = "The name of the application"
      type        = string
      default     = "manual-jar-tf"
    }
    
    # 应用描述
    variable "app_description" {
      default     = "description created by Terraform"
      description = "The description of the application"
      type        = string
    }
    
    # 应用部署方式
    variable "package_type" {
      default     = "FatJar"
      description = "The package type of the application"
      type        = string
    }
    
    # 实例CPU规格
    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
    }
    
    # JAR包地址
    variable "jar_url" {
      description = "The JAR url of the application, like `oss://my-bucket/my-app.jar`"
      type        = string
      default     = "https://edas-sz.oss-cn-shenzhen.aliyuncs.com/prod/demo/SPRING_CLOUD_CONSUMER.jar"
    }
    
    # 应用实例数
    variable "replicas" {
      default     = "1"
      description = "The replicas of the application"
      type        = string
    }
    
    # 命名空间名称
    variable "namespace_name" {
      description = "Namespace Name"
      type        = string
      default     = "tfjardemo"
    }
    
    # 命名空间ID
    variable "namespace_id" {
      description = "Namespace ID"
      type        = string
      default     = "cn-shenzhen:tfjardemo"  # 引用现有的命名空间ID
    }
    
    # 命名空间描述
    variable "namespace_description" {
      description = "Namespace Description"
      default     = "a namespace"
    }
    
    # VPC和安全组
    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
    }
    
    # CIDR地址
    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-e"  # 选择一个资源充足的可用区
    }
    
    # 应用日志采集到SLS
    variable "slsConfig" {
      default     = "[{\"logDir\":\"\",\"logType\":\"stdout\"},{\"logDir\":\"/home/admin/logs/*.log\"}]"
      description = "The config of sls log collect"
      type        = string
    }
    
    resource "alicloud_vpc" "vpc" {
      vpc_name   = "tf-vpc"
      cidr_block = "172.16.0.0/16"
    }
    
    resource "alicloud_vswitch" "vswitch" {
      vpc_id       = alicloud_vpc.vpc.id
      cidr_block   = "172.16.1.0/24"
      zone_id      = var.zone_id
      vswitch_name = "tf-vswitch"
      description  = "tf-vswitch description"
    }
    
    resource "alicloud_sae_namespace" "default" {
      namespace_id          = var.namespace_id
      namespace_name        = var.namespace_name
      namespace_description = var.namespace_description
    }
    
    output "namespace_id" {
      value       = var.namespace_id
      description = "Namespace ID"
    }
    
    resource "alicloud_security_group" "sg" {
      name        = var.name
      description = var.description
      vpc_id      = alicloud_vpc.vpc.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
      package_url        = var.jar_url
      namespace_id       = alicloud_sae_namespace.default.id
      vswitch_id         = alicloud_vswitch.vswitch.id
      vpc_id             = alicloud_vpc.vpc.id
      security_group_id  = alicloud_security_group.sg.id
      package_type       = var.package_type
      jdk                = "Open JDK 8"
      timezone           = "Asia/Beijing"
      replicas           = var.replicas
      cpu                = var.cpu
      memory             = var.memory
      micro_registration = "0"
    
      lifecycle {
        ignore_changes = [
          micro_registration
        ]
      }
    }
    
    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
    }
  4. 执行以下命令,初始化配置。
    terraform init
  5. 预期结果:

    image

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

terraform apply
  1. 预期结果:

image

如果输出代码符合预期输出,说明已成功创建以镜像部署的应用。

  1. 验证结果

执行terraform show命令

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

terraform show

image

Serverless应用引擎SAE控制台

登录Serverless应用引擎SAE控制台,查看创建应用列表。

image

image

自定义配置:JAR包部署

本示例以在华南1(深圳)地域下创建应用为例,介绍如何通过JAR包方式自定义部署应用。

  1. 创建一个用于存放Terraform资源的项目文件夹,命名为terraform
  2. 执行以下命令,进入项目目录。
    cd terraform
  3. 创建名为main.tf的配置文件。内容如下。

    provider "alicloud" {
      region = var.region_id
    }
    
    # 区域ID
    variable "region_id" {
      type    = string
      default = "cn-shenzhen"
    }
    
    # 应用名称
    variable "app_name" {
      description = "The name of the application"
      type        = string
      default     = "manual-jar-tf"
    }
    
    # 应用描述
    variable "app_description" {
      default     = "description created by Terraform"
      description = "The description of the application"
      type        = string
    }
    
    # 应用部署方式
    variable "package_type" {
      default     = "FatJar"
      description = "The package type of the application"
      type        = string
    }
    
    # 实例CPU规格
    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
    }
    
    # JAR包地址
    variable "jar_url" {
      description = "The JAR url of the application, like `oss://my-bucket/my-app.jar`"
      type        = string
      default     = "https://edas-sz.oss-cn-shenzhen.aliyuncs.com/prod/demo/SPRING_CLOUD_CONSUMER.jar"
    }
    
    # 应用实例数
    variable "replicas" {
      default     = "1"
      description = "The replicas of the application"
      type        = string
    }
    
    # 命名空间名称
    variable "namespace_name" {
      description = "Namespace Name"
      type        = string
      default     = "tfjardemo"
    }
    
    # 命名空间ID
    variable "namespace_id" {
      description = "Namespace ID"
      type        = string
      default     = "cn-shenzhen:tfjardemo"  # 引用现有的命名空间ID
    }
    
    # 命名空间描述
    variable "namespace_description" {
      description = "Namespace Description"
      default     = "a namespace"
    }
    
    # VPC和安全组
    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
    }
    
    # CIDR地址
    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-e"  # 选择一个资源充足的可用区
    }
    
    # 应用日志采集到SLS
    variable "slsConfig" {
      default     = "[{\"logDir\":\"\",\"logType\":\"stdout\"},{\"logDir\":\"/home/admin/logs/*.log\"}]"
      description = "The config of sls log collect"
      type        = string
    }
    
    resource "alicloud_vpc" "vpc" {
      vpc_name   = "tf-vpc"
      cidr_block = "172.16.0.0/16"
    }
    
    resource "alicloud_vswitch" "vswitch" {
      vpc_id       = alicloud_vpc.vpc.id
      cidr_block   = "172.16.1.0/24"
      zone_id      = var.zone_id
      vswitch_name = "tf-vswitch"
      description  = "tf-vswitch description"
    }
    
    resource "alicloud_sae_namespace" "default" {
      namespace_id          = var.namespace_id
      namespace_name        = var.namespace_name
      namespace_description = var.namespace_description
    }
    
    output "namespace_id" {
      value       = var.namespace_id
      description = "Namespace ID"
    }
    
    resource "alicloud_security_group" "sg" {
      name        = var.name
      description = var.description
      vpc_id      = alicloud_vpc.vpc.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
      package_url        = var.jar_url
      namespace_id       = alicloud_sae_namespace.default.id
      vswitch_id         = alicloud_vswitch.vswitch.id
      vpc_id             = alicloud_vpc.vpc.id
      security_group_id  = alicloud_security_group.sg.id
      package_type       = var.package_type
      jdk                = "Open JDK 8"
      timezone           = "Asia/Beijing"
      replicas           = var.replicas
      cpu                = var.cpu
      memory             = var.memory
      micro_registration = "0"
    
      lifecycle {
        ignore_changes = [
          micro_registration
        ]
      }
    }
    
    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
    }
  4. 执行以下命令,初始化配置。

    terraform init

    预期输出:

    image

  5. 依次执行以下命令,以JAR包方式创建应用。

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

      terraform apply

      预期输出:

      image

    如果输出代码符合预期输出,说明已成功创建以JAR包部署的应用。

  1. 验证结果:

执行terraform show命令

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

terraform show

image

Serverless应用引擎SAE控制台

登录Serverless应用引擎SAE控制台,查看创建命名空间。

image

删除应用

本文以在华东2(上海)地域下自动创建的应用auto-app-1为例,介绍如何删除应用。

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

    terraform destroy

    预期结果:image

相关文档