Automation using terraform on MultiCloud- Deploy WordPress on Kubernetes Cluster on GCP Cloud and Database on AWS Cloud using Customize VPC

Akash Pandey
8 min readAug 30, 2020

With all the experience and knowledge that I have about Automation, here’s my article on ‘What the world needs?’ The answer to it is Automation.

In this Article , I have Integrated Multi-Cloud using Terraform Code and Deployed WordPress on Kubernetes Cluster using Custom VPC on GCP Cloud while Database using Custom VPC on AWS Cloud .

I have done the Following things using Terraform Code as follows -

  • Created VPC in AWS and GCP Cloud
  • Created two Subnet in AWS and one Subnet in GCP Cloud
  • Create Internet Gateway , Route Table in AWS Cloud
  • Associate Subnet to Router Table in AWS Cloud
  • Create Security Group for Database in AWS Cloud
  • Creation of Firewall in GCP Cloud
  • Created one database subnet group in AWS Cloud
  • Created Database in Custom VPC and Security Group in AWS Cloud
  • Created Google Container Cluster — K8s Cluster in GCP Cloud
  • Launched WordPress on the top of K8s Cluster with LoadBalancer in GCP Cloud
  • Attached Database running in AWS Cloud and WordPress Application running in GCP Cloud

Here , We need to Provide -

  • AWS Credentials
  • GCP Credentials

After Creation of Google Container Engine , We need to Provide

  • Kubernetes Credentials to Connect to GCE

Before Applying Terraform Code We must first init the Terraform -

# terraform init

It’s a good Practice to Validate the terraform Code to check whether Everything is fine or not

# terraform validate

AWS Cloud -

Providing Credentials of AWS Cloud -

provider "aws" {
region = var.aws_region
profile = var.aws_profile
}

Creation of VPC in -

resource "aws_vpc" "tf_vpc" {
cidr_block = var.aws_vpc_cidr
instance_tenancy = "default"
enable_dns_hostnames = var.aws_vpc_dns_hostname
tags = {
Name = var.vpc_name
}
}

Creation of Subnet -

Here , We create two Subnet as RDS minimum requirement is to launch in two Subnet and Availability zones .

resource "aws_subnet" "tf_subnet" {
vpc_id = aws_vpc.tf_vpc.id
cidr_block = var.aws_subnet_cidr[0]
availability_zone = var.aws_availability_zone[0]
map_public_ip_on_launch = true
tags = {
Name = var.aws_subnet_name[0]
}
}
resource "aws_subnet" "tf_subnet2" {
vpc_id = aws_vpc.tf_vpc.id
cidr_block = var.aws_subnet_cidr[1]
availability_zone = var.aws_availability_zone[1]
map_public_ip_on_launch = true
tags = {
Name = var.aws_subnet_name[1]
}
}

Creation of Internet Gateways -

resource "aws_internet_gateway" "tf_gw" {
vpc_id = aws_vpc.tf_vpc.id
tags = {
Name = var.aws_ig_name
}
}

Creation of Route table -

resource "aws_route_table" "tf_rt" {
vpc_id = aws_vpc.tf_vpc.id
route {
gateway_id = aws_internet_gateway.tf_gw.id
cidr_block = var.allow_all
}
tags = {
Name = var.route_table_name
}
}

Association of Route table to both the Subnet -

resource "aws_route_table_association" "tf_sub_a" {
subnet_id = aws_subnet.tf_subnet.id
route_table_id = aws_route_table.tf_rt.id
}
resource "aws_route_table_association" "tf_sub_b" {
subnet_id = aws_subnet.tf_subnet2.id
route_table_id = aws_route_table.tf_rt.id
}

Creation of Security Group -

resource "aws_security_group" "tf_sg2" {
depends_on = [ aws_vpc.tf_vpc ]
name = var.aws_sg_name
vpc_id = aws_vpc.tf_vpc.id
ingress {
description = "MYSQL"
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = [ var.allow_all ]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [ var.allow_all ]
}
tags = {
Name = var.aws_sg_tag
}
}

Creation of Database Subnet Group -

