IaC

[Terraform] vSphere를 이용한 3티어 아키텍처 구축

인프라베어 2024. 5. 13. 23:39

Terraform과 Ansible을 이용한 3티어 아키텍처 자동화 구성에 대해 정리해보려 한다.

주어진 과제는 자동화 툴을 이용하여 WEB, WAS, DB로 구성된 VM을 생성하고 Apache, Tomcat, MariaDB를 자동으로 설치 및 연동하는 과제였다.

 

앤서블과 테라폼 모두 처음 사용해보았지만 다양한 레퍼런스들을 참조해서 완성할 수 있었다.

 

가장먼저했던 고민은 어느영역까지 자동화 할 것인가? 라는 부분이었다.

앤서블과 테라폼 모두 자동화를 하는 툴이지만 VM생성, SW설치 등에서는 어떠한 차이가 있는지 파악하는것이 중요했다.

 

조사를 조금해보니 Ansible은 SSH를 연결하여 각 노드들에 명령어를 자동으로 수행하는 것에 가까웠고, 테라폼은 생성된 VM이 없어도 Provider의 API를 통해 직접적으로 VM을 생성할 수 있도록 구성할 수 있을것 같았다.

 

작업환경은 vSphere와 Rocky Linux를 통해 작업을 하였다.

# WEB-WAS연동 total.tf
provider "vsphere" {
  user           = "[vSphereID]"
  password       = "[vSpherePW]"
  vsphere_server = "[SERVER_IP]"

  allow_unverified_ssl = true
}

data "vsphere_datacenter" "dc" { //resource와 함께 사용할 data정의
  name = "Datacenter" # 데이터센터 이름
}

data "vsphere_datastore" "datastore" { 
  name          = "datastore1"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_compute_cluster" "cluster" {
  name          = "Cluster1"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "network" {
  name          = "VM Network" # 네트워크 이름 입력
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_virtual_machine" "template" {
  name          = "[VM Template]" # VM 템플릿 이름
  datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_virtual_machine" "vm" { //리소스는 인프라 구성 요소를 설명
  for_each = tomap({
    "web01" = "VM_IP1",
    "web02" = "VM_IP2",
    "was01" = "VM_IP3",
    "was02" = "VM_IP4",
    "db01"  = "VM_IP5"
  })
  name             = each.key #VM이름
  resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore.id

  num_cpus = 2
  memory   = 4096
  guest_id = data.vsphere_virtual_machine.template.guest_id
  firmware = "efi"

  scsi_type = data.vsphere_virtual_machine.template.scsi_type

  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = "vmxnet3"
  }

  disk {
    label            = "disk0"
    size             = data.vsphere_virtual_machine.template.disks[0].size
    thin_provisioned = false
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id

    customize {
      linux_options {
        host_name = each.key
        domain    = "localhost" # 도메인입력
      }

      network_interface {
        ipv4_address = each.value
        ipv4_netmask = 24
      }

      ipv4_gateway = "VM_GW"
      dns_server_list = ["DNSIP"]
    }
  }

  provisioner "file" {
    source      = "/root/.ssh/id_rsa.pub"
    destination = "/tmp/id_rsa.pub"
  }

  provisioner "remote-exec" {
    inline = [
      "mkdir -p /root/.ssh",
      "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys",
      "chmod 700 /root/.ssh",
      "chmod 600 /root/.ssh/authorized_keys",
      "rm -f /tmp/id_rsa.pub"
    ]
  }

  connection {
    type     = "ssh"
    user     = "[SSH_USER]"
    password = "[SSH_PW]"
    host     = self.default_ip_address
  }
}

resource "null_resource" "ansible_install_DB" {
  depends_on = [vsphere_virtual_machine.vm]

  provisioner "local-exec" {
    command = "ansible-playbook -i /home/bastion/Ansible/Final/hosts.ini /home/bastion/Ansible/Final/DB/install_DB.yml"
    working_dir = "/home/bastion/Ansible/Final/DB"
  }
}
# Ansible을 사용한 Tomcat 설치
resource "null_resource" "ansible_install_tomcat" {
  depends_on = [null_resource.ansible_install_DB]

  provisioner "local-exec" {
    command = "ansible-playbook -i /home/bastion/Ansible/Final/hosts.ini /home/bastion/Ansible/Final/WAS/install_tomcat.yml"
    working_dir = "/home/bastion/Ansible/Final/WAS"
  }
}

# Ansible을 사용한 Apache 설치
resource "null_resource" "ansible_install_apache" {
  depends_on = [null_resource.ansible_install_tomcat]

  provisioner "local-exec" {
    command = "ansible-playbook -i /home/bastion/Ansible/Final/hosts.ini /home/bastion/Ansible/Final/WEB/install_apache.yml"
    working_dir = "/home/bastion/Ansible/Final/WEB"
  }
}

