← بازگشت به خانه · راهنمای انگلیسی کوتاه: ansible/README.md
این صفحه مرجع کامل استقرار production با Ansible است: فلسفهٔ طراحی، ساختار پوشه، نقش هر فایل، جریان اجرای playbook، تضمین idempotency، راهنمای گامبهگام برای سرور واقعی، و تمام دستورها و سوئیچهای موردنیاز این پروژه. پس از خواندن باید بتوانید بدون حدس زدن، از صفر تا استقرار کامل و بهروزرسانیهای بعدی را اجرا کنید.
فهرست:
- فلسفه و جایگاه Ansible در پروژه
- ساختار پوشهٔ
ansible/ - نقشها (Roles) و کار هر کدام
- جریان کامل یک Deploy
- Idempotency — چرا اجرای دوباره امن است
- متغیرها، Vault و قالب
.env - راهنمای گامبهگام Production
- مرجع دستورها، تگها و سوئیچها
- پیوند با اسکریپتهای پروژه
- چکلیست و نکات عملیاتی
۱. فلسفه و جایگاه Ansible در پروژه
Ansible اینجا یک لایهٔ نازک روی ابزار خود پروژه است، نه جایگزین Compose یا منطق راهاندازی. منطق واقعی «بالا آوردن استک» داخل اسکریپتهای مخزن است:
scripts/bring_up.sh— آمادهسازی env، راهاندازی مرحلهای Compose، seed اپهاscripts/infra/check_infra.sh— Smoke Test زیرساختscripts/run_tests_in_docker.sh— تست ایزوله (اختیاری، قبل از bring_up)
کار Ansible این است که روی سرور Ubuntu خام: Docker را نصب کند، مخزن را clone/pull کند، فایل .env را از قالب و Vault بسازد، سپس همان اسکریپتها را صدا بزند. اگر فردا منطق bring_up عوض شود، playbook عمداً آن را کپی نمیکند — فقط همان اسکریپت را اجرا میکند.
مرز مسئولیت:
| لایه | مسئولیت | چه چیزی نیست |
|---|---|---|
| Ansible | Provisioning سرور + تحویل کد + رندر .env + فراخوانی اسکریپتها |
بازنویسی docker compose یا منطق seed/crawl |
اسکریپتهای scripts/ |
راهاندازی استک، seed، smoke، تست ایزوله | نصب Docker روی OS یا مدیریت SSH |
| Compose / سرویسها | تعریف کانتینرها، healthcheck، پروفایلها | دانستن اینکه اپراتور کی deploy میزند |
هدف سرور: production Ubuntu با SSH و کاربر sudo. Control node (لپتاپ یا CI) فقط Ansible را دارد؛ روی خود سرور لازم نیست Ansible نصب باشد.
۲. ساختار پوشهٔ ansible/
ansible/
ansible.cfg # تنظیمات پیشفرض (inventory، roles_path، become، diff)
inventory.ini.example # نمونهٔ inventory — کپی به inventory.ini
playbook.yml # play اصلی: docker → project_setup → deploy
group_vars/
all.yml # متغیرهای غیرحساس (قابل commit)
vault.yml.example # قالب رمزها — فایل واقعی vault.yml رمزنگاریشده و gitignore
roles/
docker/tasks/main.yml
project_setup/tasks/main.yml
deploy/tasks/main.yml
templates/
env.j2 # Jinja2 برای .env سرور (آینهٔ .env.example ریشه)
README.md # خلاصهٔ انگلیسی
| مسیر | نقش |
|---|---|
ansible.cfg |
inventory پیشفرض inventory.ini، مسیر roles، host_key_checking=False برای اولین اتصال، همیشه نمایش diff برای قالبها، و become=True (sudo به root). |
inventory.ini.example |
گروه [production] با placeholder IP. فایل واقعی inventory.ini gitignore است و نباید commit شود. |
playbook.yml |
تعریف play روی hosts گروه production؛ بارگذاری Vault؛ ترتیب سه role. |
group_vars/all.yml |
URL مخزن، مسیر نصب روی سرور، پورتها، فلگ گزارش چرخه، run_tests_before_deploy. |
group_vars/vault.yml |
رمز Postgres (db/user/password). فقط با ansible-vault ساخته میشود؛ در git نیست. |
templates/env.j2 |
خروجی: {{ project_dir }}/.env با mode 0600 و backup زماندار هنگام تغییر. |
roles/* |
هر role یک مسئولیت شفاف؛ تگگذاری برای اجرای جزئی. |
۳. نقشها (Roles) و کار هر کدام
۳.۱ نقش docker — تگ docker
نصب idempotent موتور Docker و پلاگین Compose از مخزن رسمی APT داکر:
- پیشنیازهای apt (
ca-certificates,curl,gnupg) - کلید GPG و ریپازیتوری Docker برای Ubuntu هدف
- نصب
docker-ce، CLI، containerd، buildx،docker-compose-plugin - سرویس docker:
started+enabled - افزودن کاربر SSH (
ansible_user) به گروهdockerتا بعداً بدون sudo بتواند docker بزند
اجرای دوم معمولاً فقط ok میدهد و چیزی نصب دوباره نمیکند.
۳.۲ نقش project_setup — تگهای project_setup و بخشی deploy
- اطمینان از نصب
git - ساخت دایرکتوری
project_dir(پیشفرض/opt/playpulse) git cloneیاpullرویproject_version(پیشفرضmain) — باforce: falseتا تغییرات محلی ناخواسته پاک نشوند- رندر
templates/env.j2→{{ project_dir }}/.env
تسکهای clone و template علاوه بر project_setup تگ deploy هم دارند؛ بنابراین --tags deploy کد و .env را بهروز میکند بدون دست زدن به نصب Docker.
۳.۳ نقش deploy — تگهای deploy و tests
ترتیب ثابت داخل این role:
| گام | دستور | رفتار شکست |
|---|---|---|
| ۰ (اختیاری) | ./scripts/run_tests_in_docker.sh |
فقط وقتی run_tests_before_deploy=true. با failed_when: false کل playbook را نمیشکند؛ خروجی و در صورت rc≠۰ یک Warning چاپ میشود. |
| ۱ | ./scripts/bring_up.sh --skip-check |
شکست اسکریپت → شکست play. --skip-check تا smoke جدا و شفاف در گام بعد باشد. |
| ۲ | ./scripts/infra/check_infra.sh |
rc≠۰ → شکست play (استک «بالا آمده اما سالم نیست» پذیرفته نمیشود). |
خروجی هر اسکریپت با تسک debug در لاگ Ansible دیده میشود تا در CI یا ترمینال، لاگ bring_up / تست / smoke کامل باشد.
۴. جریان کامل یک Deploy
اجرای کامل پیشفرض (run_tests_before_deploy=false):
Control node Target Ubuntu server
───────────── ────────────────────
ansible-playbook ...
│
├─ role: docker ────────► نصب/تأیید Docker + Compose + گروه docker
│
├─ role: project_setup ► git clone/pull در /opt/playpulse
│ رندر .env از Vault + all.yml
│
└─ role: deploy
├─ (tests skipped)
├─ bring_up.sh --skip-check
│ infra → app-api healthy → seed_apps.sh → crawler/consumer …
└─ check_infra.sh (Postgres / Kafka / Metabase)
با تست ایزوله قبل از bring_up (-e run_tests_before_deploy=true):
- همان docker + project_setup
- سپس روی سرور: استک جدا
playpulse_test+.env.test(دست به root.envو استک live نمیزند) - خلاصهٔ PASS/FAIL/SKIPPED چاپ میشود
- بعد bring_up و check_infra — حتی اگر تست soft-fail شده باشد (تصمیم نهایی با اپراتور)
چرا تست قبل از bring_up؟ سوئیت ایزوله استک live را verify نمیکند؛ health واقعی بعد از bring_up با check_infra است. اجرای تست قبل از بالا آوردن سرویسهای production از رقابت منابع با crawler/Metabase جلوگیری میکند و مشکل واضح کد/ماشین را زودتر نشان میدهد.
داخل bring_up.sh (خلاصه — جزئیات در مستند bring_up):
- زیرساخت: postgres، zookeeper، kafka، kafka-init، kafka-ui، metabase
- فقط
app-apiتا healthy seed_apps.sh— ثبت ۱۵ اپ اولیه- بقیه: storage-consumer، crawler (+ اختیاری cycle-reporter)
- sentiment فقط اگر image از قبل باشد؛ بدون cold-build
۵. Idempotency — چرا اجرای دوباره امن است
Idempotent یعنی بار دوم و سوم همان playbook نباید سیستم را خراب کند یا state متناقض بسازد. در این پروژه لایهلایه تضمین شده:
| جزء | چگونه idempotent است | علامت در Ansible |
|---|---|---|
| نصب Docker (apt / key / repo / service) | ماژولهای رسمی؛ اگر بسته نصب باشد دوباره نصب سنگین نمیشود | اجرای دوم: بیشتر ok، نه changed |
git module |
اگر dest موجود باشد update میکند؛ force: false |
changed فقط وقتی ref عوض شود |
قالب .env |
فقط وقتی محتوای رندرشده فرق کند مینویسد؛ backup زماندار | changed + diff در خروجی |
bring_up.sh / Compose |
docker compose up -d و seed با HTTP 409 برای duplicate |
Ansible تسک command را معمولاً changed میزند (چون shell است)، ولی اثر جانبی روی سرور idempotent است |
check_infra.sh |
فقط read/write تستی موقت و پاکسازی | changed_when: false |
| تست ایزوله Docker | پروژهٔ جدا + teardown volume در پایان | changed_when: false؛ استک live دستنخورده |
نکتهٔ ذهنی مهم: «Ansible گفت changed» برای تسکهای command مربوط به bring_up بهمعنی «سرور خراب شد» نیست؛ یعنی «اسکریپت دوباره اجرا شد». سلامت واقعی را از خروجی اسکریپت و موفقیت check_infra بخوانید.
۶. متغیرها، Vault و قالب .env
۶.۱ group_vars/all.yml (غیرحساس — commit میشود)
| متغیر | پیشفرض مفهومی | کاربرد |
|---|---|---|
project_repo_url | URL گیتهاب PlayPulse | منبع clone/pull |
project_version | main | branch / tag / commit |
project_dir | /opt/playpulse | مسیر کار روی سرور |
postgres_port / app_api_port / … | مطابق .env.example | پورتهای publish در .env |
crawler_cycle_reports_enabled | false | گزارش چرخه crawl+persist |
run_tests_before_deploy | false | اجرای اختیاری تست ایزوله قبل از bring_up |
۶.۲ Vault (حساس — commit نمیشود)
کلیدهای لازم در vault.yml:
vault_postgres_dbvault_postgres_uservault_postgres_password
اینها داخل env.j2 به POSTGRES_* تبدیل میشوند. playbook فایل Vault را با vars_files صریح لود میکند؛ برای decrypt هنگام اجرا معمولاً --ask-vault-pass لازم است.
۶.۳ خروجی .env روی سرور
فقط برای substitution در docker-compose.yml است (اعتبارنامه و پورتها). فایل با mode 0600 نوشته میشود. ویرایش دستی روی سرور در deploy بعدی با رندر قالب ممکن است overwrite شود — منبع حقیقت Vault + all.yml است.
۷. راهنمای گامبهگام Production
گام ۰ — پیشنیازها
- یک سرور Ubuntu با IP عمومی/خصوصی قابل SSH
- کاربر با sudo (مثلاً
ubuntu) - روی لپتاپ/CI: Ansible نصب باشد (
ansible --version) - مخزن PlayPulse روی control node کلون شده باشد تا پوشهٔ
ansible/در دسترس باشد
گام ۱ — نصب Ansible روی control node
# Ubuntu/Debian
sudo apt update && sudo apt install -y ansible
# یا با pipx
pipx install --include-deps ansible
ansible --version
گام ۲ — Inventory واقعی
cd ansible
cp inventory.ini.example inventory.ini
# ویرایش: ansible_host = IP واقعی سرور، ansible_user = کاربر SSH
نمونهٔ مفهومی:
[production]
prod-server ansible_host=203.0.113.10
[production:vars]
ansible_user=ubuntu
# ansible_ssh_private_key_file=~/.ssh/id_ed25519
ansible_python_interpreter=/usr/bin/python3
تست اتصال:
ansible -i inventory.ini production -m ping
گام ۳ — ساخت Vault رمزنگاریشده
cd ansible
ansible-vault create group_vars/vault.yml
# پسورد Vault را تنظیم کنید و این کلیدها را با مقادیر واقعی production بگذارید:
#
# vault_postgres_db: "playpulse_prod"
# vault_postgres_user: "playpulse"
# vault_postgres_password: "a-long-random-secret"
بعداً:
ansible-vault edit group_vars/vault.yml
ansible-vault view group_vars/vault.yml
گام ۴ — تنظیمات غیرحساس (در صورت نیاز)
در group_vars/all.yml مثلاً project_version را روی tag انتشار بگذارید، یا پورتها را با سیاست فایروال همتراز کنید. برای deploy عادی run_tests_before_deploy را false بگذارید.
گام ۵ — اولین استقرار کامل
cd ansible
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass
# اگر sudo روی سرور پسورد میخواهد:
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass -K
انتظار: نصب Docker (اولین بار طولانیتر)، clone، نوشتن .env، bring_up مرحلهای، seed اپها، سپس check_infra سبز. URLهای مفید روی سرور: App API روی APP_API_PORT، Kafka UI، Metabase.
گام ۶ — بهروزرسانی بعدی کد (بدون نصب دوباره Docker)
ansible-playbook -i inventory.ini playbook.yml --tags deploy --ask-vault-pass
این مسیر: pull + رندر .env + (اختیاری تست) + bring_up + check_infra.
گام ۷ — Deploy با تست ایزوله قبل از bring_up
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass \
-e "run_tests_before_deploy=true"
خلاصهٔ PASS/FAIL/SKIPPED را در خروجی debug بخوانید. SKIPPED برای sentiment بدون image یا محدودیت محیطی live/oracle طبیعی است؛ هر FAIL واقعی را قبل از اعتماد به سرور بررسی کنید. این گام playbook را بهخاطر soft-fail متوقف نمیکند.
۸. مرجع دستورها، تگها و سوئیچها
۸.۱ تگهای playbook این پروژه
| تگ | چه چیزی اجرا میشود |
|---|---|
docker | فقط نقش نصب Docker/Compose |
project_setup | git + ساخت مسیر + (با تگ کاملتر) رندر env — مطابق تگهای تسکها |
deploy | بهروزرسانی کد + .env + مسیر deploy (تست اختیاری + bring_up + check_infra) |
tests | فقط بلوک تست ایزوله؛ همچنان نیاز به -e run_tests_before_deploy=true |
۸.۲ دستورهای رایج
cd ansible
# استقرار کامل
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass
# استقرار کامل + sudo password
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass -K
# فقط redeploy (بدون نقش docker)
ansible-playbook -i inventory.ini playbook.yml --tags deploy --ask-vault-pass
# فقط Docker
ansible-playbook -i inventory.ini playbook.yml --tags docker --ask-vault-pass
# فقط تست ایزوله (روی سرور، قبل از/بدون bring_up در همین تگ)
ansible-playbook -i inventory.ini playbook.yml --tags tests --ask-vault-pass \
-e "run_tests_before_deploy=true"
# فعالسازی گزارش چرخه از طریق متغیر (در all.yml یا -e)
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass \
-e "crawler_cycle_reports_enabled=true"
# شاخه/تگ مشخص برای deploy
ansible-playbook -i inventory.ini playbook.yml --tags deploy --ask-vault-pass \
-e "project_version=v1.2.3"
# اعتبارسنجی بدون تغییر
ansible-playbook -i inventory.ini playbook.yml --syntax-check
ansible-playbook -i inventory.ini playbook.yml --check --diff --ask-vault-pass
# لیست تسکها قبل از اجرا
ansible-playbook -i inventory.ini playbook.yml --list-tasks
ansible-playbook -i inventory.ini playbook.yml --list-tags
۸.۳ سوئیچهای Ansible که در این پروژه زیاد به کار میآیند
| سوئیچ | معنا برای این پروژه |
|---|---|
-i inventory.ini | فایل hosts؛ اگر از داخل ansible/ اجرا کنید معمولاً از cfg هم خوانده میشود |
--ask-vault-pass / -J | رمزگشایی group_vars/vault.yml |
-K / --ask-become-pass | پسورد sudo روی سرور |
--tags / --skip-tags | اجرای جزئی نقشها |
-e KEY=VAL | override متغیر (مثل تست یا version) |
--check | dry-run؛ بعضی تسکهای command ممکن است کامل شبیهسازی نشوند |
--diff | نمایش diff قالبها؛ در cfg این پروژه diff همیشه روشن است |
--limit hostname | اگر چند host در inventory دارید، محدود کردن هدف |
-v / -vv | جزئیات بیشتر برای دیباگ |
۸.۴ دستورهای کمکی روی خود سرور (بعد از deploy)
cd /opt/playpulse # یا project_dir شما
docker compose ps -a
./scripts/infra/check_infra.sh
./scripts/seed_apps.sh # معمولاً لازم نیست؛ bring_up زده
curl -sS "http://localhost:${APP_API_PORT:-8000}/api/applications/" | python3 -m json.tool
docker compose logs crawler | grep "Crawl cycle summary"
۹. پیوند با اسکریپتهای پروژه
| اسکریپت | مستند | نقش در Ansible |
|---|---|---|
bring_up.sh |
مستند | هستهٔ بالا آوردن استک live؛ با --skip-check |
seed_apps.sh |
مستند | غیرمستقیم داخل bring_up، قبل از crawler |
check_infra.sh |
مستند | گام اجباری سلامت بعد از bring_up |
run_tests_in_docker.sh |
مستند | اختیاری قبل از bring_up؛ جایگزین health live نیست |
۱۰. چکلیست و نکات عملیاتی
- هرگز
inventory.iniیاgroup_vars/vault.ymlرا commit نکنید. - اولین اتصال: از control node
ansible … -m pingبایدpongبدهد. - بعد از اولین Docker install، اگر کاربر تازهوارد گروه docker شده، برای session دستی SSH ممکن است یکبار logout/login لازم باشد؛ خود playbook با become/root اسکریپتها را اجرا میکند.
- تغییر رمز Postgres در Vault روی volume قدیمی دیتابیس موجود را «جادویی» عوض نمیکند — سیاست migrate/rotate جداگانه است؛ Vault برای رندر env و استقرارهای تازه/همتراز است.
- اگر
gitروی سرور بهخاطر تغییر محلی fail شد (force: false)، عمدی است؛ دستی تصمیم بگیرید، نه force کور. - تست ایزوله و استک live میتوانند همزمان روی یک ماشین باشند، ولی در playbook تست را قبل از bring_up میگذاریم تا تداخل کمتر شود.
- برای درک جزئیات Compose و seed، این صفحه را همراه bring_up و فهرست اسکریپتها بخوانید.
جمعبندی یک خطی: Ansible سرور را آماده و کد/.env را تحویل میدهد؛ اسکریپتهای پروژه استک را درست و idempotent بالا میآورند؛ check_infra مهر سلامت میزند؛ تست Docker اختیاری و جدا از استک live است.