resource "aws_db_subnet_group" "subnetdb" {
name = var.aws_db_subnet_name
subnet_ids = [ aws_subnet.tf_subnet.id , aws_subnet.tf_subnet2.id ]
}

Creation of Database —

resource "aws_db_instance" "mydb" {

identifier = var.db_identifier
engine = var.db_engine
engine_version = var.db_engine_version
instance_class = var.db_instance_class
allocated_storage = var.db_storage
db_subnet_group_name = aws_db_subnet_group.subnetdb.id
name = var.database_name
username = var.database_username
password = var.database_password
port = var.database_port
vpc_security_group_ids = [ aws_security_group.tf_sg2.id ]
publicly_accessible = var.db_public_accessible
iam_database_authentication_enabled = true
parameter_group_name = var.db_parameter_name
tags = {
Name = var.db_tag
}
}

GCP Cloud -

Providing Credentials of GCP Cloud -

provider "google" {
credentials = file(var.gcp_credentials)
project = var.gcp_project_id
region = var.gcp_region
}

Creation of VPC -

resource "google_compute_network" "vpc_network" {
name = var.vpc_name
auto_create_subnetworks = var.gcp_auto_create_subnetwork
routing_mode = var.gcp_routing_mode
}

Creation of Subnet -

resource "google_compute_subnetwork" "subnet" {
network = google_compute_network.vpc_network.id
name = var.gcp_subnet_name
ip_cidr_range = var.gcp_subnet_cidr
region = var.gcp_region
}

Creation of Firewall -

resource "google_compute_firewall" "firewall" {
name = var.gcp_firewall_name
network = google_compute_network.vpc_network.name
source_ranges = [ var.allow_all ]
allow {
protocol = var.gcp_protocol
}
}

Creation of Google Container Engine — K8s Cluster

resource "google_container_cluster" "gce" {
name = var.cluster_name
location = var.gcp_region
remove_default_node_pool = var.gcp_remove_default_node_pool
initial_node_count = var.gcp_initial_node_count
network = google_compute_network.vpc_network.name
subnetwork = google_compute_subnetwork.subnet.name
}
resource "google_container_node_pool" "node_pool" {
location = var.gcp_region
name = var.gcp_container_node_pool_name
cluster = google_container_cluster.gce.name
node_count = var.gcp_node_count
node_config {
machine_type = var.gcp_container_machine_type
}
}

Then , We can apply the terraform Code to deploy these things .

# terraform apply -auto-approve

After All the Services are Running in the Cloud , Here we can Provide Kubernetes Credentials to automatically launch the WordPress and LoadBalancer .

First , We have to init terraform Code so that they can download the Kubernetes Plugin -

# terraform init

So , Here we fetch name and Cluster of CKE and then provide Kubernetes Credentials -

data "google_client_config" "provider" {}
data "google_container_cluster" "gce" {
name = var.cluster_name
location = var.gcp_region
}
provider "kubernetes" {
load_config_file = false
host = "https://${data.google_container_cluster.gce.endpoint}"
token = data.google_client_config.provider.access_token
cluster_ca_certificate = base64decode(
data.google_container_cluster.gce.master_auth[0].cluster_ca_certificate,
)
}

Creation of WordPress Pod on the top of K8s Cluster -

resource "kubernetes_pod" "wppod" {
metadata {
name = var.pod_name
labels = {
dc = var.pod_labels[0]
app = var.pod_labels[1]
}
}
spec {
container {
image = var.image_name
name = var.container_name
}
}

}

Creation of Kubernetes ( CKE ) LoadBalancer Service -

resource "kubernetes_service" "wplb" {
metadata {
name = var.loadbalancer_name
}
spec {
selector = {
app = var.pod_labels[1]
}
port {
port = 80
target_port = 80
}
type = var.pod_expose_type
}
}

Print the Output of LoadBalancer Ip :-

output "loadbalancer_IP_Address" {
value = "${kubernetes_service.wplb.load_balancer_ingress.0.ip}"
}

Now , run the tf Code -

# terraform apply -auto-approve

Finally , Set-up Deployed Successfully . Now we attached the WordPress with Database .

