تكوين مجموعة Kubernetes HA على المعادن المجردة باستخدام GlusterFS & MetalLB. الجزء 2/3


الجزء 1/3 هنا
الجزء 3/3 هنا


مرحبا ومرحبا بكم مرة أخرى! هذا هو الجزء الثاني من المقالة حول إنشاء مجموعة Kubernetes على المعدن العاري. في وقت سابق قمنا بتكوين مجموعة Kubernetes HA باستخدام etcd خارجي ، ماجستير وميزان تحميل. حسنًا ، حان الوقت الآن لإعداد بيئة إضافية وأدوات مساعدة لجعل المجموعة أكثر فائدة وأقرب وقت ممكن إلى حالة العمل.


في هذا الجزء من المقالة ، سنركز على تكوين موازن التحميل الداخلي لخدمات الكتلة - سيكون هذا MetalLB. سنقوم أيضًا بتثبيت وتكوين تخزين الملفات الموزع بين عقد العمل لدينا. سوف نستخدم GlusterFS لوحدات التخزين الثابتة المتوفرة في Kubernetes.
بعد الانتهاء من جميع الخطوات ، سيبدو مخطط المجموعة الخاص بنا كما يلي:



1. قم بإعداد MetalLB كموازن تحميل داخلي.


بضع كلمات حول MetalLB ، مباشرة من صفحة المستند:


MetalLB هو تطبيق موازن التحميل لمجموعات Kubernetes العارية المعدنية مع بروتوكولات التوجيه القياسية.

لا تقدم Kubernetes تطبيق موازين تحميل الشبكة ( نوع الخدمة LoadBalancer ) للمعادن المجردة . جميع خيارات تطبيق Network LB التي تأتي معها Kubernetes عبارة عن برامج وسيطة ، وهي تصل إلى العديد من منصات IaaS (GCP ، AWS ، Azure ، إلخ). إذا كنت لا تعمل على نظام أساسي مدعوم من IaaS (GCP ، AWS ، Azure ، وما إلى ذلك) ، فسيظل برنامج LoadBalancer في حالة "الاستعداد" لفترة غير محددة عند الإنشاء.

لدى مشغلي خادم BM أدواتين أقل فاعلية لإدخال حركة مرور المستخدم في مجموعاتهم ، وخدمات NodePort و externalIPs. كل من هذه الخيارات لديها أوجه قصور كبيرة في الإنتاج ، الأمر الذي يحول مجموعات BM إلى مواطنين من الدرجة الثانية في النظام البيئي Kubernetes.

تسعى MetalLB إلى تصحيح هذا الخلل من خلال تقديم تطبيق Network LB ، والذي يتكامل مع معدات الشبكة القياسية ، بحيث "تعمل فقط" الخدمات الخارجية على مجموعات BM بأقصى سرعة.

وبالتالي ، باستخدام هذه الأداة ، نطلق خدمات في نظام Kubernetes باستخدام موازن التحميل ، والذي بفضل الكثير من الشكر لفريق MetalLB. عملية الإعداد بسيطة حقا ومباشرة.


في وقت سابق في المثال ، اخترنا الشبكة الفرعية 192.168.0.0/24 لتلبية احتياجات مجموعتنا. الآن ، خذ بعضًا من هذه الشبكة الفرعية لموازن التحميل المستقبلي.


ندخل نظام الجهاز باستخدام الأداة المساعدة kubectl التي تم تكوينها ونعمل :


control# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml 

سيؤدي ذلك إلى نشر MetalLB في الكتلة ، في metallb-system . تأكد من أن جميع مكونات MetalLB تعمل بشكل صحيح:


 control# kubectl get pod --namespace=metallb-system NAME READY STATUS RESTARTS AGE controller-7cc9c87cfb-ctg7p 1/1 Running 0 5d3h speaker-82qb5 1/1 Running 0 5d3h speaker-h5jw7 1/1 Running 0 5d3h speaker-r2fcg 1/1 Running 0 5d3h 

الآن تكوين MetalLB باستخدام configmap. في هذا المثال ، نستخدم تخصيص Layer 2. للحصول على معلومات حول خيارات التخصيص الأخرى ، راجع وثائق MetalLB.


