ساخت ماژول سفارشی Terraform

مقدمه

ماژول های Terraform به شما امکان می دهند منابع متمایز زیرساخت خود را در یک منبع واحد و یکپارچه گروه بندی کنید. می‌توانید بعداً با سفارشی‌سازی‌های احتمالی بدون تکرار تعاریف منابع هر بار که به آنها نیاز دارید، دوباره از آنها استفاده کنید، که برای پروژه‌های بزرگ و ساختار پیچیده مفید است. می‌توانید نمونه‌های ماژول را با استفاده از متغیرهای ورودی که تعریف می‌کنید سفارشی کنید و همچنین اطلاعات را با استفاده از خروجی‌ها از آنها استخراج کنید. به غیر از ایجاد ماژول های سفارشی خود، می توانید از ماژول های از پیش ساخته شده که به صورت عمومی در رجیستری Terraform منتشر شده اند نیز استفاده کنید. توسعه‌دهندگان می‌توانند با استفاده از ورودی‌هایی مانند ماژول‌هایی که ایجاد می‌کنید از آنها استفاده کرده و سفارشی‌سازی کنند، اما کد منبع آنها در فضای ابری ذخیره شده و از آن خارج می‌شود. در این آموزش، شما یک ماژول Terraform ایجاد می کنید که چندین Droplet را در پشت یک Load Balancer برای افزونگی راه اندازی می کند. همچنین از ویژگی‌های for_each و count Looping Hashicorp Configuration Language (HCL) برای استقرار چندین نمونه سفارشی‌شده ماژول به طور همزمان استفاده خواهید کرد.

پیش نیازها
  • یک رمز دسترسی شخصی DigitalOcean
  • Terraform روی سیستم شما نصب شده و پروژه ای با ارائه دهنده DO راه اندازی شده است
  • آشنایی با انواع داده ها و حلقه های HCL
  • آشنایی با خروجی های Terraform و کاربرد آنها

ساختار ماژول و مزایا

در این بخش، مزایایی را که ماژول ها به ارمغان می آورند، معمولاً در کجای پروژه قرار می گیرند و چگونه باید ساختار شوند، خواهید آموخت. ماژول‌های Terraform سفارشی برای کپسوله‌سازی اجزای متصل ایجاد شده‌اند که اغلب در پروژه‌های بزرگ‌تر استفاده می‌شوند و با هم مستقر می‌شوند. آنها مستقل هستند و فقط منابع، متغیرها و ارائه دهندگان مورد نیازشان را در کنار هم قرار می دهند. ماژول‌ها معمولاً در یک پوشه مرکزی در ریشه پروژه، هر کدام در زیر پوشه مربوطه خود ذخیره می‌شوند. به منظور حفظ یک جدایی تمیز بین ماژول ها، همیشه آنها را به گونه ای طراحی کنید که یک هدف واحد داشته باشند و مطمئن شوید که هرگز حاوی زیر ماژول نیستند. بسته بندی یک منبع واحد به عنوان یک ماژول می تواند اضافی باشد و به تدریج سادگی معماری کلی را حذف کند. برای پروژه‌های کوچک توسعه و آزمایش، ترکیب ماژول‌ها ضروری نیست، زیرا در آن موارد پیشرفت زیادی به همراه ندارند. ماژول ها همچنین این مزیت را ارائه می دهند که تعاریف فقط نیاز به اصلاح در یک مکان دارند، که سپس در بقیه زیرساخت ها منتشر می شود.

در مرحله بعد، ماژول ها را در پروژه های Terraform خود تعریف، استفاده و سفارشی می کنید.

ایجاد یک ماژول

در این بخش، چندین قطره و یک Load Balancer را به عنوان منابع Terraform تعریف کرده و آنها را در یک ماژول بسته بندی می کنید. همچنین ماژول حاصل را با استفاده از ورودی های ماژول قابل تنظیم می کنید.

