ویرگول
ورودثبت نام
احمد رفیعی
احمد رفیعیمشاور زیرساخت. موسس سایت آموزشی DockerMe.ir
احمد رفیعی
احمد رفیعی
خواندن ۱۴ دقیقه·۱ سال پیش

استورج کوبرنتیز (قسمت هشتم)

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

Kubernetes Storage
Kubernetes Storage

خب یه مروری کنیم پست‌های قبلی رو:دواپس چیه و چرا لازمه؟  اینجا در مورد دواپس و ضرورت استفاده از آن صحبت کردم.

  • چطور اپلیکیشن مناسب کلاد آماده کنیم؟ و اینجا توضیح دادم که چطور می‌تونیم یه اپلیکیشن مناسب کلاد توسعه بدیم.

  • چه عمقی از لینوکس برای دواپس لازمه؟ و اینجا توضیح دادم که کدوم موارد لینوکس برای دواپس الزامی هست که اول سراغ اون موارد بریم.

  • خودکارش کن,مشکلاتت حل میشه در اینجا در مورد اتومیشن و اینکه انسیبل چیه و چه کمکی به ما می‌کنه صحبت کردم.

  • در مسیر دواپس اینبار اجزای اصلی انسیبل تو این پست اجزای انسیبل رو معرفی کردم و آنها را شرح دادم.

  • در مسیر دواپس به داکر رسیدیم (قسمت اول) تو این پست داکر رو شروع کردیم و اونو معرفی کردیم.

  • در مسیر دواپس اینبار: پشت داکر چه خبره؟ (قسمت دوم) توی این پست در مورد تکنولوژی هایی که داکر ازشون استفاده میکنه توضیح دادیم.

  • تست نوشتن و شروع مسیر CI/CD (قسمت اول) توی این پست انواع تست رو بررسی کردیم و با ابزارهای CI/CD آشنا شدیم و یه مقایسه بین گیت‌لب و جنکینز داشتیم.

  • در مسیر CI/CD گیت رو بررسی می‌کنیم (قسمت دوم) توی این پست قبل ورود به گیت‌لب نیاز بود که گیت و ورژن کنترل سیستم ها رو یه بررسی کنیم.

  • در مسیر ‌CI/CD شناخت گیت‌لب (قسمت سوم) توی این پست اجزای گیت‌لب رو بررسی کردیم و با کامپوننت‌های مختلفی که داره بیشتر آشنا شدیم.

  • در مسیر ‌CI/CD پایپ‌لاین و رانر گیت‌لب (قسمت چهارم) توی این پست پایپ‌لاین و رانر گیت‌لب رو بررسی کردیم.

  • در مسیر CI/CD وریبل، گیت‌آپس و جمع‌بندی (قسمت پنجم) توی این پست وریبل‌های گیت‌لب رو بررسی کردیم و یه معرفی کوتاه از گیت‌آپس و آتودواپس کردیم و در انتها یه مقدار تجربه‌های خودم رو در گیت‌لب باهاتون به اشتراک گذاشتم.

  • در مسیر Observability، الک (قسمت دوم) توی این پست استک قدرتمند ELK رو بررسی کردیم.

  • در مسیر Observability، جمع بندی استک الک (قسمت سوم) توی این پست بقیه کامپوننت‌های استک الک رو بررسی کردیم و fluentd و fluentbit رو مقایسه کردیم و نهایتا یه معرفی هم روی opensearch داشتیم.

  • در مسیر Observability، استک پرومتئوس (قسمت چهارم) توی این پست یه معرفی اولیه داشتیم روی استک پرومتئوس.

  • در مسیر Observability، استک پرومتئوس (قسمت پنجم) توی این پست یه مقدار کامپوننت های استک پرومتئوس رو بیشتر بررسی کردیم.

  • در مسیر Observability، استک ویکتوریا (قسمت ششم) توی این پست استک ویکتوریا رو معرفی کردیم و سعی کردیم با پرومتئوس مقایسه‌اش کنیم.

  • در مسیر Observability، می‌می‌ر (قسمت هفتم) توی این پست در مورد ابزار میمیر از ابزارهای گرافانا توضیح دادیم و کاربردش رو بررسی کردیم.

  • در مسیر Observability، لوکی (قسمت هشتم) توی این پست در مورد ابزار گرافانا برای مدیریت لاگ یعنی لوکی توضیح دادیم و آخرشم یه معرفی کوتاه رو graylog داشتیم.

  • در مسیر Observability، تمپو (قسمت نهم) توی این پست در مورد تریسینگ توضیح دادیم و گرافانا تمپو رو بررسی کردیم و یه معرفی کوتاه روی Jaeger داشتیم

  • در مسیر Observability، گرافانا (قسمت دهم) توی این پست در مورد گرافانا و HA کردنش و همچنین یه سری از ابزارهاش مثل alloy , incident, on-call توضیح دادیم.

  • آغاز مسیر کوبر (قسمت اول) تو این قدم به معرفی ابزارهای ارکستریشن پرداختیم و مدارک کوبرنتیز رو بررسی کردیم.

  • کوبر سینگل ( قسمت دوم ) توی این قدم در مورد kubectl , kubeconfig توضیح دادیم و تعدادی ابزار رو معرفی کردیم که به کمک اونها میتونیم یک کوبرنتیز دمه‌دستی واسه تست‌هامون داشته باشیم.

  • کامپوننت‌های کوبر ( قسمت سوم ) توی این پست کامپوننت‌های مختلف کوبرنتیز رو بررسی کردیم و اجزای نودهای مستر و ورکر رو دونه دونه بررسی کردیم و توضیح دادیم.

  • پادها و مدیریت اونها در کوبرنتیز (قسمت چهارم) توی این پست در مورد پاد توی کوبرنتیز توضیح دادیم و موارد مربوط به اون رو بررسی کردیم.

  • ورک‌لودهای کوبر و مدیریت منابع کوبر (قسمت پنجم) توی این پست در مورد namespaceها توی کوبر توضیح دادیم و انواع ورک‌لود کوبر رو بررسی کردیم.

  • اگه لازم شد کوبر خودش گنده میشه‌! ( قسمت ششم ) توی این پست در مورد سه نوع ورک‌لود‌ مرتبط با scaling به صورت خودکار در کوبرنتیز توضیح دادیم.

  • نتورک کوبر (قسمت هفتم) توی این قسمت انواع سرویس توی کوبرنتیز رو بررسی کردیم و در مورد مفاهیم اینگرس و نتورک پالیسی توضیح دادیم.

  • استورج کوبرنتیز (قسمت هشتم) توی این قسمت در مورد انواع استورج توی کوبرنتیز توضیح دادیم و مفاهیم PV و PVC و Storage Class رو بررسی کردیم.

  • پراب، ریکوئست و لیمیت (قسمت نهم) توی این قسمت موارد مربوط به محدود کردن منابع کانتینر توی کوبرنتیز رو بررسی کردیم و در مورد انواع ‌probe ها توی کوبرنتیز توضیح دادیم.

  • پاد تو نود (قسمت دهم) توی این قسمت درمورد فرآیند انتقال پاد به نود مناسب مفاهیم پیشرفته‌تری مثل affinity و anti-affinity و taint و toleration رو بررسی کردیم.

  • اولویت پاد و امنیت (قسمت یازدهم) توی این قسمت در مورد تعیین اولویت برای پادها و جنبه‌های مختلف امنیت در کوبرنتیز توضیح دادیم.

  • کنترل دسترسی به کوبر (قسمت دوازدهم) توی این قسمت در مورد مراحل دسترسی به api کوبرنتیز صحبت کردیم و بعدش مفاهیمی مثل سرویس اکانت رو توضیح دادیم.

  • دیزاین کلاستر (قسمت سیزدهم) توی این قسمت در مورد طراحی و دیزاین یک کلاستر و روش‌های مختلفی که داره توضیح دادیم و همچنین تفاوت روش‌های مختلف تقسیم منابع در کلاسترها را بررسی کردیم.

  • مالتی تننسی در کوبر (قسمت چهاردهم) توی این قسمت چالش‌های مربوط به داشتن چند مستاجر بر روی کلاستر کوبرنتیز توضیح دادیم.

  • هلم (قسمت پانزدهم) توی این قسمت پکیج منیجر معروف کوبرنتیز یعنی Helm رو بررسی کردیم و در موردش ویژگی‌ها و کاربردهاش توضیح دادیم.

  • سی آر دی و اُپراتور (قسمت شانزدهم) توی این قسمت در مورد اینکه چطوری یه ریسورس کاستوم شده به کلاستر اضافه کنیم توضیح دادیم و مفهوم اُپراتور رو توی کوبر بررسی کردیم.

  • نصب کلاستر با kubeadm (قسمت هفدهم) توی این قسمت قدم به قدم نحوه نصب یک کلاستر کوبرنتیز رو با استفاده از ابزار kubeadm توضیح دادیم.

  • نصب کلاستر با kubespray (قسمت هجدهم) توی این قسمت نحوه نصب کلاستر با یه پروژه خیلی خوب به نام کیوب اسپری که یه انسیبل خفن برای ستاپ کلاستر رائه میده رو توضیح دادیم.

  • نصب کلاستر با rancher (قسمت نوزدهم) توی این قسمت توضیح دادیم که چطور با استفاده از ابزار RKE یک کلاستر کوبرنتیز راه‌اندازی کنیم.

