如何使用MySQL Terraform提供商
#教程 #devops #mysql #terraform

在本教程中,我们将为Docker提供MySQL Server,然后使用Terraform为MySQL用户,数据库schemas和MySQL赠款提供MySQL Terraform Provider。

关于

Terraform超级强大,可以做很多事情。它在提供基础设施时会发光。因此,在我们使用TerraForm提供RDS MySQL数据库实例的情况下,我们可能仍然希望为额外的MySQL用户或数据库架构和各自的MySQL赠款提供。

通常,您会登录到数据库,并使用SQL语法手动创建它们。但是在本教程中,我们想利用Docker来提供我们的MySQL Server,我们想利用Terraform来提供MySQL数据库模式,赠款和用户。

我将在Docker上提供MySQL Server,而不是使用AWS RDS,以便我们可以免费保持成本。

我们还将详细介绍如何旋转我们将为用户提供的数据库密码的步骤。

mysql Server

首先,我们将在Docker容器上提供MySQL Server,我有一个docker-compose.yaml,它在我的quick-starts GitHub存储库中可用:

version: "3.8"

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    ports:
      - 3306:3306
    environment:
      - MYSQL_DATABASE=sample
      - MYSQL_ROOT_PASSWORD=rootpassword

将其保存在当前的工作目录中后,您可以使用Docker组成:
启动容器

docker-compose up -d

您可以通过正确的auth登录MySQL Server来测试MySQL容器:

docker exec -it mysql mysql -u root -prootpassword -e 'show databases;'

这应该或多或少是输出:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sample             |
| sys                |
+--------------------+

Terraform

如果您没有安装Terraform,则可以从其documentation安装它。

如果您想要此示例的源代码,则可以在我的terraform-mysql/petoju-provider存储库中使用。您可以克隆并跳入terraform/mysql/petoju-provider目录。

首先,我们将定义providers.tf

terraform {
  required_providers {
    mysql = {
      source = "petoju/mysql"
      version = "3.0.37"
    }
  }
}

provider "mysql" {
  alias    = "local"
  endpoint = "127.0.0.1:3306"
  username = "root"
  password = "rootpassword"
}

然后main.tf

resource "random_password" "user_password" {
  length           = 24
  special          = true
  min_special      = 2
  override_special = "!#$%^&*()-_=+[]{}<>:?"
  keepers = {
    password_version = var.password_version
  }
}

resource "mysql_database" "user_db" {
  provider = mysql.local
  name = var.database_name
}

resource "mysql_user" "user_id" {
  provider = mysql.local
  user = var.database_username
  plaintext_password = random_password.user_password.result
  host = "%"
  tls_option = "NONE"
}

resource "mysql_grant" "user_id" {
  provider = mysql.local
  user = var.database_username
  host = "%"
  database = var.database_name
  privileges = ["SELECT", "UPDATE"]
  depends_on = [
    mysql_user.user_id
  ]
}

然后variables.tf

variable "database_name" {
  description = "The name of the database that you want created."
  type        = string
  default     = null
}

variable "database_username" {
  description = "The name of the database username that you want created."
  type        = string
  default     = null
}

variable "password_version" {
  description = "The password rotates when this value gets updated."
  type        = number
  default     = 0
}

然后我们的outputs.tf

output "user" {
  value = mysql_user.user_id.user
}

output "password" {
  sensitive = true
  value = random_password.user_password.result
}

定义我们变量值的terraform.tfvars

database_name     = "foobar"
database_username = "ruanb"
password_version  = 0

现在,我们准备运行我们的Terraform代码,该代码最终将创建一个数据库,用户和赠款。输出密码的加密字符串,该字符串已加密您的keybase_username

初始terraform:

terraform init

运行计划以查看Terraform想要提供的内容:

terraform plan