ماژول را در دایرکتوری به نام droplet-lb، تحت دایرکتوری به نام ماژول ها ذخیره خواهید کرد. با فرض اینکه شما در دایرکتوری terraform-modules هستید که به عنوان بخشی از پیش نیازها ایجاد کرده اید، هر دو را به طور همزمان با اجرای:

mkdir -p modules/droplet-lb

آرگومان -p به mkdir دستور می دهد تا همه دایرکتوری ها را در مسیر ارائه شده ایجاد کند.

به آن بروید:

cd modules/droplet-lb

همانطور که در بخش قبل ذکر شد، ماژول ها حاوی منابع و متغیرهایی هستند که استفاده می کنند. با شروع از Terraform 0.13، آنها باید تعاریف ارائه دهندگان مورد استفاده را نیز شامل شوند. ماژول ها به پیکربندی خاصی نیاز ندارند تا توجه داشته باشید که کد نشان دهنده یک ماژول است، زیرا Terraform هر دایرکتوری حاوی کد HCL را به عنوان یک ماژول در نظر می گیرد، حتی دایرکتوری ریشه پروژه.

متغیرهای تعریف شده در یک ماژول به عنوان ورودی های آن در معرض دید قرار می گیرند و می توان از آنها در تعاریف منابع برای سفارشی کردن آنها استفاده کرد. ماژولی که ایجاد می‌کنید دو ورودی خواهد داشت: تعداد قطرات برای ایجاد و نام گروه آنها. برای ویرایش فایلی به نام variables.tf ایجاد و باز کنید که در آن متغیرها را ذخیره خواهید کرد:

nano variables.tf

خطوط زیر را اضافه کنید:

variable "droplet_count" {}
variable "group_name" {}

ذخیره کنید و فایل را ببندید.

شما تعریف Droplet را در فایلی به نام droplets.tf ذخیره خواهید کرد. آن را برای ویرایش ایجاد و باز کنید:

nano droplets.tf

خطوط زیر را اضافه کنید:

resource "digitalocean_droplet" "droplets" {
count = var.droplet_count
image = "ubuntu-22-04-x64"
name = "${var.group_name}-${count.index}"
region = "fra1"
size = "s-1vcpu-1gb"
lifecycle {
precondition {
condition = var.droplet_count >= 2
error_message = "At least two droplets must be created."
}
}
}

برای پارامتر count، که مشخص می‌کند چند نمونه از یک منبع ایجاد شود، متغیر droplet_count را ارسال می‌کنید. زمانی که ماژول از کد اصلی پروژه فراخوانی شود، مقدار آن مشخص خواهد شد. نام هر یک از قطره های مستقر شده متفاوت خواهد بود، که با اضافه کردن شاخص قطره فعلی به نام گروه ارائه شده، به آن دست پیدا می کنید. استقرار Droplets در منطقه fra1 خواهد بود و اوبونتو 22.04 را اجرا خواهد کرد.

بخش Lifecycle حاوی یک Preccondition است که قبل از اینکه منابع واقعاً مستقر شوند اجرا می شود. در اینجا، تأیید می‌کند که حداقل دو قطره ایجاد خواهد شد – داشتن تنها یکی، هدف Load Balancer را شکست می‌دهد. نمونه دیگری از اعتبارسنجی ها را می توان در مخزن k8s-bootstrapper یافت که حاوی الگوهایی برای راه اندازی یک خوشه DigitalOcean Kubernetes با استفاده از Terraform است. در آنجا، اعتبارسنجی ها برای اطمینان از اینکه تعداد گره ها در خوشه در محدوده است استفاده می شود.

پس از اتمام کار، فایل را ذخیره و ببندید.

با تعریف Droplets، می توانید به سمت ایجاد Load Balancer بروید. تعریف منبع آن را در فایلی به نام lb.tf ذخیره خواهید کرد. با اجرای زیر آن را برای ویرایش ایجاد و باز کنید:

nano lb.tf

تعریف منبع آن را اضافه کنید:

resource "digitalocean_loadbalancer" "www-lb" {
name = "lb-${var.group_name}"
region = "fra1"
forwarding_rule {
entry_port = 80
entry_protocol = "http"
target_port = 80
target_protocol = "http"
}
healthcheck {
port = 22
protocol = "tcp"
}
droplet_ids = [
for droplet in digitalocean_droplet.droplets:
droplet.id
]
}

شما Load Balancer را با نام گروه در نام آن تعریف می کنید تا قابل تشخیص باشد. شما آن را به همراه قطره ها در منطقه fra1 مستقر می کنید. دو بخش بعدی پورت ها و پروتکل های هدف و نظارت را مشخص می کند.

بلوک droplet_ids برجسته شده، شناسه‌های قطره‌ها را می‌گیرد که باید توسط Load Balancer مدیریت شوند. از آنجایی که چندین قطره وجود دارد و تعداد آنها از قبل مشخص نیست، از یک حلقه for برای عبور از مجموعه قطرات (digitalocean_droplet.droplets) و گرفتن شناسه آنها استفاده می کنید. شما حلقه for را با براکت ([]) احاطه می کنید تا مجموعه به دست آمده یک لیست باشد.

ذخیره کنید و فایل را ببندید.

اکنون Droplet، Load Balancer و متغیرها را برای ماژول خود تعریف کرده اید. شما باید الزامات ارائه دهنده را تعریف کنید و مشخص کنید که ماژول از کدام ارائه دهندگان استفاده می کند، از جمله نسخه آنها و مکان آنها. از Terraform 0.13، ماژول ها باید به صراحت منابع ارائه دهندگان غیر Hashicorp را که استفاده می کنند تعریف کنند. این به این دلیل است که آنها آنها را از پروژه مادر به ارث نمی برند.

شما الزامات ارائه دهنده را در فایلی به نام provider.tf ذخیره خواهید کرد. با اجرای موارد زیر آن را برای ویرایش ایجاد کنید:

nano provider.tf

خطوط زیر را برای نیاز به ارائه دهنده Digitalocean اضافه کنید:

terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
}

پس از اتمام، فایل را ذخیره کرده و ببندید. ماژول droplet-lb اکنون به ارائه دهنده Digitalocean نیاز دارد.

ماژول ها همچنین از خروجی ها پشتیبانی می کنند که می توانید از آنها برای استخراج اطلاعات داخلی در مورد وضعیت منابع آنها استفاده کنید. شما خروجی ای تعریف می کنید که آدرس IP Load Balancer را نشان می دهد و آن را در فایلی به نام outputs.tf ذخیره می کنید. آن را برای ویرایش ایجاد کنید:

nano outputs.tf

تعریف زیر را اضافه کنید:

output "lb_ip" {
value = digitalocean_loadbalancer.www-lb.ip
}

این خروجی آدرس IP Load Balancer را بازیابی می کند. ذخیره کنید و فایل را ببندید.

ماژول droplet-lb اکنون از نظر عملکرد کامل و آماده برای استقرار است. شما آن را از کد اصلی فراخوانی خواهید کرد که در ریشه پروژه ذخیره خواهید کرد. ابتدا، با دو بار رفتن به سمت بالا در فهرست فایل خود، به آن بروید:

cd ../..

سپس فایلی به نام main.tf ایجاد و برای ویرایش باز کنید که در آن از ماژول استفاده خواهید کرد:

nano main.tf

خطوط زیر را اضافه کنید:

module "groups" {
source = "./modules/droplet-lb"
droplet_count = 3
group_name = "group1"
}
output "loadbalancer-ip" {
value = module.groups.lb_ip
}

در این اعلان، ماژول droplet-lb را که در دایرکتوری مشخص شده به عنوان منبع قرار دارد فراخوانی می کنید. ورودی ای که ارائه می دهد، droplet_count و group_name را پیکربندی می کنید که روی group1 تنظیم شده است تا بعدا بتوانید بین نمونه ها تشخیص دهید.

