From 529f48e79a315d298f98e4c66971d0494301ac02 Mon Sep 17 00:00:00 2001 From: shaobolin Date: Fri, 8 Aug 2025 16:12:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88ser?= =?UTF-8?q?verless-high-availability-architecture=20tf=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tech-solution/serverless-ha/README.md | 59 ++++ solution/tech-solution/serverless-ha/main.tf | 318 ++++++++++++++++++ .../tech-solution/serverless-ha/outputs.tf | 61 ++++ .../tech-solution/serverless-ha/provider.tf | 3 + .../tech-solution/serverless-ha/variables.tf | 23 ++ 5 files changed, 464 insertions(+) create mode 100644 solution/tech-solution/serverless-ha/README.md create mode 100644 solution/tech-solution/serverless-ha/main.tf create mode 100644 solution/tech-solution/serverless-ha/outputs.tf create mode 100644 solution/tech-solution/serverless-ha/provider.tf create mode 100644 solution/tech-solution/serverless-ha/variables.tf diff --git a/solution/tech-solution/serverless-ha/README.md b/solution/tech-solution/serverless-ha/README.md new file mode 100644 index 0000000000..1f4a2cac4a --- /dev/null +++ b/solution/tech-solution/serverless-ha/README.md @@ -0,0 +1,59 @@ +## Introduction + +本示例用于实现解决方案[极简运维,Serverless 高可用架构](https://www.aliyun.com/solution/tech-solution/serverless-ha), 涉及到专有网络(VPC)、交换机(VSwitch)、云原生数据库PolarDB MySQL版、应用型负载均衡(ALB)等资源的部署。 + + + +This example is used to implement solution [Minimal Operations, Serverless High Availability Architecture](https://www.aliyun.com/solution/tech-solution/serverless-ha), which involves the creation and deployment of resources such as Virtual Private Cloud (VPC), VSwitch, PolarDB for MySQL, Application Load Balancer (ALB). + + + +## Providers + +| Name | Version | +|------|---------| +| [alicloud](#provider\_alicloud) | n/a | +| [random](#provider\_random) | n/a | +| [time](#provider\_time) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [alicloud_alb_load_balancer.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/alb_load_balancer) | resource | +| [alicloud_polardb_account.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/polardb_account) | resource | +| [alicloud_polardb_account_privilege.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/polardb_account_privilege) | resource | +| [alicloud_polardb_cluster.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/polardb_cluster) | resource | +| [alicloud_polardb_database.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/polardb_database) | resource | +| [alicloud_sae_application.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/sae_application) | resource | +| [alicloud_sae_ingress.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/sae_ingress) | resource | +| [alicloud_sae_namespace.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/sae_namespace) | resource | +| [alicloud_security_group.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group) | resource | +| [alicloud_security_group_rule.allow_http](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.allow_https](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.allow_mysql](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_vpc.main](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vpc) | resource | +| [alicloud_vswitch.db_01](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.pub_01](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.pub_02](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.web_01](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.web_02](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vswitch) | resource | +| [random_string.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [time_sleep.wait_app](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource | +| [alicloud_polardb_node_classes.default](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/polardb_node_classes) | data source | +| [alicloud_regions.default](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/regions) | data source | +| [alicloud_zones.default](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/zones) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [common\_name](#input\_common\_name) | 通用名称前缀 | `string` | `"serverless"` | no | +| [db\_password](#input\_db\_password) | MySQL数据库密码,长度8-30,必须包含三项(大写字母、小写字母、数字、特殊符号) | `string` | n/a | yes | +| [db\_user\_name](#input\_db\_user\_name) | MySQL数据库账号 | `string` | `"applets"` | no | +| [region](#input\_region) | 地域 | `string` | `"cn-hangzhou"` | no | + \ No newline at end of file diff --git a/solution/tech-solution/serverless-ha/main.tf b/solution/tech-solution/serverless-ha/main.tf new file mode 100644 index 0000000000..e1bf94b06b --- /dev/null +++ b/solution/tech-solution/serverless-ha/main.tf @@ -0,0 +1,318 @@ + +locals { + zone_id_1 = data.alicloud_polardb_node_classes.default.classes[0].zone_id + zone_id_2 = data.alicloud_zones.default.zones.0.id +} +# 生成随机后缀用于资源命名 +resource "random_string" "suffix" { + length = 5 + special = false + upper = false +} + +data "alicloud_regions" "default" { + current = true +} +data "alicloud_polardb_node_classes" "default" { + db_type = "MySQL" + db_version = "8.0" + category = "Normal" + pay_type = "PostPaid" + db_node_class = "polar.mysql.sl.small" +} + +data "alicloud_zones" "default" { + available_resource_creation = "VSwitch" +} + +# 创建VPC +resource "alicloud_vpc" "main" { + vpc_name = "${var.common_name}-vpc" + cidr_block = "192.168.0.0/16" + + tags = { + Name = "${var.common_name}-vpc" + } +} + +# 创建交换机1 (Web层 - 可用区1) +resource "alicloud_vswitch" "web_01" { + vpc_id = alicloud_vpc.main.id + cidr_block = "192.168.1.0/24" + zone_id = local.zone_id_1 + vswitch_name = "${var.common_name}-web-01" + + tags = { + Name = "${var.common_name}-web-01" + } +} + +# 创建交换机2 (Web层 - 可用区2) +resource "alicloud_vswitch" "web_02" { + vpc_id = alicloud_vpc.main.id + cidr_block = "192.168.2.0/24" + zone_id = local.zone_id_2 + vswitch_name = "${var.common_name}-web-02" + + tags = { + Name = "${var.common_name}-web-02" + } +} + +# 创建交换机3 (数据库层 - 可用区1) +resource "alicloud_vswitch" "db_01" { + vpc_id = alicloud_vpc.main.id + cidr_block = "192.168.3.0/24" + zone_id = local.zone_id_1 + vswitch_name = "${var.common_name}-db-01" + + tags = { + Name = "${var.common_name}-db-01" + } +} + +# 创建交换机4 (公网层 - 可用区1) +resource "alicloud_vswitch" "pub_01" { + vpc_id = alicloud_vpc.main.id + cidr_block = "192.168.4.0/24" + zone_id = local.zone_id_1 + vswitch_name = "${var.common_name}-pub-01" + + tags = { + Name = "${var.common_name}-pub-01" + } +} + +# 创建交换机5 (公网层 - 可用区2) +resource "alicloud_vswitch" "pub_02" { + vpc_id = alicloud_vpc.main.id + cidr_block = "192.168.5.0/24" + zone_id = local.zone_id_2 + vswitch_name = "${var.common_name}-pub-02" + + tags = { + Name = "${var.common_name}-pub-02" + } +} + +# 创建安全组 +resource "alicloud_security_group" "main" { + security_group_name = "${var.common_name}-sg" + vpc_id = alicloud_vpc.main.id + description = "Serverless高可用架构安全组" + + tags = { + Name = "${var.common_name}-sg" + } +} + +# 安全组规则 - 允许HTTPS访问 +resource "alicloud_security_group_rule" "allow_https" { + type = "ingress" + ip_protocol = "tcp" + port_range = "443/443" + security_group_id = alicloud_security_group.main.id + cidr_ip = "0.0.0.0/0" +} + +# 安全组规则 - 允许HTTP访问 +resource "alicloud_security_group_rule" "allow_http" { + type = "ingress" + ip_protocol = "tcp" + port_range = "80/80" + security_group_id = alicloud_security_group.main.id + cidr_ip = "0.0.0.0/0" +} + +# 安全组规则 - 允许MySQL访问 +resource "alicloud_security_group_rule" "allow_mysql" { + type = "ingress" + ip_protocol = "tcp" + port_range = "3306/3306" + security_group_id = alicloud_security_group.main.id + cidr_ip = "0.0.0.0/0" +} + +# 创建PolarDB集群 +resource "alicloud_polardb_cluster" "main" { + db_type = "MySQL" + db_version = "8.0" + db_node_class = data.alicloud_polardb_node_classes.default.classes.0.supported_engines.0.available_resources.0.db_node_class + pay_type = "PostPaid" + vswitch_id = alicloud_vswitch.db_01.id + zone_id = local.zone_id_1 + security_group_ids = [alicloud_security_group.main.id] + + # Serverless配置 + serverless_type = "AgileServerless" + scale_min = 1 + scale_max = 16 + scale_ro_num_min = 1 + scale_ro_num_max = 4 + + description = "Serverless高可用架构PolarDB集群" + + tags = { + Name = "${var.common_name}-polardb" + } +} + +# 创建数据库 +resource "alicloud_polardb_database" "main" { + db_cluster_id = alicloud_polardb_cluster.main.id + db_name = "applets" + character_set_name = "utf8mb4" + db_description = "serverless demo" +} + +# 创建数据库账号 +resource "alicloud_polardb_account" "main" { + db_cluster_id = alicloud_polardb_cluster.main.id + account_name = var.db_user_name + account_password = var.db_password + account_type = "Normal" +} + +# 为账号授权数据库 +resource "alicloud_polardb_account_privilege" "main" { + db_cluster_id = alicloud_polardb_cluster.main.id + account_name = alicloud_polardb_account.main.account_name + db_names = [alicloud_polardb_database.main.db_name] + account_privilege = "ReadWrite" +} + +# 创建应用负载均衡器(ALB) +resource "alicloud_alb_load_balancer" "main" { + load_balancer_name = "${var.common_name}-alb" + load_balancer_edition = "Basic" + vpc_id = alicloud_vpc.main.id + address_type = "Internet" + address_allocated_mode = "Fixed" + + load_balancer_billing_config { + pay_type = "PayAsYouGo" + } + + zone_mappings { + zone_id = local.zone_id_1 + vswitch_id = alicloud_vswitch.web_01.id + } + + zone_mappings { + zone_id = local.zone_id_2 + vswitch_id = alicloud_vswitch.web_02.id + } + + tags = { + Name = "${var.common_name}-alb" + } +} + +# 创建SAE命名空间 +resource "alicloud_sae_namespace" "main" { + namespace_name = "serverless-demo" + namespace_id = "${data.alicloud_regions.default.regions.0.id}:serverless${random_string.suffix.result}" +} + +# 创建SAE应用 +resource "alicloud_sae_application" "main" { + app_name = "serverless-demo-${random_string.suffix.result}" + app_description = "serverless-demo" + namespace_id = alicloud_sae_namespace.main.id + + package_type = "FatJar" + package_version = "1718956564756" + package_url = "https://help-static-aliyun-doc.aliyuncs.com/tech-solution/sae-demo-0.0.3.jar" + + vpc_id = alicloud_vpc.main.id + security_group_id = alicloud_security_group.main.id + vswitch_id = "${alicloud_vswitch.pub_01.id},${alicloud_vswitch.pub_02.id}" + + cpu = 2000 + memory = 4096 + replicas = 2 + + jdk = "Open JDK 8" + timezone = "Asia/Shanghai" + + jar_start_args = "$JAVA_HOME/bin/java $Options -jar $CATALINA_OPTS \"$package_path\" $args" + jar_start_options = "-XX:+UseContainerSupport -XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=70.0 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/admin/nas/gc-$${POD_IP}-$(date '+%s').log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/nas/dump-$${POD_IP}-$(date '+%s').hprof" + + envs = jsonencode([ + { + name = "APPLETS_MYSQL_ENDPOINT" + value = alicloud_polardb_cluster.main.connection_string + }, + { + name = "APPLETS_MYSQL_USER" + value = var.db_user_name + }, + { + name = "APPLETS_MYSQL_PASSWORD" + value = var.db_password + }, + { + name = "APPLETS_MYSQL_DB_NAME" + value = "applets" + }, + { + name = "APP_MANUAL_DEPLOY" + value = "false" + } + ]) + + readiness_v2 { + exec { + command = ["sleep", "6s"] + } + initial_delay_seconds = 15 + timeout_seconds = 12 + } + + liveness_v2 { + http_get { + path = "/" + port = 80 + scheme = "HTTP" + } + initial_delay_seconds = 10 + timeout_seconds = 10 + period_seconds = 10 + } + + tags = { + Name = "serverless-demo-${random_string.suffix.result}" + } +} + +# 等待应用部署完成 +resource "time_sleep" "wait_app" { + depends_on = [alicloud_sae_application.main] + create_duration = "180s" +} + +# 创建SAE Ingress规则 +resource "alicloud_sae_ingress" "main" { + depends_on = [time_sleep.wait_app] + namespace_id = alicloud_sae_namespace.main.id + slb_id = alicloud_alb_load_balancer.main.id + description = "serverless-demo-router" + + load_balance_type = "alb" + listener_protocol = "HTTP" + listener_port = 80 + + rules { + app_name = alicloud_sae_application.main.app_name + app_id = alicloud_sae_application.main.id + container_port = 80 + domain = "example.com" + path = "/" + } + + default_rule { + app_name = alicloud_sae_application.main.app_name + app_id = alicloud_sae_application.main.id + container_port = 80 + } +} diff --git a/solution/tech-solution/serverless-ha/outputs.tf b/solution/tech-solution/serverless-ha/outputs.tf new file mode 100644 index 0000000000..7e2c8d6886 --- /dev/null +++ b/solution/tech-solution/serverless-ha/outputs.tf @@ -0,0 +1,61 @@ +output "web_url" { + description = "Web访问地址" + value = "http://${alicloud_alb_load_balancer.main.dns_name}" +} + +output "vpc_id" { + description = "VPC ID" + value = alicloud_vpc.main.id +} + +output "vpc_cidr_block" { + description = "VPC CIDR块" + value = alicloud_vpc.main.cidr_block +} + +output "vswitch_ids" { + description = "交换机ID列表" + value = { + web_01 = alicloud_vswitch.web_01.id + web_02 = alicloud_vswitch.web_02.id + db_01 = alicloud_vswitch.db_01.id + pub_01 = alicloud_vswitch.pub_01.id + pub_02 = alicloud_vswitch.pub_02.id + } +} + +output "security_group_id" { + description = "安全组ID" + value = alicloud_security_group.main.id +} + +output "polardb_cluster_id" { + description = "PolarDB集群ID" + value = alicloud_polardb_cluster.main.id +} + +output "polardb_connection_string" { + description = "PolarDB连接地址" + value = alicloud_polardb_cluster.main.connection_string + sensitive = true +} + +output "alb_id" { + description = "应用负载均衡器ID" + value = alicloud_alb_load_balancer.main.id +} + +output "alb_dns_name" { + description = "应用负载均衡器DNS名称" + value = alicloud_alb_load_balancer.main.dns_name +} + +output "sae_namespace_id" { + description = "SAE命名空间ID" + value = alicloud_sae_namespace.main.id +} + +output "sae_application_id" { + description = "SAE应用ID" + value = alicloud_sae_application.main.id +} diff --git a/solution/tech-solution/serverless-ha/provider.tf b/solution/tech-solution/serverless-ha/provider.tf new file mode 100644 index 0000000000..5e236864d5 --- /dev/null +++ b/solution/tech-solution/serverless-ha/provider.tf @@ -0,0 +1,3 @@ +provider "alicloud" { + region = var.region +} \ No newline at end of file diff --git a/solution/tech-solution/serverless-ha/variables.tf b/solution/tech-solution/serverless-ha/variables.tf new file mode 100644 index 0000000000..ac8081bcfc --- /dev/null +++ b/solution/tech-solution/serverless-ha/variables.tf @@ -0,0 +1,23 @@ +variable "region" { + description = "地域" + type = string + default = "cn-hangzhou" +} + +variable "common_name" { + description = "通用名称前缀" + type = string + default = "serverless" +} + +variable "db_user_name" { + description = "MySQL数据库账号" + type = string + default = "applets" +} + +variable "db_password" { + description = "MySQL数据库密码,长度8-30,必须包含三项(大写字母、小写字母、数字、特殊符号)" + type = string + sensitive = true +}