كل إعداد Terraform غير بديهي يحتاج إلى قراءة العالم قبل أن يتمكن من تغييره. تحتاج إلى معرف أحدث صورة Amazon Linux قبل إطلاق نسخة EC2. تحتاج إلى ARN شهادة تديرها فريق آخر قبل إرفاقها بموازن التحميل. تحتاج إلى كتل CIDR لشبكة VPC أُنشئت منذ ستة أشهر — قبل وجود وحدتك بكثير. وهذا بالضبط ما تحله مصادر البيانات (data sources).
مصدر البيانات هو استعلام للقراءة فقط ضد API المزود أو ملف الحالة. صرّح به بكتلة data، وأشر إلى سماته تماماً كما تفعل مع مورد، وسيبني Terraform حافة التبعية الصحيحة تلقائياً. فهم مصادر البيانات — وكيف يستخدمها رسم بياني الموارد في Terraform — هو ما يُفرّق بين المهندسين الذين يكتبون إعدادات تجريبية والمهندسين الذين يديرون بنية تحتية إنتاجية على نطاق واسع.
كتلة data
تمتلك كتلة data نفس هيكل resource: نوع، واسم محلي، وجسم من وسيطات التصفية. يحل المزود الاستعلام في وقت التخطيط ويكشف كل سمة للكائن المتطابق بصيغة data.<type>.<name>.<attribute>.
# جلب أحدث صورة Amazon Linux 2023 المملوكة من Amazon
data "aws_ami" "al2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# استخدامها — يحل Terraform معرف الصورة في وقت التخطيط
resource "aws_instance" "web" {
ami = data.aws_ami.al2023.id
instance_type = "t3.medium"
tags = { Name = "web-server" }
}
# --- البحث عن شبكة VPC موجودة بالوسم (أُنشئت خارج Terraform) ---
data "aws_vpc" "shared" {
tags = {
Name = "platform-vpc"
Environment = var.environment
}
}
# استخدام مصدر بيانات VPC لاشتقاق قائمة CIDR للشبكات الفرعية
data "aws_subnets" "private" {
filter {
name = "vpc-id"
values = [data.aws_vpc.shared.id]
}
tags = { Tier = "private" }
}
resource "aws_db_subnet_group" "main" {
name = "main-db-subnet-group"
subnet_ids = data.aws_subnets.private.ids
}
مصادر البيانات تُنفَّذ في وقت التخطيط، وليس وقت التطبيق. هذا يعني أنه إذا لم يكن المورد المُستعلَم موجوداً بعد — مثلاً سر سيُنشئه مكدس Terraform آخر لاحقاً — فإن التخطيط سيفشل. صمّم مكداتك بحيث تستهدف مصادر البيانات دائماً كائنات موجودة بالفعل. استخدم depends_on أو قسّم تطبيقك إلى مراحل مُرتّبة عند الحاجة إلى ترتيب بين المكدسات.
أنماط مصادر البيانات الشائعة
الأنماط الثلاثة التي ستستخدمها في كل مشروع هي: (1) جلب معرفات ديناميكية مثل الصور والشهادات، (2) استيراد طوبولوجيا VPC المشتركة التي يديرها فريق المنصة، (3) قراءة المخرجات من ملف حالة Terraform آخر عبر terraform_remote_state.
# النمط 1 — جلب شهادة ديناميكية (ACM)
data "aws_acm_certificate" "api" {
domain = "api.example.com"
statuses = ["ISSUED"]
most_recent = true
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.api.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificate_arn = data.aws_acm_certificate.api.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.api.arn
}
}
# النمط 2 — قراءة الحالة البعيدة لفريق المنصة
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "mycompany-terraform-state"
key = "network/terraform.tfstate"
region = "us-east-1"
}
}
# الوصول لأي مخرج صدّره مكدس الشبكة
locals {
vpc_id = data.terraform_remote_state.network.outputs.vpc_id
private_subnets = data.terraform_remote_state.network.outputs.private_subnet_ids
}
# النمط 3 — هوية المُستدعي (مفيدة للتسمية وـ IAM)
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
locals {
account_id = data.aws_caller_identity.current.account_id
region = data.aws_region.current.name
# بناء بادئة ARN دون ترميز الحساب/المنطقة
log_group_arn = "arn:aws:logs:${local.region}:${local.account_id}:log-group:/app/web"
}
التبعيات الضمنية والرسم البياني للموارد
لا يُنفّذ Terraform الموارد من الأعلى إلى الأسفل. بدلاً من ذلك، يبني رسماً بيانياً موجّهاً لا دوري (DAG) — رسم بياني الموارد — بتحليل كل مرجع في إعدادك. عندما يُشير مورد B إلى resource_a.foo.id، يرسم Terraform حافة من A إلى B، ضامناً إنشاء A قبل B. يحدث هذا تلقائياً من المراجع؛ وبالكاد تحتاج إلى التصريح به صراحةً.
يمتلك الرسم البياني ثلاثة أنواع من العُقد: عقد المزود (تُهيئ عميل API لـ AWS أو GCP أو Vault)، وعقد الموارد (كائنات البنية التحتية الحقيقية)، وعقد البيانات (استعلامات للقراءة فقط). يتجول Terraform عبر الرسم البياني بالتوازي: العقد المستقلة تعمل في آنٍ واحد؛ العقد المعتمدة تنتظر. في إعداد كبير، هذا التوازي — المُتحكَّم به بـ -parallelism=N (افتراضي 10) — هو ما يجعل Terraform سريعاً رغم إدارة مئات الموارد.
الرسم البياني لموارد Terraform لمكدس ويب نموذجي — تُستعلَم عقد البيانات (الزرقاء) أولاً؛ وتُنشأ عقد الموارد (الخضراء) بترتيب التبعية؛ ونسخة قاعدة البيانات تنتظر كلاً من مجموعة الشبكات الفرعية ونسخة EC2.
فحص الرسم البياني
يمكنك تجسيد الرسم البياني في أي وقت بـ terraform graph، الذي يُخرج صيغة DOT. مرّره إلى Graphviz لإنتاج PNG ومراجعة ترتيب العقد قبل تطبيق عالي المخاطر:
استخدم terraform graph أثناء مراجعة الكود في كل طلب سحب كبير. حافة تبعية مفقودة تعني أن مورديْن يجب أن يكونا متسلسلَيْن سيعملان بالتوازي، مما يتسبب في أعطال متقطعة بسبب ظروف التسابق يصعب إعادة إنتاجها. الرسم البياني يُجعل افتراضات الترتيب غير المرئية صريحةً. في Google وAmazon، تطلب فرق المنصة مراجعة الرسم البياني كجزء من قائمة تدقيق قبول وحدة Terraform.
التبعيات الصريحة مع depends_on
يستنتج رسم Terraform البياني التبعيات من المراجع، لكن ليس من الآثار الجانبية. إذا كان مورد B يستلزم تطبيق مورد A مسبقاً — رغم أن B لا يُشير مباشرةً إلى أي من سمات A — فيجب عليك التعبير عن ذلك بـ depends_on. المثال الكلاسيكي هو سياسة دور IAM التي يجب أن تنتشر قبل أن تتمكن دالة Lambda من التنفيذ.
resource "aws_iam_role_policy_attachment" "lambda_exec" {
role = aws_iam_role.lambda.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "processor" {
function_name = "event-processor"
role = aws_iam_role.lambda.arn
# ...
# تتكاثر تغييرات IAM بشكل غير متزامن — قد تفشل الدالة
# في البدء إذا لم يُرفَق السياسة بالكامل بعد.
# depends_on يجبر Terraform على الانتظار رغم إشارتنا بالفعل إلى
# aws_iam_role.lambda.arn (الذي لا يضمن وجود الإرفاق).
depends_on = [aws_iam_role_policy_attachment.lambda_exec]
}
# depends_on يعمل أيضاً على مصادر البيانات — يجبر مصدر بيانات
# على إعادة القراءة بعد إنشاء مورد محدد:
data "aws_secretsmanager_secret_version" "db_pass" {
secret_id = aws_secretsmanager_secret.db.id
depends_on = [aws_secretsmanager_secret_version.db_initial]
}
الإفراط في استخدام depends_on يُفسد توازي Terraform. كل حافة غير ضرورية تُسلسل عملاً كان يمكن تشغيله بالتوازي، وترفع وقت التطبيق. والأخطر، أن depends_on على وحدة يجبر كل مورد داخل تلك الوحدة على الانتظار — حتى الموارد التي لا علاقة منطقية لها بالتبعية. أضف الحواف الصريحة فقط عندما يعجز Terraform فعلاً عن استنتاج الترتيب من المراجع وحدها.
نمط فشل إنتاجي: مصادر بيانات قديمة
تُعاد تقييم مصادر البيانات في كل plan وapply. إذا تغيّر الكائن المصدر بين تطبيقَيْن — مثلاً دوّر فريق الأمان شهادة ACM، أو غيّر فريق المنصة تخصيصات CIDR لـ VPC — فإن تخطيطك التالي سيرى القيمة الجديدة. هذا صحيح في الغالب، لكنه قد يُسبّب مفاجآت: معرف صورة جديد يُعيده most_recent = true سيجبر على استبدال كل نسخة EC2 تُشير إليه. في الإنتاج، ثبّت معرفات الصور بإضافة name_regex يلتقط مستوى رقعة محدداً، أو استخدم filter على وسم image-id الذي تضعه خطوط أنابيب الصور الذهبية. لا تستخدم أبداً most_recent = true على الصور في الإنتاج دون خطة رجوع مُختبَرة.
في الدرس التالي، ستستكشف الوسيطات التعريفية — count وfor_each وlifecycle — التي تتيح لك التعبير عن التكرار وسياسات دورة حياة الموارد داخل كتلة واحدة، مُزيلاً التكرار على نطاق واسع.
نستخدم ملفات تعريف الارتباط لتشغيل هذا الموقع وتحليل الزيارات وعرض إعلانات مخصّصة. يمكنك قبول كل ملفات تعريف الارتباط أو رفض غير الأساسية منها.
سياسة الخصوصية