از آنجایی که خروجی Load Balancer IP در یک ماژول تعریف شده است، هنگامی که پروژه را اعمال می کنید به طور خودکار نشان داده نمی شود. راه حل این امر ایجاد خروجی دیگری با بازیابی مقدار آن است (loadbalancer_ip).

پس از اتمام، فایل را ذخیره کرده و ببندید.

ماژول را با اجرای:

terraform init

خروجی به شکل زیر خواهد بود:

OutputInitializing modules...
- groups in modules/droplet-lb
Initializing the backend...
Initializing provider plugins...
- Finding digitalocean/digitalocean versions matching "~> 2.0"...
- Installing digitalocean/digitalocean v2.34.1...
- Installed digitalocean/digitalocean v2.34.1 (signed by a HashiCorp partner, key ID F82037E524B9C0E8)
...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

می‌توانید پروژه را برنامه‌ریزی کنید تا ببینید Terraform چه اقداماتی را با اجرا انجام می‌دهد:

terraform plan -var "do_token=${DO_PAT}"

خروجی مشابه این خواهد بود:

Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] will be created
+ resource "digitalocean_droplet" "droplets" {
...
+ name = "group1-0"
...
}
# module.groups.digitalocean_droplet.droplets[1] will be created
+ resource "digitalocean_droplet" "droplets" {
...
+ name = "group1-1"
...
}
# module.groups.digitalocean_droplet.droplets[2] will be created
+ resource "digitalocean_droplet" "droplets" {
...
+ name = "group1-2"
...
}
# module.groups.digitalocean_loadbalancer.www-lb will be created
+ resource "digitalocean_loadbalancer" "www-lb" {
...
+ name = "lb-group1"
...
}
Plan: 4 to add, 0 to change, 0 to destroy.
...

این خروجی توضیح می دهد که Terraform سه قطره به نام های group1-0، group1-1 و group1-2 ایجاد می کند و همچنین یک Load Balancer به نام group1-lb ایجاد می کند که ترافیک به و از سه قطره را مدیریت می کند.

می توانید با اجرای زیر پروژه را در فضای ابری اعمال کنید:

terraform apply -var "do_token=${DO_PAT}"

وقتی از شما خواسته شد، بله را وارد کنید. خروجی تمام اقدامات را نشان می دهد و آدرس IP Load Balancer نیز نشان داده می شود:

Outputmodule.groups.digitalocean_droplet.droplets[1]: Creating...
module.groups.digitalocean_droplet.droplets[0]: Creating...
module.groups.digitalocean_droplet.droplets[2]: Creating...
...
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
loadbalancer-ip = ip_address

شما یک ماژول حاوی تعداد قابل تنظیم قطرات و یک بار متعادل کننده ایجاد کرده اید که به طور خودکار برای مدیریت ترافیک ورودی و خروجی آنها پیکربندی می شود.

تغییر نام منابع مستقر شده

در قسمت قبل، ماژولی را که تعریف کردید مستقر کردید و آن را گروه نامیدید. اگر بخواهید نام آن را تغییر دهید، صرفاً تغییر نام فراخوانی ماژول نتایج مورد انتظار را به همراه نخواهد داشت. تغییر نام تماس باعث می شود Terraform منابع را از بین ببرد و دوباره ایجاد کند و باعث خرابی بیش از حد شود.

به عنوان مثال، main.tf را برای ویرایش با اجرای زیر باز کنید:

nano main.tf

همانطور که مشخص شده است، ماژول گروه ها را به group_renamed تغییر نام دهید:

module "groups_renamed" {
source = "./modules/droplet-lb"
droplet_count = 3
group_name = "group1"
}
output "loadbalancer-ip" {
value = module.groups_renamed.lb_ip
}