قم بإنشاء ملف metallb-config.yaml في أي دليل داخل نطاق IP المحدد للشبكة الفرعية لمجموعتنا:


 control# vi metallb-config.yaml apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - 192.168.0.240-192.168.0.250 

وتطبيق هذا الإعداد:


 control# kubectl apply -f metallb-config.yaml 

تحقق وتعديل configmap في وقت لاحق إذا لزم الأمر:


 control# kubectl describe configmaps -n metallb-system control# kubectl edit configmap config -n metallb-system 

الآن لدينا موازن التحميل المحلي المكونة لدينا. دعونا نرى كيف تعمل ، وذلك باستخدام خدمة Nginx كمثال.


 control# vi nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 control# vi nginx-service.yaml apiVersion: v1 kind: Service metadata: name: nginx spec: type: LoadBalancer selector: app: nginx ports: - port: 80 name: http 

ثم قم بإنشاء اختبار نشر وخدمة Nginx:


 control# kubectl apply -f nginx-deployment.yaml control# kubectl apply -f nginx-service.yaml 

والآن - تحقق من النتيجة:


 control# kubectl get po NAME READY STATUS RESTARTS AGE nginx-deployment-6574bd76c-fxgxr 1/1 Running 0 19s nginx-deployment-6574bd76c-rp857 1/1 Running 0 19s nginx-deployment-6574bd76c-wgt9n 1/1 Running 0 19s control# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx LoadBalancer 10.100.226.110 192.168.0.240 80:31604/TCP 107s 

تم إنشاء 3 قرون Nginx ، كما أشرنا في النشر مسبقًا. ستقوم خدمة Nginx بتوجيه حركة المرور إلى جميع هذه القرون وفقًا لمخطط الموازنة الدورية. ويمكنك أيضًا رؤية عنوان IP الخارجي المستلم من موازن التحميل MetalLB الخاص بنا.


جرّب الآن الانتقال إلى عنوان IP 192.168.0.240 وستظهر لك صفحة Nginx index.html. تذكر إزالة نشر الاختبار وخدمة Nginx.


 control# kubectl delete svc nginx service "nginx" deleted control# kubectl delete deployment nginx-deployment deployment.extensions "nginx-deployment" deleted 

حسنًا ، كل ذلك مع MetalLB ، دعنا ننتقل - سنقوم بتكوين وحدات تخزين GlusterFS لـ Kubernetes.


2. تكوين GlusterFS مع Heketi على عقد العمل.


في الواقع ، لا يمكن استخدام كتلة Kubernetes بدون وحدات تخزين بداخلها. كما تعلمون ، فإن الموقد سريع الزوال ، أي يمكن إنشاؤها وحذفها في أي وقت. سيتم فقد جميع البيانات الموجودة بداخلها. وبالتالي ، في الكتلة الحقيقية ، يلزم التخزين الموزع لضمان تبادل الإعدادات والبيانات بين العقد والتطبيقات داخله.


في Kubernetes ، تتوفر وحدات التخزين بعدة طرق ؛ اختر ما تريد. في هذا المثال ، سأوضح كيفية إنشاء تخزين GlusterFS لأي تطبيقات داخلية ، فهو يشبه وحدات التخزين الثابتة. في وقت سابق ، استخدمت التثبيت "النظام" لـ GlusterFS لجميع العقد العاملة Kubernetes لهذا الغرض ، ثم قمت ببساطة بإنشاء وحدات تخزين hostPath في دلائل GlusterFS.


الآن لدينا أداة جديدة Heketi مفيد.


بضع كلمات من وثائق Heketi:


بنية تحتية لإدارة وحدة التخزين مريحة لـ GlusterFS.

يقدم Heketi واجهة إدارة مريحة يمكن استخدامها لإدارة دورة حياة وحدات تخزين GlusterFS. بفضل Heketi ، يمكن للخدمات السحابية مثل OpenStack Manila و Kubernetes و OpenShift توفير وحدات تخزين GlusterFS بشكل حيوي مع أي نوع من الموثوقية المدعومة. يحدد Heketi موقع الكتل في الكتلة تلقائيًا ، مما يوفر موقع الكتل والنسخ المتماثلة الخاصة بها في مناطق مختلفة من الفشل. يدعم Heketi أيضًا أي عدد من مجموعات GlusterFS ، مما يسمح للخدمات السحابية بتقديم تخزين ملفات عبر الإنترنت ، وليس فقط مجموعة GlusterFS واحدة.

يبدو جيدًا ، وبالإضافة إلى ذلك ، ستجعل هذه الأداة مجموعة VM الخاصة بنا أقرب إلى مجموعات سحابة Kubernetes الكبيرة. في النهاية ، ستتمكن من إنشاء PersistentVolumeClaims ، والذي سيتم إنشاؤه تلقائيًا ، وأكثر من ذلك بكثير.


يمكنك أن تأخذ محركات أقراص صلبة إضافية للنظام لتكوين GlusterFS أو مجرد إنشاء بعض أجهزة كتلة وهمية. في هذا المثال ، سأستخدم الطريقة الثانية.


إنشاء أجهزة كتلة وهمية على جميع العقد العمل الثلاثة:


 worker1-3# dd if=/dev/zero of=/home/gluster/image bs=1M count=10000 

سوف تحصل على ملف بحجم 10 جيجابايت. ثم استخدم losetup - لإضافته إلى هذه العقد ، كجهاز استرجاع:


 worker1-3# losetup /dev/loop0 /home/gluster/image 

يرجى ملاحظة: إذا كان لديك بالفعل نوع من أجهزة الاسترجاع 0 ، فستحتاج إلى اختيار أي رقم آخر.

أخذت الوقت ووجدت لماذا Heketi لا يريد أن يعمل بشكل صحيح. لذلك ، لمنع حدوث أي مشكلات في التكوينات المستقبلية ، تأكد أولاً من أننا قمنا بتحميل وحدة dm_thin_pool kernel وتثبيت حزمة glusterfs-client على جميع عقد العمل.


 worker1-3# modprobe dm_thin_pool worker1-3# apt-get update && apt-get -y install glusterfs-client 

حسنًا ، أنت الآن بحاجة إلى الملف / الصفحة الرئيسية / اللمعان / الصورة والجهاز / dev / loop0 ليكون حاضرًا في جميع نقاط العمل. تذكر أن تنشئ خدمة systemd ستبدأ تلقائيًا تشغيل losetup و modprobe في كل مرة يتم فيها تشغيل هذه الخوادم.


 worker1-3# vi /etc/systemd/system/loop_gluster.service [Unit] Description=Create the loopback device for GlusterFS DefaultDependencies=false Before=local-fs.target After=systemd-udev-settle.service Requires=systemd-udev-settle.service [Service] Type=oneshot ExecStart=/bin/bash -c "modprobe dm_thin_pool && [ -b /dev/loop0 ] || losetup /dev/loop0 /home/gluster/image" [Install] WantedBy=local-fs.target 

وتشغيله:


 worker1-3# systemctl enable /etc/systemd/system/loop_gluster.service Created symlink /etc/systemd/system/local-fs.target.wants/loop_gluster.service → /etc/systemd/system/loop_gluster.service. 

اكتمال العمل التحضيري ، ونحن على استعداد لنشر GlusterFS و Heketi في مجموعتنا. لهذا ، سأستخدم هذا الدليل الرائع. يتم تشغيل معظم الأوامر من كمبيوتر تحكم خارجي ، ويتم تشغيل أوامر صغيرة جدًا من أي عقدة رئيسية داخل الكتلة.


أولاً ، قم بنسخ المستودع وإنشاء DaemonSet GlusterFS:


 control# git clone https://github.com/heketi/heketi control# cd heketi/extras/kubernetes control# kubectl create -f glusterfs-daemonset.json 

