توفير جهاز ظاهري Linux باستخدام Terraform

مكتمل

ينفذ Terraform البنية الأساسية المستهدفة ويتحكم فيها باستخدام ملفات التكوين التي تصف الحالة المطلوبة لمكوناتها. التنسيق الأساسي للملفات وبناء الجملة العام الخاص بها - يتم التعبير عنه بلغة تكوين Hashicorp (HCL) - هو نفسه بغض النظر عن اختيار السحابة. ومع ذلك، تعتمد أوصاف المكونات الفردية على السحابة، كما يحددها موفر Terraform المقابل.

على الرغم من وجود العديد من موفري Terraform الذين يدعمون إدارة البنية الأساسية ل Azure، فإن AzureRM له صلة خاصة. يسهل موفر AzureRM توفير موارد Azure IaaS الشائعة وتكوينها، مثل الأجهزة الظاهرية وحسابات التخزين وواجهات الشبكات. هناك أيضا موفرون إضافيون غير محددين للسحابة قد ترغب في دمجهم في عمليات التوزيع الخاصة بك. وتشمل هذه الموفر العشوائي، الذي يساعد في تجنب تعارضات تسمية الموارد عن طريق إنشاء سلاسل أحرف عشوائية الزائفة؛ وموفر tls، الذي يبسط إدارة المفاتيح غير المتماثلة لتأمين مصادقة Linux.

يتوفر Terraform كثنائي واحد يمكنك تنزيله من موقع Hashicorp على الويب. ينفذ هذا الثنائي واجهة سطر الأوامر Terraform (CLI)، والتي يمكنك استدعاؤها بعد ذلك من جلسة shell لتهيئة Terraform ومعالجة ملفات التكوين. يمكنك استخدام Terraform CLI من أي من shells التي تدعم Azure CLI.

إشعار

عند استخدام Azure Cloud Shell، تأكد من تشغيل الإصدار الحالي من Terraform باتباع الإرشادات الواردة في تكوين Terraform في Azure Cloud Shell باستخدام Bash.

نشر جهاز Linux الظاهري باستخدام Terraform

يتيح لك Terraform تحديد الموارد ومعاينةها ونشرها في بنية أساسية سحابية خاصة بموفر. تبدأ عملية التوفير بإنشاء ملفات التكوين التي تستخدم بناء جملة HCL، والتي تسمح لك بتعيين بيئة السحابة المستهدفة - مثل Azure - والموارد التي تشكل البنية الأساسية السحابية الخاصة بك. بعد أن تكون جميع ملفات التكوين ذات الصلة في مكانها (عادة داخل نفس موقع نظام الملفات)، يمكنك إنشاء خطة تنفيذ تسمح لك بمعاينة تغييرات البنية الأساسية الناتجة قبل النشر الفعلي. يتطلب هذا منك تهيئة Terraform لتنزيل وحدات الموفر النمطية اللازمة لتنفيذ موارد السحابة. بعد التحقق من صحة التغييرات، يمكنك تطبيق خطة التنفيذ لنشر البنية الأساسية.

إشعار

يعد إنشاء خطة تنفيذ أمرا اختياريا، ولكن نوصي بالقيام بذلك لأنه يسمح لك بتحديد أي تأثير من التوزيع المخطط له دون التأثير على البيئة المستهدفة. عند نشر موارد Azure بشكل تفاعلي، يدعم Terraform مصادقة Azure CLI بشفافية عن طريق إعادة استخدام بيانات الاعتماد الخاصة بك للوصول إلى اشتراك Azure الهدف.

تتضمن عملية توفير جهاز Azure ظاهري يعمل بنظام Linux باستخدام Terraform عادة التسلسل التالي من الخطوات عالية المستوى:

  • تحديد صورة الجهاز الظاهري المناسبة.
  • تحديد حجم الجهاز الظاهري المناسب.
  • إنشاء ملفات التكوين التي تحدد مورد Azure VM مع تبعياته.
  • تهيئة Terraform.
  • إنشاء خطة تنفيذ Terraform.
  • بدء نشر Terraform.