resource "null_resource" "ansible_secure_apache" {
  depends_on = [null_resource.ansible_install_apache]

  provisioner "local-exec" {
    command = "ansible-playbook -i /home/bastion/Ansible/Final/hosts.ini /home/bastion/Ansible/Final/WEB/secure_WEB.yml"
    working_dir = "/home/bastion/Ansible/Final/WEB"
  }
}

resource "null_resource" "ansible_secure_tomcat" {
  depends_on = [null_resource.ansible_install_apache]

  provisioner "local-exec" {
    command = "ansible-playbook -i /home/bastion/Ansible/Final/hosts.ini /home/bastion/Ansible/Final/WAS/secure_WAS.yml"
    working_dir = "/home/bastion/Ansible/Final/WEB"
  }
}

resource "null_resource" "ansible_secure_db" {
  depends_on = [null_resource.ansible_install_apache]

  provisioner "local-exec" {
    command = "ansible-playbook -i /home/bastion/Ansible/Final/hosts.ini /home/bastion/Ansible/Final/DB/secure_DB.yml"
    working_dir = "/home/bastion/Ansible/Final/WEB"
  }
}

Provider

테라폼을 사용하며 가장 신경써야 했던 부분이 프로바이더였다. 프로바이더는 테라폼이 어떤 환경에서 적용시킬지에 대해 선택하는것이라고 볼 수 있는데 각각의 CSP또는 가상화 솔루션에 대한 API통신을 추상화하여 테라폼 리소스를 생성할 수 있도록 해준다.

클라우드가 아닌 VMware의 가상화 환경이어서 내용을 찾아보는데 어려웠고 공식문서를 참고하여 코드를 작성하였다.

 

vSphere의 datacenter, datastore, cluster, network등의 구성을 알지 못한다면 구성을 하는데 어려움이 조금은 있을 것 같다.

resource

"vsphere_virtual_machine" 리소스에서 실질적인 VM생성에 필요한 구성들을 설정할 수 있다. 위의 코드에서는 각각 VM들의 이름과 IP, 어떠한 리소스풀을 사용할 것인지에 대한 설정이 있으며 network interface와 disk옵션, 마지막으로는 VM에서 사용할 기본적인 이미지(골든이미지?)를 템플릿화하여 이를 사용할 수 있도록 하였다.

Provisioner

프로비저너는 인프라 구성요소가 생성된 후 VM들의 초기설정 및 구성을 담당한다. 나는 VM생성이후 3티어 아키텍처를 구축해야했으므로 작성한 앤서블 플레이북을 실행시키기 위해 앤서블 설치에 필요한 스크립트를 작성하고 ssh연결에 필요한 키를 복사할 수 있도록 하였다.

Ansible

VM생성과 Ansible구성을 마친 후 가장 먼저 DB와 WAS, WEB서버 설치를 자동적으로 할 수 있는 각각의 플레이북을 실행하게 된다. 3티어 구축시 DB, WAS, WEB순서로 구축이 완료되어야 순차적으로 연결을 시킬 수 있으므로 DB, WAS, WEB의 설치순서를 고려하였고 마지막으로는 리눅스 방화벽을 자동적으로 셋팅할 수 있는 플레이북을 실행시켜주었다.

과제를 마치며...

이번 과제를 하며 인프라에서 실력적으로 가장 많이 성장할 수 있는 시기였지 않나 생각한다. 짧은 시간동안 깊은 몰입을 할 수 있었으며 내가 하고싶은 것을 직접 한다는 것이 오랜기간 집중할 수 있는 원동력이라고 생각한다.

이제는 취업준비생이 아닌 신입의 입장이지만, 이때의 마음가짐을 가지고 꾸준히 성장하는 자세를 가지고자 한다.

 

구성에 대해 조금 말하자면 기존의 vSphere구성을 잘 이해하고 구축을 수행해야 자동화 툴을 더 잘 사용할 수 있을 것 같다. 이번 과제를 수행하며 아쉬운점은 다음과 같다.

  • 테라폼 생성시 오류를 제외하고 제대로 구성이 되었음을 확인하는 방법은?
  • 실 적용시 아이피가 고정되어있지 않는경우 아이피를 어떻게 관리할 것인지(IP 동적할당에 대한 고민)
  • 테라폼의 리소스와 각종변수들을 별도의 파일로 보관하지 않은점

위의 내용들이 크게 아쉬운점인데 대부분 테라폼과 앤서블의 구성에 대해 제대로 학습하지 않고 빠르게 수행하다보니 놓치는 부분이 있었다. 이러한 부분들은 올해가 가기전에 정리하고 코드를 리팩토링하는 시간을 가져보는 것이 목표다...

 

직접구축하는 동안 힘들었지만 취업을 준비할 때 기술의 장단점과 왜 이 기술을 사용하는지에 대해 생각해볼 수 있는기회였어서 좋았다. 

 

 

'IaC' 카테고리의 다른 글

[Terraform, NCP, GCP] NCP 서버에서 GCP Cloud Storage 생성하기  (0) 2024.07.15