# Terraform with Openstack

## **Prerequisites**

* มี instance หรือ Devices ที่ติดตั้ง Terraform ([How to install](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli))
* การกำหนด Provider ([OpenStack Provider](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs))
* Data ที่ต้องใช้ใน Terraform (สามารถหาได้จาก [space.nipa.cloud](https://space.nipa.cloud/))
  * Provider
    1. `username` and `password`  : นำมาจากที่ผู้ใช้กรอกเข้าเว็ป portal
    2. `tenant_id` or `tenant_name`: เอาไว้ระบุ project ที่เราจะใช้งาน Terraform สามารถหาได้จาก project\_id หรือ project\_name&#x20;
    3. Terraform version **:** รองรับversion >= 1.8.4
    4. Openstack version **:** รองรับversion \~> 2.0.0
    5. `auth_url` : ต้องใช้ url นี้ [https://identity-api.nipa.cloud](https://identity-api.nipa.cloud/) ในการ Authentication
    6. `region` : เลือกพื้นที่ หรือ เขตในการสร้าง instance
  * Instance
    1. `image_id` หรือ `image_name` : ใช้สำหรับกำหนด OS ให้กับ instance
    2. `flavor_id` หรือ `flavor_name` : ใช้สำหรับกำหนด Machine Type ให้กับ instance
    3. `availability_zone` : ระบุพื้นที่ที่กำลังใช้งาน&#x20;
       * NCP-BKK
       * NCP-BKK2
       * NCP-NON
       * NCP-KKN
    4. `key_pair` : จำเป็นต้องสร้าง key pair ก่อนจึงจะนำไปใช้งานได้

       1. ซึ่งเมื่อสร้างเสร็จเเล้วจะได้ไฟล์ **.pem** สามารถใช้ remote เข้า instance ด้วยคำสั่ง

       `ssh -i [target = pathfile] username@hostname`
    5. `security_groups` : สามารถระบุชื่อ security group เพื่อนำมาใช้ได้
  * **Network**
    1. `network_id` : เป็น id networkเเต่ละตัว ซึ่งสามารถนำไปใช้ในการสร้าง port เเละ subnet
    2. `pool` : เป็น External network ที่เป็น public ของเเต่ละ AZ ที่เราสามารถนำมาใช้สร้าง floating ip ใน Terraform
    3. `port_id` : id port ของ instance ตัวนั้นๆ

## **วิธีการสร้าง instance**

1. สร้างไฟล์ openstack\_provider.tf

{% code overflow="wrap" %}

```bash
touch openstack_provider.tf
```

{% endcode %}

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FhDJRTD39rrndwWtqyrga%2Fimage.png?alt=media&#x26;token=c6499cdb-ab66-49ab-9611-d497b918064d" alt=""><figcaption></figcaption></figure>

2. เเก้ไขไฟล์ openstack\_provider.tf ดังนี้

```yaml
# Define required providers   #กำหนด Provider สำหรับใช้งาน
terraform {
  required_version = ">= 1.8.2" 
  required_providers {
    openstack = {
      source  = "terraform-provider-openstack/openstack"
      version = "~> 2.0.0"
    }
  }
}

# Configure the OpenStack Provider
provider "openstack" {
  user_name   = "xxxxxx"  #user name ใช้ user เดียวกันกับที่ login ใน portal
  password    = "xxxxxx"   #password ใช้ password เดียวกันกับที่ login ใน portal
  tenant_name     = "xxxxxx"   #เป็น ID ของ tenant หากเว้นไว้จะใช้จากตัวเเปร OS_PROJECT_NAME ของ environment
  auth_url      = " https://identity-api.nipa.cloud"
  region        = "NCP-TH"  #เขตหรือพื้นที่ใช้สำหรับสร้างตัว instance 
}
```

Note : สามารถอ่านข้อมูลเพิ่มเติมได้ที่ [openstack provider](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs)

3. ใช้คำสั่ง `terraform init` เพื่อเริ่มใช้งาน terraform เป็นขั้นตอนแรกที่สำคัญในการเริ่มต้นใช้งาน Terraform เนื่องจากมันจะจัดเตรียมสภาพแวดล้อมให้พร้อมสำหรับการดำเนินการคำสั่ง Terraform อื่น ๆ เช่น `terraform plan` หรือ `terraform apply`

```bash
terraform init
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FmK7qSnsLA5heXi7Pnm8n%2Fimage.png?alt=media&#x26;token=c6a2a733-84c6-48ef-947d-4128751c0d03" alt=""><figcaption></figcaption></figure>

เมื่อ init สำเร็จจะปรากฎ ผลลัพธ์ดังรูป

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FOo3Pet55PxszBJlFLhQT%2Fimage.png?alt=media&#x26;token=1b185508-4ea2-43b9-9c62-1a1e08dfc5e0" alt=""><figcaption></figcaption></figure>

folder `.terraform` และ file `.terraform.lock.hcl`  ที่เกิดขึ้นจากการใช้คำสั่ง `terraform init`เมื่อทำการ init เรียบร้อย ก็จะสามารถเพิ่ม resource ต่างๆ เพื่อใช้จัดการ infrastructure ด้วย terraform ได้

4. สร้างไฟล์ ที่ชื่อว่า **compute\_instance.tf**

```bash
touch compute_instance.tf
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FNFcGMKHR6DYpsoOT6H2k%2Fimage.png?alt=media&#x26;token=73a70bf7-9c20-48bf-8f43-d61aaa205389" alt=""><figcaption></figcaption></figure>

5. ทำการเเก้ไขไฟล์ compute\_instance.tf

```yaml
resource "openstack_networking_port_v2" "port_for_test" {
  name       = "openstack_networking_floatingip_associate_v2_port"
  network_id = "{Network_id}" # network id
}
resource "openstack_compute_instance_v2" "myinstance" {
  name            = "myinstance"   #ชื่อของ instance
  flavor_id       = "{flavor_id}" #ใส่ instance flavor id ที่ต้องการ
  key_pair        = "my_key_pair_name"   #ใส่ชื่อ key pair ที่ generate จาก Portal
  security_groups = ["default"]
  availability_zone = "NCP-BKK" #สามารถเลือก availability_zone ได้

  block_device {
    uuid                  = "af3ea4e9-f664-4801-9b1a-59aa3c206342"
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
  }

  network {
    port = openstack_networking_port_v2.port_for_test.id
  }
}
```

Note : สามารถอ่านข้อมูลเพิ่มเติมได้ที่ [openstack\_compute\_instance\_v2](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/compute_instance_v2) , [openstack\_networking\_port\_v2](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_port_v2)

6. ใช้คำสั่ง **`terraform plan`** เพื่อตรวจสอบ script เเละดูว่ามีการเปลี่ยนแปลงใดจะเกิดขึ้นเมื่อใช้คำสั่ง **`terraform apply`**

```bash
terraform plan
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2Fjhi85fTV4U2jB06Ceunw%2Fimage.png?alt=media&#x26;token=247d2248-3110-4528-adec-d0cdd64fbfb9" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FJ9yWD8RHmoqJ5xi4PpMl%2Fimage.png?alt=media&#x26;token=8260a4ee-087a-4915-a912-f9f3baf94334" alt=""><figcaption></figcaption></figure>

7. ใช้คำสั่ง **`terraform apply`** เพื่อสร้าง instance

```bash
terraform apply
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FZKxu32FuvMRsb8HftI30%2Fimage.png?alt=media&#x26;token=7d2eb0fb-591d-4332-88c3-f40894f86b4c" alt=""><figcaption></figcaption></figure>

หลังจากใช้คำสั่ง terraform จะถามว่าต้องการ perform action หรือไม่ ถ้าต้องการให้พิมพ์ yes ถ้าไม่ต้องการให้พิมพ์ no\
หากสร้าง instance สำเร็จจะได้ผลลัพธ์ดังรูป

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FkH5P21XL5lyLWzazLbKb%2Fimage.png?alt=media&#x26;token=ef9469bd-f961-47ca-856b-532547a0e347" alt=""><figcaption></figcaption></figure>

โดย instance ที่สร้างจะปรากฎในหน้า [space.nipa.cloud](https://space.nipa.cloud/) ที่หัวข้อ COMPUTE > Instances

### การ attach floating ip  เข้ากับ  instance

1. &#x20;สร้างไฟล์ **openstack\_networking\_floatingip.tf**

```bash
touch openstack_networking_floatingip.tf
```

2. เเก้ไขไฟล์ **openstack\_networking\_floatingip.tf**

{% code overflow="wrap" %}

```yaml
resource "openstack_networking_floatingip_v2" "floatip_1" {
  pool = "Standard_Public_IP_Pool_NON"  #ให้กรอกชื่อของ pool ที่มีอยู่ โดยจะต้องอยู่ใน AZ เดียวกัย Instances
}
```

{% endcode %}

3. สร้างไฟล์ **openstack\_networking\_floatingip\_associate.tf**

```bash
touch openstack_networking_floatingip_associate.tf
```

4. เเก้ไขไฟล์ **openstack\_networking\_floatingip\_associate.tf**

{% code overflow="wrap" %}

```
resource "openstack_networking_floatingip_associate_v2" "floating_ip_associate" {
  floating_ip = openstack_networking_floatingip_v2.floatip_1.address    #เป็นการนำ floating ip จาก resource ในข้อสองมาใส่
  port_id     = openstack_networking_port_v2.port_for_test.id  
}
```

{% endcode %}

5. ใช้คำสั่ง **`terraform plan`**

```bash
terraform plan
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FMDuiDL4iH6P9A2nJTKsq%2Fimage.png?alt=media&#x26;token=38a51ee2-8578-4325-a8b0-d75a71b12954" alt=""><figcaption></figcaption></figure>

6. ใช้คำสั่ง **`terraform apply`** เพื่อสร้าง floating ip เเละผูกเข้ากับ instance

```bash
terraform apply
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2F3ZE0DWpoc1wGVSdyfDnk%2Fimage.png?alt=media&#x26;token=7ee2db9f-b364-4f15-aa05-1e4dee2f2c55" alt=""><figcaption></figcaption></figure>

หลังจากใช้คำสั่ง terraform จะถามว่าต้องการ perform action หรือไม่ ถ้าต้องการให้พิมพ์ yes ถ้าไม่ต้องการให้พิมพ์ no

หลังจากใช้คำสั่งเเล้วจะปรากฎผลลัพธ์ ดังรูป<br>

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FPMLexkXE3qeyhFrggiIt%2Fimage.png?alt=media&#x26;token=66f78138-1a3b-46d1-90a2-93516b1504d4" alt=""><figcaption></figcaption></figure>

เมื่อตรวจสอบ Instance ในหน้า [space.nipa.cloud](https://space.nipa.cloud/) จะพบว่า Instance จะมี External Ip ที่ทำให้ instance สามารถเข้าถูกเข้าถึงได้จากภายนอก

### วิธีการลบ Instance

**`terraform destroy`** คำสั่งสำหรับลบ infrastructure ที่ถูกสร้างขึ้นทั้งหมดที่ถูกสร้างขึ้นด้วยไฟล์ .tf ใน folder นั้นๆ

```bash
terraform destroy
```

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2Fc65GJAV7mMMozn3w9nD2%2Fimage.png?alt=media&#x26;token=bac70e96-83a0-4708-a074-6a7939ceba6f" alt=""><figcaption></figcaption></figure>

หลังจากใช้คำสั่ง terraform จะถามว่าต้องการ perform action หรือไม่ ถ้าต้องการ ให้พิมพ์ yes ถ้าไม่ต้องการ ให้พิมพ์ no

จะได้ผลลัพธ์ดังรูป

<figure><img src="https://1352697161-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fq2BYmWTMiaonrEL8QBP2%2Fuploads%2FrjNY2U2xnFEAIFxz5n7K%2Fimage.png?alt=media&#x26;token=0c46fc3c-01b4-4be3-ba75-cab005d5d0e2" alt=""><figcaption></figcaption></figure>
