Terraform을 활용한 Azure cloud에서 Wordpress 자동 배포(임시)

강재민·2022년 5월 2일
0
post-custom-banner

아키텍처 개념도


Azure provider 구성

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0.2"
    }
  }

  required_version = ">= 1.1.0"
}

provider "azurerm" {
  features {
    resource_group {
        prevent_deletion_if_contains_resources = false
      }
  }
}
Code의미
prevent_deletion_if_contains_resources = false리소스 그룹을 deletion 할 때 안에있는 리소스들을 지우지 못하게 방지 할 것인지에 대해서 false 해주겠다는 의미

리소스 그룹

resource "azurerm_resource_group" "rg" {
  name     = "wordpressrg"
  location = "koreacentral"
}

Azure에서는 AWS와 다르게 가장 외곽에 리소스 그룹이 존재한다. 네트워크 구성도 이 리소스 그룹 안에서 이루어진다. 다만, 리소스 그룹이 다르다고 하여도 AWS에서 VPC가 다른것 처럼 작동하지 않고 그냥 리소스를 담아놓는 그룹이므로 전혀 상관없이 서로 다른 리소스 그룹안에 있어도 통신이 가능하다.


가상네트워크 및 서브넷

네트워크 구성

네트워크address_prefixes
virtual_network20.0.0.0/16
subnet.frontend20.0.0.0/24
subnet.backend20.0.10.0/24
subnet.database20.0.20.0/24

가상네트워크

resource "azurerm_virtual_network" "wordpressvn" {
  name                = "wpvn"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  address_space       = ["20.0.0.0/16"]
}

서브넷

resource "azurerm_subnet" "frontend" {
  name                 = "frontendserver"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.wordpressvn.name
  address_prefixes     = ["20.0.0.0/24"]
}

resource "azurerm_subnet" "backend" {
  name                 = "backendserver"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.wordpressvn.name
  address_prefixes     = ["20.0.10.0/24"]
}

resource "azurerm_subnet" "dbserver" {
  name                 = "dbserver"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.wordpressvn.name
  address_prefixes     = ["20.0.20.0/24"]
}

서브넷주소의 prefix를 편의상 큰 범위로 잡아놨다. 이후에 적절한 서브넷 범위로 수정이 필요해 보인다.


데이터베이스

네트워크 인터페이스

resource "azurerm_network_interface" "db" {
  name                = "dbif"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "dbconf"
    subnet_id                     = azurerm_subnet.dbserver.id
    private_ip_address_allocation = "Dynamic"
  }
}

가상머신

resource "azurerm_linux_virtual_machine" "db" {
  name                  = "databasesv"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.db.id]
  size               = "Standard_DS1_v2"
  admin_username = "centos"
  custom_data = "IyEvYmluL2Jhc2gNCnN1ZG8gc2V0ZW5mb3JjZSAwDQpzZXRlbmZvcmNlIDA="

  source_image_id = "/subscriptions/8638e904-9ff3-48e8-85ff-7f37869d4e0c/resourceGroups/wordpress/providers/Microsoft.Compute/galleries/dbserver/images/dbserver"

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "StandardSSD_LRS"
  }
  admin_ssh_key {
    username   = "centos"
    public_key = file("~/.ssh/id_rsa.pub")
  }
  user_data = "IyEvYmluL2Jhc2gNCnN1ZG8gc2V0ZW5mb3JjZSAwDQpzZXRlbmZvcmNlIDA="}
Code의미
source_image_id데이터베이스 가상머신을 시작할 이미지의 주소를 정의하는 부분이다. 해당 id는 리소스그룹/리소스/이미지버전/속성/리소스 ID 에서 확인할 수 있다.
custom_dataAzure에서는 AWS와 다르게 사용자 데이터를 입력할 때 Base64 인코딩을 사용한다. 인코딩한 내용은 #!bin/bash setenforce 0 sudo setenforce 0 이다.
user_datacustom_data와의 차이는 정확히 모르겠지만 둘 다 정의해 주었을 때 제대로 작동하는 것을 확인했다.
public_key = file("~/.ssh/id_rsa.pub")terraform을 실행시키는 가상머신에서 만든 공개키를 붙여넣어서 나중에 ssh접속이 가능하게 해줄 수 있다. 주의할 점으로는 password방식과 공개키 방식중에 하나는 꼭 정의되어야 한다는 것이다.

