Tất cả tài liệu

Cloud Server

    IaC
    IaC
    Updated on 12 Apr 2024

    I. Initial setup & service authentication

    terraform {
    required_version = ">= 0.14.0"
      required_providers {
        openstack = {
          source  = "terraform-provider-openstack/openstack"
          version = "~> 1.53.0"
        }
      }
    }
    
    # Configure the OpenStack Provider
    provider "openstack" {
      user_name   = "usera"
      tenant_name   = "project_name"
      password    = "pwd"
      auth_url    = <fptcloud identity endpoint>
      region      = "RegionOne"
    }
    
    # Create infratructures
    resource "openstack_compute_instance_v2" "test-server" {
      # ...
    }
    Parameters Description Environment Variable
    auth_url URL of Identity Service OS_AUTH_URL
    region Region of FPT cloud OS_REGION_NAME
    user_name Username provided by FPT Cloud OS_USERNAME
    user_id OS_USER_ID
    user_domain_name OS_USER_DOMAIN_NAME
    user_domain_id OS_USER_DOMAIN_ID
    tenant_id OS_PROJECT_ID
    tenant_name VPC name provided by FPTCloud OS_PROJECT_NAME
    project_domain_name OS_PROJECT_DOMAIN_NAME
    project_domain_id OS_PROJECT_DOMAIN_ID
    domain_name OS_DOMAIN_NAME
    domain_id OS_DOMAIN_ID
    insecure OS_INSECURE
    interface OS_INTERFACE
    ...

    II. Core components

    A. Networking

    1. Router

       resource "openstack_networking_router_v2" "router_1" {
            name                = "my_router"
            admin_state_up      = true
            external_network_id = "f67f0d72-0ddf-11e4-9d95-e1f29f417e2f"
        }
    Parameters Description Required
    region Region of vRouter
    name Name of vRouter
    external_network_id ID of external gateway, a router with an external gateway is required if any compute instances or load balancers will be using floating IPs.
    ...

    2. Network

        resource "openstack_networking_network_v2" "network_1" {
          name           = "network_1"
          admin_state_up = "true"
        }
    
        resource "openstack_networking_subnet_v2" "subnet_1" {
          name       = "subnet_1"
          network_id = openstack_networking_network_v2.network_1.id
          cidr       = "192.168.199.0/24"
          ip_version = 4
        }
    
        resource "openstack_compute_secgroup_v2" "secgroup_1" {
          name        = "secgroup_1"
          description = "a security group"
    
          rule {
            from_port   = 22
            to_port     = 22
            ip_protocol = "tcp"
            cidr        = "0.0.0.0/0"
          }
        }
    
        resource "openstack_networking_port_v2" "port_1" {
          name               = "port_1"
          network_id         = openstack_networking_network_v2.network_1.id
          admin_state_up     = "true"
          security_group_ids = [openstack_compute_secgroup_v2.secgroup_1.id]
    
          fixed_ip {
            subnet_id  = openstack_networking_subnet_v2.subnet_1.id
            ip_address = "192.168.199.10"
          }
        }
    
        resource "openstack_compute_instance_v2" "instance_1" {
          name            = "instance_1"
          security_groups = [openstack_compute_secgroup_v2.secgroup_1.name]
    
          network {
            port = openstack_networking_port_v2.port_1.id
          }
        }
    Parameters Description Type Default Required
    name Name of network. string Yes
    shared Specifies whether the network resource can be accessed by any tenant or not. bool false No
    ...

    3. Subnet

       resource "openstack_networking_network_v2" "network_1" {
          name           = "tf_test_network"
          admin_state_up = "true"
        }
    
        resource "openstack_networking_subnet_v2" "subnet_1" {
          network_id = openstack_networking_network_v2.network_1.id
          cidr       = "192.168.199.0/24"
        }
    Parameters Description Type Default Required
    network_id ID of network from previous step. string Yes
    cidr CIDR representing IP range for this subnet, based on IP version. string Yes
    ip_version IP version of subnet. int 4 No
    enable_dhcp Enable DHCP for subnet. bool true No
    allocation_pools IP pools of DHCP . list No
    gateway_ip Default IP Gateway. string No
    host_routes List of default static host routes. list No
    dns_nameservers List of DNS server of subnet. list No
    prefixlen Prefix length of subnet. int No
    ...

    4. Port

        resource "openstack_networking_network_v2" "network_1" {
          name           = "network_1"
          admin_state_up = "true"
        }
    
        resource "openstack_networking_port_v2" "port_1" {
          name           = "port_1"
          network_id     = openstack_networking_network_v2.network_1.id
          admin_state_up = "true"
        }
    Parameters Description Type Default Required
    network_id ID of network from previous step. string Yes
    mac_address Fix MAC address for port. string No
    name Port name. string No
    fixed_ips Fixed IP for port. list No
    allowed_address_pairs An IP/MAC Address pair of additional IP addresses that can be active on this port. list No
    security_group_ids A list of security group IDs to apply to the port. list No
    ...

    5. FloatingIP

        resource "openstack_networking_floatingip_v2" "floatip_1" {
          pool = "provider-net4"
        }
    Parameters Description Type Default Required
    pool The name of the pool from which to obtain the floating IP. Changing this creates a new floating IP. E.g. provider-net4 string Yes
    port_id ID of an existing port with at least one IP address to associate with this floating IP. string No
    fixed_ip Fixed IP of the port to associate with this floating IP. string No
    description Human-readable description for the floating IP. string No
    ...

    6. Security Group

        resource "openstack_networking_secgroup_v2" "secgroup_1" {
          name        = "secgroup_1"
          description = "My neutron security group"
        }
    Parameters Description Type Default Required
    name A unique name for the security group. string Yes
    description Human-readable description for the security group. string No
    tenant_id The owner of the security group. Required if admin wants to create a port for another tenant. string No
    ...

    7. Security Group Rule

        resource "openstack_networking_secgroup_v2" "secgroup_1" {
          name        = "secgroup_1"
          description = "My neutron security group"
        }
    
        resource "openstack_networking_secgroup_rule_v2" "secgroup_rule_1" {
          direction         = "ingress"
          ethertype         = "IPv4"
          protocol          = "tcp"
          port_range_min    = 22
          port_range_max    = 22
          remote_ip_prefix  = "0.0.0.0/0"
          security_group_id = openstack_networking_secgroup_v2.secgroup_1.id
        }
    Parameters Description Type Default Required
    security_group_id The security group id the rule should belong to, the value needs to be an Openstack ID of a security group in the same tenant. string Yes
    direction ingress or egress. string Yes
    ethertype Layer 3 protocol type (IPv4, IPv6). string Yes
    protocol Layer 4 protocol type (tcp, udp, icmp, ...). string Yes
    remote_ip_prefix remote CIDR string No
    remote_group_id The remote group id, the value needs to be an Openstack ID of a security group in the same tenant. string No
    port_range_min int No
    port_range_max int No
    description A description of the rule. string No
    ...

    B. Storage

    1. Volume

        resource "openstack_blockstorage_volume_v3" "volume_1" {
          region      = "RegionOne"
          name        = "volume_1"
          description = "first test volume"
          volume_type = "PremiumSSD-2000_floor5"
          availability_zone = "floor5"
          size        = 40
        }
    Parameters Description Type Default Required
    size The size of the volume to create (in gigabytes). int Yes
    name A unique name for the volume. string No
    description A description of the volume. string No
    availability_zone The availability zone for the volume. string No
    image_id The image ID from which to create the volume. string No
    volume_type The type of volume to create. string No
    ...

    C. Compute

    1. Instance

    resource "openstack_blockstorage_volume_v3" "myvol" {
      name = "myvol"
      size = 40
      volume_type = "PremiumSSD-2000_floor5"
      availability_zone = "floor5"
    }
    
    resource "openstack_compute_instance_v2" "myinstance" {
      name            = "myinstance"
      image_name        = "UBUNTU-20.04-10072023"
      flavor_name       = "Small.2"
      key_pair        = "my_key_pair_name"
      security_groups = ["default"]
      availability_zone = "floor5"
    
      network {
        name = "my_network"
      }
    }
    
    resource "openstack_compute_volume_attach_v2" "attached" {
      instance_id = openstack_compute_instance_v2.myinstance.id
      volume_id   = openstack_blockstorage_volume_v3.myvol.id
    }
    Parameters Description Type Default Required
    name A unique name for the resource. string Yes
    flavor_name The name of the desired flavor for the server. string Yes
    image_name The name of the desired image for the server. string Yes
    key_pair The name of a key pair to put on the server. string No
    user_data cloud-init script, the user data to provide when launching the instance. string No
    metadata map No
    security_groups An array of one or more security group names to associate with the server. list No
    network An array of one or more networks to attach to the instance. string No
    block_device Configuration of block devices. list No
    availability_zone  The availability zone in which to create the server. string No
    ...

    III. Example

    This section focus on show up the actual use case of FPT Cloud Iac by using terraform to deploy new Web Application on FPT Cloud, the step described as the following:

    • Setting up terraform
    • Create new project directory include main.tf file with the following content:
    terraform {
    required_version = ">= 0.14.0"
      required_providers {
        openstack = {
          source  = "terraform-provider-openstack/openstack"
          version = "~> 1.53.0"
        }
      }
    }
    
    # Configure the OpenStack Provider
    provider "openstack" {
      user_name   = <user-name>
      tenant_id = <project-uuid>
      user_domain_name = <domain-name>
      password    = <password>
      auth_url    = <fptcloud identity endpoint>
      region      = "RegionOne"
    }
    
    # Network  
    data "openstack_networking_network_v2" "provider_net" {  
      name = "provider-net5"  
    }  
    
    resource "openstack_networking_router_v2" "webapp_router" {  
      name                = "webapp_router"  
      admin_state_up      = true  
      external_network_id = data.openstack_networking_network_v2.provider_net.id  
    }  
    
    resource "openstack_networking_network_v2" "webapp_network" {  
      name           = "webapp_network"  
      admin_state_up = true  
    }  
    
    resource "openstack_networking_subnet_v2" "webapp_subnet" {  
      name            = "webapp_subnet"  
      network_id      = openstack_networking_network_v2.webapp_network.id  
      cidr            = "10.0.0.0/24"  
      ip_version      = 4  
      dns_nameservers = ["1.1.1.1"]  
    }  
    
    resource "openstack_networking_router_interface_v2" "webapp_router_interface" {  
      router_id = openstack_networking_router_v2.webapp_router.id  
      subnet_id = openstack_networking_subnet_v2.webapp_subnet.id  
    }  
    
    resource "openstack_compute_secgroup_v2" "webapp_secgroup" {  
      name        = "webapp_secgroup"  
      description = "Allow web traffic"  
      rule {  
        from_port   = 80  
        to_port     = 80  
        ip_protocol = "tcp"  
        cidr        = "0.0.0.0/0"  
      }  
      rule {  
        from_port   = 22  
        to_port     = 22  
        ip_protocol = "tcp"  
        cidr        = "0.0.0.0/0"  
      }  
    }  
    
    resource "openstack_compute_floatingip_v2" "webapp_floatingip" {  
      pool = "provider-net5"  
    }  
    
    # Volume  
    data "openstack_images_image_v2" "ubuntu_image" {  
      name = "UBUNTU-22.04-10072023"  
    }  
    
    resource "openstack_blockstorage_volume_v3" "webapp_volume" {  
      name        = "webapp_volume"  
      description = "Volume for webapp"  
      size        = 40  
      volume_type        = "Premium-SSD_floor5"  
      image_id    = data.openstack_images_image_v2.ubuntu_image.id  
    }  
    
    # Instance  
    data "openstack_compute_keypair_v2" "webapp_key" {  
      name = "webapp_key"  
    }  
    
    data "openstack_compute_flavor_v2" "s2_medium_1" {  
      name = "2C2G"  
    }  
    
    /* Userdata  
    #cloud-config  
    package_update: true  
    chpasswd:  
      list: |    root:<password-vm>
      packages:  
      - nginx  - gitruncmd:  
      - systemctl enable nginx  
      - systemctl start nginx  
      - git clone https://github.com/cloudacademy/static-website-example.git  
      - cp -r ./static-website-example/* /var/www/html/  
      - rm -r ./static-website-example*/  
    
    resource "openstack_compute_instance_v2" "webapp_instance" {  
      name            = "webapp_instance"  
      image_id        = data.openstack_images_image_v2.ubuntu_image.id  
      flavor_id       = data.openstack_compute_flavor_v2.s2_medium_1.id  
      key_pair        = data.openstack_compute_keypair_v2.webapp_key.name  
      security_groups = [openstack_compute_secgroup_v2.webapp_secgroup.name]  
      availability_zone = "floor5"  
    
      user_data = "#cloud-config\npackage_update: true\nchpasswd:\n  list: |\n    root:Welcome***123\npackages:\n  - nginx\n  - git\nruncmd:\n  - systemctl enable nginx\n  - systemctl start nginx\n  - git clone https://github.com/cloudacademy/static-website-example.git\n  - cp -r ./static-website-example/* /var/www/html/\n  - rm -r ./static-website-example"  
      network {  
        name = openstack_networking_network_v2.webapp_network.name  
      }  
      block_device {  
        uuid                  = openstack_blockstorage_volume_v3.webapp_volume.id  
        source_type           = "volume"  
        destination_type      = "volume"  
        boot_index            = 0  
        delete_on_termination = true  
      }  
    }  
    
    resource "openstack_compute_floatingip_associate_v2" "webapp_floatingip_associate" {  
      floating_ip = openstack_compute_floatingip_v2.webapp_floatingip.address  
      instance_id = openstack_compute_instance_v2.webapp_instance.id  
    }
    
    output "webapp_public_ip" {  
      value       = openstack_compute_floatingip_v2.webapp_floatingip.address  
      description = "Web Application URL"  
    }  
    
    output "webapp_private_ip" {  
      value       = openstack_compute_instance_v2.webapp_instance.access_ip_v4  
      description = "Web Application Private IP"  
    }
    • Deploying application

      terraform init
      terraform apply --auto-approve
    • The result of terraform CLI: file

    • Acces the floating IP and enjoy the result of webapp file

    • Cleaning-up the whole resources created by IaC stack:

      terraform destroy --auto-approve

    References