ملاحظة perev. : يشغل مؤلف المقال ، مارشال بريكا ، منصب مدير تصميم النظام في Fair.com ، والذي يقدم تطبيقه لتأجير السيارات. في وقت فراغه ، يحب استخدام خبرته الواسعة في حل المشكلات "المنزلية" التي من غير المرجح أن تفاجئ أي مهووس (وبالتالي ، فإن السؤال "لماذا؟" - فيما يتعلق بالإجراءات الموضحة أدناه - تم حذفه مسبقًا). لذلك ، في نشره ، يشارك مارشال نتائج نشر Kubernetes مؤخرا على ... لوحات ARM.
مثل العديد من المهوسون الآخرين ، على مر السنين ، جمعت مجموعة متنوعة من لوحات التطوير مثل Raspberry Pi. ومثل العديد من المهوسون ، فقد غمروا أنفسهم على الأرفف بفكرة أنهم سيأتون يومًا ما في متناول يدي. والآن بالنسبة لي هذا اليوم قد حان أخيرا!
خلال العطلة الشتوية ، ظهرت عدة أسابيع خارج العمل ، وفيها كان هناك ما يكفي من الوقت لجرد كل الحديد المتراكم وتحديد ما يجب فعله به. إليكم ما كان لدي:
- حاوية RAID ذات 5 محركات مع اتصال USB3 ؛
- توت العليق بي نموذج B (نموذج OG) ؛
- CubbieBoard 1؛
- Banana Pi M1؛
- HP netbook (2012؟).
من بين مكونات الحديد الخمسة المدرجة ، استخدمت ما لم يكن RAID و netbook بمثابة NAS مؤقت. ومع ذلك ، بسبب عدم وجود دعم USB3 في نتبووك ، لم تستخدم RAID إمكانات السرعة الكاملة.
أهداف الحياة
نظرًا لأن العمل مع RAID لم يكن الأمثل عند استخدام netbook ، فقد حددت الأهداف التالية للحصول على أفضل تكوين:
- NAS مع USB3 وإيثرنت جيجابت ؛
- أفضل طريقة لإدارة البرنامج على جهازك
- (مكافأة) القدرة على دفق محتوى الوسائط المتعددة من RAID إلى Fire TV.
نظرًا لعدم دعم أي من الأجهزة المتاحة USB3 وإيثرنت جيجابت ، للأسف ، كان علي إجراء عمليات شراء إضافية. وقع الاختيار على
ROC-RK3328-CC . كانت تمتلك جميع المواصفات اللازمة والدعم الكافي لأنظمة التشغيل.
بعد أن حلّت احتياجات الأجهزة الخاصة بي (وانتظر وصول هذا الحل) ، انتقلت إلى الهدف الثاني.
إدارة البرنامج على الجهاز
جزئيًا ، فشلت مشاريعي السابقة المتعلقة بلوحات التطوير بسبب عدم كفاية الاهتمام بمسائل التكاثر والتوثيق. عند إنشاء التكوين التالي لاحتياجاتي الحالية ، لم أزعج نفسك بتدوين الخطوات المتخذة أو روابط منشورات المدونة التي اتبعتها. وعندما حدث خطأ بعد شهور أو سنوات وحاولت حل المشكلة ، لم أكن أفهم كيف تم ترتيب كل شيء في الأصل.
قلت لنفسي إن هذه المرة سيكون كل شيء مختلفًا!