ذخیره کنید و فایل را ببندید. سپس دوباره پروژه را مقداردهی اولیه کنید:

terraform init

اکنون می توانید پروژه را برنامه ریزی کنید:

terraform plan -var "do_token=${DO_PAT}"

خروجی طولانی خواهد بود اما شبیه به این خواهد بود:

Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
- destroy
Terraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] will be destroyed
...
# module.groups_renamed.digitalocean_droplet.droplets[0] will be created
...

Terraform از شما می خواهد که نمونه های موجود را از بین ببرید و نمونه های جدید ایجاد کنید. این مخرب و غیر ضروری است و ممکن است منجر به خرابی ناخواسته شود.

در عوض، با استفاده از بلوک منتقل شده، می توانید به Terraform دستور دهید تا منابع قدیمی را با نام جدید منتقل کند. main.tf را برای ویرایش باز کنید و خطوط زیر را به انتهای فایل اضافه کنید:

moved {
from = module.groups
to = module.groups_renamed
}

وقتی کارتان تمام شد، فایل را ذخیره و ببندید.

اکنون می توانید پروژه را برنامه ریزی کنید:

terraform plan -var "do_token=${DO_PAT}"

هنگامی که با بلوک منتقل شده در main.tf برنامه ریزی می کنید، Terraform می خواهد منابع را به جای ایجاد مجدد آنها جابجا کند:

OutputTerraform will perform the following actions:
# module.groups.digitalocean_droplet.droplets[0] has moved to module.groups_renamed.digitalocean_droplet.droplets[0]
...
# module.groups.digitalocean_droplet.droplets[1] has moved to module.groups_renamed.digitalocean_droplet.droplets[1]
...

منابع متحرک جای خود را در حالت Terraform تغییر می‌دهند، به این معنی که منابع واقعی ابر تغییر، نابود یا دوباره ایجاد نمی‌شوند.

از آنجایی که در مرحله بعد پیکربندی را به طور قابل توجهی تغییر خواهید داد، منابع مستقر شده را با اجرای:

terraform destroy -var "do_token=${DO_PAT}"

وقتی از شما خواسته شد، Yes را وارد کنید. خروجی به پایان می رسد:

Output...
Destroy complete! Resources: 4 destroyed.

در این بخش، شما نام منابع را در پروژه Terraform خود بدون از بین بردن آنها تغییر دادید. اکنون چندین نمونه از یک ماژول را از همان کد با استفاده از for_each و count مستقر خواهید کرد.

استقرار نمونه های چندگانه ماژول

در این بخش، از count و for_each برای استقرار ماژول droplet-lb چندین بار با سفارشی‌سازی استفاده می‌کنید.

 استفاده از count

یکی از راه‌های استقرار چند نمونه از یک ماژول به طور همزمان، ارسال تعداد به پارامتر شمارش است که به طور خودکار برای هر ماژول در دسترس است. main.tf را برای ویرایش باز کنید:

nano main.tf

با حذف تعریف خروجی موجود و بلوک منتقل شده، آن را به شکل زیر تغییر دهید:

module "groups" {
source = "./modules/droplet-lb"
count = 3
droplet_count = 3
group_name = "group1-${count.index}"
}

با تنظیم تعداد روی 3، به Terraform دستور می دهید که ماژول را سه بار، هر کدام با نام گروه متفاوتی، مستقر کند. وقتی کارتان تمام شد، فایل را ذخیره و ببندید.

استقرار را با اجرا کردن برنامه ریزی کنید:

terraform plan -var "do_token=${DO_PAT}"

