From 950290471003c1928ff103af2d8b0098de396437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=93=E6=BA=AA?= Date: Mon, 18 Aug 2025 06:43:50 +0800 Subject: [PATCH] the-headless-architecture-solution-of-alibaba-cloud-ecs --- .../README.md | 63 +++ .../main.tf | 413 ++++++++++++++++++ .../outputs.tf | 24 + .../variables.tf | 16 + 4 files changed, 516 insertions(+) create mode 100644 solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/README.md create mode 100644 solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/main.tf create mode 100644 solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/outputs.tf create mode 100644 solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/variables.tf diff --git a/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/README.md b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/README.md new file mode 100644 index 000000000..60c70d30f --- /dev/null +++ b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/README.md @@ -0,0 +1,63 @@ +## Introduction + + +本示例用于实现解决方案[10分钟完成前后端分离架构升级(ECS版)](https://www.aliyun.com/solution/tech-solution-deploy/2867383), 涉及到专有网络(VPC)、交换机(VSwitch)、云服务器(ECS)等资源的创建。 + + + +This example is used to implement solution [The Headless Architecture Solution of Alibaba Cloud(ECS)](https://www.aliyun.com/solution/tech-solution-deploy/2867383). It involves the creation, and deployment of resources such as Virtual Private Cloud (VPC), VSwitch, Elastic Compute Service (ECS). + + + +## Providers + +| Name | Version | +|------|---------| +| [alicloud](#provider\_alicloud) | n/a | +| [random](#provider\_random) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [alicloud_alb_listener.backend_listener](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/alb_listener) | resource | +| [alicloud_alb_listener.frontend_listener](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/alb_listener) | resource | +| [alicloud_alb_load_balancer.backend_alb](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/alb_load_balancer) | resource | +| [alicloud_alb_load_balancer.frontend_alb](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/alb_load_balancer) | resource | +| [alicloud_alb_server_group.backend_server_group](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/alb_server_group) | resource | +| [alicloud_alb_server_group.frontend_server_group](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/alb_server_group) | resource | +| [alicloud_ecs_command.run_command_start_backend](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/ecs_command) | resource | +| [alicloud_ecs_command.run_command_start_frontend](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/ecs_command) | resource | +| [alicloud_ecs_invocation.invoke_script_backend](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/ecs_invocation) | resource | +| [alicloud_ecs_invocation.invoke_script_frontend](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/ecs_invocation) | resource | +| [alicloud_instance.ecs_instance_be_2](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/instance) | resource | +| [alicloud_instance.ecs_instance_be_4](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/instance) | resource | +| [alicloud_instance.ecs_instance_fe_1](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/instance) | resource | +| [alicloud_instance.ecs_instance_fe_3](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/instance) | resource | +| [alicloud_security_group.security_group_backend](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/security_group) | resource | +| [alicloud_security_group.security_group_frontend](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/security_group) | resource | +| [alicloud_security_group_rule.be_allow_ssh](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.be_allow_tomcat](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.fe_allow_nginx](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.fe_allow_ssh](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_vpc.vpc](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/vpc) | resource | +| [alicloud_vswitch.vswitch_1](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.vswitch_2](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.vswitch_3](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/vswitch) | resource | +| [alicloud_vswitch.vswitch_4](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/resources/vswitch) | resource | +| [random_string.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [alicloud_images.default](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/data-sources/images) | data source | +| [alicloud_zones.default](https://registry.terraform.io/providers/hashicorp/alicloud/latest/docs/data-sources/zones) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ecs\_instance\_password](#input\_ecs\_instance\_password) | 服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)` | `string` | n/a | yes | +| [instance\_type](#input\_instance\_type) | 实例类型 | `string` | `"ecs.e-c1m2.large"` | no | +| [region](#input\_region) | n/a | `string` | `"cn-hangzhou"` | no | + \ No newline at end of file diff --git a/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/main.tf b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/main.tf new file mode 100644 index 000000000..53a7ee4c3 --- /dev/null +++ b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/main.tf @@ -0,0 +1,413 @@ +provider "alicloud" { + region = var.region +} + +data "alicloud_zones" "default" { + available_disk_category = "cloud_essd" + available_resource_creation = "VSwitch" + available_instance_type = var.instance_type +} + +resource "random_string" "suffix" { + length = 8 + lower = true + upper = false + numeric = false + special = false +} + +locals { + common_name = random_string.suffix.id +} + +resource "alicloud_vpc" "vpc" { + cidr_block = "192.168.0.0/16" + vpc_name = "vpc-${local.common_name}" +} + +resource "alicloud_vswitch" "vswitch_1" { + vpc_id = alicloud_vpc.vpc.id + cidr_block = "192.168.1.0/24" + zone_id = data.alicloud_zones.default.zones.0.id + vswitch_name = "vswitch-1-${local.common_name}" +} + +resource "alicloud_vswitch" "vswitch_2" { + vpc_id = alicloud_vpc.vpc.id + cidr_block = "192.168.2.0/24" + zone_id = data.alicloud_zones.default.zones.0.id + vswitch_name = "vswitch-2-${local.common_name}" +} + +resource "alicloud_vswitch" "vswitch_3" { + vpc_id = alicloud_vpc.vpc.id + cidr_block = "192.168.3.0/24" + zone_id = data.alicloud_zones.default.zones.1.id + vswitch_name = "vswitch-3-${local.common_name}" +} + +resource "alicloud_vswitch" "vswitch_4" { + vpc_id = alicloud_vpc.vpc.id + cidr_block = "192.168.4.0/24" + zone_id = data.alicloud_zones.default.zones.1.id + vswitch_name = "vswitch-4-${local.common_name}" +} + +resource "alicloud_security_group" "security_group_frontend" { + vpc_id = alicloud_vpc.vpc.id + security_group_name = "sg-fe-${local.common_name}" +} + +resource "alicloud_security_group" "security_group_backend" { + vpc_id = alicloud_vpc.vpc.id + security_group_name = "sg-be-${local.common_name}" +} + +resource "alicloud_security_group_rule" "fe_allow_ssh" { + type = "ingress" + ip_protocol = "tcp" + nic_type = "intranet" + policy = "accept" + port_range = "22/22" + priority = 1 + security_group_id = alicloud_security_group.security_group_frontend.id + cidr_ip = "0.0.0.0/0" +} + +resource "alicloud_security_group_rule" "be_allow_ssh" { + type = "ingress" + ip_protocol = "tcp" + nic_type = "intranet" + policy = "accept" + port_range = "22/22" + priority = 1 + security_group_id = alicloud_security_group.security_group_backend.id + cidr_ip = "0.0.0.0/0" +} + +resource "alicloud_security_group_rule" "fe_allow_nginx" { + type = "ingress" + ip_protocol = "tcp" + nic_type = "intranet" + policy = "accept" + port_range = "80/80" + priority = 1 + security_group_id = alicloud_security_group.security_group_frontend.id + cidr_ip = "0.0.0.0/0" +} + +resource "alicloud_security_group_rule" "be_allow_tomcat" { + type = "ingress" + ip_protocol = "tcp" + nic_type = "intranet" + policy = "accept" + port_range = "8080/8080" + priority = 1 + security_group_id = alicloud_security_group.security_group_backend.id + cidr_ip = "0.0.0.0/0" +} + +data "alicloud_images" "default" { + name_regex = "^aliyun_3_x64_20G_alibase_.*" + most_recent = true + owners = "system" +} + +# the 1st ECS instance where the frontend app runs +resource "alicloud_instance" "ecs_instance_fe_1" { + instance_name = "ecs-fe-1-${local.common_name}" + image_id = data.alicloud_images.default.images[0].id + instance_type = var.instance_type + system_disk_category = "cloud_essd" + security_groups = [alicloud_security_group.security_group_frontend.id] + vswitch_id = alicloud_vswitch.vswitch_1.id + password = var.ecs_instance_password + internet_max_bandwidth_out = 5 +} + +# the 2ns ECS instance where the backend app runs +resource "alicloud_instance" "ecs_instance_be_2" { + instance_name = "ecs-be-2-${local.common_name}" + image_id = data.alicloud_images.default.images[0].id + instance_type = var.instance_type + system_disk_category = "cloud_essd" + security_groups = [alicloud_security_group.security_group_backend.id] + vswitch_id = alicloud_vswitch.vswitch_2.id + password = var.ecs_instance_password + internet_max_bandwidth_out = 5 +} + +# the 3rd ECS instance where the frontend app runs +resource "alicloud_instance" "ecs_instance_fe_3" { + instance_name = "ecs-fe-3-${local.common_name}" + image_id = data.alicloud_images.default.images[0].id + instance_type = var.instance_type + system_disk_category = "cloud_essd" + security_groups = [alicloud_security_group.security_group_frontend.id] + vswitch_id = alicloud_vswitch.vswitch_3.id + password = var.ecs_instance_password + internet_max_bandwidth_out = 5 +} + +# the 4th ECS instance where the backend app runs +resource "alicloud_instance" "ecs_instance_be_4" { + instance_name = "ecs-be-4-${local.common_name}" + image_id = data.alicloud_images.default.images[0].id + instance_type = var.instance_type + system_disk_category = "cloud_essd" + security_groups = [alicloud_security_group.security_group_backend.id] + vswitch_id = alicloud_vswitch.vswitch_4.id + password = var.ecs_instance_password + internet_max_bandwidth_out = 5 +} + +resource "alicloud_ecs_command" "run_command_start_backend" { + name = "command-start-backend-${local.common_name}" + command_content = base64encode(< /etc/nginx/nginx.conf +# For more information on configuration, see: +# * Official English Documentation: http://nginx.org/en/docs/ +# * Official Russian Documentation: http://nginx.org/ru/docs/ + +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log; +pid /run/nginx.pid; + +# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic. +include /usr/share/nginx/modules/*.conf; + +events { + worker_connections 1024; +} + +http { + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 4096; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Load modular configuration files from the /etc/nginx/conf.d directory. + # See http://nginx.org/en/docs/ngx_core_module.html#include + # for more information. + include /etc/nginx/conf.d/*.conf; + + server { + listen 80; + listen [::]:80; + server_name _; + root /usr/share/nginx/html; + + # Load configuration files for the default server block. + include /etc/nginx/default.d/*.conf; + + # 客户端访问具体页面地址时对应的静态资源地址 + location / { + root /usr/share/nginx/html; + index index.html; + } + + # 配置请求转发规则 + location /api/ { + # proxy_pass http://${alicloud_instance.ecs_instance_be_2.primary_ip_address}:8080/api/; + proxy_pass http://${alicloud_alb_load_balancer.backend_alb.dns_name}:8080/api/; + + } + + error_page 404 /404.html; + location = /40x.html { + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } + } +} +EOT + +# Start frontend +sudo systemctl start nginx +sudo systemctl enable nginx + +EOF + ) + working_dir = "/root" + type = "RunShellScript" + timeout = 3600 + depends_on = [alicloud_instance.ecs_instance_be_2, alicloud_instance.ecs_instance_be_4] +} + +resource "alicloud_ecs_invocation" "invoke_script_frontend" { + instance_id = [alicloud_instance.ecs_instance_fe_1.id, alicloud_instance.ecs_instance_fe_3.id] + command_id = alicloud_ecs_command.run_command_start_frontend.id + timeouts { + create = "15m" + } + depends_on = [alicloud_instance.ecs_instance_fe_1, alicloud_instance.ecs_instance_fe_3] +} + +resource "alicloud_alb_load_balancer" "backend_alb" { + address_allocated_mode = "Fixed" + load_balancer_name = "lb-be-${local.common_name}" + vpc_id = alicloud_vpc.vpc.id + address_type = "Intranet" + load_balancer_edition = "Basic" + load_balancer_billing_config { + pay_type = "PayAsYouGo" + } + zone_mappings { + zone_id = data.alicloud_zones.default.zones.0.id + vswitch_id = alicloud_vswitch.vswitch_2.id + } + zone_mappings { + zone_id = data.alicloud_zones.default.zones.1.id + vswitch_id = alicloud_vswitch.vswitch_4.id + } +} + +resource "alicloud_alb_server_group" "backend_server_group" { + server_group_name = "alb-be-server-group-${local.common_name}" + protocol = "HTTP" + vpc_id = alicloud_vpc.vpc.id + server_group_type = "Instance" + sticky_session_config { + sticky_session_enabled = false + } + health_check_config { + health_check_enabled = false + } + servers { + server_type = "Ecs" + port = 8080 + server_id = alicloud_instance.ecs_instance_be_2.id + server_ip = alicloud_instance.ecs_instance_be_2.primary_ip_address + weight = 50 + } + + servers { + server_type = "Ecs" + port = 8080 + server_id = alicloud_instance.ecs_instance_be_4.id + server_ip = alicloud_instance.ecs_instance_be_4.primary_ip_address + weight = 50 + } +} + +resource "alicloud_alb_listener" "backend_listener" { + load_balancer_id = alicloud_alb_load_balancer.backend_alb.id + listener_protocol = "HTTP" + listener_port = 8080 + default_actions { + type = "ForwardGroup" + forward_group_config { + server_group_tuples { + server_group_id = alicloud_alb_server_group.backend_server_group.id + } + } + } +} + +resource "alicloud_alb_load_balancer" "frontend_alb" { + address_allocated_mode = "Fixed" + load_balancer_name = "lb-fe-${local.common_name}" + vpc_id = alicloud_vpc.vpc.id + address_type = "Internet" + load_balancer_edition = "Basic" + load_balancer_billing_config { + pay_type = "PayAsYouGo" + } + zone_mappings { + zone_id = data.alicloud_zones.default.zones.0.id + vswitch_id = alicloud_vswitch.vswitch_1.id + } + zone_mappings { + zone_id = data.alicloud_zones.default.zones.1.id + vswitch_id = alicloud_vswitch.vswitch_3.id + } +} + +resource "alicloud_alb_server_group" "frontend_server_group" { + server_group_name = "alb-fe-server-group-${local.common_name}" + protocol = "HTTP" + vpc_id = alicloud_vpc.vpc.id + server_group_type = "Instance" + sticky_session_config { + sticky_session_enabled = false + } + health_check_config { + health_check_enabled = false + } + servers { + server_type = "Ecs" + port = 80 + server_id = alicloud_instance.ecs_instance_fe_1.id + server_ip = alicloud_instance.ecs_instance_fe_1.primary_ip_address + weight = 50 + } + servers { + server_type = "Ecs" + port = 80 + server_id = alicloud_instance.ecs_instance_fe_3.id + server_ip = alicloud_instance.ecs_instance_fe_3.primary_ip_address + weight = 50 + } +} + +resource "alicloud_alb_listener" "frontend_listener" { + load_balancer_id = alicloud_alb_load_balancer.frontend_alb.id + listener_protocol = "HTTP" + listener_port = 80 + default_actions { + type = "ForwardGroup" + forward_group_config { + server_group_tuples { + server_group_id = alicloud_alb_server_group.frontend_server_group.id + } + } + } +} diff --git a/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/outputs.tf b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/outputs.tf new file mode 100644 index 000000000..fec5ca268 --- /dev/null +++ b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/outputs.tf @@ -0,0 +1,24 @@ +output "ecs_backend_login_address" { + description = "后端应用的ECS实例的登录地址。通过此地址登录ECS后,在本地验证后端应用部署成功的命令为:curl -I http://localhost:8080/api/getEcsReleaseNotes" + value = format("https://ecs-workbench.aliyun.com/?from=ecs&instanceType=ecs®ionId=%s&instanceId=%s&resourceGroupId=", var.region, alicloud_instance.ecs_instance_be_2.id) +} + +output "ecs_frontend_login_address" { + description = "前端应用的ECS实例的登录地址。通过此地址登录ECS后,在本地验证前端应用部署成功的命令为:curl -I http://localhost:80/;进一步验证请求能成功转发到后端应用的命令:curl -I http://localhost:80/api/getEcsReleaseNotes" + value = format("https://ecs-workbench.aliyun.com/?from=ecs&instanceType=ecs®ionId=%s&instanceId=%s&resourceGroupId=", var.region, alicloud_instance.ecs_instance_fe_1.id) +} + +output "web_url" { + description = "示例网站地址/Sample website address" + value = "http://${alicloud_alb_load_balancer.frontend_alb.dns_name}" +} + +output "frontend_dns_name" { + description = "前端ALB的DNS名称。" + value = alicloud_alb_load_balancer.frontend_alb.dns_name +} + +output "backend_dns_name" { + description = "后端ALB的DNS名称。" + value = alicloud_alb_load_balancer.backend_alb.dns_name +} \ No newline at end of file diff --git a/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/variables.tf b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/variables.tf new file mode 100644 index 000000000..71ca380f0 --- /dev/null +++ b/solution/tech-solution/the-headless-architecture-solution-of-alibaba-cloud-ecs/variables.tf @@ -0,0 +1,16 @@ +variable "region" { + type = string + default = "cn-hangzhou" +} + +variable "instance_type" { + type = string + default = "ecs.t6-c1m2.large" + description = "实例类型" +} + +variable "ecs_instance_password" { + type = string + sensitive = true + description = "服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)" +}