보안그룹

resource "azurerm_network_security_group" "dbsg" {
  name                = "database-nsg"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "dbin"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "3306"
    source_address_prefix      = "20.0.0.0/16"
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "dbbastionin"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

현재는 보안그룹이 너무 많은 주소범위에 대해서 열려있는 상태이다. 22번 포트는 bastionhost에 대해서만 그리고 3306포트에 대해서는 webserver 인스턴스들이 존재하는 backend 서브넷에 대해서만 열어주도록 변경해주어야 한다.

보안그룹 할당

resource "azurerm_subnet_network_security_group_association" "dbsga" {
  subnet_id = azurerm_subnet.dbserver.id
  network_security_group_id = azurerm_network_security_group.dbsg.id
}

보안그룹을 만들었으니 보안그룹을 서브넷에 할당시킨다. 그러면 해당 서브넷에서 만들어진 리소스들이 보안그룹을 모두 할당받는다.


웹서버

네트워크 인터페이스

resource "azurerm_network_interface" "web" {
  name                = "webif"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "webconf"
    subnet_id                     = azurerm_subnet.backend.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.web.id
  }
}

공개 IP

resource "azurerm_public_ip" "web" {
  name                = "myPublicIP"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

웹서버 가상머신은 웹사이트를 호스팅하기 위해 외부에서 접속할 공개 IP가 필요하다. 공개IP 리소스를 미리 선언하고 이 리소스의 id를 네트워크 인터페이스에 참조시킨다. 그러면 네트워크 인터페이스가 참조하는 서브넷 즉, subnet.backend에서 생성되는 모든 가상머신들은 공개IP를 가지게된다.

가상머신

resource "azurerm_linux_virtual_machine" "web" {
  name                  = "websv"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.web.id]
  size               = "Standard_DS1_v2"
  admin_username = "centos"
  custom_data = "IyEvYmluL2Jhc2gNCnN1ZG8gc2V0ZW5mb3JjZSAwDQpzZXRlbmZvcmNlIDA
="

  source_image_id = "/subscriptions/8638e904-9ff3-48e8-85ff-7f37869d4e0c/res
ourceGroups/wordpress/providers/Microsoft.Compute/galleries/webfinal/images/
webfinal/versions/0.0.1"

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "StandardSSD_LRS"
  }
  admin_ssh_key {
    username   = "centos"
    public_key = file("~/.ssh/id_rsa.pub")
  }
  user_data = "IyEvYmluL2Jhc2gNCnN1ZG8gc2V0ZW5mb3JjZSAwDQpzZXRlbmZvcmNlIDA="
}

웹서버용 가상머신의 구성도 데이터베이스와 비슷하다. 다만 당연히 참조하는 이미지가 다르다.

보안그룹

resource "azurerm_network_security_group" "websg" {
  name                = "web-nsg"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "webin"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "dbbastionin"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

웹서버로 들어오는 80포트에 대한 인바운드를 열어주었다. 그리고 ssh 접속을 위한 22번 포트를 열어주었는데, 이후에 배스천 호스트에서만 접속할 수 있게 변경해주어야한다.

보안그룹 할당

resource "azurerm_subnet_network_security_group_association" "websga" {
  subnet_id = azurerm_subnet.backend.id
  network_security_group_id = azurerm_network_security_group.websg.id
}

wordpress 접속

/홈/리소스 그룹/wordpressrg/websv/개요 에서 [공용 IP 주소]/wordpress 로 접속하면 데이터베이스 인스턴스를 참조하는 웹서버가 호스팅하는 페이지로 접속되는 것을 확인 할 수 있다.

post-custom-banner

6개의 댓글

comment-user-thumbnail
2022년 5월 3일

4기쪽은 azure도 배우고 테라폼으로 인프라프로비저닝하는것도 다했나요? 부럽네요ㅠ

1개의 답글