توصیه می‌کنم که حتما این پست‌ها رو هم مطالعه کنید. بریم که ادامه بدیم.


Kubernetes Storage Objects
Kubernetes Storage Objects

قدم به قدم با هم بررسی می‌کنیم که از چه طریقی می‌تونیم به پادهامون توی کلاستر به استورج دسترسی بدیم و این دسترسی رو محدود کنیم و مدیریتش رو انجام بدیم.

اول ببینیم که Volume توی کوبرنتیز چیه؟

Volumes:

یه کوبرنتز والیوم در واقع یه دایرکتوری هست که شامل دیتایی میشه که در دسترس یک کانتینر هستن توی یه پاد مشخص توی کلاستر. بذارید در ادامه یه خرده بهتر اینو توضیح بدم و یه یادآوری کنیم از پست‌های داکر.

image layers
image layers

توی مثال بالا یه پاد رو می‌بینیم سمت چپ که برای نوشتن دیتای خودش همونطور که قبلا توضیح دادیم روی یک لایه writeable بالای لایه‌های ایمیج کانتینر که فقط خواندنی هستند، مینویسه. اگه میخواید دقیق‌تر در موردش بدونید این بلاگ پست در مورد تکنولوژی که داکر ازش استفاده میکنه رو بخونید و Union FS رو اونجا ببینید. حالا اگه این کانتینر سمت چپ به هردلیلی از بین بره دیتایی هم که توی لایه سبز رنگ نوشته پاک میشه و کانتینر جدید سمت راست که جایگزینش میشه دیگه اون دیتا رو نداره و از اول باید توی لایه نوشتنی خودش دیتا رو بنویسه. اگه اون دیتا و فایل‌هایی که توی لایه سبز رنگ توسط کانتینر نوشته میشه برامون اهمیت داشته باشه باید به طریقی اون رو از کانتینر خارج کنیم و در بیرون کانتینر جایی اون رو نگهداریم.

