حالت تاریک
فصل ۳ — استقرار کلاستر Kubernetes
حالا که با موفقیت یک container برنامه ساختید، گام بعدی یادگیری نحوهٔ تبدیل آن به یک سیستم توزیعشدهٔ کامل، قابلاعتماد و مقیاسپذیر است. برای این کار به یک کلاستر Kubernetes در حال اجرا نیاز دارید. در این نقطه، در بیشتر cloudهای عمومی سرویسهای Kubernetes مبتنی بر cloud وجود دارند که با چند دستور خط فرمان میتوان کلاستر ساخت. اگر تازه با Kubernetes شروع کردهاید، این رویکرد را بهشدت توصیه میکنیم. حتی اگر در نهایت قصد دارید Kubernetes را روی bare metal اجرا کنید، راه خوبی است برای شروع سریع، یادگیری خود Kubernetes و سپس یادگیری نصب آن روی ماشینهای فیزیکی. علاوه بر این، مدیریت کلاستر Kubernetes خودش کار پیچیدهای است و برای بیشتر افراد منطقی است که این مدیریت را به cloud واگذار کنند — بهویژه وقتی در بیشتر cloudها سرویس مدیریت رایگان است.
البته استفاده از راهحل مبتنی بر cloud به معنای پرداخت برای منابع cloud و داشتن اتصال شبکهٔ فعال به cloud است. به همین دلیل، توسعهٔ محلی جذابتر میشود و در آن صورت ابزار minikube راهی آسان برای راهاندازی کلاستر Kubernetes محلی در یک VM روی لپتاپ یا دسکتاپ شما فراهم میکند. اگرچه این گزینهٔ خوبی است، minikube فقط یک کلاستر تکnode میسازد که تمام جنبههای یک کلاستر Kubernetes کامل را نشان نمیدهد. به همین دلیل توصیه میکنیم مگر اینکه واقعاً برای شرایط شما جواب ندهد، با راهحل مبتنی بر cloud شروع کنید. جایگزین جدیدتر اجرای کلاستر Docker-in-Docker است که میتواند کلاستر چند-node روی یک ماشین بسازد. این پروژه هنوز در beta است؛ پس در نظر داشته باشید ممکن است با مشکلات غیرمنتظره روبهرو شوید.
اگر واقعاً اصرار دارید روی bare metal شروع کنید، پیوست A در پایان کتاب دستورالعمل ساخت کلاستر از مجموعهای از کامپیوترهای تکبرد Raspberry Pi را میدهد. این دستورالعملها از ابزار kubeadm استفاده میکنند و میتوان آنها را برای ماشینهایی غیر از Raspberry Pi هم تطبیق داد.
نصب Kubernetes روی ارائهدهندهٔ Cloud عمومی
این فصل نصب Kubernetes روی سه ارائهدهندهٔ اصلی cloud را پوشش میدهد: Amazon Web Services، Microsoft Azure و Google Cloud Platform.
اگر cloud provider را برای مدیریت Kubernetes انتخاب کنید، فقط یکی از این گزینهها را نصب کنید؛ وقتی کلاستر پیکربندی و آماده شد میتوانید به بخش «کلاینت Kubernetes» بروید، مگر اینکه ترجیح دهید Kubernetes را جای دیگری نصب کنید.
Google Kubernetes Engine
Google Cloud Platform سرویس میزبانیشدهٔ Kubernetes-as-a-Service به نام Google Kubernetes Engine (GKE) ارائه میدهد. برای شروع با GKE به حساب Google Cloud Platform با billing فعال و ابزار gcloud نصبشده نیاز دارید.
پس از نصب gcloud، ابتدا zone پیشفرض را تنظیم کنید:
bash
$ gcloud config set compute/zone us-west1-aسپس میتوانید کلاستر بسازید:
bash
$ gcloud container clusters create kuar-clusterاین چند دقیقه طول میکشد. وقتی کلاستر آماده شد، credentialها را با این دستور بگیرید:
bash
$ gcloud auth application-default loginاگر به مشکل خوردید، دستورالعمل کامل ساخت کلاستر GKE در مستندات Google Cloud Platform موجود است.
نصب Kubernetes با Azure Kubernetes Service
Microsoft Azure سرویس میزبانیشدهٔ Kubernetes-as-a-Service را بهعنوان بخشی از Azure Container Service ارائه میدهد. آسانترین راه شروع با Azure Container Service استفاده از Azure Cloud Shell داخلی در پورتال Azure است. با کلیک روی آیکون shell در نوار ابزار بالا-راست میتوانید shell را فعال کنید:
شکل ۳-۱. آیکون Azure Cloud Shell در پورتال Azure
shell بهطور خودکار ابزار az را نصب و برای کار با محیط Azure شما پیکربندی میکند.
بهجای آن میتوانید رابط خط فرمان (CLI) az را روی ماشین محلی نصب کنید.
وقتی shell بالا آمد و کار کرد، میتوانید اجرا کنید:
bash
$ az group create --name=kuar --location=westusپس از ساخت resource group، کلاستر را با این دستور بسازید:
bash
$ az aks create --resource-group=kuar --name=kuar-clusterاین چند دقیقه طول میکشد. پس از ساخت کلاستر، credentialها را با این دستور بگیرید:
bash
$ az aks get-credentials --resource-group=kuar --name=kuar-clusterاگر ابزار kubectl را ندارید، با این دستور نصب کنید:
bash
$ az aks install-cliدستورالعمل کامل نصب Kubernetes روی Azure در مستندات Azure موجود است.
نصب Kubernetes روی Amazon Web Services
Amazon سرویس مدیریتشدهٔ Kubernetes به نام Elastic Kubernetes Service (EKS) ارائه میدهد. آسانترین راه ساخت کلاستر EKS از طریق ابزار خط فرمان متنباز eksctl است.
پس از نصب eksctl و قرار دادن آن در path، این دستور را برای ساخت کلاستر اجرا کنید:
bash
$ eksctl create cluster --name kuar-cluster ...برای جزئیات بیشتر گزینههای نصب (مثل اندازهٔ node و موارد دیگر)، help را ببینید:
bash
$ eksctl create cluster --helpنصب کلاستر شامل پیکربندی مناسب برای ابزار خط فرمان kubectl هم میشود. اگر kubectl ندارید، دستورالعملهای مستندات را دنبال کنید.
نصب محلی Kubernetes با minikube
اگر به تجربهٔ توسعهٔ محلی نیاز دارید یا نمیخواهید برای منابع cloud پول بدهید، میتوانید کلاستر سادهٔ تکnode با minikube نصب کنید.
بهجای آن، اگر Docker Desktop را نصب کردهاید، نصب Kubernetes تکماشینی هم همراه آن میآید.
اگرچه minikube (یا Docker Desktop) شبیهسازی خوبی از کلاستر Kubernetes است، واقعاً برای توسعهٔ محلی، یادگیری و آزمایش در نظر گرفته شده. چون فقط در یک VM روی یک node اجرا میشود، قابلیت اطمینان کلاستر توزیعشدهٔ Kubernetes را ندارد.
علاوه بر این، برخی قابلیتهای این کتاب به یکپارچگی با cloud provider نیاز دارند. این قابلیتها یا با minikube در دسترس نیستند یا بهصورت محدود کار میکنند.
برای استفاده از minikube باید hypervisor روی ماشین نصب باشد. در Linux و macOS معمولاً virtualbox است. در Windows hypervisor پیشفرض Hyper-V است. قبل از استفاده از minikube حتماً hypervisor را نصب کنید.
ابزار minikube را در GitHub پیدا میکنید. باینری برای Linux، macOS و Windows قابل دانلود است. پس از نصب minikube، کلاستر محلی را با این دستور بسازید:
bash
$ minikube startاین یک VM محلی میسازد، Kubernetes را provision میکند و پیکربندی kubectl محلی را که به آن کلاستر اشاره میکند ایجاد میکند.
وقتی کار با کلاستر تمام شد، VM را با این دستور متوقف کنید:
bash
$ minikube stopاگر میخواهید کلاستر را حذف کنید:
bash
$ minikube deleteاجرای Kubernetes در Docker
رویکرد دیگری برای اجرای کلاستر Kubernetes اخیراً توسعه یافته که بهجای اجرای همهچیز در virtual machine، از containerهای Docker برای شبیهسازی چند node Kubernetes استفاده میکند. پروژهٔ kind تجربهٔ خوبی برای راهاندازی و مدیریت کلاسترهای تست در Docker فراهم میکند. (kind مخفف Kubernetes IN Docker است.) kind هنوز در حال توسعه است (قبل از ۱.۰)، اما توسط کسانی که Kubernetes میسازند برای تست سریع و آسان بهطور گسترده استفاده میشود.
دستورالعمل نصب برای پلتفرم شما در سایت kind موجود است. پس از نصب، ساخت کلاستر بهسادگی این است:
bash
$ kind create cluster --wait 5m \
$ export KUBECONFIG="$(kind get kubeconfig-path)"
$ kubectl cluster-info
$ kind delete clusterاجرای Kubernetes روی Raspberry Pi
اگر میخواهید با کلاستر Kubernetes واقعگرایانه آزمایش کنید اما نمیخواهید هزینهٔ زیادی بدهید، کلاستر Kubernetes بسیار خوبی را میتوان روی کامپیوترهای Raspberry Pi با هزینهٔ نسبتاً کم ساخت. جزئیات ساخت چنین کلاستری خارج از محدودهٔ این فصل است، اما در پیوست A در پایان کتاب آمده است.
کلاینت Kubernetes
کلاینت رسمی Kubernetes ابزار kubectl است: ابزار خط فرمانی برای تعامل با API Kubernetes. kubectl برای مدیریت بیشتر objectهای Kubernetes مثل Pod، ReplicaSet و Service استفاده میشود. kubectl همچنین برای کاوش و تأیید سلامت کلی کلاستر بهکار میرود.
از ابزار kubectl برای کاوش کلاستری که تازه ساختید استفاده میکنیم.
بررسی وضعیت کلاستر
اولین کاری که میتوانید انجام دهید بررسی نسخهٔ کلاستری است که اجرا میکنید:
bash
$ kubectl versionاین دو نسخهٔ متفاوت نمایش میدهد: نسخهٔ ابزار kubectl محلی و نسخهٔ سرور API Kubernetes.
اگر این نسخهها متفاوت باشند نگران نباشید. ابزارهای Kubernetes با نسخههای مختلف API Kubernetes سازگار عقبرو و جلورو هستند، بهشرطی که برای ابزار و کلاستر در محدودهٔ دو minor version بمانید و قابلیتهای جدیدتر را روی کلاستر قدیمیتر امتحان نکنید. Kubernetes از مشخصات semantic versioning پیروی میکند که minor version عدد میانی است (مثلاً ۵ در ۱.۵.۲).
حالا که ارتباط با کلاستر Kubernetes برقرار است، کلاستر را عمیقتر کاوش میکنیم.
ابتدا یک تشخیص ساده برای کلاستر بگیرید. راه خوبی است برای تأیید اینکه کلاستر بهطور کلی سالم است:
bash
$ kubectl get componentstatusesخروجی باید شبیه این باشد:
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}با تغییر و بهبود Kubernetes در طول زمان، گاهی خروجی دستور kubectl تغییر میکند. اگر خروجی دقیقاً مثل مثالهای کتاب نبود نگران نباشید.
اینجا componentهایی را میبینید که کلاستر Kubernetes را میسازند. controller-manager مسئول اجرای controllerهای مختلفی است که رفتار در کلاستر را تنظیم میکنند؛ مثلاً اطمینان از اینکه همهٔ replicaهای یک service در دسترس و سالم هستند. scheduler مسئول قرار دادن Podهای مختلف روی nodeهای مختلف کلاستر است. در نهایت سرور etcd ذخیرهٔ کلاستر است که همهٔ objectهای API در آن نگهداری میشوند.
فهرست کردن nodeهای worker Kubernetes
بعد میتوانید همهٔ nodeهای کلاستر را فهرست کنید:
bash
$ kubectl get nodes
NAME STATUS AGE VERSION
kubernetes Ready,master 45d v1.12.1
node-1 Ready 45d v1.12.1
node-2 Ready 45d v1.12.1
node-3 Ready 45d v1.12.1میبینید این یک کلاستر چهار-node است که ۴۵ روز است بالا بوده. در Kubernetes، nodeها به master nodeهایی که containerهایی مثل API server، scheduler و غیره را برای مدیریت کلاستر دارند و worker nodeهایی که containerهای شما روی آنها اجرا میشوند تقسیم میشوند. Kubernetes معمولاً کار را روی master nodeها schedule نمیکند تا workloadهای کاربر به عملکرد کلی کلاستر آسیب نزند.
با دستور kubectl describe اطلاعات بیشتری دربارهٔ یک node خاص مثل node-1 بگیرید:
bash
$ kubectl describe nodes node-1ابتدا اطلاعات پایه دربارهٔ node را میبینید:
Name: node-1
Role:
Labels: beta.kubernetes.io/arch=arm
beta.kubernetes.io/os=linux
kubernetes.io/hostname=node-1میبینید این node سیستمعامل Linux دارد و روی پردازندهٔ ARM اجرا میشود.
بعد اطلاعاتی دربارهٔ عملکرد خود node-1:
Conditions:
Type Status LastHeartbeatTime Reason Message
---- ------ ----------------- ------ -------
OutOfDisk False Sun, 05 Feb 2017… KubeletHasSufficientDisk kubelet…
MemoryPressure False Sun, 05 Feb 2017… KubeletHasSufficientMemory kubelet…
DiskPressure False Sun, 05 Feb 2017… KubeletHasNoDiskPressure kubelet…
Ready True Sun, 05 Feb 2017… KubeletReady kubelet…این وضعیتها نشان میدهند node فضای کافی disk و memory دارد و به master Kubernetes گزارش میدهد سالم است. بعد اطلاعاتی دربارهٔ ظرفیت ماشین:
Capacity:
alpha.kubernetes.io/nvidia-gpu: 0
cpu: 4
memory: 882636Ki
pods: 110
Allocatable:
alpha.kubernetes.io/nvidia-gpu: 0
cpu: 4
memory: 882636Ki
pods: 110سپس اطلاعاتی دربارهٔ نرمافزار روی node، از جمله نسخهٔ Docker در حال اجرا، نسخههای Kubernetes و kernel لینوکس و موارد بیشتر:
System Info:
Machine ID: 9122895d0d494e3f97dda1e8f969c85c
System UUID: A7DBF2CE-DB1E-E34A-969A-3355C36A2149
Boot ID: ba53d5ee-27d2-4b6a-8f19-e5f702993ec6
Kernel Version: 4.15.0-1037-azure
OS Image: Ubuntu 16.04.5 LTS
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://3.0.4
Kubelet Version: v1.12.6
Kube-Proxy Version: v1.12.6
PodCIDR: 10.244.1.0/24در نهایت اطلاعاتی دربارهٔ Podهایی که الان روی این node اجرا میشوند:
Non-terminated Pods: (3 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
kube-system kube-dns... 260m (6%) 0 (0%) 140Mi (16%) 220Mi (25%)
kube-system kube-fla... 0 (0%) 0 (0%) 0 (0%) 0 (0%)
kube-system kube-pro... 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
260m (6%) 0 (0%) 140Mi (16%) 220Mi (25%)
No events.از این خروجی Podهای روی node (مثلاً Pod kube-dns که سرویس DNS کلاستر را فراهم میکند)، CPU و memory درخواستی هر Pod از node و مجموع منابع درخواستی را میبینید. شایان ذکر است Kubernetes هم request و هم limit بالایی برای منابع هر Pod روی ماشین را ردیابی میکند. تفاوت request و limit در فصل ۵ با جزئیات توضیح داده میشود، اما بهاختصار: منابع درخواستی یک Pod روی node تضمین میشوند، در حالی که limit یک Pod حداکثر مقدار منبعی است که Pod میتواند مصرف کند. limit یک Pod میتواند از request بالاتر باشد؛ در آن صورت منابع اضافی بهصورت best-effort تأمین میشوند و روی node تضمین نمیشوند.
componentهای کلاستر
یکی از جنبههای جالب Kubernetes این است که بسیاری از componentهایی که کلاستر Kubernetes را میسازند در واقع با خود Kubernetes deploy میشوند. چند مورد را میبینیم. این componentها از مفاهیمی استفاده میکنند که در فصلهای بعد معرفی میشوند. همهٔ این componentها در namespace kube-system اجرا میشوند.¹
Kubernetes Proxy
Kubernetes proxy مسئول مسیریابی ترافیک شبکه به serviceهای load-balanced در کلاستر Kubernetes است. برای انجام کارش، proxy باید روی هر node کلاستر باشد. Kubernetes object API به نام DaemonSet دارد که بعداً در کتاب یاد میگیرید و در بسیاری از کلاسترها برای این کار استفاده میشود. اگر کلاستر شما Kubernetes proxy را با DaemonSet اجرا کند، proxyها را با این دستور میبینید:
bash
$ kubectl get daemonSets --namespace=kube-system kube-proxy
NAME DESIRED CURRENT READY NODE-SELECTOR AGE
kube-proxy 4 4 4 <none> 45dبسته به نحوهٔ راهاندازی کلاستر، DaemonSet برای kube-proxy ممکن است نام دیگری داشته باشد یا اصلاً از DaemonSet استفاده نکند. در هر صورت container kube-proxy باید روی همهٔ nodeهای کلاستر در حال اجرا باشد.
Kubernetes DNS
Kubernetes همچنین سرور DNS اجرا میکند که نامگذاری و discovery برای serviceهای تعریفشده در کلاستر را فراهم میکند. این سرور DNS هم بهصورت service تکرارشونده روی کلاستر اجرا میشود. بسته به اندازهٔ کلاستر ممکن است یک یا چند سرور DNS در کلاستر ببینید. سرویس DNS بهصورت deployment Kubernetes اجرا میشود که این replicaها را مدیریت میکند:
bash
$ kubectl get deployments --namespace=kube-system core-dns
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
core-dns 1 1 1 1 45dهمچنین service Kubernetes برای load balancing سرور DNS وجود دارد:
bash
$ kubectl get services --namespace=kube-system core-dns
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
core-dns 10.96.0.10 <none> 53/UDP,53/TCP 45dاین نشان میدهد سرویس DNS کلاستر آدرس ۱۰.۹۶.۰.۱۰ دارد. اگر به container داخل کلاستر login کنید، میبینید این در فایل /etc/resolv.conf container پر شده است.
با Kubernetes ۱.۱۲، Kubernetes از سرور DNS kube-dns به سرور DNS core-dns منتقل شد. به همین دلیل اگر کلاستر Kubernetes قدیمیتر دارید ممکن است kube-dns ببینید.
Kubernetes UI
component نهایی Kubernetes یک GUI است. UI بهصورت یک replica اجرا میشود، اما همچنان برای قابلیت اطمینان و upgradeها توسط deployment Kubernetes مدیریت میشود. این سرور UI را با این دستور میبینید:
bash
$ kubectl get deployments --namespace=kube-system kubernetes-dashboard
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kubernetes-dashboard 1 1 1 1 45ddashboard هم service برای load balancing دارد:
bash
$ kubectl get services --namespace=kube-system kubernetes-dashboard
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes-dashboard 10.99.104.174 <nodes> 80:32551/TCP 45dمیتوانید با kubectl proxy به این UI دسترسی پیدا کنید. Kubernetes proxy را با این دستور راه بیندازید:
bash
$ kubectl proxyاین سروری روی localhost:8001 بالا میآورد. اگر در مرورگر به http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ بروید، باید رابط وب Kubernetes را ببینید. میتوانید با این رابط کلاستر را کاوش کنید و containerهای جدید بسازید. جزئیات کامل این رابط خارج از محدودهٔ کتاب است و با بهبود dashboard بهسرعت در حال تغییر است.
برخی providerها dashboard Kubernetes را بهطور پیشفرض نصب نمیکنند؛ پس اگر در کلاستر نمیبینید نگران نباشید. مستندات نصب dashboard برای این کلاسترها در https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/ موجود است.
خلاصه
امیدواریم در این نقطه یک کلاستر Kubernetes (یا سه تا!) در حال اجرا داشته باشید و با چند دستور کلاستری که ساختید را کاوش کرده باشید. بعد زمان بیشتری صرف کاوش رابط خط فرمان آن کلاستر Kubernetes میکنیم و یاد میگیرید ابزار kubectl را مسلط شوید. در بقیهٔ کتاب از kubectl و کلاستر تست برای کاوش objectهای مختلف در API Kubernetes استفاده میکنید.
¹ همانطور که در فصل بعد یاد میگیرید، namespace در Kubernetes موجودیتی برای سازماندهی منابع Kubernetes است. میتوانید آن را مثل پوشه در filesystem تصور کنید.