لتحديد صورة الجهاز الظاهري المناسب وحجمه، اتبع الخطوات الموضحة في الوحدة 4 من هذه الوحدة النمطية. تركز هذه الوحدة على المهام الخاصة ب Terraform.

إنشاء ملفات التكوين

إشعار

أسماء الملفات التي تختارها لملفات Terraform عشوائية، على الرغم من أنه من الممارسات الجيدة اختيار اسم يعكس محتوى الملف أو الغرض منه. يجب استخدام ".tf" لملحق الملف.

لنشر Linux VM باستخدام Terraform، تبدأ بإنشاء دليل لاستضافة ملفات التكوين. بعد ذلك، أنشئ ملفا باسم providers.tf يفرض إصدار Terraform ويحدد الموفرين الذين ستعتمدون عليه عند تعريف الموارد المضمنة في النشر. يجب أن يحتوي هذا الملف على المحتوى المعروض في القصاصة البرمجية التالية:

terraform {
  required_version = ">=0.12"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~>2.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "~>3.0"
    }
    tls = {
      source = "hashicorp/tls"
      version = "~>4.0"
    }
  }
}

provider "azurerm" {
  features {}
}

في نفس الدليل، قم بإنشاء ملف باسم main.tf باستخدام التعليمات البرمجية التالية، والتي تحدد تكوين Azure VM وتبعياته:

resource "random_pet" "rg_name" {
  prefix = var.resource_group_name_prefix
}

resource "azurerm_resource_group" "rg" {
  location = var.resource_group_location
  name     = random_pet.rg_name.id
}

# Create virtual network
resource "azurerm_virtual_network" "terraform_network" {
  name                = "lnx-tf-vnet"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
}

# Create subnet
resource "azurerm_subnet" "terraform_subnet" {
  name                 = "subnet0"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.terraform_network.name
  address_prefixes     = ["10.1.0.0/24"]
}

# Create public IPs
resource "azurerm_public_ip" "terraform_public_ip" {
  name                = "lnx-tf-pip"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "terraform_nsg" {
  name                = "lnx-tf-nsg"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "ssh"
    priority                   = 300
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }
}

# Create network interface
resource "azurerm_network_interface" "terraform_nic" {
  name                = "lnx-tf-nic"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "nic_configuration"
    subnet_id                     = azurerm_subnet.terraform_subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.terraform_public_ip.id
  }
}

# Connect the security group to the network interface
resource "azurerm_network_interface_security_group_association" "lnx-tf-nic-nsg" {
  network_interface_id      = azurerm_network_interface.terraform_nic.id
  network_security_group_id = azurerm_network_security_group.terraform_nsg.id
}

# Generate random text for a unique storage account name
resource "random_id" "random_id" {
  keepers = {
    # Generate a new ID only when a new resource group is defined
    resource_group = azurerm_resource_group.rg.name
  }

  byte_length = 8
}

# Create storage account for boot diagnostics
resource "azurerm_storage_account" "storage_account" {
  name                     = "diag${random_id.random_id.hex}"
  location                 = azurerm_resource_group.rg.location
  resource_group_name      = azurerm_resource_group.rg.name
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

# Create (and display) an SSH key
resource "tls_private_key" "lnx-tf-ssh" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

# Create virtual machine
resource "azurerm_linux_virtual_machine" "lnx-tf-vm" {
  name                  = "lnx-tf-vm"
  location              = azurerm_resource_group.rg.location
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.terraform_nic.id]
  size                  = "Standard_F4s"

  os_disk {
    name                 = "lnx-tf-vm-osdisk"
    caching              = "ReadWrite"
    storage_account_type = "Premium_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts-gen2"
    version   = "latest"
  }

  computer_name                   = "lnx-tf-vm"
  admin_username                  = "azureuser"
  disable_password_authentication = true

  admin_ssh_key {
    username   = "azureuser"
    public_key = tls_private_key.lnx-tf-ssh.public_key_openssh
  }

  boot_diagnostics {
    storage_account_uri = azurerm_storage_account.storage_account.primary_blob_endpoint
  }
}