Variables.tf :-

variable "aws_region" {
type = string
default = "ap-south-1"
}
variable "aws_profile" {
type = string
default = "aks07"
}
variable "vpc_name" {
type = string
default = "myvpc-tf"
}
variable "aws_vpc_cidr" {
type = string
default = "192.168.0.0/16"
}
variable "aws_vpc_dns_hostname" {
type = bool
default = true
}
variable "aws_subnet_cidr" {
default = [ "192.168.0.0/24" , "192.168.1.0/24" ]
}
variable "aws_availability_zone" {
default = [ "ap-south-1a" , "ap-south-1b" ]
}
variable "aws_subnet_name" {
default = [ "subnet-1" , "subnet-2" ]
}
variable "aws_ig_name" {
type = string
default = "my-ig"
}
variable "allow_all" {
type = string
default = "0.0.0.0/0"
}
variable "route_table_name" {
type = string
default = "my_rt2"
}
variable "aws_sg_name" {
type = string
default = "db_sg"
}
variable "aws_sg_tag" {
type = string
default = "mysql_sg"
}
variable "aws_db_subnet_name" {
type = string
default = "db-subnet"
}
variable "db_identifier" {
type = string
default = "mydb-tf"
}
variable "db_engine" {
type = string
default = "mysql"
}
variable "db_engine_version" {
type = string
default = "5.7.30"
}
variable "db_instance_class" {
type = string
default = "db.t2.micro"
}
variable "db_storage" {
default = 10
}
variable "database_name" {
type = string
default = "aksdb"
}
variable "database_username" {
type = string
default = "diyaksh"
}
variable "database_password" {
type = string
default = "whoaks1234"
}
variable "database_port" {
type = string
default = "3306"
}
variable "db_public_accessible" {
type = bool
default = true
}
variable "db_parameter_name" {
type = string
default = "default.mysql5.7"
}
variable "db_tag" {
type = string
default = "aks30"
}
variable "gcp_credentials" {
type = string
default = "E:/Google_GCP/credentials/aks07.json"
}
variable "gcp_project_id" {
type = string
default = "whoaks-12345"
}
variable "gcp_region" {
type = string
default = "asia-southeast1"
}
variable "gcp_auto_create_subnetwork" {
type = bool
default = false
}
variable "gcp_routing_mode" {
type = string
default = "REGIONAL"
}
variable "gcp_subnet_name" {
type = string
default = "mylab-tf"
}
variable "gcp_subnet_cidr" {
type = string
default = "10.0.10.0/24"
}
variable "gcp_firewall_name" {
type = string
default = "firewall-tf"
}
variable "gcp_protocol" {
type = string
default = "all"
}
variable "cluster_name" {
type = string
default = "cluster-tf"
}
variable "gcp_remove_default_node_pool" {
type = bool
default = true
}
variable "gcp_initial_node_count" {
default = 1
}
variable "gcp_container_node_pool_name" {
type = string
default = "mynode-tf"
}
variable "gcp_node_count" {
default = 1
}
variable "gcp_container_machine_type" {
type = string
default = "n1-standard-1"
}
variable "pod_name" {
type = string
default = "wordpress-tf"
}
variable "pod_labels" {
default = [ "winterfell" , "wordpress" ]
}
variable "image_name" {
type = string
default = "wordpress"
}
variable "container_name" {
type = string
default = "my-wp-tf"
}
variable "loadbalancer_name" {
type = string
default = "wp-loadbalancer-tf"
}
variable "pod_expose_type" {
type = string
default = "LoadBalancer"
}

I have automate all the things using Terraform Code . Single Click and Everything is Configured in AWS and GCP Cloud .

Github :- https://github.com/whoaks/GCP_AWS_K8s_Terraform_Code

VPC , Subnet , Route Table , Internet Gateway in detail , have a look :-

https://www.linkedin.com/posts/akash-pandey-0687281a3_wordpress-database-using-terraform-activity-6687763798188728320-FjSu

Thank You

--

--

Akash Pandey

I am a Computer Science Undergraduate , who is seeking for opportunity to do work in challenging work environment .