# DevOps Training Session 7: Terraform ###### tags: `devops` `research` `reliable` Hello like i said on the last topic, terraform is way to solving anything problem with cloud ? Easy way to done job --> So go far with that && Happy with implementation --> [:coffee:](https://drive.google.com/file/d/1glnjlHG5GEi3AY_iYdTVRNfVYzpliHpl/view?usp=sharing) ## Setup the Terraform and init some extension Reference for full information --> [**LINK**](https://cloudinfrastructureservices.co.uk/how-to-install-terraform-on-ubuntu-server-20-04/) ``` #!/bin/bash wget https://releases.hashicorp.com/terraform/1.3.7/terraform_1.3.7_linux_amd64.zip unzip terraform_1.3.7_linux_amd64.zip sudo cp terraform /usr/local/bin terraform --version ``` After install you whill receive and install terraform succesful with version ![](https://i.imgur.com/JUk2y2D.png) And some extension for VSCode --> Increase productivity like ![](https://i.imgur.com/ro4HrUz.png) ![](https://i.imgur.com/v6cVLku.png) ![](https://i.imgur.com/7ZbwwdX.png) ![](https://i.imgur.com/7s0hQ8Q.png) ## Do the lab --> Run by `step by step` :coffee: After install the terraform cli for terminal --> Next step you can read some reference in the document of terraform ![](https://i.imgur.com/0tOukD8.png) --> U need to understand which terraform give for us for using to implementation for each script :sandwich: --> After that reach to my script --> I will analysis from each part to part to resolve the problem of script So i will split the bunch of script of terraform to 3 file for easy management and apply - So when i want to apply terraform --> i think you need split all of part of source into separate file like - `outputs.tf` --> Manage output from terraform - `main.tf` --> Manage the resource for update or create part on the cloud - `providers.tf` --> Manage authentication && storage configurate for terraform to associated with terraform - After split that --> reach to the scripting providers.tf ``` # Get the resource backend from the Private Storage backend terraform { backend "azurerm" { resource_group_name = <resource_group_name> storage_account_name = <storage_account_name> container_name = <container_name_on_storage_account> key = <name_of_tfstate_file> } } provider "azurerm" { features{} } ``` - So on this script, usually if you implement with terraform --> u need some kind configuration like a library contain API to association with platform you want, terraform have many options: - azurerm --> association with azure, bucket will storage it on the container on azure account - local --> This backend status using tfstate have exist on local you can import this path into that kind and use that - remote --> This backend will use tfstate on remote env kind your server, your drive, you NAS --> Anykind - aws --> association with AWS - blah blah --> Provider, backend depend on your choice, get the suitable for your target main.tf ``` # Get data_resource from RG data "azurerm_resource_group" "current" { name = "DevOpsIntern" } # Get data_resource from sshkey data "azurerm_ssh_public_key" "my_vm_public_key" { name = "DevOpsIntern" resource_group_name = data.azurerm_resource_group.current.name } # Create network resource "azurerm_virtual_network" "my_terraform_network" { name = "LinuxVMnet" address_space = ["10.0.0.0/16"] location = data.azurerm_resource_group.current.location resource_group_name = data.azurerm_resource_group.current.name } # Create the subnet resource "azurerm_subnet" "my_terraform_network_subnet" { name = "LinuxVMsubnet" resource_group_name = data.azurerm_resource_group.current.name virtual_network_name = azurerm_virtual_network.my_terraform_network.name address_prefixes = ["10.0.1.0/24"] } # Create public IP resource "azurerm_public_ip" "my_terraform_public_ip" { name = "LinuxVMpubIP" location = data.azurerm_resource_group.current.location resource_group_name = data.azurerm_resource_group.current.name allocation_method = "Dynamic" } # Create a SecurityGroup resource "azurerm_network_security_group" "my_terraform_nsg" { name = "LinuxVMNetworkingSecurityGroup" location = data.azurerm_resource_group.current.location resource_group_name = data.azurerm_resource_group.current.name security_rule { name = "SSH" priority = 1001 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "22" source_address_prefix = "*" destination_address_prefix = "*" } security_rule { name = "HTTP" priority = 1002 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "80" source_address_prefix = "*" destination_address_prefix = "*" } security_rule { name = "HTTPS" priority = 1003 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "*" destination_address_prefix = "*" } tags = { <Your_choice> = <Your_choice> <Your_choice> = <Your_choice> } } # Create NIC resource "azurerm_network_interface" "my_terraform_nic" { name = "LinuxVMNic" location = data.azurerm_resource_group.current.location resource_group_name = data.azurerm_resource_group.current.name ip_configuration { name = "my_nic_configuration" subnet_id = azurerm_subnet.my_terraform_network_subnet.id private_ip_address_allocation = "Dynamic" public_ip_address_id = azurerm_public_ip.my_terraform_public_ip.id } } # Get the connect between NIC and security group resource "azurerm_network_interface_security_group_association" "my_terraform_asNicSG" { network_interface_id = azurerm_network_interface.my_terraform_nic.id network_security_group_id = azurerm_network_security_group.my_terraform_nsg.id } # Create the virtual machine resource "azurerm_linux_virtual_machine" "my_terraform_vm" { name = "LinuxVM" computer_name = "LinuxVM" resource_group_name = data.azurerm_resource_group.current.name location = data.azurerm_resource_group.current.location size = "Standard_B1s" admin_username = "intern" network_interface_ids = [azurerm_network_interface.my_terraform_nic.id] os_disk { name = "LinuxVM_disk" caching = "ReadWrite" storage_account_type = "StandardSSD_LRS" } admin_ssh_key { username = "intern" public_key = data.azurerm_ssh_public_key.my_vm_public_key.public_key } source_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "18.04-LTS" version = "latest" } disable_password_authentication = true tags = { managed_by = "terraform" environment = "dev" } } ``` It just a bunch of script using for create a VM on Azure --> this just basic script refer with syntax from Terraform doc and using azurerm, just this :smile_cat: output.tf ``` # Output the public IP address is created from Azure output "public_ip_address" { value = azurerm_linux_virtual_machine.my_terraform_vm.public_ip_address } ``` So after create the vm you want to get ip_address to access so --> Get on it --> Well after create all kind that you just need terraform init terraform plan terraform apply -auto-approve Just use some command each times to times like - `terraform init` Using for create and get provider for terraform --> create 1 folder storage some configuration and api for using with platform --> create hcl and tfstate file if you using local - `terraform plan` Using for check the plan before apply into cloud platform mine option or your option :smiley: - `terraform apply` Do the stuff about apply plan configuration to platform you want like github, like azure, like aws, ... - After that just wait to get result :breast-feeding: - Quite easy huh So i have some script about my teammate implement with [Nguyen Hoai Bao Nguyen](https://github.com/ZGnyn) for option to choose do it with terraform `run_terraform.sh` ``` #!/bin/bash # Get the absolution of path abs_path_file_execute=$(realpath "$0") abs_path_folder_script=$(dirname "$abs_path_file_execute") abs_path_folder_root=$(dirname "$(dirname "$abs_path_file_execute")") abs_path_folder_terraform="$abs_path_folder_root""/terraform/modules/vm/" # Bash Menu Script Example echo "---------MENU------------" PS3='Please enter your choice: ' options=("Create virtual machine" "Destroy virtual machine" "Quit") select opt in "${options[@]}" do case $opt in "Create virtual machine") cd $abs_path_folder_terraform terraform init terraform plan terraform apply -auto-approve ;; "Destroy virtual machine") cd $abs_path_folder_terraform terraform destroy -auto-approve ;; "Quit") break ;; *) echo "invalid option $REPLY";; esac done ``` - Script like i said above about do it with manual, script do it automatic for me for instead of --> just add terraform desrtroy it will using to destroy the all configuration you create by terrafrom into platform - Just it some basic terrafrom quite easy to understand about **infra as code** :coffee: ![](https://i.imgur.com/g8E933G.png) ## Reference * [Quickstart: Use Terraform to create a Linux VM](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-terraform) * [Environment Variables](https://developer.hashicorp.com/terraform/cli/config/environment-variables) * [Spacelift](https://spacelift.io/) * [Destroy Command – How to Destroy Resources from Terraform](https://spacelift.io/blog/how-to-destroy-terraform-resources) * [How do I create multiple Security rules using Terraform in Azure?](https://stackoverflow.com/questions/54744311/how-do-i-create-multiple-security-rules-using-terraform-in-azure) * [Terraform-Doc](https://developer.hashicorp.com/terraform) * [Azurerm-doc](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs) * [Configure Azure Storage firewalls and virtual networks](https://learn.microsoft.com/en-us/azure/storage/common/storage-network-security?tabs=azure-portal) * [How to store Terraform state file in Azure Storage | How to manage Terraform state in Azure Blob Storage | Terraform Remote state in Azure Blob storage | Terraform backend](https://www.coachdevops.com/2022/03/how-to-store-terraform-state-file-in.html) * [Can I export a variable to the environment from a Bash script without sourcing it?](https://stackoverflow.com/questions/16618071/can-i-export-a-variable-to-the-environment-from-a-bash-script-without-sourcing-i) * [Azurerm-provider](https://developer.hashicorp.com/terraform/language/settings/backends/azurerm) * [Getting Started with Terraform for Azure: Authentication Demo](https://www.youtube.com/watch?v=IHHIXf39Igo&ab_channel=SkylinesAcademy) * [Azure-Ad](https://www.testpreptraining.com/tutorial/explain-azure-ad-identity-types/) * [hashicorp/terraform-provider-azurerm](https://github.com/hashicorp/terraform-provider-azurerm)