خروجی طولانی خواهد بود و به شکل زیر خواهد بود:

Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.groups[0].digitalocean_droplet.droplets[0] will be created
...
# module.groups[0].digitalocean_droplet.droplets[1] will be created
...
# module.groups[0].digitalocean_droplet.droplets[2] will be created
...
# module.groups[0].digitalocean_loadbalancer.www-lb will be created
...
# module.groups[1].digitalocean_droplet.droplets[0] will be created
...
# module.groups[1].digitalocean_droplet.droplets[1] will be created
...
# module.groups[1].digitalocean_droplet.droplets[2] will be created
...
# module.groups[1].digitalocean_loadbalancer.www-lb will be created
...
# module.groups[2].digitalocean_droplet.droplets[0] will be created
...
# module.groups[2].digitalocean_droplet.droplets[1] will be created
...
# module.groups[2].digitalocean_droplet.droplets[2] will be created
...
# module.groups[2].digitalocean_loadbalancer.www-lb will be created
...
Plan: 12 to add, 0 to change, 0 to destroy.
...

Terraform در خروجی توضیح می دهد که هر یک از سه نمونه ماژول دارای سه Droplet و یک Load Balancer مرتبط با آنها هستند.

استفاده از for_each

زمانی که به سفارشی‌سازی نمونه پیچیده‌تری نیاز دارید یا زمانی که تعداد نمونه‌ها به داده‌های شخص ثالث (اغلب به صورت نقشه ارائه می‌شوند) بستگی دارد که هنگام نوشتن کد مشخص نیست، می‌توانید از for_each برای ماژول‌ها استفاده کنید.

اکنون نقشه‌ای را تعریف می‌کنید که نام گروه‌ها را با تعداد قطره‌ها جفت می‌کند و نمونه‌هایی از droplet-lb را بر اساس آن پیاده‌سازی می‌کند. main.tf را برای ویرایش با اجرای زیر باز کنید:

nano main.tf

فایل را به شکل زیر تغییر دهید:

variable "group_counts" {
type = map
default = {
"group1" = 1
"group2" = 3
}
}
module "groups" {
source = "./modules/droplet-lb"
for_each = var.group_counts
droplet_count = each.value
group_name = each.key
}

ابتدا نقشه ای به نام group_counts تعریف می کنید که حاوی تعداد قطره های یک گروه معین است. سپس، ماژول droplet-lb را فراخوانی می‌کنید، اما مشخص می‌کنید که حلقه for_each باید بر روی var.group_counts، نقشه‌ای که قبلاً تعریف کرده‌اید، عمل کند. droplet_count هر.value را می گیرد، مقدار جفت فعلی، که تعداد قطرات برای گروه فعلی است. group_name نام گروه را دریافت می کند.

پس از اتمام، فایل را ذخیره کرده و ببندید.

سعی کنید پیکربندی را با اجرای زیر اعمال کنید:

terraform plan -var "do_token=${DO_PAT}"

خروجی جزئیات اقدامات Terraform برای ایجاد این دو گروه با Droplets و Load Balancers را نشان می دهد:

Output...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.groups["group1"].digitalocean_droplet.droplets[0] will be created
...
# module.groups["group1"].digitalocean_loadbalancer.www-lb will be created
...
# module.groups["group2"].digitalocean_droplet.droplets[0] will be created
...
# module.groups["group2"].digitalocean_droplet.droplets[1] will be created
...
# module.groups["group2"].digitalocean_droplet.droplets[2] will be created
...
# module.groups["group2"].digitalocean_loadbalancer.www-lb will be created
...

در این مرحله، از count و for_each برای استقرار چندین نمونه سفارشی شده از یک ماژول از همان کد استفاده کرده اید.

نتیجه

در این آموزش ماژول های Terraform را ایجاد و اجرا کردید. شما از ماژول‌ها برای گروه‌بندی منابع مرتبط منطقی با یکدیگر و سفارشی‌سازی آن‌ها به منظور استقرار چندین نمونه مختلف از یک تعریف کد مرکزی استفاده کردید. شما همچنین از خروجی ها برای نشان دادن ویژگی های منابع موجود در ماژول استفاده کردید.

[تعداد: 1   میانگین: 5/5]
دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

شاید دوست داشته باشید