في نفس الدليل، قم بإنشاء ملف آخر يسمى variables.tf باستخدام التعليمات البرمجية التالية، والتي تعين القيمة إلى المتغيرات التي تظهر في ملف main.tf :

variable "resource_group_location" {
  default     = "eastus"
  description = "Location of the resource group"
}

variable "resource_group_name_prefix" {
  default     = "rg"
  description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription"
}

وأخيرا، قم بإنشاء ملف باسم outputs.tf باستخدام التعليمات البرمجية التالية، والتي تحدد الإخراج الذي يعرض بعد نشر ناجح:

output "resource_group_name" {
  value = azurerm_resource_group.rg.name
}

output "public_ip_address" {
  value = azurerm_linux_virtual_machine.lnx-tf-vm.public_ip_address
}

output "tls_private_key" {
  value     = tls_private_key.lnx-tf-ssh.private_key_pem
  sensitive = true
}

تهيئة Terraform

لتهيئة نشر Terraform، قم بتشغيل الأمر التالي من موجه shell:

terraform init

يقوم هذا الأمر بتنزيل وحدات Azure النمطية اللازمة لتوفير موارد Azure وإدارتها.

إنشاء خطة تنفيذ

بعد التهيئة، قم بإنشاء خطة تنفيذ عن طريق تشغيل خطة terraform. ينشئ الأمر خطة تنفيذ، ولكنه لا يقوم بتشغيلها. بدلا من ذلك، يحدد الإجراءات الضرورية لإنشاء الموارد المعرفة في ملفات التكوين الخاصة بك. تسمح لك المعلمة الاختيارية -out بتحديد ملف إخراج للخطة، والذي يمكنك الرجوع إليه أثناء النشر الفعلي. يضمن استخدام هذا الملف أن الخطة التي تراجعها تطابق نتيجة النشر الدقيقة. استخدم الأمر التالي لإنشاء خطة تنفيذ:

terraform plan -out <terraform_plan>.tfplan

بدء عملية نشر

عندما تكون مستعدا لتطبيق خطة التنفيذ على بيئة Azure، قم بتشغيل terraform apply، بما في ذلك اسم الملف الذي أنشأته في الخطوة السابقة. سيكون لديك فرصة أخرى لمراجعة النتيجة المتوقعة. يطالبك Terraform بالتأكيد على المتابعة، على الرغم من أنه يمكنك إزالة المطالبة -auto-approve عن طريق إضافة مفتاح التبديل. استخدم الأمر التالي لبدء النشر:

terraform apply <terraform_plan>.tfplan

سيبدأ تشغيل Azure VM قريبا، عادة في غضون بضع دقائق. terraform apply يتضمن إخراج الأمر قائمة المخرجات، ولكن terraform سيستبدل قيمة tls_private_key بالتسمية الحساسة<>:

Apply complete! Resources: 12 added, 0 changed, 0 destroyed.

المخرجات:

public_ip_address = "74.235.10.136"
resource_group_name = "rg-flexible-shark"
tls_private_key = <sensitive>

لاستخدام المفتاح الخاص الذي تم إنشاؤه تلقائيا لمصادقة اتصال SSH، قم بتخزينه في ملف ثم قم بتعيين أذونات الملف للتأكد من عدم إمكانية وصول الآخرين إليه. لإنجاز ذلك، قم بتشغيل الأوامر التالية:

terraform output -raw tls_private_key > id_rsa
chmod 600 id_rsa

عند هذه النقطة، ستتمكن من الاتصال بجهاز Azure الظاهري عن طريق تشغيل الأمر التالي (بعد استبدال <العنصر النائب public_ip_address> بعنوان IP الذي حددته في الإخراج الذي تم إنشاؤه بواسطة terraform):

ssh -i id_rsa azureuser@<public_ip_address>