volume in kubernetes
volume in kubernetes

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

حالا بریم ببینم انواع والیوم توی کوبرنتیز چی هستن؟

hostPath:

قبل از اینکه توضیحش بدم لازمه بدونید که به هیچ عنوان استفاده از این مدل والیوم توصیه نمیشه و نباید ازش استفاده کنید! مشکل امینتی داره و اگر درست کانفیگ نکنید هر کی می‌تونه به راحتی ادمین کوبرنتیز بشه و کلا کلاستر رو بفرسته اردوگاه توریستی که اصلا چیز مطلوبی نیست. این نوع از والیوم یه‌جورایی شبیه bind mount توی داکر هست.

hostpath
hostpath

والیوم از نوع hostPath یک فایل یا دایرکتوری هست که به صورت مستقیم از فایل سیستم نود کوبرنتیز mount میشه به پاد در حالیکه این میزان از دسترسی به فایل سیستم برای پاد دسترسی زیادی هست و میتونه خطرات امنیتی زیادی رو برامون به همراه بیاره. مثلا فرض کنید ما اومدیم یه مقدار دیسک بدیم به یه پاد که دیتاشو اونجا نگه‌داره بعد اون پاد از همون طریق سکرت‌های ادمین کلاسترمون رو تونسته بره برداره!!! چون دسترسی‌ای که بهش دادیم بیشتر از نیازیه که داشته. میتونید اینجا بیشتر در مورد hostPath بخونید. کلا توصیه می‌کنم که این نوع والیوم رو کلا جلوش رو بگیرید یا فقط یه سری مسیر‌های خاص رو بهش اجازه بدید.

emptyDir:

این نوع والیوم زمانیکه پاد به یک نود اختصاص داده میشه، ساخته میشه و مثل اسمش از اول خالیه. تمام کانتینرهای توی پاد میتونن توی این والیوم بنویسن و ازش بخونن، بنابراین این والیوم میتونه در مسیرهای یکسان یا متفاوت توی کانتینرهای مختلف mount بشه. زمانیکه پاد از روی نود کلاستر پاک بشه به هردلیلی، دیتای emptyDir هم به صورت کامل پاک میشه. اما crash کردن کانتینر درون پاد منجر به پاک شدن دیتای این نوع والیوم نمیشه. مثلا ازین نوع والیوم میتونیم برای چک پوینت گذاشتن طی انجام یک فرآیند محاسباتی استفاده کنیم تا اگر کانتینری crash کرد دیتا از بین نره.

emptyDir
emptyDir

توی کوبرنتیز emptyDir.medium کنترل میکنه که والیوم کجا ذخیره بشه، به صورت دیفالت والیوم‌های emptyDir روی همونجایی که نود بهش برمیگرده ذخیره میشن حالا میتونه دیسک HDD باشه یا SSD یا نتورک استورج. حتی میتونیم emptyDir.medium رو روی Memory تنظیم کنیم و عملکردی شبیه tmpfs توی داکر رو داشته باشیم و دیتای والیوم روی RAM ذخیره بشه، فقط در این حالت محدود به حجم مموری هستیم که باید حواسمون بهش باشه.

به طور کلی والیوم هارو توی کوبر میتونیم توی دوتا دسته کلی جا بدیم دسته اول Ephmeral Volumeها و دسته دوم که در ادامه توضیح میدیم Persistent Volumeها. دسته اول در واقع والیوم‌هایی هستن که ماندگار نیستند مثل همین emptyDir که توضیش دادیم، انواع دیگه‌ای مثل configMap و downwardAPI و secret هم هستند توی این دسته که هرکدوم استفاده‌های خودشون رو دارند، اینجا میتونید بیشتر در مورد والیوم‌های Ephemeral بخونید.

اما دسته دوم والیوم‌های ‌Persistent هستند که در ادامه توضیح میدیم در موردشون.

Persistent Volume:

این نوع والیوم یک API کوبرنتیز رو در اختیار ادمین کلاستر میذاره که جزئیات و پیچیدگی‌های دسترسی به استورج رو پنهان میکنه و در قالب یک مفهوم abstract امکان استفاده از استورج رو فراهم میکنه. یک PV یا PersistentVolume قسمتی از استورج هست که توسط ادمین کلاستر یا مکانیزمی که در ادامه توضیحش میدیم یعنی استفاده از استورج‌کلاس ایجاد شده.

