Terraform in der Cloud

Terraform_in_der_Cloud
Im Laufe meiner ersten Praxisphase des Studiums bei der ORDIX AG habe ich mich mit Terraform beschäftigt. Meine Aufgabe war es, mithilfe von Terraform eine IT-Infrastruktur in einer Cloud aufzubauen. Im Blog-Artikel Terraform von Jan Husemann am 30. Januar 2020 wurden die Grundlagen von Terraform bereits erläutert und an einem kleinen Beispiel gezeigt, wie mit Terraform gearbeitet werden kann. In diesem Blog-Artikel möchte ich nun zeigen, welche Möglichkeiten Terraform im Bereich Cloud Computing bietet. Als Beispiel dafür soll in der Microsoft Azure Cloud ein Webserver-Cluster mit vorgeschaltetem Load Balancer aufgebaut werden.

Beschreibung des Webserver-Clusters

Ein Webserver-Cluster besteht aus einer Proxy Instanz, auch Load Balancer genannt, und einem Backend Pool. Dieser ist eine Ansammlung von Webservern, welche der Load Balancer ansprechen kann. Der Load Balancer erhält eine Public-IP, um über das Internet erreichbar zu sein. Anfragen der Clients an den Load Balancer werden von diesem an einen freien Webserver aus dem Backend Pool weitergeleitet. Die Antwort sendet der Webserver dann entweder direkt an den Client, oder zurück an den Load Balancer, welcher die Antwort an den Client weiterleitet.

Konfiguration Load Balancer

Mit dem Ressourcenblock in Zeile 8 wird einen Load Balancer zur Verfügung gestellt. Dieser erhält eine Public-IP in Zeile 14. Über die Public-IP kann auf den Load Balancer zugegriffen werden. Zu Beginn wird ein leerer Backend Pool in Zeile 17 erstellt. Dieser wird im Laufe des Artikels mit den virtuellen Maschinen gefüllt. Zusätzlich zu dieser Konfiguration wird ein Netzwerk (Virtual Network) aufgebaut, aus dem virtuellen Maschinen eine private Netzwerkadresse zugeordnet werden. Über eine Regel-Ressource des Load Balancers wird festgelegt, über welchen Port und mit welchem Protokoll auf den Load Balancer zugegriffen werden kann.
1.	resource "azurerm_public_ip" "lb_pubip"{
2.	    name                = "lb_pubip"
3.	    location            = var.location
4.	    resource_group_name = var.resource_group
5.	    allocation_method   = "Dynamic"
6.	    domain_name_label   = "webtest"
7.	}
8.	resource "azurerm_lb" "lb"{
9.	    name                = "lb"
10.	    location            = var.location
11.	    resource_group_name = var.resource_group
12.	    frontend_ip_configuration {
13.	        name                = "lb_pubip"
14.	        public_ip_address_id = azurerm_public_ip.lb_pubip.id
15.	    }
16.	}
17.	resource "azurerm_lb_backend_address_pool" "bepool"{
18.	    resource_group_name = var.resource_group
19.	    loadbalancer_id     = azurerm_lb.lb.id
20.	    name                = "backend_address_pool"
21.	}
22.	resource "azurerm_lb_probe" "probe"{
23.	    resource_group_name = var.resource_group
24.	    name                = "http-probe"
25.	    loadbalancer_id     = azurerm_lb.lb.id
26.	    port                = 80
27.	    interval_in_seconds = 15
28.	    number_of_probes    = 2
29.	}
30.	resource "azurerm_lb_rule" "lbrule"{
31.	    resource_group_name = var.resource_group
32.	    loadbalancer_id     = azurerm_lb.lb.id
33.	    name                = "http"
34.	    protocol            = "Tcp"
35.	    frontend_port       = 80
36.	    backend_port        = 80
37.	    backend_address_pool_id = azurerm_lb_backend_address_pool.bepool.id   
38.	    frontend_ip_configuration_name = azurerm_public_ip.lb_pubip.name
39.	    probe_id            = azurerm_lb_probe.probe.id
40.	}
 

Voreinstellung für die Konfiguration 

Über die Voreinstellungen wird festgelegt, welcher Provider benutzt wird. In diesem Fall ist es der Azure Provider in der Version 2.0.0. Des Weiteren wird angegeben, in welchem Storage Container die State-Datei abgespeichert werden soll. Dieser Container wird jedem Nutzer zur Speicherung von Daten zur Verfügung gestellt. Um auf den Container zugreifen zu können, wird ein Schlüssel erwartet, welcher hier anonymisiert in Zeile 10 angegeben wurde.
1.	provider "azurerm"{
2.	  version   = "2.0.0"
3.	  features{}
4.	}
5.	 
6.	terraform {
7.	  backend "azurerm" {
8.	    storage_account_name  = "lb_beispiel"
9.	    container_name        = "lb-beispiel "
10.	    access_key            = "*****************************"
11.	    key                   = "terraform.tfstate"            
12.	  }
13.	}
 

Konfiguration Netzwerk