والتفت إلى حقيقة أنني أعرف جيدا بما فيه الكفاية - ل Kubernetes.
على الرغم من أن K8s يعد حلًا لمشكلة بسيطة جدًا ، إلا أنه بعد مرور ثلاث سنوات تقريبًا على إدارة المجموعات باستخدام أدوات مختلفة (بلدي ، kops ، إلخ) في وظيفتي الرئيسية ، أنا على دراية بهذا النظام. بالإضافة إلى ذلك ، نشر K8s خارج بيئة سحابية ، وحتى على أجهزة ARM - بدا كل هذا مهمة شيقة.
اعتقدت أيضًا أنه نظرًا لأن الأجهزة المتوفرة لا تفي بالمتطلبات الضرورية لنظام NAS ، سأحاول على الأقل تجميع مجموعة منه ، وربما تكون بعض البرامج التي لا تتطلب الكثير من الموارد قادرة على العمل على الأجهزة القديمة.
Kubernetes على أرمينيا
في العمل ، لم تتح لي الفرصة لاستخدام الأداة المساعدة
kubeadm
لنشر الكتل ، لذلك قررت أن الوقت قد حان لتجربتها في العمل.
تم اختيار Raspbian كنظام تشغيل ، لأنه يشتهر بتقديم أفضل دعم للوحاتي.
لقد وجدت
مقالًا جيدًا حول إعداد Kubernetes على Raspberry Pi باستخدام HypriotOS. نظرًا لأنني لم أكن متأكدًا من توفر HypriotOS لجميع اللوحات الخاصة بي ، فقد عدلت هذه التعليمات لـ Debian / Raspbian.
المكونات المطلوبة
أولاً ، يلزم تثبيت الأدوات التالية:
- عامل الميناء ،
- kubelet
- kubeadm ،
- كوبكتل.
يجب تثبيت عامل الميناء باستخدام برنامج نصي خاص
للراحة (كما هو موضح لحالة استخدام Raspbian).
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
بعد ذلك ، قمت بتثبيت مكونات Kubernetes وفقًا للتعليمات الواردة من مدونة Hypriot ، مع تكييفها بحيث يتم استخدام إصدارات محددة لجميع التبعيات:
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list apt-get update apt-get install -y kubelet=1.13.1-00 kubectl=1.13.1-00 kubeadm=1.13.1-00
التوت بي ب
نشأت أول صعوبة عند محاولة تمهيد مجموعة على Raspberry Pi B:
$ kubeadm init Illegal instruction
اتضح أن Kubernetes
أزال الدعم لـ ARMv6 . حسنًا ، لدي أيضًا CubbieBoard و Banana Pi.
الموز بي
في البداية ، بدا أن نفس تسلسل الإجراءات الخاصة بـ Banana Pi كان أكثر نجاحًا ، ومع ذلك ،
kubeadm init
أمر
kubeadm init
أثناء محاولة الانتظار حتى تعمل طائرة التحكم:
error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
عندما اكتشفت مع
docker ps
ما كان يحدث مع الحاويات ، رأيت أن كلا من
kube-controller-manager
و
kube-scheduler
كانا يعملان لمدة لا تقل عن 4-5 دقائق ، لكن
kube-api-server
استيقظ منذ 1-2 دقائق فقط:
$ docker ps CONTAINER ID COMMAND CREATED STATUS de22427ad594 "kube-apiserver --au…" About a minute ago Up About a minute dc2b70dd803e "kube-scheduler --ad…" 5 minutes ago Up 5 minutes 60b6cc418a66 "kube-controller-man…" 5 minutes ago Up 5 minutes 1e1362a9787c "etcd --advertise-cl…" 5 minutes ago Up 5 minutes
من الواضح أن
api-server
كان يموت أو أن عملية السترونتيوم كانت تقتله وتعيد تشغيله.
عند التحقق من السجلات ، رأيت إجراءات بدء تشغيل قياسية للغاية - كان هناك سجل لبداية الاستماع إلى المنفذ الآمن وتوقف مؤقت طويل قبل ظهور العديد من الأخطاء في مصافحة TLS:
20:06:48.604881 naming_controller.go:284] Starting NamingConditionController 20:06:48.605031 establishing_controller.go:73] Starting EstablishingController 20:06:50.791098 log.go:172] http: TLS handshake error from 192.168.1.155:50280: EOF 20:06:51.797710 log.go:172] http: TLS handshake error from 192.168.1.155:50286: EOF 20:06:51.971690 log.go:172] http: TLS handshake error from 192.168.1.155:50288: EOF 20:06:51.990556 log.go:172] http: TLS handshake error from 192.168.1.155:50284: EOF 20:06:52.374947 log.go:172] http: TLS handshake error from 192.168.1.155:50486: EOF 20:06:52.612617 log.go:172] http: TLS handshake error from 192.168.1.155:50298: EOF 20:06:52.748668 log.go:172] http: TLS handshake error from 192.168.1.155:50290: EOF
وبعد ذلك بفترة قصيرة ، ينهي الخادم عمله. أدى غوغلينغ إلى
مثل هذه المشكلة ، مما يشير إلى سبب محتمل للتشغيل البطيء لخوارزميات التشفير على بعض الأجهزة ARM.
ذهبت أبعد من ذلك وأعتقد أنه ربما يحصل
api-server
على الكثير من الطلبات المتكررة من
scheduler
ومدير
controller-manager
.
ستؤدي إزالة هذه الملفات من دليل البيان إلى إخبار kubelet بإيقاف تنفيذ القرون المقابلة:
mkdir /etc/kubernetes/manifests.bak mv /etc/kubernetes/manifests/kube-scheduler.yaml /etc/kubernetes/manifests.bak/ mv /etc/kubernetes/manifests/kube-controller-mananger.yaml /etc/kubernetes/manifests.bak/
أظهر عرض أحدث سجلات
api-server
أن العملية ذهبت الآن إلى أبعد من ذلك ، ومع ذلك ، فقد ماتت بعد حوالي دقيقتين. بعد ذلك تذكرت أن البيان يمكن أن يحتوي على عينة حيوية مع مهل لها قيم منخفضة جدًا لمثل هذا الجهاز البطيء.
لذلك ، راجعت
/etc/kubernetes/manifests/kube-api-server.yaml
-
/etc/kubernetes/manifests/kube-api-server.yaml
، بالطبع ...
livenessProbe: failureThreshold: 8 httpGet: host: 192.168.1.155 path: /healthz port: 6443 scheme: HTTPS initialDelaySeconds: 15 timeoutSeconds: 15
قتل Pod بعد 135 ثانية (
initialDelaySeconds
+
timeoutSeconds
*
failureThreshold
). زيادة
initialDelaySeconds
إلى 120 ...
النجاح! حسنًا ، لا تزال أخطاء المصافحة تحدث (من المفترض أن تكون من kubelet) ، ومع ذلك ما زال الإطلاق يحدث:
20:06:54.957236 log.go:172] http: TLS handshake error from 192.168.1.155:50538: EOF 20:06:55.004865 log.go:172] http: TLS handshake error from 192.168.1.155:50384: EOF 20:06:55.118343 log.go:172] http: TLS handshake error from 192.168.1.155:50292: EOF 20:06:55.252586 cache.go:39] Caches are synced for autoregister controller 20:06:55.253907 cache.go:39] Caches are synced for APIServiceRegistrationController controller 20:06:55.545881 controller_utils.go:1034] Caches are synced for crd-autoregister controller ... 20:06:58.921689 storage_rbac.go:187] created clusterrole.rbac.authorization.k8s.io/cluster-admin 20:06:59.049373 storage_rbac.go:187] created clusterrole.rbac.authorization.k8s.io/system:discovery 20:06:59.214321 storage_rbac.go:187] created clusterrole.rbac.authorization.k8s.io/system:basic-user
عندما نهض
api-server
، قمت بنقل ملفات YAML لوحدة التحكم والجدولة مرة أخرى إلى دليل البيان ، وبعد ذلك بدأت بشكل طبيعي أيضًا.
حان الوقت للتأكد من نجاح التنزيل إذا تركت جميع الملفات في الدليل المصدر: هل يكفي تغيير التأخير المسموح به في تهيئة
livenessProbe
؟
20:29:33.306983 reflector.go:134] k8s.io/client-go/informers/factory.go:132: Failed to list *v1.Service: Get https://192.168.1.155:6443/api/v1/services?limit=500&resourceVersion=0: dial tcp 192.168.1.155:6443: i/o timeout 20:29:33.434541 reflector.go:134] k8s.io/client-go/informers/factory.go:132: Failed to list *v1.ReplicationController: Get https://192.168.1.155:6443/api/v1/replicationcontrollers?limit=500&resourceVersion=0: dial tcp 192.168.1.155:6443: i/o timeout 20:29:33.435799 reflector.go:134] k8s.io/client-go/informers/factory.go:132: Failed to list *v1.PersistentVolume: Get https://192.168.1.155:6443/api/v1/persistentvolumes?limit=500&resourceVersion=0: dial tcp 192.168.1.155:6443: i/o timeout 20:29:33.477405 reflector.go:134] k8s.io/client-go/informers/factory.go:132: Failed to list *v1beta1.PodDisruptionBudget: Get https://192.168.1.155:6443/apis/policy/v1beta1/poddisruptionbudgets?limit=500&resourceVersion=0: dial tcp 192.168.1.155:6443: i/o timeout 20:29:33.493660 reflector.go:134] k8s.io/client-go/informers/factory.go:132: Failed to list *v1.PersistentVolumeClaim: Get https://192.168.1.155:6443/api/v1/persistentvolumeclaims?limit=500&resourceVersion=0: dial tcp 192.168.1.155:6443: i/o timeout 20:29:37.974938 controller_utils.go:1027] Waiting for caches to sync for scheduler controller 20:29:38.078558 controller_utils.go:1034] Caches are synced for scheduler controller 20:29:38.078867 leaderelection.go:205] attempting to acquire leader lease kube-system/kube-scheduler 20:29:38.291875 leaderelection.go:214] successfully acquired lease kube-system/kube-scheduler
نعم ، كل شيء يعمل ، على الرغم من أن هذه الأجهزة القديمة ، على ما يبدو ، لم يكن المقصود منها إطلاق طائرة التحكم ، لأن اتصالات TLS المتكررة تسبب فرامل كبيرة. بطريقة أو بأخرى - تم استلام تثبيت عملي لـ K8s على ARM! دعنا نذهب أبعد من ذلك ...
RAID تصاعد
نظرًا لأن بطاقات SD ليست مناسبة للتسجيل على المدى الطويل ، فقد قررت استخدام تخزين أكثر موثوقية للأجزاء الأكثر تقلبًا في نظام الملفات - في هذه الحالة ، RAID. تم تسليط الضوء على 4 أقسام على ذلك:
- 50 جيجابايت ؛
- 2 × 20 جيجابايت ؛
- 3.9 تيرابايت.
لم أتوصل بعد إلى غرض محدد للأقسام التي تبلغ سعتها 20 غيغابايت ، لكنني أردت ترك فرص إضافية للمستقبل.
في الملف
/etc/fstab
بالنسبة لقسم 50 غيغابايت ، تم تحديد نقطة التحميل كـ
/mnt/root
، وبالنسبة إلى 3.9 تيرابايت -
/mnt/raid
. بعد ذلك ، قمت بتثبيت الدلائل مع etcd ورسو السفن إلى قسم 50 جيجابايت:
UUID=655a39e8-9a5d-45f3-ae14-73b4c5ed50c3 /mnt/root ext4 defaults,rw,user,auto,exec 0 0 UUID=0633df91-017c-4b98-9b2e-4a0d27989a5c /mnt/raid ext4 defaults,rw,user,auto 0 0 /mnt/root/var/lib/etcd /var/lib/etcd none defaults,bind 0 0 /mnt/root/var/lib/docker /var/lib/docker none defaults,bind 0 0
وصول ROC-RK3328-CC
عندما تم تسليم اللوحة الجديدة ، قمت بتثبيت المكونات الضرورية لـ K8s
(انظر بداية المقالة) وأطلقت
kubeadm init
. بضع دقائق من الانتظار هي نجاح وإخراج الأمر
join
لتعمل على العقد الأخرى.
عظيم! لا ضجة مع المهلات.
ونظرًا لأنه سيتم استخدام RAID أيضًا في هذه اللوحة ، فسوف تحتاج إلى إعادة التكوين. لتلخيص كل الخطوات:
1. جبل الأقراص في / الخ / fstab
UUID=655a39e8-9a5d-45f3-ae14-73b4c5ed50c3 /mnt/root ext4 defaults,rw,user,auto,exec 0 0 UUID=0633df91-017c-4b98-9b2e-4a0d27989a5c /mnt/raid ext4 defaults,rw,user,auto 0 0 /mnt/root/var/lib/etcd /var/lib/etcd none defaults,bind 0 0 /mnt/root/var/lib/docker /var/lib/docker none defaults,bind 0 0
2. تثبيت ثنائيات Docker و K8s
curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list apt-get update apt-get install -y kubelet=1.13.1-00 kubectl=1.13.1-00 kubeadm=1.13.1-00
3. تكوين اسم مضيف فريد (مهم يتم إضافة العديد من العقد)
hostnamectl set-hostname k8s-master-1
4. التهيئة Kubernetes
لقد حذفت المرحلة باستخدام طائرة التحكم ، لأنني أريد أن أكون قادرًا على التخطيط للقرون العادية على هذه العقدة:
kubeadm init --skip-phases mark-control-plane
5. تثبيت البرنامج المساعد للشبكة
كانت المعلومات الواردة في هذا المقال في Hypriot مؤرخة قليلاً لأن المكون الإضافي لشبكة Weave أصبح
معتمدًا أيضًا
على ARM :
export KUBECONFIG=/etc/kubernetes/admin.conf kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
6. إضافة تسميات المضيف
على هذه العقدة ، سأبدأ تشغيل خادم NAS ، لذلك سأضع علامة عليه مع تسميات للاستخدام المستقبلي المحتمل في المجدول:
kubectl label nodes k8s-master-1 marshallbrekka.raid=true kubectl label nodes k8s-master-1 marshallbrekka.network=gigabit
ربط العقد الأخرى إلى الكتلة
كان إعداد الأجهزة الأخرى (Banana Pi، CubbieBoard) بنفس السهولة. بالنسبة لهم ، تحتاج إلى تكرار الخطوات الثلاث الأولى (تغيير الإعدادات الخاصة بتركيب الأقراص / وسائط الفلاش ، حسب توفرها) وتشغيل الأمر
kubeadm join
بدلاً من
kubeadm init
.
العثور على حاويات قفص الاتهام ل ARM
تم تصميم معظم حاويات Docker الضرورية بشكل طبيعي على جهاز Mac ، ولكن بالنسبة إلى نظام ARM ، فهي أكثر تعقيدًا بعض الشيء. بعد أن وجدت العديد من المقالات حول كيفية استخدام QEMU لهذه الأغراض ، توصلت إلى
استنتاج مفاده أن معظم التطبيقات التي أحتاج
إليها قد تم تجميعها بالفعل ، والكثير منها متاح على
linuxserver .
الخطوات التالية
ما زلت لا أحصل على التكوين الأولي للأجهزة بصيغة تلقائية / نصية كما نود ، فقد قمت على الأقل بتكوين مجموعة من الأوامر الأساسية (
kubeadm
docker
kubeadm
) وقمت بتوثيقها في مستودع Git. تلقت بقية التطبيقات المستخدمة أيضًا تكوينات YAML لـ K8s المخزّنة في نفس المستودع ، لذا أصبح من السهل جدًا الآن الحصول على التكوين الضروري من البداية.
في المستقبل ، أود تحقيق ما يلي:
- اجعل المواقع الرئيسية متوفرة للغاية
- إضافة المراقبة / الإخطارات لمعرفة الفشل في أي مكونات ؛
- تغيير إعدادات DCHP للموجه لاستخدام خادم DNS من الكتلة من أجل تبسيط اكتشاف التطبيقات (من يريد أن يتذكر عناوين IP الداخلية؟) ؛
- قم بتشغيل MetalLB لإعادة توجيه خدمات الكتلة إلى شبكة خاصة (DNS ، وما إلى ذلك).
PS من المترجم
اقرأ أيضًا في مدونتنا: