راهنمای تخصصی پلتفرم ابری و Kubernetes برای مبتدیان
برای استفادهی تخصصی از پلتفرم ابری آروان نیاز است که با مفاهیم پایه Kubernetes آشنایی پیدا کنید. در این بخش بهشکل کلی به بررسی مفاهیم عمومی خواهیم پرداخت و پس از آن با مراجعه به مقالات تخصصی میتوانید اطلاعات دقیقتری در مورد هر کدام از مفاهیم پایه پلتفرم ابری بدست آورید.
مقدمه
در صورتی که با فرآید استقرار نرمافزار درگیر بودهاید با مراحل مختلف آن آشنایی دارید. مثلا برای استقرار backend applicationای که با laravel php نوشتهاید. نیاز دارید یک سرور خریداری کنید. بعد از نصب سیستمعامل پیشنیازهای نرمافزار خود مانند php-fpm را نصب کنید. با نصب nginx یا apache ترافیک را به نرمافزار خود برسانید. fpm و nginx را برای serve درخواستهای کاربران پیکربندی کنید. در پایان با خرید دامنه و تنظیم کردن آن بر روی ip سرور، ترافیک کاربران را به سرور هدایت کنید.
مهمترین بخشی که پلتفرم ابری ابر آروان به شما کمک میکند و به کار شما سرعت میبخشد، همین بخش استقرار نرمافزار است.
به این دلیل که پلتفرم ابری آروان بر مبنای Kubernetes (یا بهطور دقیقتر OpenShift) طراحی شده، در این مقاله به بررسی مفاهیم کلی آن و همینطور ارتباط این مفاهیم با روال سنتی استقرار نرمافزار میپردازیم.
Kubernetes چیست و چگونه از آن استفاده میکنیم؟
برای درک بهتر از Kubernetes به پروسهی سنتی استقرار نرمافزار برمیگردیم.
۱- اجرای نرمافزار
در این پروسه شما نیاز دارید نرمافزار خود را روی سرور اجرا کنید. معمولا این کار با انتقال فایلهای نرمافزار روی سرور انجام میشود. مثلا اگر یک پروژهی laravel php داشته باشید فایلها را به سرور منتقل میکنید؛ یا اگر پروژهی شما به golang نوشته شده باشد، فایل کامپایل شدهی پروژه را به سرور میفرستید.
در Kubernetes دقیقا همین پروسه انجام میشود. با این تفاوت که نرمافزار شما باید داخل کانتینر (container) قرار گیرد. کانتینر در واقع همان فایل یا فایلهای اجرای نرمافزار شماست که داخل یک فایل آرشیوی (فایل tar) قرار گرفته و بعد از انتقال بر روی سرور اجرا میشود.
کانتینرها یک تفاوت دیگر هم با اجرای مستقیم روی سرور دارند؛ اینکه نرمافزار شما وقتی بهصورت کانتینر (مثلا با استفاده از docker) روی سرور اجرا میشود، دسترسیهای بسیار محدودتری دارد و حتی میتوان میزان استفاده از منابع آن را از کل منابع سیستم محدودتر کرد. مثلا میتوان از هشت هسته پردازشگر، یک هسته و حتا ۰.۵ هسته را به آن اختصاص داد. همچنین، بهدلیل محدودیتهای زیاد اجرای نرمافزار داخل کانتینر، نرمافزار شما حتی به کتابخانههای (libraries) سیستمعامل هم دسترسی ندارد. به همین دلیل شما برای ساخت کانتینر نرمافزار خود، باید تمامی کتابخانههای مورد نیاز را درون کانتینر، قرار دهید.
یک تفاوت دیگر در اجرای نرمافزار درون کانتینر، با روش سنتی دارد، موقتی و میرا بودن (ephemeral) حافظهی آن است! یعنی شما هر میزان اطلاعاتی که بعد از اجرای نرمافزار داخل کانتینر، روی دیسک بنویسید، تمامی فایلهای این اطلاعات نوشته شده بعد از اجرای مجدد نرمافزار بر اثر restart کردن container یا توقف آن به هر صورت دیگری، از بین خواهد رفت. به همین دلیل برای اجرای نرمافزارهایی مانند پایگاههای داده، نیاز است دیسک دائمی به کانتینر خود متصل کنید.
توجه داشته باشید که در Kubernetes نرمافزارها بهجای اینکه در داخل کانتینر اجرا شوند، داخل یک pod اجرا میشوند، اما توضیح تفاوتهای pod و container از حوصله این مقاله خارج است، و از دید کاربری در اکثر موارد میتوانید این دو را معادل فرض کنید.
۲- مدیریت اجرای نرمافزار
اگر تاکنون نرمافزاری را روی سرور مستقر کرده باشید احتمالا به این موضوع برخوردهاید که همیشه به سرویسی احتیاج است که در صورت به خطا خوردن نرمافزار شما یا اینکه ریست شدن سرور، نرمافزار شما را دوبار اجرا کند. مثلا شاید از systemd و یا upstart برای این کار استفاده کرده باشید. (البته در مورد زمانی که از سرویس مانند php-fpm برای اجرای نرمافزار استفاده میکنید، در واقع systemd اجرای php-fpm را مدیریت میکند و نرمافزار شما توسط php-fpm اجرا میشود.)
در این حالت مثلا سرویسی که برای systemd تعریف کردهاید تضمین میکند که نرمافزار شما همیشه روی سرور در حال اجرا باشد.
به عنوان مثال نرمافزار sshd که مسئول پذیرش درخواستها ssh به سرور در لینوکس است، سرویسی بهصورت زیر در محل /etc/systemd/system/sshd.service دارد:
[Unit] Description=OpenBSD Secure Shell server After=network.target auditd.service ConditionPathExists=!/etc/ssh/sshd_not_to_be_run [Service] EnvironmentFile=-/etc/default/ssh ExecStartPre=/usr/sbin/sshd -t ExecStart=/usr/sbin/sshd -D $SSHD_OPTS ExecReload=/usr/sbin/sshd -t ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartPreventExitStatus=255 Type=notify [Install] WantedBy=multi-user.target Alias=sshd.service
فایل بالا و استارت کردن سرویس sshd با استفاده از دستور systemctl start sshd.service این تضمین را میدهد که همیشه سرویس بالا بوده و حتی در صورت مختل شدن و توقف نرمافزار، دوباره آن را اجرا کند.
مشابه همین موضوع، در Kubernetes مفهوم Deployment وجود دارد با یک تفاوت بسیار مهم. سرویسهای systemd و یا سرویسهای مشابه، این قابلیت و تضمین را به شما میدهند که نرمافزار شما روی یک سرور همیشه در حال اجرا باشد، در حالی که Deployment این تضمین را میدهد که نرمافزار شما روی یکی از سرورهای کلاستر Kubernetes در حال اجرا باشد و شما بهطور معمول کنترلی برای اینکه نرمافزار روی چه سروری اجرا شود اعمال نمیکنید و حتی از آن مطلع نیستید.
این یک قابلیت بسیار مهم Kubernetes است که شما مستقل از اینکه اطلاعی از وضعیت سرور خود داشته باشید، مطمئن هستید که حتی اگر سروری که نرمافزار شما بر روی آن قرار دارد به هر دلیلی از دسترس خارج شود، نرمافزار شما روی سروری دیگری از کلاستر اجرا خواهد شد.
همچنین با توجه به همین قابلیت مهم، شما میتوانید بهراحتی تعریف کنید که چند نسخه از نرمافزار شما روی کلاستر اجرا شود (با تعریف تعداد replica)، و بدون اینکه مطلع باشید کانتینر نرمافزار شما روی هر تعداد سروری که موجود باشید اجرا خواهد شد.
برای تعریف هر نوع ماهیتی در Kubernetes از جمله Deployment معمولن از فایلهای yaml استفاده میشود. این فایلها که توسط شما باید ساخته شود، تعیین میکند که مثلن Deployment شما، کانتینر نرمافزار را از کجا دریافت نماید، چه تعداد نسخه از نرمافزار شما را اجرا کند، و یا اینکه چه حجم از منابع پردازشی و حافظه را به نرمافزار شما اختصاص دهد. بهعنوان مثال فایل yaml مربوط به Deployment یک نرمافزار nginx را میتوانید اینجا مشاهده کنید:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 2368 protocol: TCP resources: limits: cpu: '1' ephemeral-storage: 2G memory: 1G requests: cpu: '1' ephemeral-storage: 2G memory: 1G
به غیر از ماهیت Deployment ماهیتهای دیگری نیز برای مدیریت وضعیت اجرای پادها مانند SatefulSet وجود دارند که مجال توضیح بیشتر در اینجا برای این ماهیتهای وجود ندارند.
به دلیلی وجود این ماهیتهای مختلف، در پنل ابر آروان تمامی اینها بهعنوان یک اپلیکیشن در صفحه اول لیست میشوند و مدل (kind) این ماهیت بعنوان زیرتیتر هر کدام از نرمافزارها شما نوشته میشود.
برای مطالعهی بیشتر در مورد Deployment به مقالهی اختصاصی آن مراجعه کنید.
۳- شبکه و توزیع بار
زمانی که نرمافزاری را روی سرور نصب میکنیم، معمولا از سرویسهایی مانند nginx و یا haproxy برای فرستادن ترافیک ورودی به سمت نرمافزار استفاده میشود. این روش این قابلیت را به ما میدهد که مثلن ترافیک ورودی را بین چند سرور تقسیم کنیم و یا اینکه با قرار دادن health-check روی haproxy مطمئن باشیم که در صورت داون شدن یک سرور ترافیک کاربران ما به سمت سروری که سالم است هدایت خواهد شد.
با توجه به ماهیت Deployment توضیح دادیم که در هر زمان ممکن است نرمافزار ما روی یک سرور متفاوت اجرا شود. همچنین بر اساس تنظیماتی که ما برای deployment تعیین کردهایم، میتواند چندین نسخه از نرمافزار روی سرورهای کلاستر اجرا شود. این توزیع بار در داخل کلاستر Kubernetes با استفاده از مفهوم سرویس صورت میگیرد. شما برای هر کدام از نرمافزارهای backend خود و همچنین نرمافزارهای پشتیبان آنها مانند cacheها و پایگاههای داده، و در واقع برای هر deployment باید یک سرویس تعریف کنید. بعنوان مثال برای یک سرویس مانند Redis بعد از تعریف deployment باید service را بصورت زیر تعریف کنیم:
apiVersion: v1 kind: Service metadata: name: redis-service spec: selector: app: redis ports: - name: input protocol: TCP port: 6379 targetPort: 6379
استفاده از Service یک مزیت بسیار مهم دارد. اینکه برای ارتباط بین نرمافزارهای شما دیگر نیازی به استفاده از IP نیست و به راحتی میتوانید با استفاده از نام Service به سایر نرمافزارهای خود داخل کلاستر دسترسی داشته باشید. بهعنوان مثال شما در نرمافزار php خود برای اتصال یه Redisی که در بالا تعریف شده میتوانید به آدرس redis-service:6379 درخواست دهید.
برای مطالعه بیشتر در مورد Service و نحوه استفاده آن در پلتفرم ابری آروان به مقاله اختصاصی Service مراجعه کنید.
همانطور که توضیح داده شد، سرویسها صرفن برای ارتباط داخل کلاستری مورد استفاده قرار میگیرند، اما زمانی که نیاز است که ترافیک کاربران را از خارج دیتاسنتر به نرمافزار خود منتقل کنیم چطور؟
برای این کار در روش سنتی نیاز است که یک دامنه تعریف کرده سپس با قرار دادن یک سرویس مانند Apache و یا nginx ترافیکهای http و https را serve کنیم. در Kubernetes این کار توسط ingress و در OpenShift توسط route صورت میگیرد. تعریف route بسیار راحت بود و صرفن تعیین میکند که ترافیک ورودی به کلاستر برای یک دامنه مشخص به چه Serviceی منتقل شود. شما پس از تعریف Service برای Deployment نرمافزار خود، به راحتی میتوانید ترافیک را از خارج از کلاستر به داخل هدایت کنید. بهعنوان مثال در زیر تعریف یک route را میتوانید مشاهده کنید:
apiVersion: v1 kind: Route metadata: name: my-app-route spec: host: my-app-example-project.apps.ir-thr-at1.arvan.run to: kind: Service name: nginx-service tls: termination: edge insecureEdgeTerminationPolicy: Allow port: targetPort: http
برای مطالعه بیشتر در مورد route و نحوه پیکربندی آن برای دریافت ترافیک از خارج کلاستر به مقالهی اختصاصی route مراجعه نمایید.
۴- پیکربندی نرمافزار
احتمالن برای تولید هر نرمافزار نیاز است یک یا چند فایل config داشته باشیم تا نرمافزار اطلاعاتی مانند آدرس و رمز دسترسی به پایگاه داده را از روی این فایلها بخواند. این اطلاعات ممکن است مثل اطلاعات دسترسی به پایگاه داده دارای محرمانگی بالایی باشند و یا اینکه اطلاعات غیرمحرمانهای باشند مانند اینکه نرمافزار روی چه دامنهای سرو میشود.
در مدل استقرار سنتی تنظیم اطلاعات config یا پیکربندی معمولن با یک یا چند فایل بر روی سرور انجام میشوند که sysadmin یا مسئول سرور با اعمال تغییر در این فایل تنظیمات نرمافزار را تغییر میدهد.
در Kubernetes گرچه میتوان فایل پیکربندی را داخل کانتینر قرار داد، اما این کار ضمن اینکه از لحاظ امنیت توصیه نمیشود، امکان تغییر در آن را سخت میکند. برای این منظور مفاهیم Secret و ConfigMap وجود دارند که میتوانند با attach شدن به کانتینر نرمافزار شما بهعنوان یک فایل خوانده شوند و همچنین امنیتی بالاتری برای تنظیمات حساس شما ایجاد میکنند. (بطور کلی تفاوت زیادی بین Secret و ConfigMap وجود ندارد و صرفن توصیه میشود اطلاعات محرمانه را با استفاده از Secret برای نرمافزار تعریف کنید.)
برای مطالعه اطلاعات دقیقتر در مورد این مفاهیم به مقاله اختصاصی Secret مراجعه نمایید.
جمعبندی
بهطور کلی میتوانید Kubernetes را بهعنوان یک فرد مسئول (agent) در نظر بگیرید که همواره در تلاش است با مانیتور کردن مستمر وضعیت فعلی کلاستر (current state) آن را به وضعیت مطلوبی (desired state) که شما تعریف میکنید برساند. وجود تفاوتی بین این دو وضعیت مثلا تعریف deployment جدید و یا سوختن یک سرور و کم شدن تعداد نسخههای فعال نرمافزار شما منجر به انجام یک عمل در جهت تغییر وضعیت فعلی به سمت وضعیت مطلوب شما خواهد شد.
پلتفرم ابری و Kubernetes، زیرساختهایی هستند در جهت سادهسازی پروسه استقرار نرمافزار و سهولت مدیریت منابع سختافزاری، پیادهسازی نرمافزار بر این بسترها این امکان را به شما میدهد که در کمترین زمان ممکن، نرمافزار خود را به مرحله اجرای کامل رسانده و همچنین بدون داشتن دغدغه زیرساخت، نرمافزار خود را مدیریت کنید.
برای دریافت راهنماهای اجرای مفاهیم ذکر شده میتوانید به بخش راهنمای پلتفرم ابری مراجعه کرده و همچنین برای مطالعهی سناریوهای پیادهسازی نرمافزارهای مختلف به بخش مقالات مراجعه نمایید.