Terraform is the infrastructure as code offering from HashiCorp. It is a tool for building, changing, and managing infrastructure in a safe, repeatable way. Operators and Infrastructure teams can use Terraform to manage environments with a configuration language called the HashiCorp Configuration Language (HCL) for human-readable, automated deployments.
Infrastructure as Code
Infrastructure as code is the process of managing infrastructure in a file or files rather than manually configuring resources using a user interface. A resource in this instance is any piece of infrastructure in a given environment, such as a virtual machine, security group, network interface, etc.
A simple workflow for deployment will follow following steps:
- Scope
- Author
- Initialize
- Plan & apply
Terraform provides following few advantages for operators and organizations of any size.
- Platform Agnostic
- State Management
- Operator Confidence
Basically I have used the following files with terraform.
1. env-vars
3. vcn.tf
4. subnet.tf
5. compute.tf
6. output.tf
Execute source and environment variable files to reflect environment variables.
source env-vars
Execute terraform init to initialize the backend and provider plugins..
terraform init
Execute terraform with validate command to validate syntax on all the terraform files
terraform validate
Execute terraform plan to display the plan. With the help of plan command with terraform we will be able to view what terraform is going to create and destroy during apply command. It is best practice to use out option to save the output to the file.
terraform plan -out terraform.plan
...........
Final step is to apply terraform with terraform apply command.
terraform apply
....
Final output of terraform apply is below.
env-vars
-----------------------------------------------------------------------------------
#!/usr/bin/env bash
### Authentication details
export TF_VAR_tenancy_ocid="ocid1.tenancy.oc1..*********ia"
export TF_VAR_user_ocid="ocid1.user.oc1..**********da"
export TF_VAR_fingerprint="e6:********:51"
export TF_VAR_private_key_path="//Users//dilli//.oci//private.pem"
### Region
export TF_VAR_region="us-ashburn-1"
### Compartment
export TF_VAR_compartment_ocid="ocid1.compartment.oc1..************mq"
### Public/private keys used on the instance
export TF_VAR_ssh_public_key=$(cat /Users/dilli/.ssh/rsa_public)
export TF_VAR_ssh_private_key=$(cat /Users/dilli/.ssh/rsa_private)
-----------------------------------------------------------------------------------
terraform.tfvars
-----------------------------------------------------------------------------------
anywhere = "0.0.0.0/0"
-----------------------------------------------------------------------------------
vcn.tf
-----------------------------------------------------------------------------------
variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "compartment_ocid" {}
variable "region" {}
variable "anywhere" {
type = string
}
provider "oci" {
tenancy_ocid = var.tenancy_ocid
user_ocid = var.user_ocid
fingerprint = var.fingerprint
private_key_path = var.private_key_path
region = var.region
}
resource "oci_core_vcn" "TFDemoVCN" {
cidr_block = "192.168.100.0/23"
dns_label = "TFDemoVCN"
compartment_id = var.compartment_ocid
display_name = "TFDemoVCN"
}
resource "oci_core_internet_gateway" "TFDemo-IGW" {
compartment_id = var.compartment_ocid
display_name = "TFDemo-IGW"
vcn_id = oci_core_vcn.TFDemoVCN.id
}
resource "oci_core_default_route_table" "default_route_table" {
manage_default_resource_id = oci_core_vcn.TFDemoVCN.default_route_table_id
display_name = "defaultRouteTable"
route_rules {
destination = var.anywhere
destination_type = "CIDR_BLOCK"
network_entity_id = oci_core_internet_gateway.TFDemo-IGW.id
}
}
resource "oci_core_default_dhcp_options" "default_dhcp_options" {
manage_default_resource_id = oci_core_vcn.TFDemoVCN.default_dhcp_options_id
display_name = "defaultDhcpOptions"
// required
options {
type = "DomainNameServer"
server_type = "VcnLocalPlusInternet"
}
// optional
options {
type = "SearchDomain"
search_domain_names = ["abc.com"]
}
}
resource "oci_core_default_security_list" "default_security_list" {
manage_default_resource_id = oci_core_vcn.TFDemoVCN.default_security_list_id
display_name = "defaultSecurityList"
// allow outbound tcp traffic on all ports
egress_security_rules {
destination = var.anywhere
protocol = "6"
}
// allow outbound udp traffic on a port range
egress_security_rules {
destination = var.anywhere
protocol = "17" // udp
stateless = true
udp_options {
min = 319
max = 320
}
}
// allow inbound ssh traffic
ingress_security_rules {
protocol = "6" // tcp
source = var.anywhere
stateless = false
tcp_options {
min = 22
max = 22
}
}
// allow http ingress traffic
ingress_security_rules {
protocol = "6" // tcp
source = var.anywhere
stateless = false
tcp_options {
min = 80
max = 80
}
}
// allow inbound icmp traffic of a specific type
ingress_security_rules {
protocol = 1
source = var.anywhere
stateless = true
icmp_options {
type = 3
code = 4
}
}
}
-----------------------------------------------------------------------------------
subnet.tf
-----------------------------------------------------------------------------------
data "oci_identity_availability_domain" "ad" {
compartment_id = "${var.tenancy_ocid}"
ad_number = 1
}
// A regional subnet will not specify an Availability Domain
resource "oci_core_subnet" "PublicSubnet" {
cidr_block = "192.168.100.0/24"
display_name = "PublicSubnet"
dns_label = "PublicSubnet"
compartment_id = var.compartment_ocid
vcn_id = oci_core_vcn.TFDemoVCN.id
security_list_ids = [oci_core_vcn.TFDemoVCN.default_security_list_id]
route_table_id = oci_core_vcn.TFDemoVCN.default_route_table_id
dhcp_options_id = oci_core_vcn.TFDemoVCN.default_dhcp_options_id
}
// An AD based subnet will supply an Availability Domain
resource "oci_core_subnet" "PrivateSubnet" {
availability_domain = data.oci_identity_availability_domain.ad.name
cidr_block = "192.168.101.0/24"
display_name = "PrivateSubnet"
dns_label = "PrivateSubnet"
compartment_id = var.compartment_ocid
vcn_id = oci_core_vcn.TFDemoVCN.id
security_list_ids = [oci_core_vcn.TFDemoVCN.default_security_list_id]
route_table_id = oci_core_vcn.TFDemoVCN.default_route_table_id
dhcp_options_id = oci_core_vcn.TFDemoVCN.default_dhcp_options_id
prohibit_public_ip_on_vnic = true
}
-----------------------------------------------------------------------------------
compute.tf
-----------------------------------------------------------------------------------
variable "ssh_public_key" {}
variable "ssh_private_key" {}
variable "instance_shape" {
default = "VM.Standard2.1"
}
variable "instance_ocpus" {
default = 1
}
variable "instance_image_ocid" {
type = map
default = {
# See https://docs.us-phoenix-1.oraclecloud.com/images/
# Oracle-provided image "Oracle-Linux-7.5-2018.10.16-0"
us-phoenix-1 = "ocid1.image.oc1.phx.aaaaaaaaoqj42sokaoh42l76wsyhn3k2beuntrh5maj3gmgmzeyr55zzrwwa"
us-ashburn-1 = "ocid1.image.oc1.iad.aaaaaaaageeenzyuxgia726xur4ztaoxbxyjlxogdhreu3ngfj2gji3bayda"
eu-frankfurt-1 = "ocid1.image.oc1.eu-frankfurt-1.aaaaaaaaitzn6tdyjer7jl34h2ujz74jwy5nkbukbh55ekp6oyzwrtfa4zma"
uk-london-1 = "ocid1.image.oc1.uk-london-1.aaaaaaaa32voyikkkzfxyo4xbdmadc2dmvorfxxgdhpnk6dw64fa3l4jh7wa"
}
}
variable "db_size" {
default = "50" # size in GBs
}
resource "oci_core_instance" "TFDemoInstance" {
availability_domain = data.oci_identity_availability_domain.ad.name
compartment_id = var.compartment_ocid
display_name = "TFDemoInstance"
shape = var.instance_shape
shape_config {
ocpus = var.instance_ocpus
}
create_vnic_details {
subnet_id = oci_core_subnet.PublicSubnet.id
display_name = "Primaryvnic"
assign_public_ip = true
hostname_label = "TFDemo1"
}
source_details {
source_type = "image"
source_id = var.instance_image_ocid[var.region]
}
metadata = {
ssh_authorized_keys = var.ssh_public_key
//user_data = "${base64encode(file("./userdata/bootstrap"))}"
}
timeouts {
create = "60m"
}
}
resource "null_resource" "remote-exec" {
provisioner "remote-exec" {
connection {
agent = false
timeout = "30m"
host = oci_core_instance.TFDemoInstance.public_ip
user = "opc"
private_key = var.ssh_private_key
}
inline = [
"echo 'This instance was provisioned by Terraform.' | sudo tee /etc/motd",
"sudo yum -y update",
"sudo yum -y install httpd",
"echo 'This is index page' | sudo tee -a /var/www/html/index.html",
"sudo firewall-cmd --permanent --add-service=http",
"sudo firewall-cmd --reload",
"sudo systemctl start httpd",
"sudo systemctl enable httpd"
]
}
}
-----------------------------------------------------------------------------------
output.tf
-----------------------------------------------------------------------------------
output "vcn_id" {
description = "ocid of created VCN. "
value = oci_core_vcn.TFDemoVCN.id
}
output "subnet_ids" {
description = "ocid of subnet ids. "
value = oci_core_subnet.PublicSubnet.id
}
output "instance_public_ips" {
value = [oci_core_instance.TFDemoInstance.public_ip]
}
-----------------------------------------------------------------------------------
Beauty of terraform nicely demonstrated
ReplyDeletePerfect :)
ReplyDelete