الآن دعنا نحتفل بعُقد العمل الثلاثة الخاصة بـ GlusterFS ؛ بعد وضع العلامات عليها ، سيتم إنشاء قرون GlusterFS:


 control# kubectl label node worker1 storagenode=glusterfs control# kubectl label node worker2 storagenode=glusterfs control# kubectl label node worker3 storagenode=glusterfs control# kubectl get pod NAME READY STATUS RESTARTS AGE glusterfs-5dtdj 1/1 Running 0 1m6s glusterfs-hzdll 1/1 Running 0 1m9s glusterfs-p8r59 1/1 Running 0 2m1s 

قم الآن بإنشاء حساب خدمة Heketi:


 control# kubectl create -f heketi-service-account.json 

نحن نقدم لحساب هذه الخدمة القدرة على إدارة القرون اللامعة. للقيام بذلك ، قم بإنشاء دالة كتلة مطلوبة لحساب الخدمة الذي تم إنشاؤه حديثًا:


 control# kubectl create clusterrolebinding heketi-gluster-admin --clusterrole=edit --serviceaccount=default:heketi-service-account 

الآن ، لنقم بإنشاء مفتاح سر Kubernetes يمنع تكوين مثيل Heketi الخاص بنا:


 control# kubectl create secret generic heketi-config-secret --from-file=./heketi.json 

قم بإنشاء المصدر الأول تحت Heketi ، والذي نستخدمه في عمليات الإعداد الأولى ثم احذفه لاحقًا:


 control# kubectl create -f heketi-bootstrap.json service "deploy-heketi" created deployment "deploy-heketi" created control# kubectl get pod NAME READY STATUS RESTARTS AGE deploy-heketi-1211581626-2jotm 1/1 Running 0 2m glusterfs-5dtdj 1/1 Running 0 6m6s glusterfs-hzdll 1/1 Running 0 6m9s glusterfs-p8r59 1/1 Running 0 7m1s 

بعد إنشاء خدمة Bootstrap Heketi وبدء تشغيلها ، سنحتاج إلى التبديل إلى إحدى العقد الرئيسية الخاصة بنا ، حيث سنقوم بتشغيل العديد من الأوامر ، نظرًا لأن عقدة التحكم الخارجية الخاصة بنا ليست داخل مجموعتنا ، لذلك لا يمكننا الوصول إلى قرون العمل والشبكة الداخلية للمجموعة.


أولاً ، دعنا نقوم بتنزيل الأداة المساعدة heketi-client ونسخها إلى مجلد نظام bin:


 master1# wget https://github.com/heketi/heketi/releases/download/v8.0.0/heketi-client-v8.0.0.linux.amd64.tar.gz master1# tar -xzvf ./heketi-client-v8.0.0.linux.amd64.tar.gz master1# cp ./heketi-client/bin/heketi-cli /usr/local/bin/ master1# heketi-cli heketi-cli v8.0.0 

الآن ابحث عن عنوان IP لجهاز heketi وقم بتصديره كمتغير للنظام:


 master1# kubectl --kubeconfig /etc/kubernetes/admin.conf describe pod deploy-heketi-1211581626-2jotm For me this pod have a 10.42.0.1 ip master1# curl http://10.42.0.1:57598/hello Handling connection for 57598 Hello from Heketi master1# export HEKETI_CLI_SERVER=http://10.42.0.1:57598 

الآن لنزود Heketi بمعلومات حول مجموعة GlusterFS التي يجب أن تديرها. نحن نقدمها من خلال ملف طوبولوجيا. الهيكل هو بيان JSON مع قائمة بجميع العقد والأقراص والمجموعات التي تستخدمها GlusterFS.


ملاحظة تأكد من أن hostnames/manage تشير إلى الاسم الدقيق ، كما هو الحال في قسم kubectl get node ، وأن hostnames/storage هي عنوان IP لعقد التخزين.

 master1:~/heketi-client# vi topology.json { "clusters": [ { "nodes": [ { "node": { "hostnames": { "manage": [ "worker1" ], "storage": [ "192.168.0.7" ] }, "zone": 1 }, "devices": [ "/dev/loop0" ] }, { "node": { "hostnames": { "manage": [ "worker2" ], "storage": [ "192.168.0.8" ] }, "zone": 1 }, "devices": [ "/dev/loop0" ] }, { "node": { "hostnames": { "manage": [ "worker3" ], "storage": [ "192.168.0.9" ] }, "zone": 1 }, "devices": [ "/dev/loop0" ] } ] } ] } 

