برنامه نویسی

با استفاده از اسکریپت Terraform یک وب سایت استاتیک با گواهی Route53، CloudFront و AWS ایجاد کنید.

Summarize this content to 400 words in Persian Lang
اتوماسیون در این سمت از دنیای ما ملکه است، هر چه بیشتر کارهای خود را بتوانید خودکار کنید، بهتر است.

استفاده از Terraform برای مهندسین ابر برای خودکارسازی استقرار زیرساخت شما بسیار ضروری است. Terraform یک زیرساخت به عنوان ابزار کد است که به شما امکان می‌دهد منابع زیرساختی را در فایل‌های پیکربندی قابل خواندن برای انسان تعریف کنید که می‌توانید آن‌ها را نسخه‌سازی کنید، دوباره استفاده کنید و به اشتراک بگذارید. سپس می توانید از یک گردش کار ثابت برای تهیه و مدیریت ایمن و کارآمد زیرساخت خود در طول چرخه عمر آن استفاده کنید.

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

برای شروع من یک را ایجاد خواهم کرد main.tf فایل و الف provider.tf فایل برای ماژول ریشه من. اولین کار این است که ارائه دهنده AWS را برای Terraform پیکربندی کرده و برای آماده سازی آن برای استقرار منابع AWS آماده سازی اولیه کنید.

یک ارائه دهنده توسط Terraform برای ارتباط با API هر زیرساختی که می خواهید بسازید استفاده می شود. از آنجایی که ما در تلاش برای ایجاد زیرساخت AWS هستیم، از زیرساخت AWS برای پیکربندی خود استفاده خواهیم کرد. اگر در GCP یا Azure می‌سازید، از یک ارائه‌دهنده برای آن خدمات ابری استفاده خواهید کرد.

در provider.tf فایل من بلوک terraform و همچنین بلوک ارائه دهنده را اضافه می کنم، بلوک کد terraform به terraform اجازه می دهد تا از API AWS زیرساخت ما را بسازد در حالی که بلوک ارائه دهنده ارائه دهنده AWS را با اعتبارنامه های لازم پیکربندی می کند.

در provider.tf فایل خطوط کد زیر را اضافه کنید:

terraform {
required_providers {
aws = {
source = “hashicorp/aws”
}
}
}

provider “aws” {
region = “us-east-1”
shared_credentials_files = [“~/.aws/credentials”] }

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکته مهم در مورد terraform این است که شما مجبور نیستید هیچ یک از این کدها را به خاطر بسپارید زیرا به تازگی با terraform شروع می کنید، همیشه می توانید برای کمک به مستندات Terraform مراجعه کنید.

در بلوک terraform من AWS را به عنوان ارائه دهنده مورد نیاز با منبع به عنوان مشخص کردم hashicorp/aws اما من حذف کردم version آرگومان چون من مایلم terraform آخرین نسخه را هر زمان که مقداردهی اولیه شد دانلود کند.

بلوک ارائه دهنده اطلاعات مورد نیاز برای دسترسی خاص به AWS را فراهم می کند. در بلوک ارائه دهنده من را مشخص کردم region استدلال، این تنها اعتباری است که من در پیکربندی خود کدگذاری خواهم کرد. همانطور که قبلاً اعتبارنامه AWS خود را با استفاده از آن تنظیم کرده ام AWS configure با AWS CLI اضافه کردم shared_credentials_file آرگومان (اگر چندین نمایه دارید، مطمئن شوید که آن را درج کرده اید profile آرگومان کنید و نام نمایه را ارائه دهید) بنابراین Terraform از این اطلاعات برای دریافت این اعتبارنامه ها و استفاده از آنها برای ساخت زیرساخت استفاده می کند.

برای راهنمایی در مورد نحوه پیکربندی اعتبارنامه AWS خود در AWS CLI، این پست من را بررسی کنید، جایی که من شما را در این فرآیند راهنمایی می کنم.

حالا من آماده اجرای یک هستم terraform init پروژه را مقداردهی اولیه کنید تا terraform بتواند ارائه دهنده مورد نیاز این پروژه را دانلود کرده و به AWS متصل شود.

مطمئن شوید که در دایرکتوری پروژه خود هستید و دستور زیر را در ترمینال خود اجرا کنید:

terraform init

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

ماژول ها یک راه عالی برای دنبال کردن هستند Don’t Repeat Yourself (DRY) اصل توسعه نرم افزار که بیان می کند کد باید یک بار نوشته شود و تکرار نشود. ماژول ها مجموعه ای از فایل های پیکربندی Terraform را در بر می گیرند که برای خدمت به یک هدف خاص ایجاد شده اند.

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

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

ما پیکربندی خود را به صورت ماژول می نویسیم و سپس ماژول ها را برای ساخت پیکربندی اجرا می کنیم.

توصیه می شود ماژول ها را در a قرار دهید modules دایرکتوری زمانی که ماژول ها را به صورت محلی توسعه می دهید، اما می توانید آن را هر چه دوست دارید نام گذاری کنید.

برای شروع من ایجاد کردم Modules دایرکتوری، اینجا جایی است که تمام ماژول های من در آن قرار می گیرند.

برای ماژول سطل S3 خود، دایرکتوری به نام ایجاد کردم s3-bucket در Modules فهرست راهنما. در این دایرکتوری من فایل های زیر را ایجاد می کنم main.tf، variables.tf، output.tf.

سطل S3 ایجاد کنید

modules/s3-bucket/variables.tf

در variables.tf من نام سطل را به عنوان یک متغیر با کد زیر تعریف می کنم:

variable “bucket-name” {
description = “The name of the S3 bucket”
type = string

validation {
condition = (
length(var.bucket-name) >= 3 && length(var.bucket-name) = 63 &&
can(regex(“^[a-z0-9][a-z0-9-.]*[a-z0-9]$”, var.bucket-name))
)
error_message = “The bucket name must be between 3 and 63 characters, start and end with a lowercase letter or number, and can contain only lowercase letters, numbers, hyphens, and dots.”
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اعتبارسنجی به سادگی بررسی می کند که نام سطل بین 3 تا 63 کاراکتر باشد، با یک حرف یا عدد کوچک شروع و پایان یابد و فقط شامل حروف کوچک، اعداد، خط تیره و نقطه باشد. این برای جلوگیری از هرگونه خطایی که ممکن است AWS در نتیجه نامگذاری اشتباه سطل ایجاد کند، ضروری است.

اهمیت استفاده از یک فایل متغیر برای سادگی و بازسازی آسان کد است. در صورتی که ما نیاز به تغییر مقدار آن متغیر داشته باشیم، فقط باید آن را در یک مکان تغییر دهیم و این تغییر در هر جایی که آن متغیر به استفاده از .var نشانه گذاری.

modules/s3-bucket/main.tf

اکنون به ایجاد سطل S3، ما آن را اضافه می کنیم aws_s3_bucket بلوک منابع به ماژول main.tf مطابق شکل زیر فایل کنید.

# Create S3 Bucket
resource “aws_s3_bucket” “site-bucket” {
bucket = var.bucket-name
force_destroy = true
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نام سطل توسط یک متغیر عرضه می شود و در هنگام ایجاد با مقدار جایگزین می شود.

modules/s3-bucket/outputs.tf

این فایلی است که در آن برخی از مقادیری را که در بقیه تنظیمات خود استفاده خواهیم کرد، خروجی خواهیم داد.

ادامه دهید و یک فایل جدید به نام ایجاد کنید outputs.tf در ماژول سطل s3 کد زیر را به فایل اضافه کنید:

output “bucket_regional_domain_name” {
description = “This is the bucket domain name including the region name.”
value = aws_s3_bucket.site-bucket.bucket_regional_domain_name
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

S3 Bucket را به Root Module اضافه کنید

main.tf

برای آزمایش اینکه این ماژول کار می کند، با استفاده از این ماژول که به تازگی نوشته ایم، یک سطل s3 ایجاد می کنیم. به سمت main.tf فایل ماژول ریشه شما، خارج از شما Module دایرکتوری و کد زیر را در فایل وارد کنید.

module “s3-bucket” {
source = “./Modules/s3-bucket”
bucket-name = var.bucket-name
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

متغیرها.tf

سه فایل جدید نیز در ماژول ریشه خود به نام ایجاد کنید variables.tf، outputs.tf و terraform.tfvars.

در variables.tf کد زیر را اضافه کنید

variable “bucket-name” {
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی ها.tf

در outputs.tf کد زیر را اضافه کنید:

output “bucket-name” {
value = module.s3-bucket.site-bucket.bucket_regional_domain_name
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما از این خروجی هنگام ایجاد توزیع ابری خود استفاده خواهیم کرد.

terraform.tfvars

در terraform.tfvars فایل، کد زیر را وارد کنید:

bucket-name = ”

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

⚠️ توجه داشته باشید

شما .tfvars فایل هرگز نباید به کنترل نسخه متعهد شود، این فایل را به فایل خود اضافه کنید .gitignore فایل. من را بررسی کنید .gitignore فایل هایی را برای افزودن به فایل های شما تشکیل دهید.

همچنین می توانید از این سایت برای تولید فایل های gitignore خود برای این پروژه و پروژه های آینده استفاده کنید.

در ترمینال خود، را اجرا کنید terraform init مجدداً دستور، هنگام اضافه کردن یک ماژول یا تغییر ارائه دهنده، باید دستور را دوباره اجرا کنید. اگر آن را اجرا نکنید و هر دستور terraform دیگری را اجرا نکنید، با پیغام خطای زیر مواجه خواهید شد.

حالا می توانید بدوید terraform plan تا ببینید terraform قصد دارد در حساب AWS شما چه چیزی ایجاد کند.

برای ایجاد سطل، اجرا کنید

terraform apply

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر زمان که این دستور را اجرا می کنید، terraform همیشه از شما می پرسد که آیا می خواهید این عمل را انجام دهید، می توانید یا بله یا خیر پاسخ دهید. برای جلوگیری از مطرح شدن این سوال، می توانید مستقیماً آن را وارد کنید auto approve در دستور مطابق شکل زیر:

terraform apply –auto-approve

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر به درستی دنبال می‌کردید، با موفقیت یک سطل s3 ایجاد می‌کردید، ما آن را از بین می‌بریم و به نوشتن اسکریپت terraform خود ادامه می‌دهیم، زیرا ما فقط یک سطل نمی‌سازیم.

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

terraform destroy

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نام مستعار TF برای Terraform

قبل از اینکه ادامه دهیم، می‌خواهم یک نام مستعار کوتاه برای terraform بگذارم، زیرا ما باید به‌طور کلی آن را terraform بنامیم. تنظیم نام مستعار terraform to be tf هنگامی که ما در حال فراخوانی دستورات خود هستیم، کارها را برای ما ساده می کند، بنابراین دیگر نیازی به فراخوانی صریح نخواهیم داشت. terraform اما اکنون ما آن را صدا می کنیم tf به عنوان مثال tf apply بجای terraform apply. این به ما کمک می کند فرمان خود را کوتاه کنیم.

ما می توانیم این کار را با تنظیم یک نام مستعار در پروفایل bash انجام دهیم.

برای باز کردن پروفایل bash برای ترمینال، از دستور زیر استفاده کردم:

vi ~/.bash_profile

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اینجاست که می‌توانیم پیکربندی‌های bash را تنظیم کنیم، نام مستعار خود را با فراخوانی نام مستعار با شکل کوتاه همانطور که دیده می‌شود تنظیم می‌کنیم:

alias tf=”terraform”

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون برای استفاده از دستوری که به عنوان نام مستعار تنظیم کرده ایم، باید ابتدا اسکریپت پروفایل bash را اجرا کنیم تا تغییر اعمال شود.

source ~/.bash_profile

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا می توانیم به جای terraform از tf استفاده کنیم

دارایی ها را در سطل S3 آپلود کنید

قبل از نوشتن کد برای آپلود دارایی های وب سایت خود در سطل، باید یک دایرکتوری ایجاد کرده و دارایی های خود را ذخیره کنیم. من این را در ماژول ریشه خود ذخیره خواهم کرد web-assets و دارایی های وب سایت من را در آنجا اضافه کنید.

modules/s3-bucket/main.tf

ما استفاده خواهیم کرد for_each آرگومان های متا برای آپلود دارایی های سطل خود، ما از این روش استفاده می کنیم زیرا چندین فایل برای آپلود داریم. این زمانی مفید است که چندین منبع با تنظیمات مشابه ایجاد کنید.

منطقی نیست که فقط بلوک های منابع Terraform را با تغییرات جزئی در هر بلوک کپی و جایگذاری کنید. انجام این کار فقط بر خوانایی تأثیر می گذارد و فایل های پیکربندی IaC را به طور غیر ضروری طولانی می کند. کد زیر را به ماژول s3-bucket خود اضافه کنید main.tf فایل:

# Upload objects into the s3 Bucket
resource “aws_s3_object” “upload-assets” {
for_each = fileset(“${var.web-assets-path}”, “**/*”)
bucket = aws_s3_bucket.site-bucket.bucket
key = each.value
source = “${var.web-assets-path}/${each.value}”
content_type = lookup(var.mime_types, regex(“\\.[^.]+$”, each.value), “application/octet-stream”)
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این for-each از طریق فایل های موجود در فهرست وب سایت تکرار می شود. من استفاده کردم fileset تابع برای تکرار بر روی همه فایل ها و دایرکتوری ها در مسیر مشخص شده، هر فایل/دایرکتوری را برای حلقه for_each در تعریف منبع در دسترس قرار می دهد.

مسیر سخت کدگذاری نشده است، به عنوان یک متغیر در تعریف شده است variable.tf فایل را همانطور که در زیر مشاهده خواهید کرد.

این for_each حلقه روی fileset مسیرهای فایل را برمی گرداند، نه جفت های کلید-مقدار، به همین دلیل است که از آن استفاده می کنیم each.value به عنوان کلید ما و نه each.key.

ما می خواهیم که وب سایت هر نوع فایل را برای نوع MIME مربوطه تشخیص دهد و آن را به درستی در وب سایت نمایش دهد، به همین دلیل از lookup عملکرد در content_type بحث و جدل. lookup(map, key, default) تابعی است که کلید را در نقشه جستجو می کند و در صورت یافتن مقدار مربوطه را برمی گرداند. اگر کلید پیدا نشد، به طور پیش فرض برمی گردد.

تابع regex پسوند فایل را از each.value استخراج می‌کند، که نام فایلی است که از مجموعه فایل‌های دیگر برای تعیین نوع MIME دقیق‌تر به‌دست می‌آید.

modules/s3-bucket/variables.tf

در اینجا متغیرهایی را که در قطعه کد بالا فراخوانی کرده ایم تعریف می کنیم، کد زیر را به فایل اضافه می کنیم:

# Set the variable for the file path of the files to be uploaded to the bucket
variable “web-assets-path” {
description = “This is the location of our website files”
type = string
}

variable “mime_types” {
description = “Map of file extensions to MIME types”
type = map(string)
default = {
“.html” = “text/html”
“.css” = “text/css”
“.png” = “image/png”
“.jpg” = “image/jpeg”
“.jpeg” = “image/jpeg”
“.pdf” = “application/pdf”
“json” = “application/json”
“js” = “application/javascript”
“gif” = “image/gif”
# Add more extensions and MIME types as needed
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ماژول ریشه را به روز کنید main.tf، variable.tf و terraform.tfvars فایل ها

main.tf

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

module “s3-bucket” {
source = “./Modules/s3-bucket”
bucket-name = var.bucket-name
web-assets-path = var.web-assets-path
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

متغیر.tf

ماژول ریشه شما variable.tf اکنون فایل باید به شکل زیر باشد:

variable “bucket-name” {
type = string
}

variable “web-assets-path” {
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

terraform.tfvars

ماژول ریشه شما terraform.tfvars اکنون فایل باید به شکل زیر باشد:

bucket-name = ”
web-assets-path = ”

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

⚠️ توجه داشته باشید

حتی اگر شما هنوز واجد شرایط سطح رایگان AWS هستید، سرویس Route53 هرگز رایگان نیست. این منطقه میزبان هزینه 0.50 دلار در ماه را جذب می کند.

برای این مرحله به یک نام دامنه سفارشی نیاز دارید، بنابراین اگر قبلاً آن را ندارید، مکث کنید، آن را دریافت کنید و ادامه دهید.

این مرحله قرار است به صورت دستی تکمیل شود، در ابتدا می‌خواستم پس از ایجاد دستی منبع را به terraform وارد کنم، اما پس از بررسی بیشتر، دلیلی نداریم زیرا نمی‌خواهم Terraform منطقه میزبان را حذف کند.

دلیل ایجاد منطقه میزبان به صورت دستی این است که وقتی یک منطقه میزبانی شده ایجاد می کنید، مجموعه جدیدی از سرورهای نام به شما داده می شود که باید آنها را به پیکربندی دامنه سفارشی خود اضافه کنید. Terraform زیرساخت لازم برای تکمیل این مرحله را ندارد و بنابراین پیکربندی شما تا زمانی که خودتان سرورهای نام خود را به صورت دستی به دامنه سفارشی خود اضافه نکنید، ناموفق خواهد بود.

از آنجایی که ما قبلاً این را می دانیم، منطقه میزبان را به صورت دستی ایجاد می کنیم، سرورهای نام را به دامنه سفارشی خود اضافه می کنیم و سپس با استفاده از terraform data منبع، جزئیات منطقه میزبانی شده ایجاد شده را در Terraform بازیابی کنید تا از هر گونه مشکلی که ممکن است به وجود آمده باشد جلوگیری کنید.

ایجاد منطقه میزبانی شده

کنسول مدیریت AWS خود را باز کنید.
که در Services زیر Network and Content delivery دسته را انتخاب کنید Route53

انتخاب کنید create hosted zone

از آنجا بسیار ساده است، نام دامنه خود را در فضای برای وارد کنید domain name.
انتخاب کنید public hosted zone زیر type.
در صورت تمایل می توانید یک برچسب و توضیحات اضافه کنید.
در پایین صفحه بر روی آن کلیک کنید create hosted zone.

هنگامی که منطقه میزبان شما ایجاد شد، آن را برای مشاهده جزئیات باز کنید و سرورهای نام ارائه شده توسط AWS را کپی کنید.
هر سرور نام را کپی کنید و آنهایی که قبلاً در نام دامنه ما هستند را با این سرورهای جدید جایگزین کنید.

جزئیات منبع منطقه میزبانی شده را در پیکربندی Terraform بازیابی کنید

برای اضافه کردن جزئیات منبع منطقه میزبانی شده خود به terraform، ما یک ماژول جدید در آن ایجاد خواهیم کرد Module دایرکتوری فراخوانی شد route53.

Modules/route53/main.tf

کد زیر را به فایل اضافه کنید:

# Retrieve information about your hosted zone from AWS
data “aws_route53_zone” “created” {
name = var.domain_name
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا ممکن است زیاد به نظر نرسد اما جزئیات منطقه میزبانی شده را در حساب AWS ما بازیابی می کند که با نامی که ارائه می کنیم مطابقت دارد و سپس از آن در هر کجا که آن را صدا می کنیم استفاده می کند. data منبع در پیکربندی ما

Modules/route53/variables.tf

شما مته را می شناسید، متغیرهای اعلام شده را اضافه کنید تا کد شما قابل استفاده مجدد باشد.

# domain name variable
variable “domain_name” {
description = “This is the name of the hosted zone.”
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این یک فرآیند یک مرحله‌ای در terraform نیست، ابتدا باید منبع را ایجاد کنیم و سپس آن را با یک بلوک منبع دیگر تأیید کنیم.

گواهی ایجاد کنید

ما گواهینامه خود را قبل از توزیع ابری خود ایجاد می کنیم زیرا از گواهی SSL خود در توزیع ابری خود استفاده می کنیم.

طبق معمول، یک را ایجاد کنید certificate دایرکتوری در Module دایرکتوری که ماژول گواهی ما را در خود جای می دهد. 3 فایل جدید در آن دایرکتوری ایجاد کنید main.tf، variable.tf و output.tf.

ماژول ها/گواهینامه/main.tf

# Create the TLS/SSL certificate
resource “aws_acm_certificate” “cert” {
domain_name = var.domain_name
validation_method = var.validation_method
subject_alternative_names = var.subject_alternative_names

# Ensure that the resource is rebuilt before destruction when running an update
lifecycle {
create_before_destroy = true
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/certificate/variables.tf

متغیرهای لازم را به فایل متغیرهای خود اضافه کنید:

variable “domain_name” {
description = “Domain name for which the certificate should be issued”
type = string
}

variable “validation_method” {
description = “Which method to use for validation.”
type = string
default = “DNS”
}

variable “subject_alternative_names” {
description = “Set of domains that should be SANs in the issued certificate.”
type = list(string)
default = [] }

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/certificate/outputs.tf

خروجی هایی را که باید در ماژول های دیگر ارجاع دهیم را تعریف کنید

output “cert-arn” {
value = aws_acm_certificate.cert.arn
}

output “domain_validation_options” {
value = aws_acm_certificate.cert.domain_validation_options
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

رکورد اعتبار سنجی گواهی ACM را ایجاد کنید

قبل از ایجاد منبع اعتبار گواهی، باید یک رکورد DNS در AWS Route 53 ایجاد کنیم که برای تأیید مالکیت دامنه برای گواهی AWS ACM استفاده می‌شود. جزئیات رکورد DNS (نام، مقدار، نوع) از گزینه های اعتبارسنجی دامنه گواهی ACM به دست می آید.

ما این رکورد را در route53 ایجاد خواهیم کرد، پس به سراغ خودتان بروید Modules/route53/main.tf فایل. موارد زیر را به فایل خود اضافه کنید:

Modules/route53/main.tf

# Create DNS record that will be used for our certificate validation
resource “aws_route53_record” “cert_validation” {
for_each = { for dvo in var.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
type = dvo.resource_record_type
record = dvo.resource_record_value
} }

name = each.value.name
type = each.value.type
records = [each.value.record] ttl = 60
zone_id = data.aws_route53_zone.created.zone_id
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا یک رکورد CNAME در منطقه میزبانی دامنه شما ایجاد می کند که برای تأیید اعتبار گواهی که ایجاد کرده اید استفاده می شود. با این حال، اگر همزمان سعی کنید کد ایجاد گواهی te و ایجاد رکورد را اعمال کنید، با یک پیغام خطایی شبیه به خط زیر مواجه خواهید شد.

به همین دلیل است که ما آن را اجرا خواهیم کرد terraform apply دستور در دو مرحله همانطور که در نهایت خواهید دید.

Modules/route53/variables.tf

موارد زیر را به فایل متغیرهای ماژول route53 خود اضافه کنید

variable “domain_validation_options” {
description = “The domain validation options from the ACM certificate.”
type = list(object({
domain_name = string
resource_record_name = string
resource_record_type = string
resource_record_value = string
}))
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

گواهینامه را تأیید کنید

این aws_acm_certificate منبع اعتبار سنجی گواهی را در Terraform انجام نمی دهد، ما باید از آن استفاده کنیم aws_acm_certificate_validation منبعی برای انجام آن

همانطور که قبلا توضیح دادم و از پیام خطا مشاهده کردید، ابتدا گواهینامه باید وجود داشته باشد و مقدار آن وجود داشته باشد domain_validation_options ابتدا شناخته شده قبل از terraform دستور for_each ما را ارج می نهد، به همین دلیل است که باید ابتدا گواهی را ایجاد کنیم، سپس رکورد و سپس تأیید کنیم.

به دلیل بالا، ما مرحله اعتبار سنجی را در ماژول گواهی قرار نمی دهیم، بلکه در ماژول Route53 قرار می دهیم. Route53 مدول.

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

Modules/route53/main.tf

# Validate the certificate
resource “aws_acm_certificate_validation” “validate-cert” {
certificate_arn = var.certificate_arn
validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]

depends_on = [aws_route53_record.cert_validation] }

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این depends_on آرگومان terraform را مجبور به ایجاد aws_route53_record.cert_validation قبل از تلاش برای تأیید اعتبار گواهی ما، ابتدا منبع را تهیه کنید.

Modules/route53/variables.tf

متغیرهای مورد نیاز را به فایل variables.tf ماژول اضافه کنید

variable “certificate_arn” {
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/route53/outputs.tf

موارد زیر را به فایل outputs.tf ماژول route53 خود اضافه کنید

output “dns_records” {
value = aws_route53_record.cert_validation
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما هنوز باید رکورد مستعار توزیع CloudFront را ایجاد کنیم، این رکوردی است که در آن نام دامنه توزیع cloudfront خود را به عنوان نام مستعار برای نام دامنه سفارشی خود تنظیم می کنیم. ما این کار را پس از ایجاد توزیع ابری خود انجام خواهیم داد.

اکنون می‌توانیم پیش برویم و توزیع ابری خود را ایجاد کنیم. ایجاد یک cloudfront دایرکتوری در Modules دایرکتوری و اضافه کردن ایجاد main.tf و variables.tf فایل های موجود در دایرکتوری

ایجاد کنترل دسترسی مبدا – OAC

اولین کاری که باید انجام دهیم این است که آن را ایجاد کنیم Origin Access Control ما در پیکربندی توزیع خود استفاده خواهیم کرد. این کار را با اضافه کردن کد زیر به خود انجام دهید main.tf فایل:

Modules/cloudfront/main.tf

# Create the access origin control that will be used in creating our cloudfront distribution with s3 origin
resource “aws_cloudfront_origin_access_control” “assign-oac” {
name = var.oac-name
description = “An origin access control with s3 origin domain for cloudfront”
origin_access_control_origin_type = var.origin_access_control_origin_type
signing_behavior = var.signing_behavior
signing_protocol = var.signing_protocol
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/cloudfront/variables.tf

متغیرها را اعلام کنید:

variable “oac-name” {
description = “This is the name of the cloudfront origin Access control with s3 bucket origin domain”
type = string
default = “s3-bucket-oac”
}

variable “origin_access_control_origin_type” {
description = “The origin type must be the same as the origin domain”
type = string
default = “s3”
}

variable “signing_behavior” {
description = “Specifies which requests CloudFront signs.”
type = string
default = “always”
}

variable “signing_protocol” {
description = “Determines how CloudFront signs (authenticates) requests.”
type = string
default = “sigv4” # The only valid value
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایجاد توزیع

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

Modules/cloudfront/main.tf

# Create CloudFront Distribution
resource “aws_cloudfront_distribution” “cdn” {
origin {
domain_name = var.cdn-domain_name-and-origin_id
origin_id = var.cdn-domain_name-and-origin_id
origin_access_control_id = aws_cloudfront_origin_access_control.assign-oac.id
}

default_cache_behavior {
compress = true
viewer_protocol_policy = “redirect-to-https”
allowed_methods = [ “GET”, “HEAD” ] cached_methods = [ “GET”, “HEAD” ] target_origin_id = var.cdn-domain_name-and-origin_id
min_ttl = 0
default_ttl = 3600
max_ttl = 86400

forwarded_values {
query_string = false
cookies {
forward = “all”
}
}
}

restrictions {
geo_restriction {
restriction_type = var.restriction_type
}
}

viewer_certificate {
acm_certificate_arn = var.acm_certificate_arn
ssl_support_method = “sni-only”
minimum_protocol_version = “TLSv1.2_2021”
cloudfront_default_certificate = false
}

enabled = true
is_ipv6_enabled = true
default_root_object = var.default_root_object
aliases = [var.domain_name, “www.${var.domain_name}”] }

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/cloudfront/variables.tf

متغیرهای مورد نیاز را اضافه کنید

variable “restriction_type” {
description = “Method that you want to use to restrict distribution of your content by country”
type = string
default = “none”
}

variable “default_root_object” {
description = “Object that you want CloudFront to return when an end user requests the root URL.”
type = string
default = “index.html”
}

variable “domain_name” {
description = “your custom Domain name for which the certificate should be issued”
type = string
}

variable “cdn-domain_name-and-origin_id” {
type = string
}

variable “acm_certificate_arn” {
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/cloudfront/outputs.tf

output “cloudfront-arn” {
value = aws_cloudfront_distribution.cdn.arn
}

output “cloudfront_domain_name” {
value = aws_cloudfront_distribution.cdn.domain_name
}

output “cloudfront_hosted-zone_id” {
value = aws_cloudfront_distribution.cdn.hosted_zone_id
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون باید مجوزهای سطل خاصی را اضافه کنیم، آن cloudfront باید بتواند به اندازه کافی با سطل s3 ما تعامل داشته باشد، به سطل s3 ما.

به ماژول سطل s3 خود برگردید.

Modules/s3-bucket/main.tf

این خط مشی است که به ما امکان دسترسی به توزیع ابری ما را به سطل s3 و شیء آن از طریق کنترل مبدا دسترسی آن می دهد.

کد زیر را به فایل main.tf ماژول سطل s3 اضافه کنید

Modules/s3-bucket/main.tf

# Add the permissions needed by cloudfront’s origin access control to access the bucket and it’s objects
resource “aws_s3_bucket_policy” “cloudfront-oac-policy” {
bucket = aws_s3_bucket.site-bucket.bucket
policy = jsonencode({
Version = “2012-10-17”,
Statement = [
{
Sid = “AllowCloudFrontServicePrincipal”,
Effect = “Allow”,
Principal = {
Service = “cloudfront.amazonaws.com”
},
Action = “s3:GetObject”,
Resource = “${aws_s3_bucket.site-bucket.arn}/*”,
Condition = {
StringLike = {
“aws:UserAgent” = “Amazon CloudFront”
}
}
}
] })
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما یک ماژول جدید ایجاد خواهیم کرد، به خصوص برای این، یک ماژول جدید به نام ایجاد می کنیم alias، دو فایل ایجاد کنید main.tf و variables.tf.

Modules/alias/main.tf

# Retrieve information about your hosted zone from AWS
data “aws_route53_zone” “created” {
name = var.domain_name
}

# Create an alias that will point to the cloudfront distribution domain name
resource “aws_route53_record” “alias” {
zone_id = data.aws_route53_zone.created.zone_id
name = var.domain_name
type = “A”

alias {
name = var.cloudfront_domain_name
zone_id = var.cloudfront-zone-id
evaluate_target_health = false
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/alias/variables.tf

متغیرهای لازم را طبق معمول اعلام کنید:

variable “domain_name” {
description = “your custom domain name”
type = string
}

variable “cloudfront_domain_name” {
type = string
}

variable “cloudfront-zone-id” {
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

ما قبلا ماژول s3-bucket خود را در اوایل پروژه زمانی که می خواستیم ماژول s3-bucket خود را آزمایش کنیم به main.tf خود اضافه کرده بودیم، اکنون بقیه ماژول های خود را به ماژول اضافه می کنیم. main.tf.

main.tf

پیکربندی نهایی شما در شما main.tf ماژول ریشه شما باید به شکل زیر باشد:

# Create S3 bucket, upload objects into the bucket and set bucket policy.
module “s3-bucket” {
source = “./Modules/s3-bucket”
bucket-name = var.bucket-name
web-assets-path = var.web-assets-path
}

# Create and validate TLS/SSL certificate
module “certificate” {
source = “./Modules/certificate”
domain_name = var.domain_name
subject_alternative_names = [“www.${var.domain_name}”] }

# Create OAC and cloudfront distribution,
module “cloudfront” {
source = “./Modules/cloudfront”
domain_name = var.domain_name
cdn-domain_name-and-origin_id = module.s3-bucket.bucket_regional_domain_name
acm_certificate_arn = module.certificate.cert-arn
depends_on = [ module.route53 ] }

# Import the hosted zone from AWS, create dns records for certificate validation, and create A and CNAME records.
module “route53” {
source = “./Modules/route53”
domain_name = var.domain_name
domain_validation_options = module.certificate.domain_validation_options
certificate_arn = module.certificate.cert-arn
}

# Create an alias to point the cloudfront cdn to our domain name.
module “alias” {
source = “./Modules/alias”
domain_name = var.domain_name
cloudfront_domain_name = module.cloudfront.cloudfront_domain_name
cloudfront-zone-id = module.cloudfront.cloudfront_hosted-zone_id
depends_on = [ module.cloudfront ] }

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

متغیرها.tf

اکنون متغیرهای لازم را اعلام می کنیم، فایل variable.tf نهایی شما باید به شکل زیر باشد:

variable “bucket-name” {
type = string
}

variable “web-assets-path” {
type = string
}

variable “domain_name” {
type = string
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

terraform.tfvars

اسرار خود را به خود اضافه کنید *.tfvars فایل مانند این:

bucket-name = ”
web-assets-path = “the path to your website files (best to supply the absolute path)>
domain_name = “”

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون همه ما آماده ایم که برنامه خود را مستقر کنیم.

ماژول ها را نصب کنید

اولین اجرا tf init برای نصب تمام ماژول های اضافه شده

tf init

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اعتبار سنجی پیکربندی

در مرحله بعد می توانید دستور validate را برای تایید پیکربندی خود اجرا کنید

tf validate

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایجاد زیرساخت

همانطور که قبلا توضیح دادم for_each تابع فقط روی مقادیری تکرار می‌شود که در آن زمان شناخته شده‌اند apply دستور این است، بنابراین اگر ما قبل از ایجاد گواهینامه خود را اعمال کنیم، terraform خطایی ایجاد می کند.

برای جلوگیری از این خطا در دو مرحله ابتدا با –target پرچم گذاری کنید و سپس کل پیکربندی را اعمال کنید.

اجرای اول:

tf apply –target module.certificate

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت، منابع باقی مانده را ایجاد کنید:

tf apply

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ساخت را تایید کنید

می توانید کنسول AWS خود را باز کنید تا ببینید که منابع ساخته شده اند.

مرورگر خود را باز کنید و به دامنه سفارشی خود بروید و خواهید دید که وب سایت شما نمایش داده می شود، اینجا مال من است.

به یاد داشته باشید که پس از اتمام کار، محیط خود را تمیز کنید. برای جلوگیری از صورتحساب غیر ضروری، منابع را در AWS در حال اجرا رها نکنید.

از دستور تخریب استفاده کنید:

tf destroy

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اتوماسیون در این سمت از دنیای ما ملکه است، هر چه بیشتر کارهای خود را بتوانید خودکار کنید، بهتر است.

استفاده از Terraform برای مهندسین ابر برای خودکارسازی استقرار زیرساخت شما بسیار ضروری است. Terraform یک زیرساخت به عنوان ابزار کد است که به شما امکان می‌دهد منابع زیرساختی را در فایل‌های پیکربندی قابل خواندن برای انسان تعریف کنید که می‌توانید آن‌ها را نسخه‌سازی کنید، دوباره استفاده کنید و به اشتراک بگذارید. سپس می توانید از یک گردش کار ثابت برای تهیه و مدیریت ایمن و کارآمد زیرساخت خود در طول چرخه عمر آن استفاده کنید.


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

برای شروع من یک را ایجاد خواهم کرد main.tf فایل و الف provider.tf فایل برای ماژول ریشه من. اولین کار این است که ارائه دهنده AWS را برای Terraform پیکربندی کرده و برای آماده سازی آن برای استقرار منابع AWS آماده سازی اولیه کنید.

یک ارائه دهنده توسط Terraform برای ارتباط با API هر زیرساختی که می خواهید بسازید استفاده می شود. از آنجایی که ما در تلاش برای ایجاد زیرساخت AWS هستیم، از زیرساخت AWS برای پیکربندی خود استفاده خواهیم کرد. اگر در GCP یا Azure می‌سازید، از یک ارائه‌دهنده برای آن خدمات ابری استفاده خواهید کرد.

در provider.tf فایل من بلوک terraform و همچنین بلوک ارائه دهنده را اضافه می کنم، بلوک کد terraform به terraform اجازه می دهد تا از API AWS زیرساخت ما را بسازد در حالی که بلوک ارائه دهنده ارائه دهنده AWS را با اعتبارنامه های لازم پیکربندی می کند.

در provider.tf فایل خطوط کد زیر را اضافه کنید:

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region = "us-east-1"
  shared_credentials_files = ["~/.aws/credentials"]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نکته مهم در مورد terraform این است که شما مجبور نیستید هیچ یک از این کدها را به خاطر بسپارید زیرا به تازگی با terraform شروع می کنید، همیشه می توانید برای کمک به مستندات Terraform مراجعه کنید.

در بلوک terraform من AWS را به عنوان ارائه دهنده مورد نیاز با منبع به عنوان مشخص کردم hashicorp/aws اما من حذف کردم version آرگومان چون من مایلم terraform آخرین نسخه را هر زمان که مقداردهی اولیه شد دانلود کند.

بلوک ارائه دهنده اطلاعات مورد نیاز برای دسترسی خاص به AWS را فراهم می کند. در بلوک ارائه دهنده من را مشخص کردم region استدلال، این تنها اعتباری است که من در پیکربندی خود کدگذاری خواهم کرد. همانطور که قبلاً اعتبارنامه AWS خود را با استفاده از آن تنظیم کرده ام AWS configure با AWS CLI اضافه کردم shared_credentials_file آرگومان (اگر چندین نمایه دارید، مطمئن شوید که آن را درج کرده اید profile آرگومان کنید و نام نمایه را ارائه دهید) بنابراین Terraform از این اطلاعات برای دریافت این اعتبارنامه ها و استفاده از آنها برای ساخت زیرساخت استفاده می کند.

برای راهنمایی در مورد نحوه پیکربندی اعتبارنامه AWS خود در AWS CLI، این پست من را بررسی کنید، جایی که من شما را در این فرآیند راهنمایی می کنم.

حالا من آماده اجرای یک هستم terraform init پروژه را مقداردهی اولیه کنید تا terraform بتواند ارائه دهنده مورد نیاز این پروژه را دانلود کرده و به AWS متصل شود.

مطمئن شوید که در دایرکتوری پروژه خود هستید و دستور زیر را در ترمینال خود اجرا کنید:

terraform init
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

tf-init


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

ماژول ها یک راه عالی برای دنبال کردن هستند Don't Repeat Yourself (DRY) اصل توسعه نرم افزار که بیان می کند کد باید یک بار نوشته شود و تکرار نشود. ماژول ها مجموعه ای از فایل های پیکربندی Terraform را در بر می گیرند که برای خدمت به یک هدف خاص ایجاد شده اند.

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

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

ما پیکربندی خود را به صورت ماژول می نویسیم و سپس ماژول ها را برای ساخت پیکربندی اجرا می کنیم.

توصیه می شود ماژول ها را در a قرار دهید modules دایرکتوری زمانی که ماژول ها را به صورت محلی توسعه می دهید، اما می توانید آن را هر چه دوست دارید نام گذاری کنید.

برای شروع من ایجاد کردم Modules دایرکتوری، اینجا جایی است که تمام ماژول های من در آن قرار می گیرند.


برای ماژول سطل S3 خود، دایرکتوری به نام ایجاد کردم s3-bucket در Modules فهرست راهنما. در این دایرکتوری من فایل های زیر را ایجاد می کنم main.tf، variables.tf، output.tf.

فهرست مطالب

سطل S3 ایجاد کنید

modules/s3-bucket/variables.tf

در variables.tf من نام سطل را به عنوان یک متغیر با کد زیر تعریف می کنم:

variable "bucket-name" {
  description = "The name of the S3 bucket"
  type        = string

  validation {
    condition     = (
      length(var.bucket-name) >= 3 && length(var.bucket-name) = 63 && 
      can(regex("^[a-z0-9][a-z0-9-.]*[a-z0-9]$", var.bucket-name))
    )
    error_message = "The bucket name must be between 3 and 63 characters, start and end with a lowercase letter or number, and can contain only lowercase letters, numbers, hyphens, and dots."
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اعتبارسنجی به سادگی بررسی می کند که نام سطل بین 3 تا 63 کاراکتر باشد، با یک حرف یا عدد کوچک شروع و پایان یابد و فقط شامل حروف کوچک، اعداد، خط تیره و نقطه باشد. این برای جلوگیری از هرگونه خطایی که ممکن است AWS در نتیجه نامگذاری اشتباه سطل ایجاد کند، ضروری است.

اهمیت استفاده از یک فایل متغیر برای سادگی و بازسازی آسان کد است. در صورتی که ما نیاز به تغییر مقدار آن متغیر داشته باشیم، فقط باید آن را در یک مکان تغییر دهیم و این تغییر در هر جایی که آن متغیر به استفاده از .var نشانه گذاری.

modules/s3-bucket/main.tf

اکنون به ایجاد سطل S3، ما آن را اضافه می کنیم aws_s3_bucket بلوک منابع به ماژول main.tf مطابق شکل زیر فایل کنید.

# Create S3 Bucket
resource "aws_s3_bucket" "site-bucket" {
  bucket = var.bucket-name
  force_destroy = true
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نام سطل توسط یک متغیر عرضه می شود و در هنگام ایجاد با مقدار جایگزین می شود.

modules/s3-bucket/outputs.tf

این فایلی است که در آن برخی از مقادیری را که در بقیه تنظیمات خود استفاده خواهیم کرد، خروجی خواهیم داد.

ادامه دهید و یک فایل جدید به نام ایجاد کنید outputs.tf در ماژول سطل s3 کد زیر را به فایل اضافه کنید:

output "bucket_regional_domain_name" {
  description = "This is the bucket domain name including the region name."
  value = aws_s3_bucket.site-bucket.bucket_regional_domain_name
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

S3 Bucket را به Root Module اضافه کنید

main.tf

برای آزمایش اینکه این ماژول کار می کند، با استفاده از این ماژول که به تازگی نوشته ایم، یک سطل s3 ایجاد می کنیم. به سمت main.tf فایل ماژول ریشه شما، خارج از شما Module دایرکتوری و کد زیر را در فایل وارد کنید.

module "s3-bucket" {
  source = "./Modules/s3-bucket"
  bucket-name = var.bucket-name
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

متغیرها.tf

سه فایل جدید نیز در ماژول ریشه خود به نام ایجاد کنید variables.tf، outputs.tf و terraform.tfvars.

در variables.tf کد زیر را اضافه کنید

variable "bucket-name" {
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خروجی ها.tf

در outputs.tf کد زیر را اضافه کنید:

output "bucket-name" {
  value = module.s3-bucket.site-bucket.bucket_regional_domain_name
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما از این خروجی هنگام ایجاد توزیع ابری خود استفاده خواهیم کرد.

terraform.tfvars

در terraform.tfvars فایل، کد زیر را وارد کنید:

bucket-name = "
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

⚠️ توجه داشته باشید

شما .tfvars فایل هرگز نباید به کنترل نسخه متعهد شود، این فایل را به فایل خود اضافه کنید .gitignore فایل. من را بررسی کنید .gitignore فایل هایی را برای افزودن به فایل های شما تشکیل دهید.

همچنین می توانید از این سایت برای تولید فایل های gitignore خود برای این پروژه و پروژه های آینده استفاده کنید.

در ترمینال خود، را اجرا کنید terraform init مجدداً دستور، هنگام اضافه کردن یک ماژول یا تغییر ارائه دهنده، باید دستور را دوباره اجرا کنید. اگر آن را اجرا نکنید و هر دستور terraform دیگری را اجرا نکنید، با پیغام خطای زیر مواجه خواهید شد.

Uninstalled-module-error

حالا می توانید بدوید terraform plan تا ببینید terraform قصد دارد در حساب AWS شما چه چیزی ایجاد کند.

برای ایجاد سطل، اجرا کنید

terraform apply
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر زمان که این دستور را اجرا می کنید، terraform همیشه از شما می پرسد که آیا می خواهید این عمل را انجام دهید، می توانید یا بله یا خیر پاسخ دهید. برای جلوگیری از مطرح شدن این سوال، می توانید مستقیماً آن را وارد کنید auto approve در دستور مطابق شکل زیر:

terraform apply --auto-approve
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر به درستی دنبال می‌کردید، با موفقیت یک سطل s3 ایجاد می‌کردید، ما آن را از بین می‌بریم و به نوشتن اسکریپت terraform خود ادامه می‌دهیم، زیرا ما فقط یک سطل نمی‌سازیم.

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

terraform destroy
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


نام مستعار TF برای Terraform

قبل از اینکه ادامه دهیم، می‌خواهم یک نام مستعار کوتاه برای terraform بگذارم، زیرا ما باید به‌طور کلی آن را terraform بنامیم. تنظیم نام مستعار terraform to be tf هنگامی که ما در حال فراخوانی دستورات خود هستیم، کارها را برای ما ساده می کند، بنابراین دیگر نیازی به فراخوانی صریح نخواهیم داشت. terraform اما اکنون ما آن را صدا می کنیم tf به عنوان مثال tf apply بجای terraform apply. این به ما کمک می کند فرمان خود را کوتاه کنیم.

ما می توانیم این کار را با تنظیم یک نام مستعار در پروفایل bash انجام دهیم.

برای باز کردن پروفایل bash برای ترمینال، از دستور زیر استفاده کردم:

vi ~/.bash_profile
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اینجاست که می‌توانیم پیکربندی‌های bash را تنظیم کنیم، نام مستعار خود را با فراخوانی نام مستعار با شکل کوتاه همانطور که دیده می‌شود تنظیم می‌کنیم:

alias tf="terraform"
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون برای استفاده از دستوری که به عنوان نام مستعار تنظیم کرده ایم، باید ابتدا اسکریپت پروفایل bash را اجرا کنیم تا تغییر اعمال شود.

source ~/.bash_profile
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا می توانیم به جای terraform از tf استفاده کنیم

دارایی ها را در سطل S3 آپلود کنید

قبل از نوشتن کد برای آپلود دارایی های وب سایت خود در سطل، باید یک دایرکتوری ایجاد کرده و دارایی های خود را ذخیره کنیم. من این را در ماژول ریشه خود ذخیره خواهم کرد web-assets و دارایی های وب سایت من را در آنجا اضافه کنید.

modules/s3-bucket/main.tf

ما استفاده خواهیم کرد for_each آرگومان های متا برای آپلود دارایی های سطل خود، ما از این روش استفاده می کنیم زیرا چندین فایل برای آپلود داریم. این زمانی مفید است که چندین منبع با تنظیمات مشابه ایجاد کنید.

منطقی نیست که فقط بلوک های منابع Terraform را با تغییرات جزئی در هر بلوک کپی و جایگذاری کنید. انجام این کار فقط بر خوانایی تأثیر می گذارد و فایل های پیکربندی IaC را به طور غیر ضروری طولانی می کند. کد زیر را به ماژول s3-bucket خود اضافه کنید main.tf فایل:

# Upload objects into the s3 Bucket
resource "aws_s3_object" "upload-assets" {
  for_each = fileset("${var.web-assets-path}", "**/*")
  bucket = aws_s3_bucket.site-bucket.bucket
  key = each.value
  source = "${var.web-assets-path}/${each.value}"
  content_type = lookup(var.mime_types, regex("\\.[^.]+$", each.value), "application/octet-stream")
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این for-each از طریق فایل های موجود در فهرست وب سایت تکرار می شود. من استفاده کردم fileset تابع برای تکرار بر روی همه فایل ها و دایرکتوری ها در مسیر مشخص شده، هر فایل/دایرکتوری را برای حلقه for_each در تعریف منبع در دسترس قرار می دهد.

مسیر سخت کدگذاری نشده است، به عنوان یک متغیر در تعریف شده است variable.tf فایل را همانطور که در زیر مشاهده خواهید کرد.

این for_each حلقه روی fileset مسیرهای فایل را برمی گرداند، نه جفت های کلید-مقدار، به همین دلیل است که از آن استفاده می کنیم each.value به عنوان کلید ما و نه each.key.

ما می خواهیم که وب سایت هر نوع فایل را برای نوع MIME مربوطه تشخیص دهد و آن را به درستی در وب سایت نمایش دهد، به همین دلیل از lookup عملکرد در content_type بحث و جدل. lookup(map, key, default) تابعی است که کلید را در نقشه جستجو می کند و در صورت یافتن مقدار مربوطه را برمی گرداند. اگر کلید پیدا نشد، به طور پیش فرض برمی گردد.

تابع regex پسوند فایل را از each.value استخراج می‌کند، که نام فایلی است که از مجموعه فایل‌های دیگر برای تعیین نوع MIME دقیق‌تر به‌دست می‌آید.

modules/s3-bucket/variables.tf

در اینجا متغیرهایی را که در قطعه کد بالا فراخوانی کرده ایم تعریف می کنیم، کد زیر را به فایل اضافه می کنیم:

# Set the variable for the file path of the files to be uploaded to the bucket
variable "web-assets-path" {
  description = "This is the location of our website files"
  type = string
}

variable "mime_types" {
  description = "Map of file extensions to MIME types"
  type        = map(string)
  default = {
    ".html" = "text/html"
    ".css"  = "text/css"
    ".png"  = "image/png"
    ".jpg"  = "image/jpeg"
    ".jpeg" = "image/jpeg"
    ".pdf"  = "application/pdf"
    "json" = "application/json"
    "js"   = "application/javascript"
    "gif"  = "image/gif"
    # Add more extensions and MIME types as needed
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ماژول ریشه را به روز کنید main.tf، variable.tf و terraform.tfvars فایل ها

main.tf

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

module "s3-bucket" {
  source = "./Modules/s3-bucket"
  bucket-name = var.bucket-name
  web-assets-path = var.web-assets-path
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

متغیر.tf

ماژول ریشه شما variable.tf اکنون فایل باید به شکل زیر باشد:

variable "bucket-name" {
  type = string
}

variable "web-assets-path" {
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

terraform.tfvars

ماژول ریشه شما terraform.tfvars اکنون فایل باید به شکل زیر باشد:

bucket-name = "
web-assets-path = "
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


⚠️ توجه داشته باشید

حتی اگر شما هنوز واجد شرایط سطح رایگان AWS هستید، سرویس Route53 هرگز رایگان نیست. این منطقه میزبان هزینه 0.50 دلار در ماه را جذب می کند.

برای این مرحله به یک نام دامنه سفارشی نیاز دارید، بنابراین اگر قبلاً آن را ندارید، مکث کنید، آن را دریافت کنید و ادامه دهید.

این مرحله قرار است به صورت دستی تکمیل شود، در ابتدا می‌خواستم پس از ایجاد دستی منبع را به terraform وارد کنم، اما پس از بررسی بیشتر، دلیلی نداریم زیرا نمی‌خواهم Terraform منطقه میزبان را حذف کند.

دلیل ایجاد منطقه میزبان به صورت دستی این است که وقتی یک منطقه میزبانی شده ایجاد می کنید، مجموعه جدیدی از سرورهای نام به شما داده می شود که باید آنها را به پیکربندی دامنه سفارشی خود اضافه کنید. Terraform زیرساخت لازم برای تکمیل این مرحله را ندارد و بنابراین پیکربندی شما تا زمانی که خودتان سرورهای نام خود را به صورت دستی به دامنه سفارشی خود اضافه نکنید، ناموفق خواهد بود.

از آنجایی که ما قبلاً این را می دانیم، منطقه میزبان را به صورت دستی ایجاد می کنیم، سرورهای نام را به دامنه سفارشی خود اضافه می کنیم و سپس با استفاده از terraform data منبع، جزئیات منطقه میزبانی شده ایجاد شده را در Terraform بازیابی کنید تا از هر گونه مشکلی که ممکن است به وجود آمده باشد جلوگیری کنید.

ایجاد منطقه میزبانی شده

  • کنسول مدیریت AWS خود را باز کنید.
  • که در Services زیر Network and Content delivery دسته را انتخاب کنید Route53
  • انتخاب کنید create hosted zone
  • از آنجا بسیار ساده است، نام دامنه خود را در فضای برای وارد کنید domain name.
  • انتخاب کنید public hosted zone زیر type.
  • در صورت تمایل می توانید یک برچسب و توضیحات اضافه کنید.
  • در پایین صفحه بر روی آن کلیک کنید create hosted zone.

میزبانی منطقه

  • هنگامی که منطقه میزبان شما ایجاد شد، آن را برای مشاهده جزئیات باز کنید و سرورهای نام ارائه شده توسط AWS را کپی کنید.
  • هر سرور نام را کپی کنید و آنهایی که قبلاً در نام دامنه ما هستند را با این سرورهای جدید جایگزین کنید.

جزئیات منبع منطقه میزبانی شده را در پیکربندی Terraform بازیابی کنید

برای اضافه کردن جزئیات منبع منطقه میزبانی شده خود به terraform، ما یک ماژول جدید در آن ایجاد خواهیم کرد Module دایرکتوری فراخوانی شد route53.

Modules/route53/main.tf

کد زیر را به فایل اضافه کنید:

# Retrieve information about your hosted zone from AWS
data "aws_route53_zone" "created" {
  name = var.domain_name
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا ممکن است زیاد به نظر نرسد اما جزئیات منطقه میزبانی شده را در حساب AWS ما بازیابی می کند که با نامی که ارائه می کنیم مطابقت دارد و سپس از آن در هر کجا که آن را صدا می کنیم استفاده می کند. data منبع در پیکربندی ما

Modules/route53/variables.tf

شما مته را می شناسید، متغیرهای اعلام شده را اضافه کنید تا کد شما قابل استفاده مجدد باشد.

# domain name variable
variable "domain_name" {
  description = "This is the name of the hosted zone."
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


این یک فرآیند یک مرحله‌ای در terraform نیست، ابتدا باید منبع را ایجاد کنیم و سپس آن را با یک بلوک منبع دیگر تأیید کنیم.

گواهی ایجاد کنید

ما گواهینامه خود را قبل از توزیع ابری خود ایجاد می کنیم زیرا از گواهی SSL خود در توزیع ابری خود استفاده می کنیم.

طبق معمول، یک را ایجاد کنید certificate دایرکتوری در Module دایرکتوری که ماژول گواهی ما را در خود جای می دهد. 3 فایل جدید در آن دایرکتوری ایجاد کنید main.tf، variable.tf و output.tf.

ماژول ها/گواهینامه/main.tf

# Create the TLS/SSL certificate
resource "aws_acm_certificate" "cert" {
  domain_name               = var.domain_name
  validation_method         = var.validation_method
  subject_alternative_names = var.subject_alternative_names

  # Ensure that the resource is rebuilt before destruction when running an update
  lifecycle {
    create_before_destroy = true
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/certificate/variables.tf

متغیرهای لازم را به فایل متغیرهای خود اضافه کنید:

variable "domain_name" {
  description = "Domain name for which the certificate should be issued"
  type = string
}

variable "validation_method" {
  description = "Which method to use for validation."
  type = string
  default = "DNS"
}

variable "subject_alternative_names" {
  description = "Set of domains that should be SANs in the issued certificate."
  type = list(string)
  default = []
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/certificate/outputs.tf

خروجی هایی را که باید در ماژول های دیگر ارجاع دهیم را تعریف کنید

output "cert-arn" {
  value = aws_acm_certificate.cert.arn
}

output "domain_validation_options" {
  value = aws_acm_certificate.cert.domain_validation_options
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

رکورد اعتبار سنجی گواهی ACM را ایجاد کنید

قبل از ایجاد منبع اعتبار گواهی، باید یک رکورد DNS در AWS Route 53 ایجاد کنیم که برای تأیید مالکیت دامنه برای گواهی AWS ACM استفاده می‌شود. جزئیات رکورد DNS (نام، مقدار، نوع) از گزینه های اعتبارسنجی دامنه گواهی ACM به دست می آید.

ما این رکورد را در route53 ایجاد خواهیم کرد، پس به سراغ خودتان بروید Modules/route53/main.tf فایل. موارد زیر را به فایل خود اضافه کنید:

Modules/route53/main.tf

# Create DNS record that will be used for our certificate validation
resource "aws_route53_record" "cert_validation" {
  for_each   = { for dvo in var.domain_validation_options : dvo.domain_name => {
    name     = dvo.resource_record_name
    type     = dvo.resource_record_type
    record   = dvo.resource_record_value
  } }

  name       = each.value.name
  type       = each.value.type
  records    = [each.value.record]
  ttl        = 60
  zone_id  = data.aws_route53_zone.created.zone_id
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا یک رکورد CNAME در منطقه میزبانی دامنه شما ایجاد می کند که برای تأیید اعتبار گواهی که ایجاد کرده اید استفاده می شود. با این حال، اگر همزمان سعی کنید کد ایجاد گواهی te و ایجاد رکورد را اعمال کنید، با یک پیغام خطایی شبیه به خط زیر مواجه خواهید شد.

for_each-error

به همین دلیل است که ما آن را اجرا خواهیم کرد terraform apply دستور در دو مرحله همانطور که در نهایت خواهید دید.

Modules/route53/variables.tf

موارد زیر را به فایل متغیرهای ماژول route53 خود اضافه کنید

variable "domain_validation_options" {
  description             = "The domain validation options from the ACM certificate."
  type                    = list(object({
    domain_name           = string
    resource_record_name  = string
    resource_record_type  = string
    resource_record_value = string
  }))
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

گواهینامه را تأیید کنید

این aws_acm_certificate منبع اعتبار سنجی گواهی را در Terraform انجام نمی دهد، ما باید از آن استفاده کنیم aws_acm_certificate_validation منبعی برای انجام آن

همانطور که قبلا توضیح دادم و از پیام خطا مشاهده کردید، ابتدا گواهینامه باید وجود داشته باشد و مقدار آن وجود داشته باشد domain_validation_options ابتدا شناخته شده قبل از terraform دستور for_each ما را ارج می نهد، به همین دلیل است که باید ابتدا گواهی را ایجاد کنیم، سپس رکورد و سپس تأیید کنیم.

به دلیل بالا، ما مرحله اعتبار سنجی را در ماژول گواهی قرار نمی دهیم، بلکه در ماژول Route53 قرار می دهیم. Route53 مدول.

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

Modules/route53/main.tf

# Validate the certificate
resource "aws_acm_certificate_validation" "validate-cert" {
  certificate_arn = var.certificate_arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]

  depends_on = [aws_route53_record.cert_validation]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این depends_on آرگومان terraform را مجبور به ایجاد aws_route53_record.cert_validation قبل از تلاش برای تأیید اعتبار گواهی ما، ابتدا منبع را تهیه کنید.

Modules/route53/variables.tf

متغیرهای مورد نیاز را به فایل variables.tf ماژول اضافه کنید

variable "certificate_arn" {
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/route53/outputs.tf

موارد زیر را به فایل outputs.tf ماژول route53 خود اضافه کنید

output "dns_records" {
  value = aws_route53_record.cert_validation
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما هنوز باید رکورد مستعار توزیع CloudFront را ایجاد کنیم، این رکوردی است که در آن نام دامنه توزیع cloudfront خود را به عنوان نام مستعار برای نام دامنه سفارشی خود تنظیم می کنیم. ما این کار را پس از ایجاد توزیع ابری خود انجام خواهیم داد.


اکنون می‌توانیم پیش برویم و توزیع ابری خود را ایجاد کنیم. ایجاد یک cloudfront دایرکتوری در Modules دایرکتوری و اضافه کردن ایجاد main.tf و variables.tf فایل های موجود در دایرکتوری

ایجاد کنترل دسترسی مبدا – OAC

اولین کاری که باید انجام دهیم این است که آن را ایجاد کنیم Origin Access Control ما در پیکربندی توزیع خود استفاده خواهیم کرد. این کار را با اضافه کردن کد زیر به خود انجام دهید main.tf فایل:

Modules/cloudfront/main.tf

# Create the access origin control that will be used in creating our cloudfront distribution with s3 origin
resource "aws_cloudfront_origin_access_control" "assign-oac" {
  name                              = var.oac-name
  description                       = "An origin access control with s3 origin domain for cloudfront"
  origin_access_control_origin_type = var.origin_access_control_origin_type
  signing_behavior                  = var.signing_behavior
  signing_protocol                  = var.signing_protocol
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/cloudfront/variables.tf

متغیرها را اعلام کنید:

variable "oac-name" {
  description = "This is the name of the cloudfront origin Access control with s3 bucket origin domain"
  type = string
  default = "s3-bucket-oac"
}

variable "origin_access_control_origin_type" {
  description = "The origin type must be the same as the origin domain"
  type = string
  default = "s3"
}

variable "signing_behavior" {
  description = "Specifies which requests CloudFront signs."
  type = string
  default = "always"
}

variable "signing_protocol" {
  description = "Determines how CloudFront signs (authenticates) requests."
  type = string
  default = "sigv4" # The only valid value
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایجاد توزیع

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

Modules/cloudfront/main.tf

# Create CloudFront Distribution
resource "aws_cloudfront_distribution" "cdn" {
  origin {
    domain_name              = var.cdn-domain_name-and-origin_id
    origin_id                = var.cdn-domain_name-and-origin_id
    origin_access_control_id = aws_cloudfront_origin_access_control.assign-oac.id
  }

  default_cache_behavior {
    compress = true
    viewer_protocol_policy = "redirect-to-https"
    allowed_methods        = [ "GET", "HEAD" ]
    cached_methods         = [ "GET", "HEAD" ]
    target_origin_id       = var.cdn-domain_name-and-origin_id
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400

    forwarded_values {
      query_string = false
      cookies {
        forward    = "all"
      }
    }
  }

  restrictions {
    geo_restriction {
      restriction_type = var.restriction_type
    }
  }

  viewer_certificate {
    acm_certificate_arn            = var.acm_certificate_arn
    ssl_support_method             = "sni-only"
    minimum_protocol_version       = "TLSv1.2_2021"
    cloudfront_default_certificate = false
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = var.default_root_object
  aliases             = [var.domain_name, "www.${var.domain_name}"] 
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/cloudfront/variables.tf

متغیرهای مورد نیاز را اضافه کنید

variable "restriction_type" {
  description = "Method that you want to use to restrict distribution of your content by country"
  type = string
  default = "none"
}

variable "default_root_object" {
  description = "Object that you want CloudFront to return when an end user requests the root URL."
  type = string
  default = "index.html"
}

variable "domain_name" {
  description = "your custom Domain name for which the certificate should be issued"
  type = string
}

variable "cdn-domain_name-and-origin_id" {
  type = string
}

variable "acm_certificate_arn" {
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/cloudfront/outputs.tf

output "cloudfront-arn" {
  value = aws_cloudfront_distribution.cdn.arn
}

output "cloudfront_domain_name" {
  value = aws_cloudfront_distribution.cdn.domain_name
}

output "cloudfront_hosted-zone_id" {
  value = aws_cloudfront_distribution.cdn.hosted_zone_id
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


اکنون باید مجوزهای سطل خاصی را اضافه کنیم، آن cloudfront باید بتواند به اندازه کافی با سطل s3 ما تعامل داشته باشد، به سطل s3 ما.

به ماژول سطل s3 خود برگردید.

Modules/s3-bucket/main.tf

این خط مشی است که به ما امکان دسترسی به توزیع ابری ما را به سطل s3 و شیء آن از طریق کنترل مبدا دسترسی آن می دهد.

کد زیر را به فایل main.tf ماژول سطل s3 اضافه کنید

Modules/s3-bucket/main.tf

# Add the permissions needed by cloudfront's origin access control to access the bucket and it's objects
resource "aws_s3_bucket_policy" "cloudfront-oac-policy" {
  bucket = aws_s3_bucket.site-bucket.bucket
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Sid = "AllowCloudFrontServicePrincipal",
        Effect = "Allow",
        Principal = {
          Service = "cloudfront.amazonaws.com"
        },
        Action = "s3:GetObject",
        Resource = "${aws_s3_bucket.site-bucket.arn}/*",
        Condition = {
          StringLike = {
            "aws:UserAgent" = "Amazon CloudFront"
          }
        }
      }
    ]
  })
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


ما یک ماژول جدید ایجاد خواهیم کرد، به خصوص برای این، یک ماژول جدید به نام ایجاد می کنیم alias، دو فایل ایجاد کنید main.tf و variables.tf.

Modules/alias/main.tf

# Retrieve information about your hosted zone from AWS
data "aws_route53_zone" "created" {
  name = var.domain_name
}

# Create an alias that will point to the cloudfront distribution domain name
resource "aws_route53_record" "alias" {
  zone_id                  = data.aws_route53_zone.created.zone_id
  name                     = var.domain_name
  type                     = "A"

  alias {
    name                   = var.cloudfront_domain_name
    zone_id                = var.cloudfront-zone-id
    evaluate_target_health = false
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

Modules/alias/variables.tf

متغیرهای لازم را طبق معمول اعلام کنید:

variable "domain_name" {
  description = "your custom domain name"
  type = string
}

variable "cloudfront_domain_name" {
  type = string
}

variable "cloudfront-zone-id" {
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید


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

ما قبلا ماژول s3-bucket خود را در اوایل پروژه زمانی که می خواستیم ماژول s3-bucket خود را آزمایش کنیم به main.tf خود اضافه کرده بودیم، اکنون بقیه ماژول های خود را به ماژول اضافه می کنیم. main.tf.

main.tf

پیکربندی نهایی شما در شما main.tf ماژول ریشه شما باید به شکل زیر باشد:

# Create S3 bucket, upload objects into the bucket and set bucket policy.
module "s3-bucket" {
  source = "./Modules/s3-bucket"
  bucket-name = var.bucket-name
  web-assets-path = var.web-assets-path
}

# Create and validate TLS/SSL certificate
module "certificate" {
  source = "./Modules/certificate"
  domain_name = var.domain_name
  subject_alternative_names  = ["www.${var.domain_name}"]
  }

# Create OAC and cloudfront distribution, 
module "cloudfront" {
  source = "./Modules/cloudfront"
  domain_name = var.domain_name
  cdn-domain_name-and-origin_id = module.s3-bucket.bucket_regional_domain_name
  acm_certificate_arn = module.certificate.cert-arn
  depends_on = [ module.route53 ]
}

# Import the hosted zone from AWS, create dns records for certificate validation, and create A and CNAME records.
module "route53" {
  source = "./Modules/route53"
  domain_name = var.domain_name
  domain_validation_options = module.certificate.domain_validation_options
  certificate_arn = module.certificate.cert-arn
  }

# Create an alias to point the cloudfront cdn to our domain name.
module "alias" {
  source = "./Modules/alias"
  domain_name = var.domain_name
  cloudfront_domain_name = module.cloudfront.cloudfront_domain_name
  cloudfront-zone-id = module.cloudfront.cloudfront_hosted-zone_id
  depends_on = [ module.cloudfront ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

متغیرها.tf

اکنون متغیرهای لازم را اعلام می کنیم، فایل variable.tf نهایی شما باید به شکل زیر باشد:

variable "bucket-name" {
  type = string
}

variable "web-assets-path" {
  type = string
}

variable "domain_name" {
  type = string
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

terraform.tfvars

اسرار خود را به خود اضافه کنید *.tfvars فایل مانند این:

bucket-name = "
web-assets-path = "the path to your website files (best to supply the absolute path)>
domain_name = ""
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون همه ما آماده ایم که برنامه خود را مستقر کنیم.


ماژول ها را نصب کنید

اولین اجرا tf init برای نصب تمام ماژول های اضافه شده

tf init
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نصب ماژول ها

اعتبار سنجی پیکربندی

در مرحله بعد می توانید دستور validate را برای تایید پیکربندی خود اجرا کنید

tf validate
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

tf- اعتبار سنجی

ایجاد زیرساخت

همانطور که قبلا توضیح دادم for_each تابع فقط روی مقادیری تکرار می‌شود که در آن زمان شناخته شده‌اند apply دستور این است، بنابراین اگر ما قبل از ایجاد گواهینامه خود را اعمال کنیم، terraform خطایی ایجاد می کند.

برای جلوگیری از این خطا در دو مرحله ابتدا با --target پرچم گذاری کنید و سپس کل پیکربندی را اعمال کنید.

اجرای اول:

tf apply --target module.certificate
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

--هدف-فرمان

--هدف

--هدف ایجاد شده

در نهایت، منابع باقی مانده را ایجاد کنید:

tf apply
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

tf-apply

کاربردی

ساخت را تایید کنید

می توانید کنسول AWS خود را باز کنید تا ببینید که منابع ساخته شده اند.

مرورگر خود را باز کنید و به دامنه سفارشی خود بروید و خواهید دید که وب سایت شما نمایش داده می شود، اینجا مال من است.

صفحه میزبانی شده


به یاد داشته باشید که پس از اتمام کار، محیط خود را تمیز کنید. برای جلوگیری از صورتحساب غیر ضروری، منابع را در AWS در حال اجرا رها نکنید.

از دستور تخریب استفاده کنید:

tf destroy
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

از بین رفتن

نابود

نوشته های مشابه

دیدگاهتان را بنویسید

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

دکمه بازگشت به بالا