Hier wird ein privates Netzwerk in der Azure-Cloud erstellt. Über dieses Netzwerk können die Ressourcen miteinander kommunizieren. Es wird außerdem ein Subnetz benötigt, in welchem die Ressourcen später liegen werden. Innerhalb dieses Subnetzes wird die Kommunikation zwischen den Webservern und dem Load Balancer stattfinden.
1.	resource "azurerm_virtual_network" "vnet"{
2.	  location            = var.location
3.	  resource_group_name = var.resource_group
4.	  address_space = ["10.0.0.0/16"] 
5.	  name                = "vnet"
6.	}
7.	resource "azurerm_subnet" "subnet"{
8.	    resource_group_name   = var.resource_group
9.	    address_prefix        = "10.0.2.0/24"
10.	    virtual_network_name  = azurerm_virtual_network.vnet.name
11.	    name                  = "subnet"
12.	}
 

Konfiguration virtuelle Maschine 

Für die virtuellen Maschinen wird die Möglichkeit Scale Set von Azure verwendet. Dabei werden mehrere identische virtuelle Maschinen automatisch bereitgestellt. Die Anzahl der Maschinen kann dabei dynamisch angegeben oder auch nach Bedarf zur Laufzeit angepasst werden. Über das Attribut „custom_data" wird ein Shell-Skript übergeben, welches auf den Maschinen einen Webserver startet. Die einzelnen Aspekte der virtuellen Maschine werden in den unterschiedlichen Blöcken beschrieben.

In dem Block ab Zeile 10 wird die Verbindung über SSH ermöglicht. Dazu wird ein SSH-Key benötigt. Des Weiteren wird im nächsten Block festgelegt, dass auf den Maschinen ein Linux Ubuntu Betriebssystem laufen soll. Über den Block „network_interface" werden die Maschinen einem Subnetz zugeordnet. Somit können die Maschinen untereinander kommunizieren. In Zeile 34 werden die virtuellen Maschinen dem Backend Pool des Load Balancers hinzugefügt. Somit kann dieser die Anfrage an die Webserver weiterleiten.

1.	resource "azurerm_linux_virtual_machine_scale_set" "vm1" {
2.	   location = var.location
3.	   name = "vms"
4.	   resource_group_name = azurerm_resource_group.rg.name
5.	   sku = "Standard_B1ls"
6.	   instances = 3
7.	   custom_data = file("init.sh");
8.	   admin_username = "adminuser"
9.	   
10.	   admin_ssh_key {
11.	    username = "adminuser"
12.	    Public_key = file("~/.ssh/id_rsa.pub")
13.	
14.	   source_image_reference {
15.	    publisher = "Canonical"
16.	    offer = "UbuntuServer"
17.	    sku = "16.04.0-LTS"
18.	    version = "latest"
19.	   }
20.	
21.	   os_disk {
22.	    caching = "ReadWrite"
23.	    Storage_account_type = "Standard_LRS"
24.	   }
25.	
26.	   network_interface {
27.	    name = "nwprofile"
28.	    primary = "true"
29.	
30.	    ip_configuration{
31.	      name = "ipconf"
32.	      subnet_id = azurerm_subnet.subnet.id
33.	  
34.	      load_balancer_backend_address_pool_ids = [      
35.	                     azurerm_lb_backend_address_pool.bepool.id]
36.	      primary = "true"
37.	    }
38.	  }
39.	} 
 
Nachdem die Konfiguration erstellt wurde, muss mit dem Befehl „terraform init" innerhalb des Arbeitsverzeichnisses zunächst Terraform initialisiert werden. Dabei werden der Provider und die Plugins installiert. Über den Befehl „terraform apply" wird anschließend die Konfiguration in der Cloud umgesetzt und die Ressourcen werden bereitgestellt.

Initialisierungsskript 

Der folgende Code-Ausschnitt zeigt das Skript, welches beim Erstellen der virtuellen Maschinen aufgerufen wird. Dieses liest zuerst die IP-Adresse der Maschine aus. Diese wird dann in eine Datei index.html geschrieben, um eine Beispiel-Homepage zu erstellen. In Zeile 8 steht der Befehl, welcher den Webserver startet. Für dieses Beispiel wird der busybox-Webserver verwendet, da dies ein sehr einfacher Webserver ist, welcher keine weiteren Konfigurationen benötigt.
1.	#!/bin/bash
2.	ip_addr="$(hostname -I)"
3.	 
4.	# Erstellen einer Homepage
5.	echo "<h1>Willkommen</h1><br>
6.	<p>Meine IP: ${ip_addr}</p><br>" > index.html
7.	 
8.	nohup busybox httpd -f -p 80 

Überprüfen des Clusters

Um zu überprüfen, ob der Cluster wie gewünscht funktioniert, wird in einem Browserfenster die Adresse des Clusters eingegeben. Es sollte nun folgende Ausgabe angezeigt werden:


Um zu testen, ob der Load Balancer die Anfragen auch auf unterschiedliche Webserver weiterleitet, muss die Seite neu geladen werden. Da im Initialisierungsskript die Host-IP ausgelesen und in die Datei index.html geschrieben wurde, sollte jeweils eine andere IP-Adresse angezeigt werden.

By accepting you will be accessing a service provided by a third-party external to https://blog.ordix.de/