نُشرت في الأصل بواسطة المدونة
مكتبة Kubernetes القياسية مليئة بالجواهر، مخبأة بعيدًا في العديد من الحزم الفرعية المتنوعة التي تشكل جزءًا من النظام البيئي. أحد الأمثلة التي اكتشفتها مؤخرًا هو k8s.io/client-go/tools/leaderelection، والذي يمكن استخدامه لإضافة بروتوكول اختيار القائد إلى أي تطبيق يعمل داخل مجموعة Kubernetes. ستناقش هذه المقالة ماهية انتخاب القائد، وكيفية تنفيذها في حزمة Kubernetes هذه، وستقدم مثالاً لكيفية استخدام هذه المكتبة في تطبيقاتنا الخاصة.
يعد انتخاب القائد مفهومًا للأنظمة الموزعة يمثل لبنة أساسية في البرامج المتوفرة بشكل كبير. فهو يسمح لعمليات متزامنة متعددة بالتنسيق فيما بينها واختيار عملية "قائدة" واحدة، والتي تكون بعد ذلك مسؤولة عن تنفيذ إجراءات متزامنة مثل الكتابة إلى مخزن البيانات.
يعد هذا مفيدًا في أنظمة مثل قواعد البيانات الموزعة أو ذاكرات التخزين المؤقت، حيث يتم تشغيل عمليات متعددة لإنشاء تكرار ضد فشل الأجهزة أو الشبكة، ولكن لا يمكن الكتابة إلى وحدة التخزين في وقت واحد لضمان اتساق البيانات. إذا أصبحت عملية القائد غير مستجيبة في مرحلة ما في المستقبل، فستبدأ العمليات المتبقية في انتخاب قائد جديد، وفي النهاية اختيار عملية جديدة لتكون بمثابة القائد.
باستخدام هذا المفهوم، يمكننا إنشاء برامج عالية التوفر مع قائد واحد ونسخ متماثلة متعددة في وضع الاستعداد.
في Kubernetes، تستخدم حزمة وقت تشغيل وحدة التحكم اختيار القائد لجعل وحدات التحكم متاحة بشكل كبير. في نشر وحدة التحكم، تحدث تسوية الموارد فقط عندما تكون العملية هي القائدة، وتكون النسخ المتماثلة الأخرى في وضع الاستعداد. إذا أصبحت حجرة القائد غير مستجيبة، فسوف تنتخب النسخ المتماثلة المتبقية قائدًا جديدًا لإجراء التسويات اللاحقة واستئناف التشغيل العادي.
تستخدم هذه المكتبة عقد Kubernetes Lease، أو القفل الموزع، الذي يمكن الحصول عليه من خلال إحدى العمليات. الإيجارات هي موارد Kubernetes الأصلية التي تحتفظ بها هوية واحدة، لمدة معينة، مع خيار التجديد. فيما يلي مثال للمواصفات من المستندات:
apiVersion: coordination.k8s.io/v1 kind: Lease metadata: labels: apiserver.kubernetes.io/identity: kube-apiserver kubernetes.io/hostname: master-1 name: apiserver-07a5ea9b9b072c4a5f3d1c3702 namespace: kube-system spec: holderIdentity: apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05 leaseDurationSeconds: 3600 renewTime: "2023-07-04T21:58:48.065888Z"
يتم استخدام عقود الإيجار بواسطة النظام البيئي k8s بثلاث طرق:
الآن دعنا نستكشف حالة الاستخدام الثانية لعقود الإيجار من خلال كتابة نموذج برنامج لتوضيح كيف يمكنك استخدامها في سيناريوهات انتخاب القائد.
في هذا المثال الرمزي، نستخدم حزمة Leaderelection للتعامل مع اختيار القائد وتفاصيل التلاعب في عقد الإيجار.
package main import ( "context" "fmt" "os" "time" "k8s.io/client-go/tools/leaderelection" rl "k8s.io/client-go/tools/leaderelection/resourcelock" ctrl "sigs.k8s.io/controller-runtime" ) var ( // lockName and lockNamespace need to be shared across all running instances lockName = "my-lock" lockNamespace = "default" // identity is unique to the individual process. This will not work for anything, // outside of a toy example, since processes running in different containers or // computers can share the same pid. identity = fmt.Sprintf("%d", os.Getpid()) ) func main() { // Get the active kubernetes context cfg, err := ctrl.GetConfig() if err != nil { panic(err.Error()) } // Create a new lock. This will be used to create a Lease resource in the cluster. l, err := rl.NewFromKubeconfig( rl.LeasesResourceLock, lockNamespace, lockName, rl.ResourceLockConfig{ Identity: identity, }, cfg, time.Second*10, ) if err != nil { panic(err) } // Create a new leader election configuration with a 15 second lease duration. // Visit https://pkg.go.dev/k8s.io/client-go/tools/leaderelection#LeaderElectionConfig // for more information on the LeaderElectionConfig struct fields el, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{ Lock: l, LeaseDuration: time.Second * 15, RenewDeadline: time.Second * 10, RetryPeriod: time.Second * 2, Name: lockName, Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: func(ctx context.Context) { println("I am the leader!") }, OnStoppedLeading: func() { println("I am not the leader anymore!") }, OnNewLeader: func(identity string) { fmt.Printf("the leader is %s\n", identity) }, }, }) if err != nil { panic(err) } // Begin the leader election process. This will block. el.Run(context.Background()) }
الأمر الجميل في حزمة انتخاب القائد هو أنها توفر إطارًا قائمًا على رد الاتصال للتعامل مع انتخابات القائد. بهذه الطريقة، يمكنك التصرف وفقًا لتغييرات محددة في الولاية بطريقة تفصيلية وتحرير الموارد بشكل صحيح عند انتخاب قائد جديد. من خلال تشغيل عمليات الاسترجاعات هذه في goroutines منفصلة، تستفيد الحزمة من دعم التزامن القوي لـ Go للاستفادة بكفاءة من موارد الجهاز.
لاختبار ذلك، دعونا ندير مجموعة اختبار باستخدام النوع.
$ kind create cluster
انسخ نموذج التعليمات البرمجية إلى main.go، وأنشئ وحدة نمطية جديدة (go mod init Leaderelectiontest) وقم بترتيبها (go mod tidy) لتثبيت تبعياتها. بمجرد تشغيل go run main.go، يجب أن تشاهد الإخراج مثل هذا:
$ go run main.go I0716 11:43:50.337947 138 leaderelection.go:250] attempting to acquire leader lease default/my-lock... I0716 11:43:50.351264 138 leaderelection.go:260] successfully acquired lease default/my-lock the leader is 138 I am the leader!
ستكون هوية القائد الدقيقة مختلفة عما هو موجود في المثال (138)، نظرًا لأن هذا مجرد معرف PID للعملية التي كانت قيد التشغيل على جهاز الكمبيوتر الخاص بي في وقت كتابة هذا التقرير.
وهذا هو عقد الإيجار الذي تم إنشاؤه في مجموعة الاختبار:
$ kubectl describe lease/my-lock Name: my-lock Namespace: default Labels:Annotations: API Version: coordination.k8s.io/v1 Kind: Lease Metadata: Creation Timestamp: 2024-07-16T15:43:50Z Resource Version: 613 UID: 1d978362-69c5-43e9-af13-7b319dd452a6 Spec: Acquire Time: 2024-07-16T15:43:50.338049Z Holder Identity: 138 Lease Duration Seconds: 15 Lease Transitions: 0 Renew Time: 2024-07-16T15:45:31.122956Z Events:
انظر أن "هوية المالك" هي نفس معرف العملية، 138.
الآن، لنفتح محطة طرفية أخرى ونشغل نفس ملف main.go في عملية منفصلة:
$ go run main.go I0716 11:48:34.489953 604 leaderelection.go:250] attempting to acquire leader lease default/my-lock... the leader is 138
سوف تنتظر هذه العملية الثانية إلى الأبد، حتى لا تستجيب العملية الأولى. دعنا ننهي العملية الأولى وننتظر حوالي 15 ثانية. الآن بما أن العملية الأولى لا تقوم بتجديد مطالبتها بعقد الإيجار، فلن يتم تحديث الحقل .spec.renewTime بعد الآن. سيؤدي هذا في النهاية إلى أن تؤدي العملية الثانية إلى إطلاق انتخاب قائد جديد، نظرًا لأن وقت تجديد عقد الإيجار أقدم من مدته. ولأن هذه العملية هي العملية الوحيدة الجارية الآن، فسوف تنتخب نفسها كزعيم جديد.
the leader is 604 I0716 11:48:51.904732 604 leaderelection.go:260] successfully acquired lease default/my-lock I am the leader!
إذا كانت هناك عمليات متعددة لا تزال قيد التشغيل بعد خروج القائد الأولي، فستكون العملية الأولى للحصول على عقد الإيجار هي القائد الجديد، وستظل بقية العمليات في وضع الاستعداد.
هذه الحزمة ليست مضمونة، من حيث أنها "لا تضمن أن يقوم عميل واحد فقط بدور القائد (المعروف أيضًا باسم المبارزة)". على سبيل المثال، إذا تم إيقاف القائد مؤقتًا وترك عقد الإيجار الخاص به ينتهي، فستحصل نسخة احتياطية أخرى على عقد الإيجار. وبعد ذلك، بمجرد أن يستأنف القائد الأصلي التنفيذ، فإنه سيعتقد أنه لا يزال هو القائد وسيواصل العمل جنبًا إلى جنب مع القائد المنتخب حديثًا. بهذه الطريقة، يمكن أن ينتهي بك الأمر مع وجود قائدين يعملان في وقت واحد.
لإصلاح هذه المشكلة، يجب تضمين رمز السياج الذي يشير إلى عقد الإيجار في كل طلب إلى الخادم. رمز المبارزة هو في الواقع عدد صحيح يزيد بمقدار 1 في كل مرة يتم فيها تغيير ملكية عقد الإيجار. لذلك سيتم رفض طلبات العميل الذي لديه رمز سياج قديم من قبل الخادم. في هذا السيناريو، إذا استيقظ القائد القديم من النوم وقام القائد الجديد بالفعل بزيادة رمز المبارزة، فسيتم رفض جميع طلبات القائد القديم لأنه يرسل رمزًا أقدم (أصغر) مما شاهده الخادم من الزعيم الأحدث.
سيكون تنفيذ السياج في Kubernetes أمرًا صعبًا دون تعديل خادم واجهة برمجة التطبيقات الأساسي لحساب رموز السياج المقابلة لكل عقد إيجار. ومع ذلك، يتم تقليل خطر وجود وحدات تحكم رائدة متعددة إلى حد ما بواسطة خادم k8s API نفسه. نظرًا لرفض التحديثات للكائنات التي لا معنى لها، يمكن فقط لوحدات التحكم التي لديها أحدث إصدار من الكائن تعديلها. لذلك، بينما يمكن أن يكون لدينا العديد من قادة وحدات التحكم قيد التشغيل، فإن حالة المورد لن تتراجع أبدًا إلى الإصدارات الأقدم إذا فاتت وحدة التحكم تغييرًا أجراه قائد آخر. وبدلاً من ذلك، فإن وقت المصالحة سيزداد حيث يحتاج كلا الزعيمين إلى تحديث حالة الموارد الداخلية الخاصة بهما لضمان أنهما يعملان وفقاً لأحدث الإصدارات.
ومع ذلك، إذا كنت تستخدم هذه الحزمة لتنفيذ انتخاب القائد باستخدام مخزن بيانات مختلف، فهذا تحذير مهم يجب أن تكون على دراية به.
يعد انتخاب القائد والقفل الموزع من العناصر الأساسية المهمة للأنظمة الموزعة. عند محاولة إنشاء تطبيقات متسامحة مع الأخطاء ومتوفرة بشكل كبير، يعد وجود أدوات مثل هذه تحت تصرفك أمرًا بالغ الأهمية. توفر لنا مكتبة Kubernetes القياسية غلافًا تم اختباره في المعركة حول عناصرها الأولية للسماح لمطوري التطبيقات ببناء اختيار القائد بسهولة في تطبيقاتهم الخاصة.
على الرغم من أن استخدام هذه المكتبة تحديدًا يحدك من نشر تطبيقك على Kubernetes، إلا أنه يبدو أن هذه هي الطريقة التي يسير بها العالم مؤخرًا. إذا كان هذا في الواقع بمثابة كسر للصفقات، فيمكنك بالطبع تقسيم المكتبة وتعديلها للعمل ضد أي مخزن بيانات متوافق مع ACID ومتوفر للغاية.
ترقبوا المزيد من التعمق في مصدر k8!
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3