我们可以看到将创建以下资源:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # mysql_database.user_db will be created
  + resource "mysql_database" "user_db" {
      + default_character_set = "utf8mb4"
      + default_collation     = "utf8mb4_general_ci"
      + id                    = (known after apply)
      + name                  = "foobar"
    }

  # mysql_grant.user_id will be created
  + resource "mysql_grant" "user_id" {
      + database   = "foobar"
      + grant      = false
      + host       = "%"
      + id         = (known after apply)
      + privileges = [
          + "SELECT",
          + "UPDATE",
        ]
      + table      = "*"
      + tls_option = "NONE"
      + user       = "ruanb"
    }

  # mysql_user.user_id will be created
  + resource "mysql_user" "user_id" {
      + host               = "%"
      + id                 = (known after apply)
      + plaintext_password = (sensitive value)
      + tls_option         = "NONE"
      + user               = "ruanb"
    }

  # random_password.user_password will be created
  + resource "random_password" "user_password" {
      + bcrypt_hash      = (sensitive value)
      + id               = (known after apply)
      + keepers          = {
          + "password_version" = "0"
        }
      + length           = 24
      + lower            = true
      + min_lower        = 0
      + min_numeric      = 0
      + min_special      = 2
      + min_upper        = 0
      + number           = true
      + numeric          = true
      + override_special = "!#$%^&*()-_=+[]{}<>:?"
      + result           = (sensitive value)
      + special          = true
      + upper            = true
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + password = (sensitive value)
  + user     = "ruanb"

运行将创建数据库的应用程序,用户,设置密码并应用赠款:

terraform apply

然后,我们的返回输出应显示这样的东西:

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

password = <sensitive>
user = "ruanb"

当我们的密码设置为敏感时,我们可以使用terraform output -raw password访问该值,让我们将密码分配给变量:

DBPASS=$(terraform output -raw password)

然后,我们可以使用我们的新凭据来执行MySQL容器,然后登录到MySQL Server:

docker exec -it mysql mysql -u ruanb -p$DBPASS

,我们可以看到我们已登录到MySQL Server:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.33 MySQL Community Server - GPL

mysql>

如果我们运行show databases;,我们应该看到以下内容:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| foobar             |
| information_schema |
| performance_schema |
+--------------------+
3 rows in set (0.03 sec)

如果要为用户旋转MySQL密码,我们可以在terraform.tfvars中或通过CLI更新password_version变量。让我们通过CLI中的变量并执行terraform plan来验证更改:

terraform plan -var password_version=1

,由于我们对正在更新的随机资源守护者参数的价值,它将触发要更改的密码的值,这将使Terraform更新我们的MySQL用户的密码:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # mysql_user.user_id will be updated in-place
  ~ resource "mysql_user" "user_id" {
        id                 = "ruanb@%"
      ~ plaintext_password = (sensitive value)
        # (5 unchanged attributes hidden)
    }

  # random_password.user_password must be replaced
-/+ resource "random_password" "user_password" {
      ~ bcrypt_hash      = (sensitive value)
      ~ id               = "none" -> (known after apply)
      ~ keepers          = { # forces replacement
          ~ "password_version" = "0" -> "1"
        }
      ~ result           = (sensitive value)
        # (11 unchanged attributes hidden)
    }

Plan: 1 to add, 1 to change, 1 to destroy.

让我们通过更新密码来继续:

terraform apply -var password_version=1 -auto-approve

要验证密码已更改,我们可以尝试使用最初创建的密码变量登录到MySQL:

docker exec -it mysql mysql -u ruanb -p$DBPASS

您可以看到身份验证失败:

mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'ruanb'@'localhost' (using password: YES)

再次将新密码设置为变量:

DBPASS=$(terraform output -raw password)

然后尝试再次登录:

docker exec -it mysql mysql -u ruanb -p$DBPASS

我们可以看到我们再次登录:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 8.0.33 MySQL Community Server - GPL

mysql>

资源

Terraform mysql提供商:

快速启动存储库:

谢谢

感谢您的阅读,请随时查看我的website,随时订阅我的newsletter或在Twitter上在@ruanbekker上关注我。