diff --git a/solution/tech-solution/redis-cache-speedup/README.md b/solution/tech-solution/redis-cache-speedup/README.md new file mode 100644 index 0000000000..89cd1cbb18 --- /dev/null +++ b/solution/tech-solution/redis-cache-speedup/README.md @@ -0,0 +1,58 @@ +## Introduction + +本示例用于实现解决方案[自建数据库迁移到云数据库](https://www.aliyun.com/solution/tech-solution/redis-cache-speedup), 涉及到专有网络(VPC)、交换机(VSwitch)、云服务器(ECS)、云数据库(RDS)MySQL版、云数据库 Tair(兼容 Redis)等资源的部署。 + + + +This example is used to implement solution [Migrate Self-Built Database to Cloud Database](https://www.aliyun.com/solution/tech-solution/redis-cache-speedup), which involves the creation and deployment of resources such as Virtual Private Cloud (VPC), VSwitch, Elastic Compute Service (ECS), ApsaraDB RDS, Tair (Redis OSS-compatible). + + + +## Providers + +| Name | Version | +|------|---------| +| [alicloud](#provider\_alicloud) | n/a | +| [random](#provider\_random) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [alicloud_db_database.rds_database](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/db_database) | resource | +| [alicloud_db_instance.rds_instance](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/db_instance) | resource | +| [alicloud_ecs_command.install_web_command](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/ecs_command) | resource | +| [alicloud_ecs_invocation.install_web_invocation](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/ecs_invocation) | resource | +| [alicloud_instance.ecs_instance](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance) | resource | +| [alicloud_kvstore_account.redis_account](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/kvstore_account) | resource | +| [alicloud_kvstore_instance.redis_instance](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/kvstore_instance) | resource | +| [alicloud_rds_account.rds_account](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/rds_account) | resource | +| [alicloud_security_group.security_group](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group) | resource | +| [alicloud_security_group_rule.security_group_rule_http](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.security_group_rule_https](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.security_group_rule_mysql](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_security_group_rule.security_group_rule_ssh](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/security_group_rule) | resource | +| [alicloud_vpc.vpc](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vpc) | resource | +| [alicloud_vswitch.vswitch](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/vswitch) | resource | +| [random_id.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [alicloud_db_instance_classes.default](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/db_instance_classes) | data source | +| [alicloud_images.ecs_image](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/images) | data source | +| [alicloud_instance_types.default](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/instance_types) | data source | +| [alicloud_kvstore_zones.default](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/kvstore_zones) | data source | +| [alicloud_regions.current](https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/data-sources/regions) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [db\_password](#input\_db\_password) | RDS数据库密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 !@#$%^&*()\_+-= 中的特殊符号)。 | `string` | n/a | yes | +| [db\_user\_name](#input\_db\_user\_name) | RDS数据库账号,由 2 到 32 个小写字母组成,支持小写字母、数字和下划线,以小写字母开头。 | `string` | `"rds"` | no | +| [ecs\_instance\_password](#input\_ecs\_instance\_password) | 实例密码,服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。` | `string` | n/a | yes | +| [redis\_account\_name](#input\_redis\_account\_name) | Redis数据库账号,由 2 到 32 个小写字母组成,支持小写字母、数字和下划线,以小写字母开头。 | `string` | `"redis"` | no | +| [redis\_account\_password](#input\_redis\_account\_password) | Redis数据库密码,数据库账号密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。` | `string` | n/a | yes | +| [region](#input\_region) | 地域 | `string` | `"cn-hangzhou"` | no | + \ No newline at end of file diff --git a/solution/tech-solution/redis-cache-speedup/main.tf b/solution/tech-solution/redis-cache-speedup/main.tf new file mode 100644 index 0000000000..ae2b1a51a5 --- /dev/null +++ b/solution/tech-solution/redis-cache-speedup/main.tf @@ -0,0 +1,247 @@ + +locals { + zone_id = data.alicloud_kvstore_zones.default.ids[length(data.alicloud_kvstore_zones.default.ids) - 1] +} + +data "alicloud_kvstore_zones" "default" { + instance_charge_type = "PostPaid" + engine = "Redis" + product_type = "OnECS" +} + +data "alicloud_db_instance_classes" "default" { + zone_id = local.zone_id + engine = "MySQL" + engine_version = "8.0" + category = "Basic" + db_instance_storage_type = "cloud_essd" + instance_charge_type = "PostPaid" +} + +# Declare the data source +data "alicloud_instance_types" "default" { + availability_zone = local.zone_id + instance_type_family = "ecs.c7" +} + +resource "random_id" "suffix" { + byte_length = 4 +} +locals { + common_name = "cache-${random_id.suffix.hex}" +} +# VPC 网络资源 +resource "alicloud_vpc" "vpc" { + vpc_name = "${local.common_name}-vpc" + cidr_block = "192.168.0.0/16" +} + +resource "alicloud_vswitch" "vswitch" { + vpc_id = alicloud_vpc.vpc.id + cidr_block = "192.168.0.0/24" + zone_id = local.zone_id + vswitch_name = "${local.common_name}-vsw" +} + +# 安全组 +resource "alicloud_security_group" "security_group" { + security_group_name = "${local.common_name}-sg" + vpc_id = alicloud_vpc.vpc.id +} + +resource "alicloud_security_group_rule" "security_group_rule_ssh" { + security_group_id = alicloud_security_group.security_group.id + type = "ingress" + ip_protocol = "tcp" + port_range = "22/22" + cidr_ip = "0.0.0.0/0" +} + +resource "alicloud_security_group_rule" "security_group_rule_http" { + security_group_id = alicloud_security_group.security_group.id + type = "ingress" + ip_protocol = "tcp" + port_range = "80/80" + cidr_ip = "0.0.0.0/0" +} + +resource "alicloud_security_group_rule" "security_group_rule_https" { + security_group_id = alicloud_security_group.security_group.id + type = "ingress" + ip_protocol = "tcp" + port_range = "443/443" + cidr_ip = "0.0.0.0/0" +} + +resource "alicloud_security_group_rule" "security_group_rule_mysql" { + security_group_id = alicloud_security_group.security_group.id + type = "ingress" + ip_protocol = "tcp" + port_range = "3306/3306" + cidr_ip = "0.0.0.0/0" +} + +# 镜像数据源 +data "alicloud_images" "ecs_image" { + name_regex = "^aliyun_3_x64_20G_alibase_.*" + most_recent = true + owners = "system" + instance_type = data.alicloud_instance_types.default.instance_types[0].id +} + +# ECS 实例 +resource "alicloud_instance" "ecs_instance" { + instance_name = "${local.common_name}-ecs" + image_id = data.alicloud_images.ecs_image.images[0].id + instance_type = data.alicloud_instance_types.default.instance_types[0].id + security_groups = [alicloud_security_group.security_group.id] + vswitch_id = alicloud_vswitch.vswitch.id + system_disk_category = "cloud_essd" + internet_max_bandwidth_out = 5 + password = var.ecs_instance_password +} + +# RDS 数据库实例 +resource "alicloud_db_instance" "rds_instance" { + engine = "MySQL" + engine_version = "8.0" + instance_type = data.alicloud_db_instance_classes.default.instance_classes.0.instance_class + instance_storage = data.alicloud_db_instance_classes.default.instance_classes.0.storage_range.min + db_instance_storage_type = "cloud_essd" + category = "Basic" + vpc_id = alicloud_vpc.vpc.id + vswitch_id = alicloud_vswitch.vswitch.id + security_group_ids = [alicloud_security_group.security_group.id] + security_ips = ["192.168.0.0/24"] + zone_id = local.zone_id + zone_id_slave_a = "Auto" +} + +# RDS 账户 +resource "alicloud_rds_account" "rds_account" { + db_instance_id = alicloud_db_instance.rds_instance.id + account_name = var.db_user_name + account_password = var.db_password + account_type = "Super" +} + +# RDS 数据库 +resource "alicloud_db_database" "rds_database" { + instance_id = alicloud_db_instance.rds_instance.id + name = "biz" + character_set = "utf8mb4" + depends_on = [alicloud_rds_account.rds_account] +} + +# Redis 实例 +resource "alicloud_kvstore_instance" "redis_instance" { + db_instance_name = "${local.common_name}-redis" + instance_class = "redis.shard.small.2.ce" + instance_type = "Redis" + engine_version = "6.0" + vswitch_id = alicloud_vswitch.vswitch.id + zone_id = local.zone_id + password = var.redis_password + security_ips = ["192.168.0.0/24"] +} + +# Redis 账户 +resource "alicloud_kvstore_account" "redis_account" { + instance_id = alicloud_kvstore_instance.redis_instance.id + account_name = var.redis_account_name + account_password = var.redis_password + account_privilege = "RoleReadWrite" + account_type = "Normal" +} + + +# 本地变量 - 安装脚本 +locals { + install_script = <<-SHELL +#!/bin/bash + +# 环境变量配置 +export PATH=/usr/local/bin:$PATH + +function log_info() { + printf "%s [INFO] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1" +} + +function log_error() { + printf "%s [ERROR] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$1" +} + +function log_fatal() { + printf "\n========================================================================\n" + printf "%s [FATAL] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$2" + printf "\n========================================================================\n" + exit $1 +} + +function debug_exec(){ + local cmd="$@" + log_info "$cmd" + eval "$cmd" + ret=$? + echo "" + log_info "$cmd, exit code: $ret" + return $ret +} + +function install_web() { + yum install nginx -y + yum install java-1.8.0-openjdk.x86_64 -y + sed -i 's/ _;/ domain.not.exists;/' /etc/nginx/nginx.conf + curl -o AppWithRedisDemo.jar 'https://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/demos/AppWithRedisDemo.jar' +} + +if ! debug_exec install_web; then + log_fatal 3 "install web failed" +fi + +cat << 'EOF' > /etc/nginx/conf.d/app_with_redis.conf +server { + listen 80 default_server; + server_name _; + + location / { + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} + +EOF + +nohup java -DMYSQL_HOST="${alicloud_db_instance.rds_instance.connection_string}" -DMYSQL_PASSWORD="${var.db_password}" -DREDIS_HOST="${alicloud_kvstore_instance.redis_instance.connection_domain}" -DREDIS_PASSWORD="redis:${var.redis_password}" -DAPP_MANUAL_DEPLOY="false" -jar AppWithRedisDemo.jar > output.log 2>&1 & +/bin/systemctl start nginx.service +SHELL +} + +# ECS 命令 +resource "alicloud_ecs_command" "install_web_command" { + name = "install-web-command" + description = "Install web application with Redis demo" + enable_parameter = false + type = "RunShellScript" + command_content = base64encode(local.install_script) + timeout = 3600 + working_dir = "/root" +} + +# 在ECS中执行命令 +resource "alicloud_ecs_invocation" "install_web_invocation" { + instance_id = [alicloud_instance.ecs_instance.id] + command_id = alicloud_ecs_command.install_web_command.id + + depends_on = [ + alicloud_db_database.rds_database, + alicloud_kvstore_account.redis_account + ] + + timeouts { + create = "10m" + } +} \ No newline at end of file diff --git a/solution/tech-solution/redis-cache-speedup/outputs.tf b/solution/tech-solution/redis-cache-speedup/outputs.tf new file mode 100644 index 0000000000..724fc7c4c0 --- /dev/null +++ b/solution/tech-solution/redis-cache-speedup/outputs.tf @@ -0,0 +1,41 @@ +## here are the updates to merge: +# ECS相关输出 +output "ecs_login_address" { + description = "ECS登录地址" + value = "https://ecs-workbench.aliyun.com/?from=EcsConsole&instanceType=ecs®ionId=${data.alicloud_regions.current.regions[0].id}&instanceId=${alicloud_instance.ecs_instance.id}" +} + +output "ecs_public_ip_address" { + description = "ECS公网IP地址" + value = alicloud_instance.ecs_instance.public_ip +} + +# RDS相关输出 +output "rds_database_endpoint" { + description = "RDS数据库连接地址" + value = alicloud_db_instance.rds_instance.connection_string +} + +output "rds_database_name" { + description = "RDS数据库名称" + value = alicloud_db_database.rds_database.name +} + +output "rds_database_user_name" { + description = "RDS数据库用户名" + value = var.db_user_name +} + +# Redis相关输出 +output "redis_account_name" { + description = "Redis数据库用户名" + value = var.redis_account_name +} + +output "redis_endpoint" { + description = "Redis数据库连接地址" + value = alicloud_kvstore_instance.redis_instance.private_connection_prefix +} + +# 获取当前区域信息的数据源 +data "alicloud_regions" "current" {} \ No newline at end of file diff --git a/solution/tech-solution/redis-cache-speedup/provider.tf b/solution/tech-solution/redis-cache-speedup/provider.tf new file mode 100644 index 0000000000..5e236864d5 --- /dev/null +++ b/solution/tech-solution/redis-cache-speedup/provider.tf @@ -0,0 +1,3 @@ +provider "alicloud" { + region = var.region +} \ No newline at end of file diff --git a/solution/tech-solution/redis-cache-speedup/variables.tf b/solution/tech-solution/redis-cache-speedup/variables.tf new file mode 100644 index 0000000000..f03fa543f5 --- /dev/null +++ b/solution/tech-solution/redis-cache-speedup/variables.tf @@ -0,0 +1,43 @@ +variable "region" { + description = "地域" + type = string + default = "cn-hangzhou" +} + +variable "db_password" { + type = string + description = "RDS数据库密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 !@#$%^&*()_+-= 中的特殊符号)。" + sensitive = true +} + +variable "db_user_name" { + type = string + description = "RDS数据库账号,由 2 到 32 个小写字母组成,支持小写字母、数字和下划线,以小写字母开头。" + validation { + condition = can(regex("^[a-z][a-z0-9_]{0,31}$", var.db_user_name)) + error_message = "由 2 到 32 个小写字母组成,支持小写字母、数字和下划线,以小写字母开头。" + } + default = "rds" +} + +variable "ecs_instance_password" { + type = string + description = "实例密码,服务器登录密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。" + sensitive = true +} + +variable "redis_account_name" { + type = string + description = "Redis数据库账号,由 2 到 32 个小写字母组成,支持小写字母、数字和下划线,以小写字母开头。" + validation { + condition = can(regex("^[a-z][a-z0-9_]{0,31}$", var.redis_account_name)) + error_message = "由 2 到 32 个小写字母组成,支持小写字母、数字和下划线,以小写字母开头。" + } + default = "redis" +} + +variable "redis_password" { + type = string + description = "Redis数据库密码,数据库账号密码,长度8-30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。" + sensitive = true +}