خب پس حالا که دسترسی ایجاد این نوع والیوم رو فقط ادمین کلاستر داره، پس یوزر کلاستر اصلا چجوری ازین والیوم استفاده کنه؟

مفهومی رو در کوبرنتیز داریم تحت عنوان Persistent Volume Claim که به نوعی می‌تونیم بگیم درخواستی هست برای PV، یعنی یوزر کلاستر با استفاده از PVC یه درخواست میده که من PV میخوام بدون اینکه نیاز باشه چیزی از جزئیات پیاده‌سازی و موارد مربوط به کلاستر و یا پروایدری که داره سرویس رو ارائه میده و نحوه ایجاد استورج بدونه.

PV and PVC
PV and PVC

بنابراین همانطور که در تصویر بالا می‌بینیم دولوپر به عنوان یوزر کلاستر نیاز داره که یک والیوم درون پاد قرار بده و این نیاز رو از طریق PVC اعلام میکنه. اما به Persistent Volume های کلاستر دسترسی نداره و اونها رو ادمین کلاستر مدیریت میکنه و باید از طریق ادمین مورد تایید قرار بگیره تا دسترسی به استورج به پاد داده بشه.

نکته‌ی مهم اینه که می‌شد مفهومی مثل PV وجود نداشته باشه ولی این طوری باید دسترسی استوریج خودمون که چیز مهمی هم هست رو در اختیار همه‌ی استفاده کننده‌های کلاستر قرار بدیم که خب حتما می‌دونید دسترسی که زیاد در اختیار دیگران باشه کلا می‌تونیم پابلیک در نظرش بگیریم چون پخش می‌شه و نمی‌تونیم جلوش رو بگیریم. ولی مفهوم PV وجود داره که این دسترسی در اختیار ادمین کلاستر باقی بمونه و پخش نشه.

مطلب دیگه‌ای که خوبه اینجا اشاره کنیم بحث مودهای دسترسی والیوم هست یا همون Access Modeها.

Access Modes
Access Modes
  • حالت Read Write Once که در اون والیوم میتونه برای خواندن و نوشتن به یک پاد یا پروسه mount بشه. که همون نوع بلاک استوریج هست که از انواع سرویس‌های استوریج می‌باشد.

  • حالت Read Write Many که در اون والیوم میتونه به چندین پاد یا پروسه mount بشه که هم از اون بخونن و هم بتونن در والیوم بنویسن. این حالت رو بهش مالتی اتچ‌منت هم می‌گن که فقط نوع فایل share استوریج می‌تونه در اختیار ما قرار بده.

  • حالت Read Only Many که در اون چندین پاد یا پروسه میتونن فقط از والیوم بخونند. حالت باحالی هست. فقط خواندنی اما برای تعدادی زیاد که داستان پر کردن دیتای آن باحاله. کلا وقتی فقط خواندنی هست چطوری داخلش دیتا می‌ریزن که بعدش بخونند. این والیوم‌ها از یه والیوم دیگه می‌تونن کلون بشن و بعدش دیگه فقط خواندنی هستند.

  • و نهایتا حالت Read Write Once Pod که در کوبرنتیز ورژن 1.22 به بعد ساپورت می‌شود و در اون تنها یک پاد میتونه برای خواندن و نوشتن از والیوم استفاده کنه.


Storage Class:

Static Provisioning
Static Provisioning

