اگر دنبال راهنمایی برای دیپلوی اولین اپلیکیشنتان روی کوبرنتیز هستید، باید بگویم که جای درستی آمدهاید. در این مطلب از وبلاگ همروش قصد داریم بهصورت مرحله به مرحله شیوه دیپلوی یا استقرار یک اپلیکیشن روی کوبرنتیز را از ابتدا پیش ببریم و بهصورت کامل با این فرایند آشنا شویم. برای دنبال کردن این آموزش نیازی نیست که توسعهدهنده حرفهای باشید، تمام موارد این مطلب براساس موضوعات ابتدایی نوشته شده است.
چرا باید از کوبرنتیز استفاده کنیم؟
کوبرنتیز به عنوان یک سیستم ارکستریشن کانتینر، امکانات بسیاری را فراهم میکند که توسعه و مدیریت برنامههای مدرن را سادهتر و کارآمدتر میسازد. یکی از اصلیترین دلایل استفاده از کوبرنتیز، خودکارسازی فرآیندهای پیچیده است. این سیستم به طور خودکار وظایفی مانند مقیاسدهی، توزیع ترافیک، و نظارت بر سلامت کانتینرها را انجام میدهد، که باعث کاهش بار کاری تیمهای توسعه و عملیات میشود.
کوبرنتیز از قابلیت خود ترمیمی برخوردار است، بدین معنا که در صورت بروز خطا در یکی از کانتینرها یا نودها، به طور خودکار تلاش میکند آن را بازیابی کند. این ویژگی به تضمین بالاترین سطح در دسترس بودن برنامهها کمک میکند. همچنین، کوبرنتیز از کانتینرها در محیطهای مختلف اعم از سرورهای محلی، مراکز داده خصوصی، و ابرهای عمومی پشتیبانی میکند، که این امر باعث افزایش انعطافپذیری در انتخاب زیرساخت میشود.
با استفاده از کوبرنتیز، توسعهدهندگان میتوانند برنامههای خود را به صورت میکروسرویس پیادهسازی کنند، که این رویکرد به بهبود قابلیت مقیاسپذیری و نگهداری کمک میکند. به علاوه، با استفاده از فایلهای پیکربندی قابل تعریف، میتوان به راحتی محیطهای توسعه، آزمایش و تولید را همسانسازی کرد و از بروز مشکلات ناسازگاری محیطی جلوگیری نمود.
کوبرنتیز همچنین امکان یکپارچهسازی با ابزارهای مختلف CI/CD (توسعه و استقرار پیوسته) را فراهم میکند، که این موضوع به تسریع فرآیندهای توسعه و انتشار نرمافزار منجر میشود. با توجه به این مزایا، کوبرنتیز یک ابزار حیاتی برای توسعهدهندگان و تیمهای عملیات فناوری اطلاعات است که به دنبال بهبود کارایی، کاهش هزینهها و افزایش قابلیت اطمینان سیستمهای خود هستند.
پیشنیازها
برای استفاده و استقرار اپلیکیشن روی کوبرنتیز نیاز است که ابتدا کوبرنتیز را روی Master Node و Worker Node نصب کنید. برای انجام اینکار میتوانید براساس قطعه کدهای زیر پیش بروید. هر بخش بهصورت کامنت از همدیگر جدا شده است:
-------------------------------------- Both Master & Worker Node ---------------------------------------
sudo su
apt update -y
apt install docker.io -y
systemctl start docker
systemctl enable docker
curl -fsSL "https://packages.cloud.google.com/apt/doc/apt-key.gpg" | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-archive-keyring.gpg
echo 'deb https://packages.cloud.google.com/apt kubernetes-xenial main' > /etc/apt/sources.list.d/kubernetes.list
apt update -y
apt install kubeadm=1.20.0-00 kubectl=1.20.0-00 kubelet=1.20.0-00 -y
# To connect with cluster execute above commands on master node and worker node respectively
--------------------------------------------- Master Node --------------------------------------------------
sudo su
kubeadm init
# To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
kubeadm token create --print-join-command
------------------------------------------- Worker Node ------------------------------------------------
sudo su
kubeadm reset pre-flight checks
-----> Paste the Join command on worker node and append `--v=5` at end
#To verify cluster connection
---------------------------------------on Master Node-----------------------------------------
kubectl get nodes
# worker
# kubeadm join 172.31.84.66:6443 --token n4tfb4.grmew1s1unug0get --discovery-token-ca-cert-hash sha256:c3fda2eaf5960bed4320d8175dc6a73b1556795b1b7f5aadc07642ed85c51069 --v=5
# kubeadm reset pre-flight checks
# kubeadm token create --print-join-command
# kubectl label node ip-172-31-20-246 node-role.kubernetes.io/worker=worker
# kubectl label nodes ip-172-31-92-99 kubernetes.io/role=worker
# kubectl config set-context $(kubectl config current-context) --namespace=dev
برای کوتاه کردن آموزش، ما از یک پروژه آماده جنگو استفاده میکنیم که داکرایز شده است. برای اینکار از این مخزن، پروژه را Clone میکنیم.
با مشاهده dockerfile این مخزن میتوانیم کدهای زیر را مشاهده کنیم:
FROM python:3
WORKDIR /data
RUN pip install django==3.2
COPY . .
RUN python manage.py migrate
EXPOSE 8000
CMD ["python","manage.py","runserver","0.0.0.0:8000"]
همانطور که مشاهده میکنید پروژه مورد نظر با زبان پایتون نوشته شده و براساس جنگو نسخه ۳.۲ کار میکند.
در مرحله بعدی نیاز است که با استفاده از داکرفایل پروژه را Build کنیم. برای این کار وارد دایرکتوری پروژه شده و دستور زیر را اجرا کنید:
docker build . -t django-todo:latest
حال برای مطمئن شدن از موفقیتآمیز بودن دستور بالا، میتوانید دستور docker image را وارد کنید تا لیستی از imageها را مشاهده کنید. در صورت وجود ایمیج django-todo میتوانید مطمئن شوید که همه چیز به درستی پیش رفته است.
بعد از انجام تمام موارد بالا نیاز است که ایمیج مربوطه را به رجیستری push کنید. برای این کار ابتدا با دستور docker login
فرایند ورود به داکرهاب را طی کنید. با وارد کردن این دستور از شما نامکاربری و رمزعبور پرسیده خواهد شد.
بعد از ورود موفقیتآمیز، میتوانید با استفاده از دستور docker push image-name
، ایمیج خود را به رجیستری ارسال کنید. برای آشنایی بیشتر با مفهوم رجیستری میتوانید مطلب «کانتینر رجیستری (container registry) چیست؟» را مطالعه کنید.
پیادهسازی کوبرنتیز
برای استفاده از قابلیت کوبرنتیز، دو راهکار کلی وجود دارد:
- استفاده از رابط کاربری متنی
- تعریف فایل YAML
در روش اول با استفاده از ابزار kubectl شما امکان ارتباط برقرار کردن با کلاستر کوبرنتیز را خواهید داشت. این ابزار شامل مجموعهای از دستورات است که برای مدیریت کوبرنتیز استفاده میشود.
در روش دوم، ما یک فایل YAML را ایجاد میکنیم و تمام ویژگیها و وضعیتهای مورد نظر را در آن ذکر خواهیم کرد. پادها، دیپلویمنتها، ConfigMap و… را میتوان در این فایل مشخص کرد.
در این آموزش ما قصد داریم از روش دوم، یعنی تعریف فایل YAML استفاده کنیم.
تعریف پاد
در قدم اول فایلی با نام pod.yml ایجاد میکنیم و قطعه کد زیر را در آن قرار میدهیم:
apiVersion: v1
kind: Pod
metadata:
name: django-app
spec:
containers:
- name: django-app
image:django-todo:latest
ports:
- containerPort: 8000
برای آشنایی با قطعه کد بالا نیاز است که هر بخش را جداگانه توضیح دهیم:
apiVersion
: مشخص کردن نسخه Kubernetes API که در این فایل مورد استفاده قرار میگیرد.kind
: در این بخش «نوع» منابع کلاستر کوبرنتیز مشخص میشود که در این مثال pod است.metadata
: این فیلد شامل متادادههای مربوط به هر پاد میشود.spec
: تعریف وضعیت مطلوب پاد.containers
: آرایهای از کانتینرها که در این پاد باید اجرا شوند. در این مثال ما تنها یک کانتینر داریم.name
: نام کانتینر مورد نظر.image
: نام و نسخه ایمیج مورد نظر.ports
: تعیین پورتهایی که کانتینر expose میکند.
حال برای اعمال این فایل روی کلاستر کوبرنتیز و انجام بهروزرسانیها نیاز است که دستور زیر را اجرا کنید:
kubectl apply -f pod.yml
برای مطمئن شدن از ایجاد پاد در درون namespace، میتوانید دستور زیر را وارد کنید:
kubectl get pods -n=my-django-app
برای حذف کردن پاد مربوطه نیز کافیست دستور زیر را وارد کنید:
kubectl delete -f pod.yml
دیپلویمنت
در Kubernetes، دیپلویمنت ابزاری است که برای اجرای برنامههای کانتینریشده استفاده میشود. دیپلویمنت به ما کمک میکند تا مدیریت مقیاسپذیری، بهروزرسانی و پایداری اپلیکیشن را سادهتر پیش ببریم.
برای آشنایی بیشتر با دیپلویمنت و نقش آن در معماری کوبرنتیز میتوانید به مطلب «آشنایی با معماری کوبرنتیز» مراجعه کنید.
ایجاد فایل دیپلویمنت
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-django-app-deployment
labels:
app: django-app
namespace: my-django-app
spec:
replicas: 3
selector:
matchLabels:
app: django-app
template:
metadata:
labels:
app: django-app
spec:
containers:
- name: django-app-container
image: trajendra/django-todo:latest
ports:
- containerPort: 8000
در این مانیفست ما موارد زیر را تعریف کردهایم:
- kind: در اینجا نوع منبع
Deployment
است که برای مدیریت بهروزرسانی و مدیریت پادها (Pods) استفاده میشود. - selector: این بخش مشخص میکند که کدام پادها باید به این Deployment مرتبط شوند.
- matchLabels: نشان میدهد که هر پادی که لیبل
app: django-app
داشته باشد. - replicas: تعداد کپیهای پاد (Pod) را که باید ایجاد شود، مشخص میکند، در این مانیفست ما ۳ عدد را تعیین کردهایم.
- template: الگوی ایجاد پادها را مشخص میکند.
- matchLabels: نشان میدهد که هر پادی که لیبل
- spec: بخش
spec
مشخصات و رفتار Deployment را تعریف میکند.
برای اعمال این فایل روی کلاستر کوبرنتیز و انجام بهروزرسانیها نیاز است که دستور زیر را اجرا کنید:
kubectl apply -f deployment.yml
Scale یا مقیاسدهی
در کوبرنتیز، مفهوم مقیاسدهی (Scale) به فرآیند تغییر تعداد پادها (یا replicaها) مربوط میشود که برای اجرای یک برنامه استفاده میشوند. این عمل معمولاً برای مدیریت بار کاری و بهینهسازی منابع سیستم انجام میشود.
اگر بخواهیم ۱۰ رپلیکا را برای اپلیکیشن کنونی ایجاد کنیم، میتوانیم با استفاده از kubectl، به شکل زیر عمل کنیم.
kubectl scale deployment my-django-app-deployment --replicas=10 -n=my-django-app
همانطور که در دستور بالا مشاهده میکنید، --replicas=10
تعداد رپلیکا مورد نیاز ما را تعیین میکند. کوبرنتیز با دریافت این دستور، تعداد پادها موجود در دیپلویمنت را با این عدد تنظیم میکند.
سرویس
در حال حاضر شما یک دیپلویمنت همراه با چندین پاد در حال اجرا دارید. هر کدام از این پادها یک IP Address منحصر به فرد دارند که بهصورت پویا تغییر میکنند. اگر شما این پادها را بهصورت مستقیم به کلاینت expose کنید، نیاز است که تغییرات ایجاد شده در IP Addressها را بهصورت دستی مدیریت کنید. کوبرنتیز مکانیزمی به نام Service دارد که این مسئله را برای شما حل خواهد کرد.
پیادهسازی service.yml
فایلی با نام service.yml را ایجاد کرده و کدهای زیر را در آن قرار دهید:
apiVersion: v1
kind: Service
metadata:
name: my-django-app-service
namespace: my-django-app
spec:
type: NodePort
selector:
app: django-app
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 80
targetPort: 8000
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: 30009
- port: مشخص کردن پورت خود Service. در این فایل ما 80 را انتخاب کردهایم.
- targetPort: پورت داخل پاد که برنامه روی آن اجرا میشود.
- nodePort: 30009: یک پورت ثابت که روی هر گره (Node) باز میشود و کاربران از طریق آن میتوانند با آدرس IP نود و آن پورت به سرویس دسترسی پیدا کنند. در این مثال ما از 30009 استفاده کردهایم.
برای درک بهتر مفهوم nodePort، فرض کنید یک اپلیکیشن وب دارید که روی پورت 8080 داخل کانتینر اجرا میشود. با استفاده از نوع سرویس NodePort، میتوانید برنامه را از طریق آدرس IP هر نود در پورت مشخصشده (مانند 30009) در دسترس قرار دهید. انجام این کار برای محیطهای آزمایشی یا سادهسازی دسترسی به برنامه مفید است.
در نهایت برای اعمال تغییرات، دستور زیر را وارد کنید:
kubectl apply -f service.yml
حال میتوانید از طریق پنل سرویسدهنده به اپلیکیشن اصلی خود که روی کوبرنتیز در حال اجرا است دسترسی داشته باشید. به یاد داشته باشید که سرویس شما روی پورت 30009 در دسترس است. در نتیجه URL شما به این شکل خواهد بود:
http://<public_ip_of_instance>:30009
در پایان
در این مطلب از وبلاگ همروش، با اصول اولیه استقرار یک برنامه در Kubernetes آشنا شدیم. مفاهیم کلیدی مانند پادها (Pods)، سرویسها (Services) و دیپلویمنتها (Deployments) را بررسی کردیم و نحوه تعامل آنها را در استقرار یک برنامه ساده وب مشاهده نمودیم. با ایجاد یک پاد، سرویس و دیپلویمنت، توانستیم برنامه را در کلاستر Kubernetes مستقر کنیم.