مقدمه
Ansible یک ابزار مدرن مدیریت پیکربندی (Configuration Management) است که کار راهاندازی و نگهداری سرورهای راه دور را ساده میکند و با طراحی مینیمال خود کاربر را خیلی زود به نتیجه میرساند. Ansible از یک فایل به نام inventory استفاده میکند تا مشخص کند کدام هاستها بخشی از زیرساخت شما هستند و چطور میشود برای اجرای دستورها و playbookها به آنها متصل شد.
بسته به محیط و نیاز پروژه، راههای مختلفی برای تنظیم فایل inventory وجود دارد. در این راهنما نشان میدهیم چطور فایل inventory بسازید و سرورها را در قالب گروهها و زیرگروهها سازماندهی کنید، چطور متغیرهای مربوط به هاست (host variables) را تعریف کنید و چطور با استفاده از الگوها (patterns) اجرای دستورها و playbookهای Ansible را روی هر هاست و هر گروه کنترل کنید.
پیشنیازها
برای دنبالکردن این راهنما به موارد زیر نیاز دارید:
یک نود کنترل Ansible (Control Node): یک ماشین با Ubuntu 24.04 که Ansible روی آن نصب و برای اتصال به هاستها از طریق کلید SSH پیکربندی شده باشد. مطمئن شوید نود کنترل یک کاربر معمولی با دسترسی sudo و یک فایروال فعال دارد. برای نصب Ansible میتوانید راهنمای نصب و پیکربندی Ansible روی Ubuntu 24.04 را دنبال کنید.
دو یا چند هاست Ansible: دو یا چند سرور راه دور با Ubuntu 24.04.
گام ۱ — ساختن یک فایل Inventory اختصاصی
هنگام نصب، Ansible یک فایل inventory پیشفرض میسازد که معمولاً در مسیر /etc/ansible/hosts قرار دارد. این مسیر پیشفرضی است که وقتی هنگام اجرای playbook یا دستور، فایل inventory اختصاصی با گزینهی -i مشخص نشود، Ansible از آن استفاده میکند.
هرچند میتوانید بدون مشکل از همین فایل استفاده کنید، اما داشتن فایل inventory جداگانه برای هر پروژه یک رویهی خوب است، چون از قاطیشدن سرورها هنگام اجرای دستورها و playbookها جلوگیری میکند. فایل inventory اختصاصی برای هر پروژه، بهاشتراکگذاری تنظیمات با همتیمیها را هم سادهتر میکند، بهویژه اگر فایل inventory را داخل مخزن کد پروژه قرار دهید.
برای شروع، وارد پوشهی خانگی (home) خود شوید و یک دایرکتوری جدید برای نگهداری فایلهای Ansible بسازید:
cd ~
mkdir ansible
به آن دایرکتوری بروید و با ویرایشگر متن دلخواهتان یک فایل inventory جدید باز کنید. اینجا از nano استفاده میکنیم:
cd ansible
nano inventory
یک فهرست از نودها، با هر سرور در یک خط، برای ساختن یک فایل inventory کارآمد کافی است. نام هاست (hostname) و آدرس IP قابل جایگزینی با هم هستند:
# ~/ansible/inventory
203.0.113.111
203.0.113.112
203.0.113.113
server_hostname
وقتی فایل inventory آماده شد، میتوانید با دستور ansible-inventory آن را بررسی (validate) کنید و اطلاعات inventory را ببینید:
ansible-inventory -i inventory --list
# خروجی
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"hosts": [
"203.0.113.111",
"203.0.113.112",
"203.0.113.113",
"server_hostname"
]
}
}
با اینکه هنوز هیچ گروهی داخل inventory تعریف نکردهایم، خروجی دو گروه مجزا را نشان میدهد که Ansible بهصورت خودکار در نظر میگیرد: all و ungrouped. همانطور که از نامش پیداست، all به همهی سرورهای فایل inventory اشاره دارد، فارغ از اینکه چطور سازماندهی شده باشند. گروه ungrouped هم به سرورهایی اشاره دارد که داخل هیچ گروهی فهرست نشدهاند.
اجرای دستورها و playbookها با Inventory اختصاصی
برای اجرای دستورهای Ansible با یک فایل inventory اختصاصی، از گزینهی -i به این شکل استفاده کنید:
ansible all -i inventory -m ping
این کار ماژول ping را روی همهی هاستهای فهرستشده در فایل inventory اختصاصی شما اجرا میکند.
به همین ترتیب، اجرای playbookهای Ansible با یک فایل inventory اختصاصی اینطور انجام میشود:
ansible-playbook -i inventory playbook.yml
نکته: برای اطلاعات بیشتر دربارهی نحوهی اتصال به نودها، به راهنمای «چگونه از Ansible استفاده کنیم» مراجعه کنید، چون گزینههای بیشتری برای اتصال را نشان میدهد.
تا اینجا دیدیم چطور یک inventory ساده بسازیم و از آن برای اجرای دستورها و playbookها استفاده کنیم. در گام بعدی میبینیم چطور نودها را در گروهها و زیرگروهها سازماندهی کنیم.
گام ۲ — سازماندهی سرورها در گروهها و زیرگروهها
داخل فایل inventory میتوانید سرورها را در گروهها و زیرگروههای مختلف سازماندهی کنید. این کار علاوه بر اینکه به مرتبنگهداشتن هاستها کمک میکند، امکان استفاده از متغیرهای گروهی (group variables) را هم فراهم میکند؛ قابلیتی که میتواند مدیریت چند محیط staging مختلف را با Ansible خیلی سادهتر کند.
یک هاست میتواند عضو چند گروه باشد. فایل inventory زیر که با قالب INI نوشته شده، یک ساختار با چهار گروه را نشان میدهد: webservers، dbservers، development و production. توجه کنید که سرورها بر اساس دو ویژگی متفاوت گروهبندی شدهاند: بر اساس کاربردشان (وب و پایگاهداده) و بر اساس نحوهی استفاده (توسعه و تولید).
# ~/ansible/inventory
[webservers]
203.0.113.111
203.0.113.112
[dbservers]
203.0.113.113
server_hostname
[development]
203.0.113.111
203.0.113.113
[production]
203.0.113.112
server_hostname
اگر دوباره دستور ansible-inventory را با این فایل inventory اجرا کنید، این چیدمان را میبینید:
# خروجی
{
"_meta": {
"hostvars": {}
},
"all": {
"children": [
"dbservers",
"development",
"production",
"ungrouped",
"webservers"
]
},
"dbservers": {
"hosts": [
"203.0.113.113",
"server_hostname"
]
},
"development": {
"hosts": [
"203.0.113.111",
"203.0.113.113"
]
},
"production": {
"hosts": [
"203.0.113.112",
"server_hostname"
]
},
"webservers": {
"hosts": [
"203.0.113.111",
"203.0.113.112"
]
}
}
همچنین میتوان چند گروه را بهعنوان زیرمجموعه (children) زیر یک گروه «والد» جمع کرد. به این گروه والد یک متاگروپ (metagroup) گفته میشود. مثال زیر روش دیگری برای سازماندهی همان inventory قبلی را نشان میدهد که با استفاده از متاگروپها به چیدمانی مشابه اما دقیقتر میرسد:
# ~/ansible/inventory
[web_dev]
203.0.113.111
[web_prod]
203.0.113.112
[db_dev]
203.0.113.113
[db_prod]
server_hostname
[webservers:children]
web_dev
web_prod
[dbservers:children]
db_dev
db_prod
[development:children]
web_dev
db_dev
[production:children]
web_prod
db_prod
هرچه تعداد سرورهایتان بیشتر باشد، شکستن گروهها به بخشهای کوچکتر یا ساختن چیدمانهای جایگزین منطقیتر میشود، تا بتوانید در صورت نیاز گروههای کوچکتری از سرورها را هدف بگیرید.
گام ۳ — تنظیم نام مستعار (Alias) برای هاستها
میتوانید با استفاده از نام مستعار (alias)، سرورها را طوری نامگذاری کنید که ارجاع به آنها هنگام اجرای دستورها و playbookها سادهتر شود.
برای استفاده از یک alias، بعد از نام مستعار یک متغیر به نام ansible_host قرار دهید که آدرس IP یا hostname سروری را که باید به آن alias پاسخ دهد، در خود دارد:
# ~/ansible/inventory
server1 ansible_host=203.0.113.111
server2 ansible_host=203.0.113.112
server3 ansible_host=203.0.113.113
server4 ansible_host=server_hostname
اگر دستور ansible-inventory را با این فایل inventory اجرا کنید، خروجی مشابه این را میبینید:
# خروجی
{
"_meta": {
"hostvars": {
"server1": {
"ansible_host": "203.0.113.111"
},
"server2": {
"ansible_host": "203.0.113.112"
},
"server3": {
"ansible_host": "203.0.113.113"
},
"server4": {
"ansible_host": "server_hostname"
}
}
},
"all": {
"children": [
"ungrouped"
]
},
"ungrouped": {
"hosts": [
"server1",
"server2",
"server3",
"server4"
]
}
}
توجه کنید که حالا به سرورها بهجای آدرس IP یا hostname، با نام مستعارشان ارجاع داده میشود. این کار هدفگیری تکتک سرورها را هنگام اجرای دستورها و playbookها سادهتر میکند.
گام ۴ — تنظیم متغیرهای هاست (Host Variables)
میتوان از فایل inventory برای تعریف متغیرهایی استفاده کرد که رفتار پیشفرض Ansible را هنگام اتصال و اجرای دستورها روی نودها تغییر میدهند. در واقع همین کار را در گام قبل هنگام تنظیم نام مستعار انجام دادیم. متغیر ansible_host به Ansible میگوید نود راه دور را کجا پیدا کند، در صورتی که از یک alias برای ارجاع به آن سرور استفاده شده باشد.
متغیرهای inventory را میتوان بهازای هر هاست یا هر گروه تنظیم کرد. این متغیرها علاوه بر سفارشیکردن تنظیمات پیشفرض Ansible، از داخل playbookها هم قابل دسترسی هستند که امکان سفارشیسازی بیشتر برای هاستها و گروههای جداگانه را فراهم میکند.
مثال زیر نشان میدهد چطور کاربر پیشفرض راه دور را هنگام اتصال به هر یک از نودهای فهرستشده در این فایل inventory تعریف کنیم:
# ~/ansible/inventory
server1 ansible_host=203.0.113.111 ansible_user=sammy
server2 ansible_host=203.0.113.112 ansible_user=sammy
server3 ansible_host=203.0.113.113 ansible_user=myuser
server4 ansible_host=server_hostname ansible_user=myuser
همچنین میتوانید یک گروه بسازید تا هاستهایی با تنظیمات مشابه را کنار هم جمع کنید و سپس متغیرهایشان را در سطح گروه تعریف کنید:
# ~/ansible/inventory
[group_a]
server1 ansible_host=203.0.113.111
server2 ansible_host=203.0.113.112
[group_b]
server3 ansible_host=203.0.113.113
server4 ansible_host=server_hostname
[group_a:vars]
ansible_user=sammy
[group_b:vars]
ansible_user=myuser
این چیدمان inventory خروجی زیر را با ansible-inventory تولید میکند:
# خروجی
{
"_meta": {
"hostvars": {
"server1": {
"ansible_host": "203.0.113.111",
"ansible_user": "sammy"
},
"server2": {
"ansible_host": "203.0.113.112",
"ansible_user": "sammy"
},
"server3": {
"ansible_host": "203.0.113.113",
"ansible_user": "myuser"
},
"server4": {
"ansible_host": "server_hostname",
"ansible_user": "myuser"
}
}
},
"all": {
"children": [
"group_a",
"group_b",
"ungrouped"
]
},
"group_a": {
"hosts": [
"server1",
"server2"
]
},
"group_b": {
"hosts": [
"server3",
"server4"
]
}
}
توجه کنید که همهی متغیرهای inventory داخل بخش _meta در خروجی JSON تولیدشده توسط ansible-inventory فهرست میشوند.
گام ۵ — استفاده از الگوها (Patterns) برای هدفگیری اجرای دستورها و playbookها
هنگام اجرای دستورها و playbookها با Ansible، باید یک هدف (target) مشخص کنید. الگوها به شما اجازه میدهند هاستها، گروهها یا زیرگروههای مشخصی از فایل inventory را هدف بگیرید. این الگوها بسیار انعطافپذیرند و از عبارتهای باقاعده (regular expressions) و کاراکترهای جانشین (wildcards) پشتیبانی میکنند.
فایل inventory زیر را در نظر بگیرید:
# ~/ansible/inventory
[webservers]
203.0.113.111
203.0.113.112
[dbservers]
203.0.113.113
server_hostname
[development]
203.0.113.111
203.0.113.113
[production]
203.0.113.112
server_hostname
حالا فرض کنید باید دستوری را اجرا کنید که فقط سرور(های) پایگاهدادهای را هدف بگیرد که در محیط production در حال اجرا هستند. در این مثال فقط server_hostname با این شرط مطابقت دارد؛ اما ممکن است در آن گروه، تعداد زیادی سرور پایگاهداده داشته باشید. بهجای هدفگیری تکتک سرورها، میتوانید از این الگو استفاده کنید:
ansible dbservers:\&production -m ping
کاراکتر & نمایندهی عملیات منطقی «و» (AND) است، یعنی هدفهای معتبر باید در هر دو گروه باشند. چون این یک دستور موقت (ad hoc) است که در Bash اجرا میشود، باید کاراکتر escape یعنی \ را در عبارت قرار دهیم.
مثال قبلی فقط سرورهایی را هدف میگیرد که هم در گروه dbservers و هم در گروه production حضور دارند. اگر بخواهید عکس آن را انجام دهید، یعنی فقط سرورهایی را هدف بگیرید که در dbservers هستند اما در گروه production نیستند، از این الگو استفاده میکنید:
ansible dbservers:\!production -m ping
برای اینکه مشخص کنید یک هدف نباید در یک گروه خاص باشد، میتوانید از کاراکتر ! استفاده کنید. باز هم کاراکتر escape یعنی \ را در عبارت قرار میدهیم تا از خطاهای خط فرمان جلوگیری کنیم، چون هر دو کاراکتر & و ! کاراکترهای خاصی هستند که ممکن است توسط Bash تفسیر شوند.
جدول زیر چند نمونه از الگوهای رایجی را که میتوانید هنگام اجرای دستورها و playbookها با Ansible استفاده کنید نشان میدهد:
| الگو | هدف نتیجه |
|---|---|
all |
همهی هاستهای فایل inventory شما |
host1 |
یک هاست واحد (host1) |
host1:host2 |
هم host1 و هم host2 |
group1 |
یک گروه واحد (group1) |
group1:group2 |
همهی سرورهای group1 و group2 |
group1:\&group2 |
فقط سرورهایی که هم در group1 و هم در group2 هستند |
group1:\!group2 |
سرورهای group1 بهجز آنهایی که در group2 هم هستند |
برای گزینههای پیشرفتهتر الگوها، مانند استفاده از الگوهای مکانی (positional) و regex برای تعریف هدفها، به مستندات رسمی Ansible دربارهی الگوها مراجعه کنید.
جمعبندی
در این راهنما نگاهی دقیق به inventoryهای Ansible داشتیم. دیدیم چطور نودها را در گروهها و زیرگروهها سازماندهی کنیم، چطور متغیرهای inventory را تنظیم کنیم و چطور با استفاده از الگوها هنگام اجرای دستورها و playbookها گروههای مختلفی از سرورها را هدف بگیریم.
از همراهی شما با پارمین کلود سپاسگزاریم.
نظرات کاربران