6.5. MySQL
Step 6.5.1: Configure AKS egress IP
By default, AKS routes traffic to the internet via a (randomly assigned) Azure public IP. For some scenarios like our MySQL instance, we want to whitelist the source IP to restrict access to the services.
Add the following content below the resource azurerm_public_ip.aks_lb_ingress in aks.tf:
// optional: only needed to control AKS egress IP(s)
resource "azurerm_public_ip" "aks_lb_egress" {
name = "pip-${local.infix}-aks-lb-egress"
location = var.location
resource_group_name = azurerm_resource_group.aks.name
allocation_method = "Static"
sku = "Standard"
}
To configure AKS to use a static egress IP, modify the azurerm_kubernetes_cluster.aks resource in aks.tf
and replace the network_profile block with the following content:
network_profile {
network_plugin = "kubenet"
load_balancer_sku = "standard"
// optional: only needed to control AKS egress IP(s)
load_balancer_profile {
outbound_ip_address_ids = [azurerm_public_ip.aks_lb_egress.id]
}
}
Now run
terraform apply -var-file=config/dev.tfvars
To verify the egress IP is correct, run the following command:
kubectl exec -n tests hello -- curl -s ifconfig.me
This lists the egress IP of the AKS cluster as reported by the website https://ifconfig.me
Now verify this IP is equal to the AKS load balancer ip by running:
terraform state show azurerm_public_ip.aks_lb_egress
Step 6.5.2: Add a MySQL instance
flowchart LR
classDef red fill:#f96
subgraph rg: db
mServer(mysql):::red --> mDb(database):::red
mFire(firewall):::red --> mDb
endCreate a new file named mysql.tf and add the following content:
resource "azurerm_resource_group" "db" {
name = "rg-${local.infix}-db"
location = var.location
}
resource "random_password" "mysql" {
length = 16
special = false
}
resource "azurerm_mysql_flexible_server" "demo" {
name = "mdb-${local.infix}"
resource_group_name = azurerm_resource_group.db.name
location = azurerm_resource_group.db.location
administrator_login = "demo"
administrator_password = random_password.mysql.result
sku_name = "B_Standard_B1ms"
backup_retention_days = 7
geo_redundant_backup_enabled = false
version = "8.0.21"
storage {
size_gb = 20
}
}
resource "azurerm_mysql_flexible_server_configuration" "ssl_off" {
name = "require_secure_transport"
resource_group_name = azurerm_resource_group.db.name
server_name = azurerm_mysql_flexible_server.demo.name
value = "off"
}
resource "azurerm_mysql_flexible_database" "demo_app" {
name ="demo_app"
resource_group_name = azurerm_resource_group.db.name
server_name = azurerm_mysql_flexible_server.demo.name
charset = "utf8"
collation = "utf8_general_ci"
}
resource "azurerm_mysql_flexible_server_firewall_rule" "aks_egress_ip" {
name = "aks-egress-ip"
resource_group_name = azurerm_resource_group.db.name
server_name = azurerm_mysql_flexible_server.demo.name
start_ip_address = azurerm_public_ip.aks_lb_egress.ip_address
end_ip_address = azurerm_public_ip.aks_lb_egress.ip_address
}
Create a new file named outputs.tf and add the following content:
output "mysql_uri" {
sensitive = true
value = format("mysql://%s:%s@%s/%s",
azurerm_mysql_flexible_server.demo.administrator_login,
azurerm_mysql_flexible_server.demo.administrator_password,
azurerm_mysql_flexible_server.demo.fqdn,
azurerm_mysql_flexible_database.demo_app.name
)
}
Now run
terraform apply -var-file=config/dev.tfvars
The MySQL URI can be displayed by running:
terraform output mysql_uri
Explanation
The MySQL instance is a managed service by Azure and has a public IP. By default, no IPs are allowed to access
the instance. The resource azurerm_mysql_flexible_server_firewall_rule.aks_egress_ip adds a firewall rule to whitelist the egress IP
of the Kubernetes AKS cluster, which allows apps deployed on the cluster to access MySQL.
To configure our demo app, we need to generate a MySQL URI. The Terraform function format has familiar syntax to
the GLIBC function snprintf() and allows better readable code.