ثم قم بتنزيل هذا الملف:


 master1:~/heketi-client# heketi-cli topology load --json=topology.json Creating cluster ... ID: e83467d0074414e3f59d3350a93901ef Allowing file volumes on cluster. Allowing block volumes on cluster. Creating node worker1 ... ID: eea131d392b579a688a1c7e5a85e139c Adding device /dev/loop0 ... OK Creating node worker2 ... ID: 300ad5ff2e9476c3ba4ff69260afb234 Adding device /dev/loop0 ... OK Creating node worker3 ... ID: 94ca798385c1099c531c8ba3fcc9f061 Adding device /dev/loop0 ... OK 

بعد ذلك ، نستخدم Heketi لتوفير وحدات تخزين لتخزين قاعدة البيانات. اسم الفريق غريب بعض الشيء ، لكن كل شيء على ما يرام. قم أيضًا بإنشاء مستودع heketi:


 master1:~/heketi-client# heketi-cli setup-openshift-heketi-storage master1:~/heketi-client# kubectl --kubeconfig /etc/kubernetes/admin.conf create -f heketi-storage.json secret/heketi-storage-secret created endpoints/heketi-storage-endpoints created service/heketi-storage-endpoints created job.batch/heketi-storage-copy-job created 

هذه هي جميع الأوامر التي تحتاج إلى تشغيلها من العقدة الرئيسية. دعنا نعود إلى عقدة التحكم ونستمر من هناك ؛ أولاً وقبل كل شيء ، تأكد من تنفيذ آخر أمر قيد التشغيل بنجاح:


 control# kubectl get pod NAME READY STATUS RESTARTS AGE glusterfs-5dtdj 1/1 Running 0 39h glusterfs-hzdll 1/1 Running 0 39h glusterfs-p8r59 1/1 Running 0 39h heketi-storage-copy-job-txkql 0/1 Completed 0 69s 

وتتم مهمة heketi-storage-copy-job.


في حالة عدم وجود حزمة glusterfs-client مثبتة حاليًا على عقد العمل ، فسيحدث خطأ.

حان الوقت لإزالة ملف التثبيت Heketi Bootstrap والقيام ببعض التنظيف:


 control# kubectl delete all,service,jobs,deployment,secret --selector="deploy-heketi" 

في المرحلة الأخيرة ، نحتاج إلى إنشاء نسخة طويلة الأجل من Heketi:


 control# cd ./heketi/extras/kubernetes control:~/heketi/extras/kubernetes# kubectl create -f heketi-deployment.json secret/heketi-db-backup created service/heketi created deployment.extensions/heketi created control# kubectl get pod NAME READY STATUS RESTARTS AGE glusterfs-5dtdj 1/1 Running 0 39h glusterfs-hzdll 1/1 Running 0 39h glusterfs-p8r59 1/1 Running 0 39h heketi-b8c5f6554-knp7t 1/1 Running 0 22m 

في حالة عدم وجود حزمة glusterfs-client مثبتة حاليًا على عقد العمل ، فسيحدث خطأ. وقد انتهينا تقريبًا ، يتم الآن تخزين قاعدة بيانات Heketi في وحدة تخزين GlusterFS ولا تتم إعادة ضبطها في كل مرة يتم فيها إعادة تشغيل موقد Heketi.


لبدء استخدام كتلة GlusterFS مع تخصيص موارد ديناميكي ، نحتاج إلى إنشاء StorageClass.


أولاً ، دعنا نعثر على نقطة نهاية التخزين Gluster ، والتي سيتم تمريرها إلى StorageClass كمعلمة (نقاط نهاية التخزين heketi):


 control# kubectl get endpoints NAME ENDPOINTS AGE heketi 10.42.0.2:8080 2d16h ....... ... .. 

الآن قم بإنشاء بعض الملفات:


 control# vi storage-class.yml apiVersion: storage.k8s.io/v1beta1 kind: StorageClass metadata: name: slow provisioner: kubernetes.io/glusterfs parameters: resturl: "http://10.42.0.2:8080" control# vi test-pvc.yml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: gluster1 annotations: volume.beta.kubernetes.io/storage-class: "slow" spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi 

