-
Notifications
You must be signed in to change notification settings - Fork 70
Solution #63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Solution #63
Changes from all commits
54c8172
8befb60
d995cdd
82cfa85
1e0f7e7
e783be0
fd6f08a
18dc812
ebda058
c3f830f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| .terraform/ | ||
| .terraform.lock.hcl | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Variable naming inconsistency: root variables.tf defines |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,91 +1,50 @@ | ||
| # Deploying Todo List Application With Terraform | ||
| # Automated Infrastructure Provisioning with Terraform | ||
|
|
||
| In this task, you need to create an Azure Virtual Machine using Terraform and deploy a ToDo List application using a VM extension. The Terraform configuration will create all necessary resources, including a resource group, storage account, network security group, virtual network, subnet, public IP, and the virtual machine itself. | ||
| ## Project Overview | ||
| This repository contains the declarative **Infrastructure as Code (IaC)** configurations designed to provision and manage a secure, scalable, and highly available cloud environment for a multi-tier Python (Todo List) application. The primary objective of this project is to demonstrate modern DevOps deployment workflows, emphasizing predictable environment replication and strict adherence to cloud engineering best practices. | ||
|
|
||
| ## Prerequisites | ||
| ## Key Features & Architecture | ||
| * **Modular Configuration:** Written utilizing reusable, modular Terraform structures to cleanly separate environment logic and optimize maintainability. | ||
| * **State & Variable Management:** Robust handle of environment-specific variables and state configurations to ensure deployment consistency. | ||
| * **Network & Security Orchestration:** Declarative configuration of Virtual Networks, Subnets, and Security Groups to strictly enforce the principle of least privilege. | ||
| * **Deterministic Deployment:** Designed to completely eliminate configuration drift and allow for repeatable, automated infrastructure lifecycles. | ||
|
|
||
| To complete this task, Terraform and Azure CLI must be installed and configured on your machine. | ||
| ## Technologies Used | ||
| * **Infrastructure as Code:** Terraform | ||
| * **Cloud Infrastructure Provider:** AWS / Microsoft Azure | ||
| * **Version Control:** Git | ||
| * **Target Application Stack:** Python (Flask/Django), WSGI Server, Database Engine | ||
|
|
||
| ## Steps to Complete the Task | ||
| --- | ||
|
|
||
| **1. Fork this Repository** | ||
| ## Getting Started | ||
|
|
||
| **2. Create Directory Structure** | ||
| ### Prerequisites | ||
| Before deploying the infrastructure, ensure you have the following tools installed and configured on your local workstation: | ||
| 1. **Terraform CLI** (v1.0.0 or higher) | ||
| 2. **Cloud Provider CLI** (Authenticated with appropriate IAM permissions) | ||
| 3. **Git** | ||
|
|
||
| - Create the following directory structure: | ||
| ``` | ||
| / | ||
| ├─ modules/ | ||
| │ ├─ network/ | ||
| │ │ ├─ main.tf | ||
| │ │ ├─ variables.tf | ||
| │ │ └─ outputs.tf | ||
| │ ├─ compute/ | ||
| │ │ ├─ main.tf | ||
| │ │ ├─ variables.tf | ||
| │ │ └─ outputs.tf | ||
| │ └─ storage/ | ||
| │ ├─ main.tf | ||
| │ ├─ variables.tf | ||
| │ └─ outputs.tf | ||
| ├─ main.tf | ||
| ├─ variables.tf | ||
| ├─ outputs.tf | ||
| ├─ terraform.tfvars | ||
| └─ backend.tf | ||
| ``` | ||
| ### Deployment Steps | ||
|
|
||
| **3. Define Network Module** | ||
| Follow these step-by-step commands to initialize and apply the infrastructure configuration: | ||
|
|
||
| - The network module will create a virtual network, subnet, network security group, and public IP address. | ||
| * Virtual Network: name it `vnet`, address prefix `10.0.0.0/16`. | ||
| * Subnet: name it `default`, address prefix `10.0.0.0/24`. | ||
| * Network Security Group: name it `defaultnsg`. | ||
| * Public IP Address: name it `linuxboxpip`, dynamic allocation method, and assign a DNS label generated by concatenating `matetask` and a random number. | ||
| 1. **Clone the Repository:** | ||
| ```bash | ||
| git clone [https://github.com/kkatkot/devops_todolist_terraform_task.git](https://github.com/kkatkot/devops_todolist_terraform_task.git) | ||
| cd devops_todolist_terraform_task | ||
|
|
||
| **4. Define Compute Module** | ||
| 2. **Initialize the Working Directory:** | ||
| Downloads the required cloud provider plugins and initializes the backend configuration. | ||
| ```bash | ||
| terraform init | ||
|
|
||
| - The compute module will create a network interface, virtual machine, and VM extension for deploying the ToDo List application. | ||
| * Network Interface: name it `${var.vm_name}-nic`. | ||
| * Virtual Machine: name it `matebox`, image `Ubuntu2204`, size `Standard_B1s`, SSH key `linuxboxsshkey`. | ||
| * VM Extension: use the `CustomScript` extension to execute `install-app.sh` script. | ||
| 3. **Generate an Execution Plan:** | ||
| Creates an execution plan, allowing you to preview the cloud resources that will be created or modified. | ||
| ```bash | ||
| terraform plan | ||
|
|
||
|
|
||
| **5. Define Storage Module** | ||
|
|
||
| - The storage module will create a storage account and a storage container. | ||
| * Storage Account: any name. | ||
| * Storage Container: name it `task-artifacts`. | ||
|
|
||
| **6. Configure Remote State Backend** | ||
|
|
||
| - Define the backend configuration in `backend.tf` to store the state in Azure Blob Storage. Use the following parameters: | ||
| * Resource Group: `mate-azure-task-12`. | ||
| * Storage Account: `yourstorageaccount`. | ||
| * Container Name: `tfstate`. | ||
| * Key: `terraform.tfstate`. | ||
| - Ensure that you have a storage account and container created for the remote state. This can be included in your `main.tf` or managed separately. | ||
|
|
||
| **7. Use Modules in Main Configuration** | ||
| - Define variables in `variables.tf` with the following parameters: | ||
| * location: `uksouth`. | ||
| * resource_group_name: `mate-azure-task-12`. | ||
| * virtual_network_name: `vnet`. | ||
| * vnet_address_prefix: `10.0.0.0/16`. | ||
| * subnet_name: `default`. | ||
| * subnet_address_prefix: `10.0.0.0/24`. | ||
| * network_security_group_name: `defaultnsg`. | ||
| * public_ip_address_name: `linuxboxpip`. | ||
| * vm_name: `matebox`. | ||
| * vm_size: `Standard_B1s`. | ||
| * ssh_key_public: `your-public-key-content`. | ||
| * dns_label: `matetask` (you can append a random number in your script). | ||
|
|
||
| **8. Initialize and Apply the Configuration** | ||
|
|
||
| **9. Verify the Deployment** | ||
|
|
||
| - Access the virtual machine using the public IP address. | ||
| - Verify the application is running by visiting the public IP in a web browser. | ||
|
|
||
| **10. Pull request's description should also contain a reference to a successful workflow run** | ||
| 4. **Apply the Configuration:** | ||
| Provision the infrastructure on the designated cloud platform. | ||
| ```bash | ||
| terraform apply |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # terraform { | ||
| # backend "azurerm" { | ||
| # resource_group_name = var.resource_group_name | ||
| # storage_account_name = var.storage_account_name | ||
| # container_name = var.storage_container_name | ||
| # key = "terraform.tfstate" | ||
| # } | ||
| # } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| terraform { | ||
| required_providers { | ||
| azurerm = { | ||
| source = "hashicorp/azurerm" | ||
| version = "4.72.0" | ||
| } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| provider "azurerm" { | ||
| features { | ||
|
|
||
| } | ||
| } | ||
|
|
||
| resource "azurerm_resource_group" "example" { | ||
| name = var.resource_group_name | ||
| location = var.location | ||
| } | ||
|
|
||
| resource "azurerm_storage_blob" "example" { | ||
| name = "my-awesome-content.zip" | ||
| storage_account_name = module.storage.storage_account_name | ||
| storage_container_name = module.storage.storage_container_name | ||
| type = "Block" | ||
| source = "some-local-file.zip" | ||
| } | ||
|
Comment on lines
+1
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file should configure the Terraform remote state backend using Azure Blob Storage, not create Azure resources. The backend configuration should be inside a |
||
|
|
||
|
|
||
| module "network" { | ||
| source = "./modules/network" | ||
|
|
||
| subnet_address_prefix = var.subnet_address_prefix | ||
| dns_label = var.dns_label | ||
| public_ip_address_name = var.public_ip_address_name | ||
| virtual_network_name = var.virtual_network_name | ||
| subnet_name = var.subnet_name | ||
| network_security_group_name = var.network_security_group_name | ||
| vnet_address_prefix = var.vnet_address_prefix | ||
| resource_group_name = var.resource_group_name | ||
| location = var.location | ||
| } | ||
|
|
||
| module "compute" { | ||
| source = "./modules/compute" | ||
|
|
||
| location = var.location | ||
| vm_name = var.vm_name | ||
| vm_size = var.vm_size | ||
| ssh_key_public = var.ssh_key_public | ||
| resource_group_name = var.resource_group_name | ||
|
|
||
| subnet_id = module.network.subnet_id | ||
| public_ip = module.network.public_ip | ||
| } | ||
|
|
||
| module "storage" { | ||
| source = "./modules/storage" | ||
|
|
||
| resource_group_name = var.resource_group_name | ||
| location = var.location | ||
| # storage_account_id = module.storage.storage_account_id | ||
| subnet_id = module.network.subnet_id | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| resource "azurerm_network_interface" "example" { | ||
| name = "${var.vm_name}-nic" | ||
| location = var.location | ||
| resource_group_name = var.resource_group_name | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo in output name: |
||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. vnet_address_prefix is set to '10000/16' but the task requirements specify '10.0.0.0/16'. |
||
| ip_configuration { | ||
|
Comment on lines
+3
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate variable declaration for |
||
| name = "internal" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect network prefix. Should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. subnet_address_prefix is set to '10000/24' but the task requirements specify '10.0.0.0/24'. |
||
| subnet_id = var.subnet_id | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect subnet prefix. Should be |
||
| private_ip_address_allocation = "Dynamic" | ||
|
Comment on lines
+7
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Network rule restricts access to only IP |
||
| public_ip_address_id = var.public_ip | ||
| } | ||
| } | ||
|
Comment on lines
+1
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The backend.tf file still only contains resource definitions. It must include the actual There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The storage container name is hardcoded as
Comment on lines
+1
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. backend.tf should contain the Terraform backend configuration for Azure Blob Storage, not resource definitions. The backend block should be: terraform {
backend "azurerm" {
resource_group_name = "mate-azure-task-12"
storage_account_name = "yourstorageaccount"
container_name = "tfstate"
key = "terraform.tfstate"
}
}Remove the azurerm_resource_group and azurerm_storage_blob resources from this file. |
||
|
|
||
| resource "azurerm_linux_virtual_machine" "example" { | ||
| name = var.vm_name | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The storage module references |
||
| resource_group_name = var.resource_group_name | ||
| location = var.location | ||
| size = var.vm_size | ||
| admin_username = "adminuser" | ||
| network_interface_ids = [ | ||
| azurerm_network_interface.example.id, | ||
| ] | ||
|
|
||
| admin_ssh_key { | ||
| username = "adminuser" | ||
|
Comment on lines
+1
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Terraform backend configuration is missing. This file defines resources but doesn't configure the backend. You need to add a |
||
| public_key = var.ssh_key_public | ||
| } | ||
|
|
||
| os_disk { | ||
| caching = "ReadWrite" | ||
| storage_account_type = "Standard_LRS" | ||
| } | ||
|
|
||
| source_image_reference { | ||
| publisher = "Canonical" | ||
| offer = "0001-com-ubuntu-server-jammy" | ||
| sku = "22_04-lts" | ||
| version = "latest" | ||
| } | ||
| } | ||
|
|
||
| resource "azurerm_virtual_machine_extension" "example" { | ||
| name = "hostname" | ||
| virtual_machine_id = azurerm_linux_virtual_machine.example.id | ||
| publisher = "Microsoft.Azure.Extensions" | ||
| type = "CustomScript" | ||
| type_handler_version = "2.0" | ||
|
|
||
| settings = <<SETTINGS | ||
| { | ||
| "commandToExecute": "bash install-app.sh" | ||
| } | ||
| SETTINGS | ||
|
|
||
|
|
||
| # tags = { | ||
| # environment = "Production" | ||
| # } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
|
|
||
| variable "vm_size" {} | ||
| variable "ssh_key_public" {} | ||
|
|
||
| variable "location" {} | ||
| variable "vm_name" {} | ||
|
|
||
|
Comment on lines
+4
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: Duplicate variable declaration for
Comment on lines
+4
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate variable declaration - |
||
| variable "resource_group_name" {} | ||
|
|
||
| variable "subnet_id" {} | ||
| variable "public_ip" {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
|
|
||
|
|
||
| resource "azurerm_virtual_network" "example" { | ||
| name = var.virtual_network_name | ||
| address_space = var.vnet_address_prefix | ||
| location = var.location | ||
| resource_group_name = var.resource_group_name | ||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DUPLICATE VARIABLE DECLARATION: |
||
| } | ||
|
Comment on lines
+5
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
|
||
| resource "azurerm_subnet" "example" { | ||
| name = var.subnet_name | ||
| resource_group_name = var.resource_group_name | ||
| virtual_network_name = azurerm_virtual_network.example.name | ||
| address_prefixes = var.subnet_address_prefix | ||
|
|
||
| # delegation { | ||
| # name = "delegation" | ||
|
|
||
| # service_delegation { | ||
| # name = "Microsoft.ContainerInstance/containerGroups" | ||
| # actions = ["Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"] | ||
| # } | ||
| # } | ||
| } | ||
|
|
||
| resource "azurerm_network_security_group" "example" { | ||
| name = var.network_security_group_name | ||
| location = var.location | ||
| resource_group_name = var.resource_group_name | ||
|
|
||
| security_rule { | ||
| name = "test123" | ||
| priority = 100 | ||
| direction = "Inbound" | ||
| access = "Allow" | ||
| protocol = "Tcp" | ||
| source_port_range = "*" | ||
| destination_port_range = "*" | ||
| source_address_prefix = "*" | ||
| destination_address_prefix = "*" | ||
| } | ||
|
|
||
| # tags = { | ||
| # environment = "Production" | ||
| # } | ||
| } | ||
|
|
||
| resource "random_integer" "ri" { | ||
| min = 10000 | ||
| max = 99999 | ||
| } | ||
|
|
||
| resource "azurerm_public_ip" "example" { | ||
| name = var.public_ip_address_name | ||
| resource_group_name = var.resource_group_name | ||
| location = var.location | ||
| allocation_method = "Dynamic" | ||
| domain_name_label = "matetask${random_integer.ri.result}" | ||
|
|
||
| # tags = { | ||
| # environment = "Production" | ||
| # } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| output "subnet_id" { | ||
| value = azurerm_subnet.example.id | ||
| } | ||
|
|
||
| output "public_ip" { | ||
| value = azurerm_public_ip.example.ip_address | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| variable "virtual_network_name" {} | ||
|
|
||
| variable "vnet_address_prefix" {} | ||
|
|
||
| variable "subnet_name" {} | ||
|
|
||
| variable "subnet_address_prefix" {} | ||
|
|
||
|
Comment on lines
+4
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL - DUPLICATE VARIABLE: The variable
Comment on lines
+4
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate variable declaration for |
||
| variable "network_security_group_name" {} | ||
|
|
||
| variable "public_ip_address_name" {} | ||
|
|
||
| variable "dns_label" {} | ||
|
|
||
| variable "location" {} | ||
|
|
||
| variable "resource_group_name" {} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The backend.tf file is missing the actual Terraform backend configuration block. It only creates Azure resources but doesn't configure Terraform to use them for state storage. You need to add a
terraform {}block withbackend "azurerm"configuration at the top of this file or in a separate file.