-
Notifications
You must be signed in to change notification settings - Fork 1
feat(mysql): 创建 MySQL 主从复制集群和单节点实例的 Terraform 配置文件 #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
包括 data.tf、main.tf、mysql_master.sh、mysql_slave.sh、outputs.tf、variables.tf、versions.tf 等文件
Summary of ChangesHello @zhangzqs, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求引入了用于在 Qiniu 云平台上部署 MySQL 数据库的 Terraform 配置。它提供了两种部署模式:一种是高可用的主从复制集群,另一种是独立的单节点实例。这些配置旨在简化 MySQL 基础设施的自动化部署和管理,通过可配置的变量和自动化脚本,用户可以快速地创建和配置满足其特定需求的 MySQL 环境。 Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
这个 PR 增加了用于创建 MySQL 单节点实例和主从复制集群的 Terraform 模块,代码结构清晰。审查中发现了一些需要解决的问题,包括安全漏洞(例如,为复制用户使用管理员密码、在 shell 脚本中暴露密码、开放的绑定地址)、正确性错误(脚本语法错误、变量名不正确、脆弱的等待逻辑)以及可维护性方面的改进(使配置更健壮和灵活)。请查看具体的审查意见。
| echo "MySQL not found, installing..." | ||
| apt-get update | ||
| DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-client-8.0 mysql-server-8.0 mysql-router mysql-shell | ||
| fi`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| echo "Setting up MySQL standalone instance..." | ||
|
|
||
| # 允许外部IP访问 | ||
| sed -i 's/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| mysql_admin_username = var.mysql_username | ||
| mysql_admin_password = var.mysql_password | ||
| mysql_replication_username = local.replication_username | ||
| mysql_replication_password = var.mysql_password |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| default = "" | ||
|
|
||
| validation { | ||
| condition = var.mysql_db_name == null ? true : ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| mysql_master_ip = qiniu_compute_instance.mysql_primary_node.private_ip_addresses[0].ipv4 | ||
| mysql_server_id = tostring(count.index + 2) // 从库ID从2开始递增 | ||
| mysql_replication_username = local.replication_username | ||
| mysql_replication_password = var.mysql_password |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| # 重启 MySQL 服务 | ||
| systemctl restart mysql | ||
| sleep 1 # 等待 MySQL 服务重启完成 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ubuntu_image_id = [ | ||
| for item in data.qiniu_compute_images.available_official_images.items : item | ||
| if item.os_distribution == "Ubuntu" && item.os_version == "24.04 LTS" | ||
| ][0].id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
当前查找 Ubuntu 镜像 ID 的方式比较脆弱。如果 data.qiniu_compute_images.available_official_images.items 没有返回任何匹配 "Ubuntu" 和 "24.04 LTS" 的镜像,[0].id 的访问会直接导致 Terraform 执行失败。建议使用 one() 函数来确保只找到一个匹配的镜像,如果找不到或找到多个,它会返回一个更明确的错误信息。
ubuntu_image_id = one([for item in data.qiniu_compute_images.available_official_images.items : item if item.os_distribution == "Ubuntu" && item.os_version == "24.04 LTS"]).id
|
|
||
| # 重启 MySQL 服务 | ||
| systemctl restart mysql | ||
| sleep 1 # 等待 MySQL 服务重启完成 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| variable "instance_system_disk_size" { | ||
| type = number | ||
| description = "System disk size in GiB" | ||
|
|
||
| validation { | ||
| condition = var.instance_system_disk_size > 0 | ||
| error_message = "instance_system_disk_size parameter must be a positive integer" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
变量 instance_system_disk_size 没有设置默认值,而 replication 模块中的同名变量设置了 default = 20。为了保持一致性并提高模块易用性,建议在此处也添加一个默认值。
variable "instance_system_disk_size" {
type = number
description = "System disk size in GiB"
default = 20
validation {
condition = var.instance_system_disk_size > 0
error_message = "instance_system_disk_size parameter must be a positive integer"
}
}
|
|
||
| # 创建 MySQL 从库节点 | ||
| resource "qiniu_compute_instance" "mysql_replication_nodes" { | ||
| depends_on = [qiniu_compute_instance.mysql_primary_node] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| echo "MySQL not found, installing..." | ||
| apt-get update | ||
| DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-client-8.0 mysql-server-8.0 mysql-router mysql-shell | ||
| fi`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical Syntax Error
There are extra backticks at the end of this line (`fi```) which will cause a bash syntax error and script failure.
| fi`` | |
| fi |
| image_id = local.ubuntu_image_id | ||
| system_disk_size = var.instance_system_disk_size | ||
|
|
||
| user_data = base64encode(templatefile("${path.module}/mysql_master.sh", { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical Security: Passwords Exposed in Terraform State
Passing passwords directly in user_data causes multiple security vulnerabilities:
- Passwords stored in plaintext in Terraform state files
- Exposed in cloud provider logs and instance metadata
- Visible in process listings during execution
Recommendation: Use a secrets management solution (AWS Secrets Manager, HashiCorp Vault, etc.) and retrieve credentials at runtime, or generate random passwords within the instance and store them securely.
References: CWE-312, CWE-532
| echo "This is the primary node." | ||
|
|
||
| # 允许外部IP访问 | ||
| sed -i 's/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical Security: MySQL Exposed Without Firewall Rules
Binding to 0.0.0.0 exposes MySQL on all network interfaces, but the Terraform configuration doesn't include any security groups or firewall rules to restrict access.
Impact: MySQL instances accessible from entire network, vulnerable to brute force attacks and exploitation.
Recommendation: Add security group/firewall resources in Terraform to restrict port 3306 access to specific IP ranges or VPC subnets only.
| fi | ||
|
|
||
| # 查看数据库 | ||
| mysql -u"${mysql_admin_username}" -p"${mysql_admin_password}" -e "SHOW DATABASES;" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical Security: Credentials Exposed in Process Listing
Passing passwords via command-line arguments (-p"${password}") exposes them in:
- Process listings (
ps aux) visible to all users - Shell history files
- System logs
Recommendation: Use MySQL config files instead:
cat > /root/.my.cnf <<MYCNF
[client]
user=${mysql_admin_username}
password=${mysql_admin_password}
MYCNF
chmod 600 /root/.my.cnf
mysql -e "SHOW DATABASES;"Reference: CWE-214
| default = "" | ||
|
|
||
| validation { | ||
| condition = var.mysql_db_name == null ? true : ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical Bug: Validation Logic Error
This validation checks for null but the variable has default = "" (empty string). The condition will never work correctly.
The replication module correctly uses var.mysql_db_name == "" at line 64 of mysql/replication/variables.tf.
| condition = var.mysql_db_name == null ? true : ( | |
| condition = var.mysql_db_name == "" ? true : ( |
| ubuntu_image_id = [ | ||
| for item in data.qiniu_compute_images.available_official_images.items : item | ||
| if item.os_distribution == "Ubuntu" && item.os_version == "24.04 LTS" | ||
| ][0].id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Unsafe Array Access
Directly accessing [0] without checking if the array is empty will cause Terraform to fail if no Ubuntu 24.04 LTS image is found.
Recommendation: Add error handling:
ubuntu_images = [
for item in data.qiniu_compute_images.available_official_images.items : item
if item.os_distribution == "Ubuntu" && item.os_version == "24.04 LTS"
]
ubuntu_image_id = length(local.ubuntu_images) > 0 ? local.ubuntu_images[0].id : (
# Trigger a clear error message
tobool("ERROR: Ubuntu 24.04 LTS image not found")
)| sleep 1 # 等待 MySQL 服务重启完成 | ||
|
|
||
| # 轮询等待主库启动 | ||
| while ! mysqladmin ping -h "${mysql_master_ip}" -u"${mysql_replication_username}" -p"${mysql_replication_password}" --silent; do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
High Priority: Unbounded Polling Loop
This while loop has no timeout, which could cause infinite waiting if the master fails to start.
Recommendation: Add timeout and exponential backoff:
MAX_RETRIES=60
RETRY_COUNT=0
SLEEP_TIME=2
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
if mysqladmin ping -h "${mysql_master_ip}" -u"${mysql_replication_username}" -p"${mysql_replication_password}" --silent; then
echo "MySQL master is ready!"
break
fi
echo "Waiting for MySQL master... (attempt $((RETRY_COUNT + 1))/$MAX_RETRIES)"
sleep $SLEEP_TIME
RETRY_COUNT=$((RETRY_COUNT + 1))
SLEEP_TIME=$((SLEEP_TIME > 10 ? 10 : SLEEP_TIME + 1))
done
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
echo "ERROR: MySQL master failed to become ready"
exit 1
fi|
|
||
| # 创建 MySQL 从库节点 | ||
| resource "qiniu_compute_instance" "mysql_replication_nodes" { | ||
| depends_on = [qiniu_compute_instance.mysql_primary_node] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance: Unnecessary Serialization
The depends_on forces all replica nodes to wait for complete master provisioning (including user_data execution), which blocks parallelization.
Since mysql_slave.sh already has a polling loop to wait for the master, this dependency can be removed to allow parallel instance provisioning, significantly reducing deployment time.
Recommendation: Remove depends_on to enable ~30-60% faster deployments.
| mysql -uroot <<EOF | ||
| ALTER USER 'root'@'localhost' IDENTIFIED BY '${mysql_admin_password}'; | ||
| CREATE USER '${mysql_admin_username}'@'%' IDENTIFIED BY '${mysql_admin_password}'; | ||
| GRANT ALL PRIVILEGES ON *.* TO '${mysql_admin_username}'@'%' WITH GRANT OPTION; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security: Overly Permissive Privileges
Granting ALL PRIVILEGES ON *.* with GRANT OPTION from any host ('%') violates the principle of least privilege.
Recommendations:
- Restrict host to specific IP ranges:
'10.0.0.0/255.0.0.0' - Grant only necessary privileges instead of ALL
- Remove
GRANT OPTIONunless required - Create separate users for different purposes
Reference: CWE-250
| @@ -0,0 +1,3 @@ | |||
| provider "qiniu" {} | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing Provider Version Constraints
No version constraints specified for providers, which can lead to unpredictable behavior across environments.
Recommendation:
| provider "qiniu" {} | |
| terraform { | |
| required_providers { | |
| qiniu = { | |
| source = "qiniu/qiniu" | |
| version = "~> 1.0" | |
| } | |
| random = { | |
| source = "hashicorp/random" | |
| version = "~> 3.0" | |
| } | |
| } | |
| required_version = ">= 1.0" | |
| } | |
| provider "qiniu" {} |
|
|
||
| # 配置从库,将自动将主库所有变更都同步过来,包括用户配置 | ||
| mysql -uroot <<EOF | ||
| CHANGE MASTER TO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deprecated MySQL Syntax
MySQL 8.0.23+ deprecated MASTER/SLAVE terminology in favor of SOURCE/REPLICA.
Recommendation: Update to modern syntax:
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '${mysql_master_ip}',
SOURCE_USER = '${mysql_replication_username}',
SOURCE_PASSWORD = '${mysql_replication_password}',
SOURCE_AUTO_POSITION = 1;
START REPLICA;
SHOW REPLICA STATUS\G;
Code Review SummaryI've completed a comprehensive review using specialized agents for code quality, security, performance, and documentation. The modules are well-structured, but several critical issues must be addressed before merging. Critical Issues (Must Fix)
High Priority
Performance Optimization
Additional Recommendations
Overall, the Terraform structure is solid, but the security posture needs significant improvement before production use. |
No description provided.