تا به اینجای کار روال نوعی از اختصاص حافظه که به اون static provisioning گفته میشه و فهمیدیم که دسترسی استورج رو نباید به یوزر به شکل مستقیم بدیم و PVهارو ادمین کلاستر مدیریت میکنه فقط، اما حالا که فقط ادمین میتونه دسترسی داشته باشه یعنی ما pend اون میمونیم برای والیوم گرفتن؟ یعنی هر کاربری که والیوم بخواد باید صبر کنه تا ادمین تایید بده؟ خیلی مسیر خوبی نیست. اینطوری مدام ما پند ادمین می‌شیم و یا ادمین به جای انجام کارهای مهم دیگه باید همش بیاد والیوم بسازه و در اختیار ما قرار بده که اصلا مسیر مطلوبی نیست و خیلی به کوبرنتیز و فرآیند‌هایی که تا الان در موردش صحبت کردیم نمی‌خوره.

Dynamic Volume Provisioning
Dynamic Volume Provisioning

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

Dynamic Volume Provisioning
Dynamic Volume Provisioning

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

و اصطلاحا در این روش flow ایجاد PV و PVC به صورت خودکار انجام می‌شود.

Storage Class
Storage Class

در تصویر بالا مراحل رو به ترتیب می‌بینیم که ابتدا ادمین کلاستر استورج‌کلاس رو ایجاد میکنه سپس کاربر یک پاد رو میسازه و میتونه ببینه که چه استورج‌کلاس‌هایی توی کلاستر ساپورت میشه و در مرحله بعد با قراردادن استورج‌کلاسی که انتخاب میکنه در PVC به صورت خودکارprovisioner برای این درخواست PV مناسبش رو آماده میکنه.

توی پست‌های قبلی مسیر کوبرنتیز در مورد pod phase گفته بودیم، والیوم‌ها هم میتونن توی phaseهای مختلفی باشند.

  • والیوم Available به ریسورسی میگیم که هنوز به هیچ pvc اختصاص داده نشده.

  • والیوم Bound به والیومی میگیم که به یک pvc اختصاص داده شده.

  • والیوم Released به والیومی گفته میشه pvc اون پاک شده اما هنوز ریسورسی که گرفته به کلاستر برنگشته یا اصطلاحا reclaim نشده.

  • والیوم Failed به والیومی گفته میشه که توی فرآیند reclamation به خطا خورده و به صورت خودکار reclaim نشده.


در انتهای این قسمت از بلاگ پست‌های کوبر هم خوبه که چنتا مفهوم دیگه رو مرتبط با بحث استورج‌ها معرفی کنیم.

مثل استورج‌ها مفاهیم مشابهی رو برای اسنپ‌شات داریم.

snapshot in kubernetes
snapshot in kubernetes


یعنی VolumeSnapshot داریم که مثل pvc هست و به نوعی درخواست یوزر برای اسنپ‌شات گرفتم از یک والیوم هست. VolumeSnapshotContent که مثل pv هست و همون اسنپ‌شات گرفته شده از یک والیوم هست که توی کلاستر توسط ادمین ایجاد شده و مشابه استورج‌کلاس VolumeSnapshotClass رو داریم که کلاس‌های مختلف استورج رو برای والیوم در اون ایجاد می‌کنیم.

و شبیه کانفیگ و secret که توی داکر داشتیم اینجا توی کوبرنتیز هم configMap و secret رو داریم که جزو Ephemeral storage هستند که بالاتر توضیح دادیم و اگه بخواید میتونید در لینک‌هایی که براشون گذاشتیم بیشتر در مورد اونها بخونید.


در ادامه مسیر میریم سراغ ادامه مطالب کوبرنتیز و موارد مربوط به probe رو بررسی می‌کنیم.

مراقب خودتون باشید. 🌹🐳🌹



با ما متخصص شوید
با ما متخصص شوید

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

🫀 Follow DockerMe 🫀

🔔 Follow YouTube 🔔

📣 Follow Instagram 📣

🖇 Follow LinkedIn DockerMe🖇

🔎 Follow Linkedin Ahmad Rafiee 🔎

🕊 Follow Twitter 🕊

kubernetesکوبرنتیزstorage
۹
۰
احمد رفیعی
احمد رفیعی
مشاور زیرساخت. موسس سایت آموزشی DockerMe.ir
شاید از این پست‌ها خوشتان بیاید