استخدم هذه الملفات لإنشاء فئة و pvc:


 control# kubectl create -f storage-class.yaml storageclass "slow" created control# kubectl get storageclass NAME PROVISIONER AGE slow kubernetes.io/glusterfs 2d8h control# kubectl create -f test-pvc.yaml persistentvolumeclaim "gluster1" created control# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE gluster1 Bound pvc-27f733cd-1c77-11e9-bb07-7efe6b0e6fa5 1Gi RWO slow 2d8h 

يمكننا أيضا مشاهدة حجم الكهروضوئية:


 control# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-27f733cd-1c77-11e9-bb07-7efe6b0e6fa5 1Gi RWO Delete Bound default/gluster1 slow 2d8h 

لدينا الآن وحدة تخزين GlusterFS تم إنشاؤها ديناميكيًا وترتبط بـ PersistentVolumeClaim ، ويمكننا استخدام هذا البيان في أي مخطط فرعي.


إنشاء واحدة بسيطة تحت Nginx واختباره:


 control# vi nginx-test.yml apiVersion: v1 kind: Pod metadata: name: nginx-pod1 labels: name: nginx-pod1 spec: containers: - name: nginx-pod1 image: gcr.io/google_containers/nginx-slim:0.8 ports: - name: web containerPort: 80 volumeMounts: - name: gluster-vol1 mountPath: /usr/share/nginx/html volumes: - name: gluster-vol1 persistentVolumeClaim: claimName: gluster1 control# kubectl create -f nginx-test.yaml pod "nginx-pod1" created 

تصفح أسفل (انتظر بضع دقائق ، قد تحتاج إلى تنزيل الصورة إذا لم تكن موجودة بالفعل):


 control# kubectl get pods NAME READY STATUS RESTARTS AGE glusterfs-5dtdj 1/1 Running 0 4d10h glusterfs-hzdll 1/1 Running 0 4d10h glusterfs-p8r59 1/1 Running 0 4d10h heketi-b8c5f6554-knp7t 1/1 Running 0 2d18h nginx-pod1 1/1 Running 0 47h 

انتقل الآن إلى الحاوية وقم بإنشاء ملف index.html:


 control# kubectl exec -ti nginx-pod1 /bin/sh # cd /usr/share/nginx/html # echo 'Hello there from GlusterFS pod !!!' > index.html # ls index.html # exit 

سوف تحتاج إلى العثور على عنوان IP الداخلي للموقد وحليقة من أي عقدة رئيسية:


 master1# curl 10.40.0.1 Hello there from GlusterFS pod !!! 

في القيام بذلك ، نحن ببساطة اختبار حجم ثابت جديد.


بعض الأوامر المفيدة للتحقق من كتلة heketi-cli cluster list الجديدة هي: heketi-cli cluster list heketi-cli volume list . يمكن تشغيلها على جهاز الكمبيوتر الخاص بك إذا تم تثبيت heketi-cli . في هذا المثال ، هذا هو master1 العقدة.

 master1# heketi-cli cluster list Clusters: Id:e83467d0074414e3f59d3350a93901ef [file][block] master1# heketi-cli volume list Id:6fdb7fef361c82154a94736c8f9aa53e Cluster:e83467d0074414e3f59d3350a93901ef Name:vol_6fdb7fef361c82154a94736c8f9aa53e Id:c6b69bd991b960f314f679afa4ad9644 Cluster:e83467d0074414e3f59d3350a93901ef Name:heketidbstorage 

في هذه المرحلة ، نجحنا في إعداد موازن تحميل داخلي مع تخزين ملفات ، وأصبحت المجموعة الآن أقرب إلى حالة التشغيل.


في الجزء التالي من المقالة ، سوف نركز على إنشاء نظام مراقبة نظام المجموعة ، وإطلاق مشروع اختبار فيه لاستخدام جميع الموارد التي قمنا بتكوينها.


ابق على اتصال وكل التوفيق!

Source: https://habr.com/ru/post/ar443110/


All Articles