# 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)