سچ پوچھیں تو مجھے 100% یقین نہیں ہے۔ لیکن مجھے لگتا ہے کہ انٹرنل کو کھودنا اور یہ دیکھنا دلچسپ ہے کہ کبرنیٹس میں اس کی تجرید کی بہت سی پرتوں کے تحت واقعی کیا ہو رہا ہے۔ تو صرف تفریح کے لیے، آئیے ایک نظر ڈالتے ہیں کہ ایک کم سے کم "Kubernetes کلسٹر" اصل میں کیسا لگتا ہے۔ (یہ اس سے کہیں زیادہ آسان ہوگا۔ Kubernetes مشکل راستہ.)
میرا فرض ہے کہ آپ کو کبرنیٹس، لینکس اور کنٹینرز کا بنیادی علم ہے۔ ہم یہاں جس چیز کے بارے میں بات کرتے ہیں وہ صرف تحقیق/سیکھنے کے مقاصد کے لیے ہے، اس میں سے کسی کو بھی پروڈکشن میں مت ڈالیں!
کا جائزہ لیں
Kubernetes بہت سے اجزاء پر مشتمل ہے. کے مطابق ویکیپیڈیا، فن تعمیر اس طرح لگتا ہے:
یہاں کم از کم آٹھ اجزاء دکھائے گئے ہیں، لیکن ہم ان میں سے بیشتر کو نظر انداز کر دیں گے۔ میں یہ بتانا چاہتا ہوں کہ کم سے کم چیز جسے معقول طور پر Kubernetes کہا جا سکتا ہے تین اہم اجزاء پر مشتمل ہے:
کیوبلیٹ
kube-apiserver (جو etcd پر منحصر ہے - اس کا ڈیٹا بیس)
کنٹینر رن ٹائم (اس معاملے میں ڈوکر)
آئیے دیکھتے ہیں کہ ان میں سے ہر ایک کے بارے میں دستاویزات کیا کہتی ہیں (rus., انگریزی.) شروع میں کیوبلیٹ:
کلسٹر میں ہر نوڈ پر ایک ایجنٹ چل رہا ہے۔ یہ یقینی بناتا ہے کہ کنٹینر پھلی میں چل رہے ہیں۔
کافی آسان لگتا ہے۔ کے بارے میں کنٹینر رن ٹائمز (کنٹینر رن ٹائم)؟
کنٹینر رن ٹائم ایک پروگرام ہے جسے کنٹینرز چلانے کے لیے ڈیزائن کیا گیا ہے۔
بہت معلوماتی. لیکن اگر آپ Docker سے واقف ہیں، تو آپ کو اس کا عمومی اندازہ ہونا چاہیے کہ یہ کیا کرتا ہے۔ (کنٹینر رن ٹائم اور کبلیٹ کے درمیان ذمہ داریوں کی علیحدگی کی تفصیلات دراصل کافی لطیف ہیں اور میں یہاں ان میں نہیں جاؤں گا۔)
И API سرور?
API سرور Kubernetes کنٹرول پینل کا جزو ہے جو Kubernetes API کو بے نقاب کرتا ہے۔ API سرور Kubernetes کنٹرول پینل کا کلائنٹ سائیڈ ہے۔
جس نے بھی کبھی کبرنیٹس کے ساتھ کچھ کیا ہے اسے براہ راست یا kubectl کے ذریعے API کے ساتھ تعامل کرنا پڑا ہے۔ یہ اس کا دل ہے جو Kubernetes Kubernetes بناتا ہے - وہ دماغ جو YAML کے پہاڑوں کو ہم سب جانتے ہیں اور پسند کرتے ہیں (؟) کو کام کرنے والے بنیادی ڈھانچے میں بدل دیتا ہے۔ ایسا لگتا ہے کہ API ہماری کم سے کم ترتیب میں موجود ہونا چاہئے۔
پیشگی شرائط
لینکس ورچوئل یا فزیکل مشین جس میں روٹ رسائی ہے (میں ورچوئل مشین پر اوبنٹو 18.04 استعمال کر رہا ہوں)۔
اور یہ سب!
بورنگ کی تنصیب
ہمیں اس مشین پر ڈوکر انسٹال کرنے کی ضرورت ہے جسے ہم استعمال کریں گے۔ (میں اس بارے میں تفصیل میں نہیں جا رہا ہوں کہ ڈوکر اور کنٹینرز کیسے کام کرتے ہیں؛ اگر آپ دلچسپی رکھتے ہیں، تو یہ ہے شاندار مضامین)۔ آئیے صرف اس کے ساتھ انسٹال کرتے ہیں۔ apt:
اس کے بعد، ہمیں Kubernetes بائنریز حاصل کرنے کی ضرورت ہے۔ درحقیقت، ہمارے "کلسٹر" کے ابتدائی آغاز کے لیے ہمیں صرف ضرورت ہے۔ kubelet، چونکہ دوسرے سرور کے اجزاء کو چلانے کے لئے ہم استعمال کرسکتے ہیں۔ kubelet. ہمارے کلسٹر کے چلنے کے بعد اس کے ساتھ بات چیت کرنے کے لیے، ہم بھی استعمال کریں گے۔ kubectl.
kubelet جڑ کے طور پر چلنا چاہئے. کافی منطقی، کیونکہ اسے پورے نوڈ کا انتظام کرنے کی ضرورت ہے۔ آئیے اس کے پیرامیٹرز کو دیکھیں:
$ ./kubelet -h
<слишком много строк, чтобы разместить здесь>
$ ./kubelet -h | wc -l
284
واہ، بہت سارے اختیارات! خوش قسمتی سے، ہمیں ان میں سے صرف ایک جوڑے کی ضرورت ہے۔ یہاں ان پیرامیٹرز میں سے ایک ہے جس میں ہماری دلچسپی ہے:
--pod-manifest-path string
جامد پوڈز کے لیے فائلوں پر مشتمل ڈائریکٹری کا راستہ، یا جامد پوڈز کو بیان کرنے والی فائل کا راستہ۔ نقطوں سے شروع ہونے والی فائلوں کو نظر انداز کر دیا جاتا ہے۔ (فرسودہ: یہ آپشن --config آپشن کے ذریعے Kubelet کو بھیجی گئی کنفیگریشن فائل میں سیٹ ہونا چاہیے۔ مزید معلومات کے لیے، دیکھیں kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file .)
یہ آپشن ہمیں چلانے کی اجازت دیتا ہے۔ جامد پھلی - پوڈز جن کا انتظام Kubernetes API کے ذریعے نہیں کیا جاتا ہے۔ جامد پوڈز شاذ و نادر ہی استعمال ہوتے ہیں، لیکن یہ ایک جھرمٹ کو تیزی سے بڑھانے کے لیے بہت آسان ہیں، اور ہمیں بالکل یہی ضرورت ہے۔ ہم اس بڑی وارننگ کو نظر انداز کر دیں گے (دوبارہ، اسے پروڈکشن میں نہ چلائیں!) اور دیکھیں گے کہ کیا ہم پوڈ کو چلا سکتے ہیں۔
پہلے ہم جامد پوڈز کے لیے ایک ڈائریکٹری بنائیں گے اور چلائیں گے۔ kubelet:
kubelet کچھ انتباہات لکھنا شروع کرتا ہے اور ایسا لگتا ہے کہ کچھ نہیں ہو رہا ہے۔ لیکن یہ سچ نہیں ہے! آئیے ڈوکر کو دیکھتے ہیں:
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c8a35e26663 busybox "echo 'hello world!'" 36 seconds ago Exited (0) 36 seconds ago k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4
68f670c3c85f k8s.gcr.io/pause:3.2 "/pause" 2 minutes ago Up 2 minutes k8s_POD_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_0
$ sudo docker logs k8s_hello_hello-mink8s_default_ab61ef0307c6e0dee2ab05dc1ff94812_4
hello world!
kubelet میں نے پوڈ مینی فیسٹ کو پڑھا اور ڈوکر کو ہماری وضاحتوں کے مطابق کچھ کنٹینرز لانچ کرنے کا حکم دیا۔ (اگر آپ "توقف" کنٹینر کے بارے میں سوچ رہے ہیں، تو یہ ایک Kubernetes ہیک ہے - دیکھیں یہ بلاگ.) کوبیلیٹ ہمارا کنٹینر لانچ کرے گا۔ busybox مخصوص کمانڈ کے ساتھ اور اسے غیر معینہ مدت تک دوبارہ شروع کرے گا جب تک کہ جامد پوڈ کو حذف نہیں کیا جاتا ہے۔
اپنے آپ کو مبارکباد دیں۔ ہم ابھی ٹرمینل پر ٹیکسٹ آؤٹ پٹ کرنے کا ایک انتہائی الجھا ہوا طریقہ لے کر آئے ہیں!
لانچ وغیرہ
ہمارا حتمی مقصد Kubernetes API کو چلانا ہے، لیکن ایسا کرنے کے لیے ہمیں پہلے چلانے کی ضرورت ہے۔ وغیرہ. آئیے پوڈ ڈائرکٹری میں اس کی سیٹنگز رکھ کر ایک کم سے کم etcd کلسٹر شروع کریں (مثال کے طور پر، pods/etcd.yaml):
اگر آپ نے کبھی کبرنیٹس کے ساتھ کام کیا ہے، تو یہ YAML فائلیں آپ کو واقف ہونی چاہئیں۔ یہاں صرف دو نکات قابل توجہ ہیں:
ہم نے میزبان فولڈر کو نصب کیا ہے۔ /var/lib/etcd پوڈ میں تاکہ etcd ڈیٹا کو دوبارہ شروع کرنے کے بعد محفوظ کیا جائے (اگر ایسا نہیں کیا جاتا ہے، تو ہر بار پوڈ کو دوبارہ شروع کرنے پر کلسٹر کی حالت مٹ جائے گی، جو کہ کم سے کم کبرنیٹس کی تنصیب کے لیے بھی اچھی نہیں ہوگی)۔
ہم نے انسٹال کر لیا ہے۔ hostNetwork: true. یہ ترتیب، حیرت انگیز طور پر، پوڈ کے اندرونی نیٹ ورک کے بجائے میزبان نیٹ ورک کو استعمال کرنے کے لیے etcd کو ترتیب دیتی ہے (اس سے API سرور کے لیے etcd کلسٹر تلاش کرنا آسان ہو جائے گا)۔
ایک سادہ چیک سے پتہ چلتا ہے کہ etcd واقعی لوکل ہوسٹ پر چل رہا ہے اور ڈیٹا کو ڈسک میں محفوظ کر رہا ہے۔
$ curl localhost:2379/version
{"etcdserver":"3.4.3","etcdcluster":"3.4.0"}
$ sudo tree /var/lib/etcd/
/var/lib/etcd/
└── member
├── snap
│ └── db
└── wal
├── 0.tmp
└── 0000000000000000-0000000000000000.wal
API سرور شروع کرنا
Kubernetes API سرور چلانا اور بھی آسان ہے۔ صرف پیرامیٹر جسے پاس کرنے کی ضرورت ہے۔ --etcd-servers، وہ کرتا ہے جس کی آپ توقع کرتے ہیں:
اس YAML فائل کو ڈائریکٹری میں رکھیں pods، اور API سرور شروع ہو جائے گا۔ کے ساتھ چیک کر رہا ہے۔ curl ظاہر کرتا ہے کہ Kubernetes API پورٹ 8080 پر مکمل طور پر کھلی رسائی کے ساتھ سن رہا ہے - کسی تصدیق کی ضرورت نہیں ہے!
(دوبارہ، اسے پروڈکشن میں مت چلائیں! میں تھوڑا حیران ہوا کہ پہلے سے طے شدہ ترتیب اتنی غیر محفوظ ہے۔ لیکن میں اندازہ لگا رہا ہوں کہ یہ ترقی اور جانچ کو آسان بنانے کے لیے ہے۔)
اور، خوشگوار حیرت، kubectl بغیر کسی اضافی ترتیبات کے باکس سے باہر کام کرتا ہے!
$ ./kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
$ ./kubectl get pod
No resources found in default namespace.
مسئلہ
لیکن اگر آپ تھوڑا سا گہرائی میں کھودیں، تو لگتا ہے کہ کچھ غلط ہو رہا ہے:
$ ./kubectl get pod -n kube-system
No resources found in kube-system namespace.
ہم نے جو جامد پوڈ بنائے تھے وہ ختم ہو گئے ہیں! درحقیقت، ہمارا کیوبلیٹ نوڈ بالکل بھی دریافت نہیں ہوا ہے:
$ ./kubectl get nodes
No resources found in default namespace.
کیا معاملہ ہے؟ اگر آپ کو کچھ پیراگراف پہلے یاد ہیں، تو ہم نے کوبیلیٹ کو کمانڈ لائن پیرامیٹرز کے ایک انتہائی آسان سیٹ کے ساتھ شروع کیا، لہذا کیوبلیٹ نہیں جانتا کہ API سرور سے کیسے رابطہ کیا جائے اور اسے اس کی حالت کے بارے میں مطلع کیا جائے۔ دستاویزات کا مطالعہ کرنے کے بعد، ہم اسی پرچم کو تلاش کرتے ہیں:
--kubeconfig string
فائل کا راستہ kubeconfig، جو API سرور سے جڑنے کا طریقہ بتاتا ہے۔ دستیابی --kubeconfig API سرور موڈ کو فعال کرتا ہے، نہیں --kubeconfig آف لائن موڈ کو فعال کرتا ہے۔
اس سارے عرصے میں، یہ جانے بغیر، ہم کبلیٹ کو "آف لائن موڈ" میں چلا رہے تھے۔ (اگر ہم پیڈینٹک ہو رہے تھے، تو ہم اسٹینڈ اسٹون کبلیٹ کو "کم سے کم قابل عمل کبرنیٹس" کے طور پر سوچ سکتے ہیں، لیکن یہ بہت بورنگ ہو گا)۔ "حقیقی" کنفیگریشن کو کام کرنے کے لیے، ہمیں kubeconfig فائل کو کیوبلیٹ میں منتقل کرنے کی ضرورت ہے تاکہ یہ جانتا ہو کہ API سرور سے کیسے بات کرنی ہے۔ خوش قسمتی سے یہ کافی آسان ہے (چونکہ ہمارے پاس کوئی تصدیق یا سرٹیفکیٹ کا مسئلہ نہیں ہے):
(ویسے، اگر آپ کرل کے ذریعے API تک رسائی حاصل کرنے کی کوشش کرتے ہیں جب کیوبلیٹ نہیں چل رہا ہے، تو آپ کو معلوم ہوگا کہ یہ اب بھی چل رہا ہے! کیوبلیٹ ڈوکر کی طرح اس کے پوڈز کا "والدین" نہیں ہے، یہ ایک "کنٹرول" کی طرح ہے۔ ڈیمون۔" کیوبلیٹ کے زیر انتظام کنٹینرز اس وقت تک چلتے رہیں گے جب تک کہ کیوبلیٹ انہیں روک نہیں دیتا۔)
چند منٹوں میں kubectl ہمیں پوڈ اور نوڈس دکھانا چاہئے جیسا کہ ہم توقع کرتے ہیں:
$ ./kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default hello-mink8s 0/1 CrashLoopBackOff 261 21h
kube-system etcd-mink8s 1/1 Running 0 21h
kube-system kube-apiserver-mink8s 1/1 Running 0 21h
$ ./kubectl get nodes -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
mink8s Ready <none> 21h v1.18.5 10.70.10.228 <none> Ubuntu 18.04.4 LTS 4.15.0-109-generic docker://19.3.6
آئیے اس بار واقعی اپنے آپ کو مبارکباد دیتے ہیں (میں جانتا ہوں کہ میں نے پہلے ہی اپنے آپ کو مبارکباد دی ہے) - ہمارے پاس ایک کم سے کم Kubernetes "کلسٹر" ہے جو مکمل طور پر فعال API کے ساتھ چل رہا ہے!
ہم کے تحت شروع
اب دیکھتے ہیں کہ API کیا قابل ہے۔ آئیے nginx pod کے ساتھ شروع کریں:
$ ./kubectl apply -f nginx.yaml
Error from server (Forbidden): error when creating "nginx.yaml": pods "nginx" is
forbidden: error looking up service account default/default: serviceaccount
"default" not found
$ ./kubectl get serviceaccounts
No resources found in default namespace.
یہاں ہم دیکھتے ہیں کہ ہمارا Kubernetes ماحول کس قدر نامکمل ہے - ہمارے پاس خدمات کے لیے کوئی اکاؤنٹ نہیں ہے۔ آئیے دستی طور پر ایک سروس اکاؤنٹ بنا کر دوبارہ کوشش کریں اور دیکھیں کہ کیا ہوتا ہے:
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
EOS
serviceaccount/default created
$ ./kubectl apply -f nginx.yaml
Error from server (ServerTimeout): error when creating "nginx.yaml": No API
token found for service account "default", retry after the token is
automatically created and added to the service account
یہاں تک کہ جب ہم دستی طور پر سروس اکاؤنٹ بناتے ہیں، توثیق ٹوکن تیار نہیں ہوتا ہے۔ جیسا کہ ہم اپنے کم سے کم "کلسٹر" کے ساتھ تجربہ کرتے رہیں گے، ہم دیکھیں گے کہ زیادہ تر مفید چیزیں جو عام طور پر خود بخود ہوتی ہیں غائب ہو جائیں گی۔ Kubernetes API سرور کافی کم سے کم ہے، جس میں زیادہ تر بھاری لفٹنگ اور خودکار کنفیگریشن مختلف کنٹرولرز اور بیک گراؤنڈ جابز میں ہو رہی ہے جو ابھی تک نہیں چل رہے ہیں۔
ہم آپشن ترتیب دے کر اس مسئلے کو حل کر سکتے ہیں۔ automountServiceAccountToken سروس اکاؤنٹ کے لیے (چونکہ ہمیں اسے بہرحال استعمال نہیں کرنا پڑے گا):
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: default
automountServiceAccountToken: false
EOS
serviceaccount/default configured
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 13m
آخر میں، پھلی نمودار ہوئی ہے! لیکن حقیقت میں یہ شروع نہیں ہوگا کیونکہ ہمارے پاس نہیں ہے۔ منصوبہ ساز (شیڈیولر) Kubernetes کا ایک اور اہم جزو ہے۔ ایک بار پھر، ہم دیکھتے ہیں کہ Kubernetes API حیرت انگیز طور پر "گونگا" ہے - جب آپ API میں ایک Pod بناتے ہیں، تو یہ اسے رجسٹر کرتا ہے، لیکن یہ جاننے کی کوشش نہیں کرتا کہ اسے کس نوڈ پر چلایا جائے۔
درحقیقت، آپ کو پوڈ چلانے کے لیے شیڈولر کی ضرورت نہیں ہے۔ آپ پیرامیٹر میں مینی فیسٹ میں دستی طور پر نوڈ شامل کر سکتے ہیں۔ nodeName:
(بدلیں۔ mink8s نوڈ کے نام پر۔) ڈیلیٹ اور اپلائی کرنے کے بعد، ہم دیکھتے ہیں کہ nginx شروع ہو چکا ہے اور اندرونی IP ایڈریس سن رہا ہے:
$ ./kubectl delete pod nginx
pod "nginx" deleted
$ ./kubectl apply -f nginx.yaml
pod/nginx created
$ ./kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 30s 172.17.0.2 mink8s <none> <none>
$ curl -s 172.17.0.2 | head -4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
اس بات کو یقینی بنانے کے لیے کہ پوڈ کے درمیان نیٹ ورک صحیح طریقے سے کام کر رہا ہے، ہم دوسرے پوڈ سے کرل چلا سکتے ہیں:
$ cat <<EOS | ./kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: curl
spec:
containers:
- image: curlimages/curl
name: curl
command: ["curl", "172.17.0.2"]
nodeName: mink8s
EOS
pod/curl created
$ ./kubectl logs curl | head -6
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
اس ماحول میں کھودنا اور یہ دیکھنا کافی دلچسپ ہے کہ کیا کام کرتا ہے اور کیا نہیں۔ میں نے محسوس کیا کہ ConfigMap اور خفیہ کام توقع کے مطابق کرتے ہیں، لیکن سروس اور تعیناتی ایسا نہیں کرتی ہے۔
!
یہ پوسٹ طویل ہوتی جا رہی ہے، اس لیے میں فتح کا اعلان کرنے جا رہا ہوں اور کہوں گا کہ یہ ایک قابل عمل ترتیب ہے جسے "Kubernetes" کہا جا سکتا ہے۔ خلاصہ کرنے کے لیے: چار بائنریز، پانچ کمانڈ لائن پیرامیٹرز اور YAML کی "صرف" 45 لائنیں (نہیں بہت زیادہ معیار کے مطابق Kubernetes) اور ہمارے پاس کچھ چیزیں کام کر رہی ہیں:
پوڈز کو باقاعدہ Kubernetes API کا استعمال کرتے ہوئے منظم کیا جاتا ہے (چند ہیکس کے ساتھ)
آپ عوامی کنٹینر کی تصاویر اپ لوڈ اور ان کا نظم کر سکتے ہیں۔
پھلیاں زندہ رہتی ہیں اور خود بخود دوبارہ شروع ہوجاتی ہیں۔
ایک ہی نوڈ کے اندر پوڈ کے درمیان نیٹ ورکنگ کافی اچھی طرح سے کام کرتی ہے۔
ConfigMap، خفیہ اور سادہ سٹوریج بڑھنے کا کام حسب توقع
لیکن جو کچھ Kubernetes کو واقعی کارآمد بناتا ہے وہ ابھی تک غائب ہے، جیسے:
پوڈ شیڈیولر
توثیق/ اجازت
متعدد نوڈس
خدمات کا نیٹ ورک
کلسٹرڈ اندرونی DNS
سروس اکاؤنٹس، تعیناتیوں، کلاؤڈ فراہم کنندگان کے ساتھ انضمام اور کوبرنیٹس کے ساتھ زیادہ تر دیگر سامان کے کنٹرولرز
تو ہمیں اصل میں کیا ملا؟ Kubernetes API، خود چل رہا ہے، واقعی میں صرف ایک پلیٹ فارم ہے۔ کنٹینر آٹومیشن. یہ زیادہ کام نہیں کرتا ہے - یہ API استعمال کرنے والے مختلف کنٹرولرز اور آپریٹرز کے لیے کام ہے - لیکن یہ آٹومیشن کے لیے ایک مستقل ماحول فراہم کرتا ہے۔