ProHoster > بلوق > إدارة > تجربتنا مع البيانات في مجموعة Kubernetes etcd مباشرة (بدون K8s API)
تجربتنا مع البيانات في مجموعة Kubernetes etcd مباشرة (بدون K8s API)
على نحو متزايد، يطلب منا العملاء توفير الوصول إلى مجموعة Kubernetes حتى نتمكن من الوصول إلى الخدمات داخل المجموعة: لتكون قادرًا على الاتصال مباشرة ببعض قواعد البيانات أو الخدمات، أو توصيل تطبيق محلي بالتطبيقات الموجودة داخل المجموعة...
على سبيل المثال، هناك حاجة للاتصال من جهازك المحلي بإحدى الخدمات memcached.staging.svc.cluster.local. نحن نقدم هذه الإمكانية باستخدام VPN داخل المجموعة التي يتصل بها العميل. للقيام بذلك، نعلن عن شبكات فرعية من القرون والخدمات وندفع DNS العنقودي إلى العميل. وهكذا، عندما يحاول العميل الاتصال بالخدمة memcached.staging.svc.cluster.local، ينتقل الطلب إلى نظام DNS للمجموعة ويتلقى ردًا على ذلك عنوان هذه الخدمة من شبكة خدمة المجموعة أو عنوان pod.
نقوم بتكوين مجموعات K8s باستخدام kubeadm، حيث توجد الشبكة الفرعية للخدمة الافتراضية 192.168.0.0/16، وشبكة القرون هي 10.244.0.0/16. عادةً ما يعمل كل شيء بشكل جيد، ولكن هناك نقطتان:
الشبكة الفرعية 192.168.*.* غالبًا ما يتم استخدامها في شبكات مكاتب العملاء، وفي كثير من الأحيان في الشبكات المنزلية للمطورين. ثم ينتهي بنا الأمر إلى حدوث تعارضات: تعمل أجهزة التوجيه المنزلية على هذه الشبكة الفرعية وتقوم VPN بدفع هذه الشبكات الفرعية من المجموعة إلى العميل.
لدينا عدة مجموعات (الإنتاج و/أو المرحلة و/أو عدة مجموعات تطوير). بعد ذلك، بشكل افتراضي، سيكون لكل منهم نفس الشبكات الفرعية للقرون والخدمات، مما يخلق صعوبات كبيرة في العمل المتزامن مع الخدمات في عدة مجموعات.
لقد اعتمدنا منذ فترة طويلة ممارسة استخدام شبكات فرعية مختلفة للخدمات والقرون داخل نفس المشروع - بشكل عام، بحيث يكون لجميع المجموعات شبكات مختلفة. ومع ذلك، هناك عدد كبير من المجموعات قيد التشغيل والتي لا أرغب في الانتقال إليها من الصفر، نظرًا لأنها تقوم بتشغيل العديد من الخدمات والتطبيقات ذات الحالة وما إلى ذلك.
ثم سألنا أنفسنا: كيف نغير الشبكة الفرعية في مجموعة موجودة؟
البحث في القرارات
الممارسة الأكثر شيوعًا هي إعادة الإنشاء جميع الخدمات من النوع ClusterIP. كخيار، يمكن تقديم المشورة وهذا:
تواجه العملية التالية مشكلة: بعد كل شيء تم تكوينه، تأتي القرون بعنوان IP القديم كخادم أسماء DNS في /etc/resolv.conf.
نظرًا لأنني لم أجد الحل بعد، فقد اضطررت إلى إعادة تعيين المجموعة بأكملها باستخدام إعادة تعيين kubeadm وتشغيلها مرة أخرى.
لكن هذا ليس مناسبًا للجميع... فيما يلي مقدمات أكثر تفصيلاً لحالتنا:
يستخدم الفانيلا.
توجد مجموعات في السحابة وفي الأجهزة؛
أود تجنب إعادة نشر كافة الخدمات في المجموعة؛
هناك حاجة إلى القيام بكل شيء بشكل عام مع الحد الأدنى من المشاكل؛
إصدار Kubernetes هو 1.16.6 (ومع ذلك، ستكون الخطوات الإضافية مماثلة للإصدارات الأخرى)؛
وتتمثل المهمة الرئيسية في التأكد من نشر المجموعة باستخدام kubeadm مع شبكة فرعية للخدمة 192.168.0.0/16، استبدله بـ 172.24.0.0/16.
وقد حدث أننا كنا مهتمين منذ فترة طويلة برؤية ماذا وكيف يتم تخزين Kubernetes في إلخ، وما الذي يمكن فعله به... لذلك اعتقدنا: "لماذا لا نقوم فقط بتحديث البيانات الموجودة في الخ، واستبدال عناوين IP القديمة (الشبكة الفرعية) بعناوين جديدة؟ »
بعد البحث عن أدوات جاهزة للعمل مع البيانات وما إلى ذلك، لم نجد أي شيء يحل المشكلة تمامًا. (بالمناسبة، إذا كنت تعرف أي أدوات مساعدة للتعامل مع البيانات مباشرة في الخ، فسوف نقدر الروابط.) ومع ذلك، نقطة انطلاق جيدة هي etcdhelper من أوبن شيفت(شكرا لمؤلفيها!).
يمكن لهذه الأداة المساعدة الاتصال بـ etcd باستخدام الشهادات وقراءة البيانات من هناك باستخدام الأوامر ls, get, dump.
إضافة الخالمساعد
الفكرة التالية منطقية: "ما الذي يمنعك من إضافة هذه الأداة المساعدة عن طريق إضافة القدرة على كتابة البيانات إلى إلخ؟"
لقد أصبح نسخة معدلة من etcdhelper بوظيفتين جديدتين changeServiceCIDR и changePodCIDR. عليها يمكنك رؤية الكود هنا.
إنشاء مُسلسل، وتحويل كائن Go إلى protobuf، وكتابة بيانات جديدة إلى etcd.
وظيفة changePodCIDR مماثلة في الأساس changeServiceCIDR - فقط بدلاً من تحرير مواصفات الخدمة، نقوم بذلك للعقدة والتغيير .spec.PodCIDR إلى شبكة فرعية جديدة.
ممارسة
تغيير خدمة CIDR
خطة تنفيذ المهمة بسيطة جدًا، ولكنها تتضمن فترة توقف في وقت إعادة إنشاء جميع القرون في المجموعة. بعد وصف الخطوات الرئيسية، سنشارك أيضًا الأفكار حول كيفية تقليل وقت التوقف هذا من الناحية النظرية.
الخطوات التحضيرية:
تثبيت البرامج الضرورية وتجميع برنامج etcdhelper المصحح؛
wget https://raw.githubusercontent.com/flant/examples/master/2020/04-etcdhelper/etcdhelper.go
go get go.etcd.io/etcd/clientv3 k8s.io/kubectl/pkg/scheme k8s.io/apimachinery/pkg/runtime
go build -o etcdhelper etcdhelper.go
4. قم بتغيير الشبكة الفرعية للخدمة في بيانات مستوى التحكم في Kubernetes. في الملفات /etc/kubernetes/manifests/kube-apiserver.yaml и /etc/kubernetes/manifests/kube-controller-manager.yaml تغيير المعلمة --service-cluster-ip-range إلى شبكة فرعية جديدة: 172.24.0.0/16 بدلا من 192.168.0.0/16.
5. نظرًا لأننا نقوم بتغيير الشبكة الفرعية للخدمة التي يُصدر لها kubeadm شهادات لخادم apiserver (بما في ذلك)، فيجب إعادة إصدارها:
دعونا نرى المجالات وعناوين IP التي تم إصدار الشهادة الحالية لها:
openssl x509 -noout -ext subjectAltName </etc/kubernetes/pki/apiserver.crt
X509v3 Subject Alternative Name:
DNS:dev-1-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:apiserver, IP Address:192.168.0.1, IP Address:10.0.0.163, IP Address:192.168.199.100
تحذير! في هذه اللحظة، يتوقف تحليل النطاق عن العمل في المجموعة، كما هو الحال في القرون الموجودة /etc/resolv.conf يتم تسجيل عنوان CoreDNS القديم (kube-dns)، ويقوم kube-proxy بتغيير قواعد iptables من الشبكة الفرعية القديمة إلى الشبكة الجديدة. علاوة على ذلك، تمت كتابة المقال حول الخيارات الممكنة لتقليل وقت التوقف عن العمل.
دعونا نصلح ConfigMap في مساحة الاسم kube-system:
kubectl -n kube-system edit cm kubelet-config-1.16
- استبدل هنا clusterDNS إلى عنوان IP الجديد لخدمة kube-dns: kubectl -n kube-system get svc kube-dns.
kubectl -n kube-system edit cm kubeadm-config
- سنقوم بإصلاحه data.ClusterConfiguration.networking.serviceSubnet إلى شبكة فرعية جديدة.
نظرًا لأن عنوان kube-dns قد تغير، فمن الضروري تحديث تكوين kubelet على جميع العقد:
6. دعونا نعيد تشغيل كافة العقد العنقودية واحدة تلو الأخرى.
7. إذا تركت عقدة واحدة على الأقل podCIDR القديم، فلن يتمكن kube-controller-manager من البدء، ولن تتم جدولة القرون الموجودة في المجموعة.
في الواقع، يمكن إجراء تغيير podCIDR بطريقة أسهل (على سبيل المثال، هكذا). لكننا أردنا أن نتعلم كيفية العمل مع etcd مباشرة، لأن هناك حالات عند تحرير كائنات Kubernetes في etcd - الوحيد البديل المحتمل. (على سبيل المثال، لا يمكنك تغيير حقل الخدمة دون توقف spec.clusterIP.)
مجموع
يناقش المقال إمكانية العمل مع البيانات في الخ مباشرة، أي. تجاوز واجهة برمجة تطبيقات Kubernetes. في بعض الأحيان يسمح لك هذا الأسلوب بالقيام بـ "أشياء صعبة". لقد اختبرنا العمليات الواردة في النص على مجموعات K8s الحقيقية. ومع ذلك، فإن حالة استعدادهم للاستخدام على نطاق واسع هي PoC (إثبات المفهوم). لذلك، إذا كنت تريد استخدام نسخة معدلة من الأداة المساعدة etcdhelper على مجموعاتك، فقم بذلك على مسؤوليتك الخاصة.