Terraform و OpenTofu
زیرساخت پروژه را در کد بنویسید، در گیت نگه دارید و با یک apply ایجاد کنید. پرووایدر فقط کلاینت API عمومی است: همان درخواستهایی را میفرستد که داشبورد و CLI میفرستند.
نصب#
پرووایدر از رجیستری خود ما روی ibel.ai نصب میشود، چون رجیستریهای عمومی از داخل ایران قابل اتکا نیستند. با Terraform نسخهٔ ۱.۵ به بعد و OpenTofu نسخهٔ ۱.۶ به بعد کار میکند.
terraform {
required_providers {
cloudhost = {
source = "ibel.ai/cloudhost/cloudhost"
}
}
}
provider "cloudhost" {}ورود#
یک کلید API ایجاد کنید (داشبورد، تنظیمات، کلیدهای API؛ یا cloudhost keys create) و در محیط به پرووایدر بدهید. بدون آن، پرووایدر کلیدی را که cloudhost login ذخیره کرده به کار میبرد.
export CLOUDHOST_API_KEY=chk_live_…
terraform init
terraform plan| تنظیم | پیشفرض |
|---|---|
api_key | CLOUDHOST_API_KEY، بعد کلید cloudhost login |
api_url | CLOUDHOST_API_URL، بعد https://api.ibel.ai |
viewer و billing فقط میخواند؛ اعضای تیم و وبهوکها نقش admin میخواهند و تغییر نقش یک عضو owner. هر کلید مال یک تیم است و همهچیز در همان تیم ایجاد میشود.منابع#
هر منبع یک data source همنام دارد که چیزی را که از قبل هست میخواند، و هر منبع را میشود با terraform import به state آورد.
| منبع | چه ایجاد میکند | شناسهٔ import |
|---|---|---|
cloudhost_project | یک فانکشن یا برنامه (kind)؛ تغییر نام درجا | <name> |
cloudhost_environment_variable | یک متغیر محیطی برای محیطها یا یک شاخه؛ plain یا sensitive | <project>/<KEY> |
cloudhost_domain | یک دامنهٔ اختصاصی؛ رکوردهای DNS در records | <domain> |
cloudhost_database | یک دیتابیس SQL؛ رمز و رشتهٔ اتصال یک بار | <name> |
cloudhost_cache | یک کش برای هر کلاینت کش و HTTP؛ توکن یک بار | <name> |
cloudhost_bucket | یک باکت؛ کلید ذخیرهسازی تیم با باکت اول | <name> |
cloudhost_alert | یک قاعدهٔ هشدار؛ هر تغییر قاعده را از نو ایجاد میکند | <id> |
cloudhost_team_member | یک دعوت، تا عضو شدن؛ نقش و محدودیت به پروژهها | <email> |
cloudhost_webhook | یک وبهوک امضاشده برای تیم یا یک پروژه؛ secret یک بار | <id> |
یک پروژهٔ کامل#
resource "cloudhost_project" "api" {
name = "shop-api"
kind = "function"
}
resource "cloudhost_database" "shop" {
name = "shop"
}
resource "cloudhost_cache" "sessions" {
name = "shop-sessions"
max_memory_mb = 128
}
resource "cloudhost_environment_variable" "database_url" {
project = cloudhost_project.api.name
key = "DATABASE_URL"
value = cloudhost_database.shop.connection_string
type = "sensitive"
}
resource "cloudhost_domain" "api" {
project = cloudhost_project.api.name
name = "api.example.ir"
}
resource "cloudhost_alert" "errors" {
project = cloudhost_project.api.name
metric = "error_rate"
op = ">"
threshold = 0.05
channels = { email = true }
}
resource "cloudhost_webhook" "deploys" {
url = "https://hooks.example.ir/deploys"
events = ["deployment.ready", "deployment.failed"]
project = cloudhost_project.api.name
}
output "dns_records" {
value = [for r in cloudhost_domain.api.records : "${r.host} ${r.type} ${r.value}"]
}کد را همچنان با cloudhost deploy یا git push منتشر کنید؛ Terraform چیزی را ایجاد میکند که کد روی آن اجرا میشود. متغیر محیطی جدید بیدرنگ اعمال میشود و استقرار جدید لازم ندارد.
سکرتها در state#
رمز دیتابیس، توکن کش، secret ذخیرهسازی و secret امضای وبهوک را API فقط یک بار، هنگام ایجاد، نشان میدهد. پرووایدر آنها را در state نگه میدارد تا منابع دیگر به کارشان ببرند؛ state را جایی نگه دارید که فقط تیم شما بخواند، و رمزنگاریشده.
- بعد از import این مقدارها معلوم نیستند. برای دیتابیس،
password_rotationرا عوض کنید تا رمز جدید بگیرید. - مقدار متغیر
sensitiveهرگز برنمیگردد؛ Terraform همان مقدار پیکربندی را نگه میدارد. مقدارplainخوانده میشود و تغییرش بیرون از Terraform در plan دیده میشود.
آنچه درجا عوض نمیشود#
- دیتابیس، کش و باکت درجا تغییر نمیکنند:
max_memory_mbدیگر یعنی کش جدید و خالی. plan را بخوانید. - دیتابیس، کش یا باکتی که نسخهٔ زندهای به آن متصل است حذف نمیشود؛ باکتی که آبجکت دارد هم. اول اتصال را بردارید (بدون آن مستقر کنید) یا باکت را خالی کنید.
- هشدار بهروزرسانی ندارد: قاعدهٔ عوضشده از نو ایجاد میشود.
- عضو تیم با دعوت میآید؛ تا دعوت را نپذیرفته،
statusبرابرinvitedاست. تغییر نقش یک دعوت، آن را پس میگیرد و دوباره میفرستد. - پروژهٔ وبهوک درجا عوض نمیشود: وبهوک و secret جدید.