در ادامهی پستهای دواپس امروز میخوام یکم بیشتر انسیبل رو توضیح بدم و در مورد اینکه چه اجزایی داره و برای هر کاری باید چی کار کنیم صحبت کنم. ابتدا خوبه یه مروری کنیم که چه مواردی رو بررسی کردیم.
توصیه میکنم که حتما این پستها رو هم مطالعه کنید. بریم که ادامه بدیم.
اجزای اصلی و مهم انسیبل شامل موارد زیر است که به اختصار هر کدوم رو توضیح میدم. البته به این موارد محدود نمیشه و موضوعات بیشتری رو در بر میگیره اما اینجا به اندازهی حوصلهی این داکیومنت این موارد رو توضیح میدم.
مثل ابزارهای دیگه پلاگینهایی رو میتونیم اضافه کنیم تا از انسیبل توی سرویسها و محیطهای بیشتری استفاده کنیم. انسیبل یه سری پلاگین built-in خودش داره و میتونید خودتون هم پلاگین خودتون رو بنویسید و داشته باشید. گاها تو پروژهها پیش میاد که ما نیاز داریم پلاگین جدیدی به انسیبل اضافه کنیم اما برای شروع پلاگینهای بیلتین خود انسیبل تمام نیازمندیهای ما رو پوشش میدهد.
ماژول ها تیکه کدهایی هستن که انسیبل اجراشون میکنه. برنامه های کوچیکی که انسیبل از نود کنترل کننده اونها رو پخش و روی سرورهای ما اجراشون میکنه. ماژولها میتونن سرویس ها و پکیج های مارو کنترل کنند و تغییرشون بدن و ما میتونیم تو تسکها از ماژولهای مختلف برای انجام کارهامون استفاده کنیم.
تو این لینک لیست ماژولهای انسیبل رو میتونید مشاهده کنید که تعدادشون زیاده و بر اساس نیازمندی ما میتونیم از آنها استفاده کنیم. خوبه که ماژولهای پر استفاده انسیبل رو بشناسیم و ازشون استفاده کنیم.
نکتهی مهم: ما باید همواره تلاش کنیم تا برای تمام کارهایی که میخواهیم روی سرور مقصد انجام دهیم از ماژولها استفاده کنیم. استفاده از ماژولها به ما کمک میکند که Idempotency داشته باشیم.
تسک یک واحد انجام عملیات در انسیبل هست که میتونیم با استفاده از آن تعدادی عملیات و کار رو روی سرورها و دیوایسهای مقصد انجام بدیم. تسکها شامل لیستی از ماژولها میباشد که کمک میکنه سناریویی که میخواهیم رو روی دیوایس مقصد پیادهسازی و ایجاد کنیم.
توی اینونتوری ما لیست دیوایسهایی که میخوایم مدیریتشون کنیم و آنها را تغییر دهیم رو مینویسیم به همین خاطر بعضی وقتا به اینونتوری hostfile هم میگن. تو اینونتوری ما اطلاعات ارتباطی دیوایس مقصد اعم از IP آدرس، SSH Port و کاربری که باهاش SSH میزنیم رو میتونیم مشخص کنیم. یه نکتهی خیلی کاربردی اینکه اگر SSH Config برای اتصال به سرورها استفاده کنید اینجا میتونید به راحتی از اون اسم استفاده کنید کامل میشناسه و دیگه نیاز نیست اطلاعات اضافهتری بهش بدید. این طوری فقط یه جا اطلاعات ارتباط به سرورها رو ایجاد کردید و تو جاهای دیگه میتونید ازش استفاده کنید.
تو Playbook ما سناریویی که میخواهیم روی اون دیوایس اجرا کنیم رو مشخص میکنیم. یه جورایی یه لیست مرتبی از تسکهایی است که میخوایم روی دیوایسهامون اجرا بشه و معمولا ما همواره Playbook رو اجرا میکنیم و مثلا به انسیبل میگیم که این کارهایی رو که من توی این Playbook برات لیست کردم رو روی اون دیوایسهایی که توی Inventory برات مشخص کردم، انجام بده. 🙂
دو نوع نود تو انسیبل داریم، دسته اول کنترلر نود و دسته دوم هم دیوایسهایی که میخوایم روی اونها اکشن بزنیم که بهشون میگیم Managed Nodes. حتما یک نود کنترل باید باشه و معمولا هم همون یکی هست ولی معمولا تو پروژههای بزرگ از ابزارهایی مثل AWX و Semaphore استفاده میکنیم. به هر نودی که توسط نود کنترل مدیریتش کنیم Managed Node میگیم.
توی انسیبل Role ها راهی هستند برای سازماندهی به تسک های مرتبط و فایل هایی که نیاز دارند. معمولا ساختار مشخصی رو با استفاده از ابزارهای دیگه انسیبل برای Role ایجاد میکنیم و توی اون ساختار تسکهامون و فایل های مورد نیازش رو قرار میدیم. مثلا من یک Role برای نصب و کانفیگ داکر روی سرورهام ایجاد میکنم و توی تسک های اون مواردی مثل نصب داکر، کانفیگ داکر و تغییراتی که میخوام بدم رو اضافه میکنم.
ساختار نرمال به این صورت است که تعدادی Playbook داریم که هر Playbook شامل چندین Role هست و هر Role شامل چندین Task و هر Task هم شامل چندین ماژول هست که ما رو کمک میکنه تا سناریویی که ایجاد کردیم رو باهاش روی دیوایسهای مدنظرمون پیادهسازی کنیم.
مطابق تصویر بالا توی انسیبل از یه ساختار یا اصطلاحا Structure برای فایل ها استفاده میکنیم که از قبل مشخص هست مثلا Inventory کجاست یا اینکه تسکها رو کجا قرار بدیم و … که باید این ساختار رو ازش تبعیت کنیم. البته میتونیم ساختار خودمون رو داشته باشیم اما توصیه میشه که از همین ساختار تبعیت کنیم چون خوانایی کدمون رو به شدت افزایش میده.
انسیبل از روش های مختلفی کانفیگ میشه مثل متغیرهای محیطی یا متغیرهایی که توی کامند یا کلمات کلیدی توی Playbook و همچنین از طریق فایل ansible.cfg که من خودم معمولا کانفیگ های مربوط به SSH یا نحوه کانکشن انسیبل و مسیر Inventory یا مسیر پسورد Vault یا تعداد فورک و … رو توی این فایل مشخص میکنم. حالا این ansible.cfg رو میتونیم تو جاهای مختلفی قرار بدیم. اول توی etc/ansible/ و دوم داخل home دایرکتوری یوزر خودمون و سوم داخل روت پروژه که آخری از همه اولویتش بالاتره و این اعمال میشه. معمولا پروژههای بزرگ کانفیگ خودشون رو تو روت خود پروژه قرار میدن.
همونطور که بالاتر هم گفتیم فایل هایی که اطلاعات مربوط به سرورهایی که میخوایم بهشون وصل بشیم و روی آنها کار انجام بدیم رو نگه میدارن، بهشون hostfile میگن که معمولا توی Inventory هستن اینها و بعضا توی Playbook هم به شکل مستقیم نوشته میشن. کلا میتونیم از روشهای مختلفی برای این کار استفاده کنیم. اسم فایلی که این اطلاعات رو داخلش قرار میدیم هم مهم نیست ولی برای خوانایی بیشتر معمولا اسمش رو inventory یا hostfile میگذارند ولی به صورت کلی مهم نیست. هم تو کانفیگ و هم زمان اجرای انسیبل میتونیم بهش آدرس بدیم و ازش استفاده کنیم. این فایل با دو تا پسوند ini و yaml در دسترس هست که توصیه میکنم از yaml استفاده کنید تا شبیه بقیهی ساختاری که داره بشه و یکدست تر باشه.
فکت ها اطلاعات مرتبط با دیوایسهامون هستن که توسط کنترلر انسیبل جمع آوری و توی مسیری داخل نود کنترلر ذخیره میشن. فکتها به فرمت json هستن و اهمیت اونها توی تصمیم گیری ما در مورد اجرای تسکها هست، مثلا با استفاده از فکتها میتونیم مشخص کنیم که تسکمون روی سرورهایی اجرا بشه که سیستم عامل آنها از خانواده مشخصی هست یا بگیم اگه توزیع لینوکس روی سرورمون دبیان بود این تسک رو اجرا نکن یا موارد مشابه … . به صورت کلی فکتها در انسیبل یه سری اطلاعات کامل از اون دیوایسمون بهمون میده که میتونیم از آنها در تسکهامون استفاده کنیم. با استفاده از فکتها ما میتونیم انسیبلی رو آماده کنیم که مالتی OS باشه یا بتونه روی توزیعهای مختلف لینوکس اجرا بشه و تو هر کدوم از ماژولهای مخصوص آنها استفاده کنه.
متغیرها توی انسیبل واقعا مهم هستن و دست مارو باز میذارن تا ساختارمون رو یکبار به شکل درست ایجاد کنیم و بعد از اون، تنها متغیرهایی که تعریف کردیم رو برای نیاز های بعدیمون و آپدیت هامون تغییر بدیم. توی انسیبل جاهای زیادی میشه متغیرها رو تعریف کرد که مهم ترینش توی Inventory هست اما توی Playbook , Role و حتی کامند لاین هم میشه متغیر تعریف کرد. خیلی جاها امکان تعریف متغیرها رو داریم که اینجا لیست آنها رو میتویند ببینید. یکی از نکات مهم دیگه تو وریبلها اولویت آنها نسبت به هم است. اینجا اولویت وریبلها نسبت به هم رو میتونید ببینید. تو استفاده از وریبلها باید به این موضوع دقت زیادی کنید.
فرض کنید میخواید فایلی رو به سرورهاتون منتقل کنید که توی اون قسمتی وجود داره که به ازای هر سرور متفاوته. با استفاده از تمپلیت میتونید فایلتون رو به صورت jinja2 بنویسید و توی فایلتون متغیر هاتون رو صدا بزنید و بعد اینکه فایل منتقل بشه به سرورها دقیقا اتفاقی که میخواید میافته 🙂 حتی میشه شرط هم نوشت توی jinja2 که حتما توصیه میکنم در موردش بخونید. اگر این قابلیت وجود نداشت ما مجبور بودیم به ازای هر دیوایس که میخواهیم فایل رو به آن منتقل کنیم یه فایل مستقل بسازیم که اصلا مسیر خوبی نبود. تمپلیتینگ به ما این امکان رو میده که یه فایل داشته باشیم و تو دیوایسهای مختلف متفاوت باهاش برخورد کنیم.
با استفاده از تگ توی انسیبل میتونیم یه جورایی لیبل بزنیم به تسک هامون. این کار به ما کمک میکنه که مثلا توی یه Playbook بزرگ بتونیم یه سری تسک های مشخصی رو که با تگ جدا کردیم اجرا کنیم. یه جورایی دستمون رو باز میگذاره که قسمتی از اون Playbook یا قسمتی از اون Task ها رو اجرا کنیم. مثلا ما یک تسک نوشتیم که ۳ تا کار انجام میده، میتونیم با تگ فقط یکی از اون کارها رو انجام بدیم.
زیاد پیش میاد که بعد از آماده کردن Playbook مون موقع اجرا به ارور بخوریم چه از نوع سینتکس چه ارور های منطقی و … دیباگ اینجا به ما کمک میکنه که بتونیم مشکل رو رفع کنیم دو نوع msg , var داره که به کمک اونها یک پیامی رو در خروجی نشون میدیم یا متغیر خاصی رو پرینت میکنیم که معمولا با استفاده از register در انسیبل خروجی تسک ها رو ذخیره میکنیم و پرینتش میکنیم که برای دیباگ بهمون کمک میکنه. یه جورایی داریم تو مسیر برای خودمون راهنما میگذاریم تا بتونیم مشکل رو پیدا کنیم. این موضوع تو مواردی که مشکل لاجیکی داریم خیلی میتونه بهمون کمک کنه تا بتونیم مشکل رو پیدا کنیم.
در ساختارهای بزرگ و مخصوصا تو کلاد پروایدرها ما اطلاعات اون سرورهای خودمون که میخواهیم مدیریتش کنیم رو نداریم. یعنی خود انسیبل داره آنها رو ایجاد میکنه. تو این موارد انسیبل میتونه با ماژولهایی که داره با اون پروایدر ارتباط بگیره و اطلاعات سرورهایی که ایجاد کرده رو بدست بیاره تا بتونه روی آنها اکشن بزنه. انسیبل از زیر ساخت هایی مثل AWS و OpenStack یا VMware که لیستی از سرورها رو دارن پشتیبانی میکنه.
با استفاده از اونها میتونیم شرط توی انسیبل هامون بنویسیم که لیستی ازشون رو براتون قرار میدم:
• when
• loop and conditionals
• custom facts
• register variables
• conditional imports
• selecting files and templates based on variables
• Commonly used facts
کلا lint ها به ما کمک میکنند که خطاهای syntax که به وجود میاد رو بتونیم برطرف کنیم. با استفاده از این ابزار میتونیم کدهای انسیبل خودمون رو ارزیابی کنیم و مواردی از قبیل خطای سینتکسی یا آپدیتهای ماژولها رو بهمون میگه تا بررسی کنیم و آنها رو اصلاح کنیم. در برخی از موارد هم خطایی وجود نداره ولی نحوهی درست استفاده از اون ماژول رو هم بهمون توصیه میکنه.
کامند هایی هستند که به صورت مستقیم اونها رو روی یک یا چند تا از دیوایس هامون اعمال میکنیم، ad-hoc راه ساده و راحت کامند زدن از طریق انسیبل هست که معمولا کارهای اصلی مون رو از این طریق انجام نمیدیم. چون ذخیره نمیشه و بعدا قابلیت بهبود و بررسی نداره. اکثرا از ad-hoc برای اینکه ببینیم ping سروری رو داریم و دسترسی مون برقرار هست یا کارهای این چنینی استفاده میشه.
انسیبل Galaxy یه ریپازیتوری تحت وب هست برای اشتراک گذاشتن و پیدا کردن کالکشن ها و Role های انسیبل. با استفاده از اون میتونیم Role ها یا پلاگینها و ماژولهایی رو که نوشتیم با بقیه به اشتراک بذاریم یا مواردی رو که در دسترس هست نصب کنیم و استفاده کنیم. همچنین با دستور ansible-galaxy init میتونیم ساختار استانداردی برای مسیر دایرکتوریهای role هامون ایجاد کنیم. این ساختار برای کدهای خودمون هم قابل دسترس هست و میتونیم ازش استفاده کنیم. مثلا نصب و کانفیگ داکر یا هاردنینگ سرور باید روی همهی سرورهای ما انجام بشه. حالا یکی از آنها وب سرور هست و یکی دیگه دیتابیس و هر کدوم پروژه و ساختار خودشون رو دارند. اما هر دو به Role نصب و کانفیگ داکر نیاز دارند. این طوری ما میتونیم پروژه نصب و کانفیگ داکر رو به صورت galaxy داخل پروژه کانفیگ وب سرورمون ازش استفاده کنیم و دیگه نیاز نیست که تمام اون کدها رو داخل این پروژه هم اد کنیم. یه جورایی بهمون کمک میکنه که پروژههای مختلفی ایجاد کنیم و هر زمان که نیاز داشتیم از آنها استفاده کنیم.
برای حفاظت از دیتای حساسمون توی انسیبل معمولا دو تا راه داریم: راه اول استفاده از ابزارهای جانبی مدیریت کلید مثل Hashicorp Vault , Amazon's AWS Key Management , Azure Key Vault هست. راه دوم استفاده از Vault توی خود انسیبل هست. به این شکل که ما پسوردی رو توی مسیر دلخواهمون قرار میدیم و به کمک Vault دیتای حساسمون مثل پسوردها رو رمز میکنیم. این ابزار به ما کمک میکنه تا دیتا حساس رو به صورت رمز شده نگه داریم و یا توی گیت قرار بدیم و خیالمون راحت تر باشه که دیتای حساسمون لیک نمیشه. کلا استفاده از ansible-vault بهمون کمک میکنه تا از دیتاهای حساسمون محافظت کنیم و آنها رو به صورت امن نگهداری کنیم.
این دوتا نام ابزارهایی هستن که به ما یه محیط گرافیکی برای کار کردن با انسیبل ارائه میدن و از خوبی هاشون میشه به امکان تعریف کردن گروه و یوزر با سطح دسترسی های مختلف اشاره کرد. معمولا کنترلر انسیبل روی لپتاپ افراد تیم هست که زیاد جالب نیست. این دو تا ابزار این امکان رو بهمون میده که بتونیم کنترلر انسیبل خودمون رو تو دیتاسنتر قرار بدیم و کلی قابلیت دیگه کنار اون داشته باشیم. معمولا افراد جدید به تیم اضافه میشن یا از تیم خارج میشوند و این ابزارها بهمون کمک میکنه که بتونیم به موقع و به اندازه دسترسی بدیم و هر زمان هم که لازم شد میتونیم دسترسی رو ازشون بگیریم. یه نکته اینکه AWX ابزار رسمی خود انسیبل هست و ansible tower نسخهی آنلاین و ارائه SaaS آن توسط خود کمپانی انسیبل هست که البته رایگان نیست.
زیاد پیش میاد که ما بخوایم سرورهایی رو در شبکه داخلی شرکت با استفاده از انسیبل کانفیگ کنیم که به صورت پابلیک در دسترس نیستند. توی این موارد معمولا یه سروری که هم به شبکه داخلی و هم به شبکه پابلیک دسترسی داره رو به عنوان راه دسترسی به سرورهای شبکه داخلیمون استفاده میکنیم که کنترلر نود انسیبل به کمک اون میتونه به سرورهای ما وصل شه که به این سرور واسطه bastion میگیم. یکی از بهترین روشهایی هست که دسترسی به سرورهای اصلی رو از روی اینترنت و به صورت پابلیک برداریم و دسترسی خصوصی به آنها داشته باشیم.
تقریبا برای هرکاری که بخواید انجام بدید انسیبل یه ماژولی داره! که با گشتن توی داک انسیبل و یه سرچ زدن میتونید پیداش کنید. از کارهای ساده اولیه مثل انتقال و کپی کردن فایل بگیر تا زدن رکورد های DNS و کارهای پیچیدهتر. حتما سعی کنید برای هر کاری از ماژول مخصوص آن استفاده کنید. این کار کمک میکنه تا Idempotency داشته باشید. معمولا ما وقتی یه کد انسیبل آماده میکنیم و آن رو روی سرورها و سرویسهامون اعمال میکنیم همواره انتظار داریم که به گونهای باشه که اگر مجدد آن کد رو اجرا کنیم هیچ تغییری روی سرورها نده و اختلالی ایجاد نکنه. مثلا تا جای ممکن کد bash وسط انسیبلتون نزنید تا اگر انسیبل رو مجدد اجرا کردید آن کار رو تکرار نکنه. همواره تو ماژولها به گونهای رفتار شده که قبل از اعمال یک اکشن آن رو بررسی میکنه و اگر نیاز بود اعمال میکنه.
سعی کنید یه نظم معنیدار و استانداردی واسه خودتون داشته باشید. این کار باعث میشه هم خوانایی کدتون زیاد بشه هم تیشوت و دیباگ کردن شما رو سادهتر میکنه. مثلا جایی که متغیر هاتون رو تعریف میکنید یا مدل تعریف متغیرها، طوری که فایلها رو تمپلیت میکنید و استانداردی برای مسیر آنها و … طوری باشه که تو همهی پروژههای شما یکسان و یکنواخت باشه.
تا جایی که میشه توی اتومیشن از تکرار تسک های مشابه دوری کنید و اگه قراره مثلا دوتا فایل رو کپی کنید تو سرورتون از دوتا تسک استفاده نکنید به جاش توی یک تسک لوپ بزنید. یا مثلا فرض کنید من میخوام ده تا پکیج مختلف رو روی سرورم نصب کنم به جای اینکه ده تا تسک بنویسم که هر کدومش یکی از پکیج هارو برام نصب کنه، یه تسک مینویسم و توی اون لوپ میزنم و هر ده تا پکیج رو با یه تسک نصب میکنم.
حتما برای کد خودتون تگ تعریف کنید و برای تگهایی که ایجاد میکنید دیسکریپشن مشخصی داشته باشید. این کار بهتون کمک میکنه خیلی استفاده بهتری از انسیبل خودتون داشته باشید. خیلی پیش میاد که نیاز باشه یه تیکه از انسیبل مون رو اجرا کنیم یا مثلا یه قسمت خاصی رو داریم دیباگ میکنیم میخوایم تغییرات رو بررسی کنیم و نیاز نداریم که تسکهای دیگه اجرا بشه، تو این موارد تگ خیلی کمک میکنه و معمولا تو مصاحبهها هم ازتون در موردش سوال میپرسند.
همونطور که بالاتر هم اشاره کردم انسیبل پایتون میخواد و SSH میزنه، یه کار زیبایی که اگه یادش بگیرید موقع استفاده ازش خیلی بهتون خوش میگذره :) اینه که اطلاعات ارتباط با سرورهاتون رو توی SSH Config تعریف کنید و توی Inventory انسیبل تون فقط اسم اونارو صدا بزنید. قبلا هم بهش اشاره کردم این طوری شما فقط اطلاعات ارتباط با سرور رو یک جا تعریف کردید و تو جاهای دیگه به راحتی ازش استفاده میکنید.
اینکه توقع داشته باشیم کسی که با انسیبل کار میکنه تمام ماژولها و متغیرهایی که میگیرند رو حفظ باشه تقریبا خنده داره و افراد حرفه ای هم به سبب استفاده زیاد از یه سری ماژول اونارو حفظ شدن، توی این موارد من دیدم بین دانشجوهام که بچه ها از هوش مصنوعی کمک میگیرن که به نظرم خوبم هست و سرعت رو بالاتر میبره اما بعد اینکه اون نوشت، باید بفهمید چیزی رو که نوشته و بتونید ایرادشو بگیرید یا ادیتش کنید که مناسب کار خودتون بشه. یعنی به صورت کلی تجربهی من میگه که نسخهی اولیه که بهتون میده اصلا چیز مناسبی نیست و باید باهاش صحبت کنی و مشکلاتش رو بگی تا یه نسخهی مناسب بهتون بده. بهتره اگر جایی گیر کردید و نمیدونستید که باید چی کار کنید ازش راهنمایی بگیرید.
من خودم معمولا کارهای مختلف که خیلی از هم مستقل هستند رو به Roleهای متفاوت تقسیم میکنم. داخل هر Role تسکهایی ایجاد میکنم. تسکها رو با اسمهای معنیدار توی فایل های yml جدا میکنم و بعد توی main.yml اونها رو دونه دونه به ترتیبی که لازم دارم import میکنم و براشون تگ های معنی دار میزنم.
مثلا نصب و کانفیگ داکر رو تو یه Role مستقل قرار میدم. بعد نصب داکر، کانفیگ داکر، نصب مقدمات لازم سرور و … رو هر کدوم تو یه تسک فایل مستقل میگذارم و توی main آنها رو به ترتیب مدنظر خودم فراخوانی میکنم. برای هر کدوم از تسک فایلها در زمان Import کردن هم tag میزنم که به راحتی بتونم آن کار مشخص رو انجام بدم. اینطوری هم خوانایی کدم بیشتر میشه و هم وقتی میخوام ازش استفاده کنم راحتتر ساختار و دیزاین فایلها رو میتونم متوجه بشم و هم به راحتی هر قسمت از کد رو که یه عملکرد مشخص داره رو میتونم فراخوانی کنم. این یه جورایی دستخطی هست که همواره رعایت میکنم.
توصیه میکنم که حتما از انسیبل استفاده کنید و سعی کنید تمام کارهایی که دارید رو خودکار کنید. کلا کار تکراری رو باید ماشین انجام بده و انسانها بهتره که ماشینها رو مدیریت کنند.