في كثير من الأحيان تأتي الطلبات التالية من العملاء: "نريدها مثل Amazon RDS ، ولكن أرخص" ؛ "نريدها مثل RDS ، ولكن في كل مكان ، في أي بنية تحتية." لتنفيذ مثل هذا الحل المُدار على Kubernetes ، نظرنا في الحالة الحالية لأكثر المشغلين شيوعًا لـ PostgreSQL (Stolon ، المشغلون من Crunchy Data و Zalando) وحددنا خيارنا.
هذه المقالة هي تجربتنا من وجهة نظر نظرية (مراجعة الحلول) ومن وجهة نظر عملية (ما تم اختياره وما نتج عنه). لكن أولاً ، دعنا نحدد المتطلبات العامة لاستبدال محتمل لـ RDS ...
ما هو RDS
عندما يتحدث الناس عن RDS ، فإنهم يقصدون في تجربتنا خدمة DBMS مُدارة والتي:
- قابل للتخصيص بسهولة
- لديه القدرة على العمل مع اللقطات والاسترداد منها (يفضل أن يكون ذلك بدعم PITR ) ؛
- يسمح لك بإنشاء طبولوجيا السيد والعبد ؛
- لديه قائمة غنية من الملحقات ؛
- يوفر التدقيق وإدارة المستخدم / الوصول.
بشكل عام ، يمكن أن تكون مناهج تنفيذ المهمة مختلفة تمامًا ، لكن المسار مع Ansible الشرطي ليس قريبًا منا. (تم التوصل إلى نتيجة مماثلة من قبل الزملاء في 2GIS نتيجة لمحاولتهم إنشاء "أداة للنشر السريع لمجموعة تجاوز الفشل على أساس Postgres.")
المشغلون هم النهج المقبول عمومًا لحل مثل هذه المشكلات في نظام Kubernetes البيئي. تم إخبار المزيد من التفاصيل عنها فيما يتعلق بقواعد البيانات التي تعمل داخل Kubernetes من قبل القسم الفني في فلانت ،توزيعفي أحد تقاريره .
ملحوظة : لإنشاء عوامل تشغيل بسيطة بسرعة ، نوصي بالاهتمام بأداة مشغل shell مفتوحة المصدر الخاصة بنا . باستخدامه ، يمكنك القيام بذلك دون معرفة Go ، ولكن بطرق مألوفة لمسؤولي النظام: في Bash و Python وما إلى ذلك.
هناك العديد من مشغلي K8s المشهورين لـ PostgreSQL:
- ستولون.
- مشغل PostgreSQL للبيانات المقرمشة ؛
- مشغل Zalando Postgres.
دعونا نلقي نظرة فاحصة عليهم.
اختيار المشغل
بالإضافة إلى الميزات المهمة التي سبق ذكرها أعلاه ، فإننا - كمهندسي عمليات البنية التحتية في Kubernetes - نتوقع أيضًا ما يلي من المشغلين:
- النشر من Git ومن الموارد المخصصة ؛
- جراب دعم مضاد للتقارب ؛
- تثبيت تقارب العقدة أو محدد العقدة ؛
- وضع التحمل
- توافر فرص التوليف ؛
- تقنيات مفهومة وحتى أوامر.
دون الخوض في التفاصيل حول كل نقطة من النقاط (اسأل في التعليقات إذا كان لديك أي أسئلة عنها بعد قراءة المقال بأكمله) ، ألاحظ بشكل عام أن هذه المعلمات مطلوبة للحصول على وصف أكثر دقة لتخصص عقد المجموعة من أجل ترتيبها لتطبيقات محددة. بهذه الطريقة يمكننا تحقيق التوازن الأمثل بين الأداء والتكلفة.
الآن لمشغلي PostgreSQL أنفسهم.
1. ستولون
تم اعتبار Stolon من شركة Sorint.lab الإيطالية في التقرير المذكور بالفعل كنوع من المعايير بين المشغلين لنظام إدارة قواعد البيانات. هذا مشروع قديم نوعًا ما: تم إصداره العام الأول في نوفمبر 2015 (!) ، ويضم مستودع GitHub ما يقرب من 3000 نجمة وأكثر من 40 مساهمًا.
في الواقع ، يعتبر Stolon مثالًا رائعًا على الهندسة المعمارية المدروسة جيدًا:

يمكن العثور على تفاصيل جهاز المشغل هذا في التقرير أو وثائق المشروع . بشكل عام ، يكفي أن نقول إنه يستطيع فعل كل ما هو موصوف: تجاوز الفشل ، والوكلاء للوصول الشفاف للعميل ، والنسخ الاحتياطية ... علاوة على ذلك ، يوفر الوكلاء الوصول من خلال خدمة نقطة نهاية واحدة - على عكس الحلين الآخرين اللذين تم بحثهما بشكل أكبر (لديهم خدمتان للوصول يتمركز).
ومع ذلك ، لا يحتوي Stolon على موارد مخصصة ، ولهذا السبب لا يمكن نشرها بطريقة سهلة وسريعة - "مثل الكعك الساخن" - لإنشاء مثيلات DBMS في Kubernetes. يتم تنفيذ الإدارة من خلال الأداة المساعدة
stolonctlوالنشر - من خلال مخطط Helm ، ويتم تحديد إعدادات المستخدم في ConfigMap.
من ناحية ، اتضح أن المشغل ليس مشغلًا كثيرًا (بعد كل شيء ، لا يستخدم CRD). ولكن من ناحية أخرى ، فهو نظام مرن يسمح لك بتخصيص الموارد في K8s بالطريقة التي تريدها.
للتلخيص ، بالنسبة لنا شخصيًا ، لم يكن من الأفضل إنشاء مخطط منفصل لكل قاعدة بيانات. لذلك ، بدأنا في البحث عن بدائل.
2. مشغل PostgreSQL للبيانات المقرمشة
بدا المشغل من شركة Crunchy Data ، وهي شركة ناشئة أمريكية شابة ، كبديل منطقي. يبدأ تاريخها العام مع الإصدار الأول في مارس 2017 ، ومنذ ذلك الحين تلقى مستودع GitHub أقل من 1300 نجمة وأكثر من 50 مساهمًا. تم اختبار أحدث إصدار من سبتمبر للعمل مع Kubernetes 1.15-1.18 و OpenShift 3.11+ و 4.4+ و GKE و VMware Enterprise PKS 1.3+.
تفي بنية مشغل Crunchy Data PostgreSQL أيضًا بالمتطلبات المذكورة:
تحدث الإدارة من خلال الأداة المساعدة
pgo، ولكنها بدورها تنشئ موارد مخصصة لـ Kubernetes. لذلك ، يسرنا المشغل كمستخدمين محتملين:
- هناك سيطرة عبر CRD ؛
- إدارة مستخدم مريحة (أيضًا عبر CRD) ؛
- التكامل مع المكونات الأخرى لـ Crunchy Data Container Suite - مجموعة متخصصة من صور الحاويات لـ PostgreSQL والأدوات المساعدة للعمل معها (بما في ذلك pgBackRest ، و pgAudit ، وإضافات المساهمات ، وما إلى ذلك).
ومع ذلك ، كشفت محاولات بدء استخدام المشغل من Crunchy Data عن عدة مشكلات:
- لم تكن هناك إمكانية للتسامح - تم توفير nodeSelector فقط.
- كانت الكبسولات التي أنشأناها جزءًا من النشر ، على الرغم من قيامنا بنشر تطبيق ذي حالة. بخلاف StatefulSets ، لا يمكن لعمليات النشر إنشاء أقراص.
يؤدي العيب الأخير إلى لحظات مضحكة: في بيئة الاختبار ، كان من الممكن تشغيل 3 نسخ متماثلة باستخدام قرص تخزين محلي واحد ، ونتيجة لذلك أبلغ المشغل أن 3 نسخ متماثلة كانت تعمل (على الرغم من أن هذا لم يكن هو الحال).
ميزة أخرى لهذا المشغل هي تكامله الجاهز مع أنظمة مساعدة مختلفة. على سبيل المثال ، من السهل تثبيت pgAdmin و pgBounce ، وتغطي الوثائق Grafana و Prometheus المكوّنين مسبقًا. يشير الإصدار الأخير 4.5.0-beta1 بشكل منفصل إلى التكامل المحسن مع مشروع pgMonitor ، والذي بفضله يقدم المشغل تصورًا مرئيًا لمقاييس PgSQL خارج الصندوق.
ومع ذلك ، فإن الاختيار الغريب لموارد Kubernetes التي تم إنشاؤها أدى بنا إلى إيجاد حل آخر.
3. مشغل Zalando Postgres
لقد عرفنا منتجات Zalando لفترة طويلة: لدينا خبرة في استخدام Zalenium ، وبالطبع ، جربنا Patroni ، حل HA الشهير لـ PostgreSQL. تحدث أحد مؤلفيها ، أليكسي كليوكين ، عن نهج الشركة في إنشاء مشغل Postgres في Postgres-Tuesday # 5 ، وقد أحببنا ذلك.
هذا هو الحل الأصغر الذي تمت مناقشته في المقالة: تم الإصدار الأول في أغسطس 2018. ومع ذلك ، على الرغم من العدد الصغير للإصدارات الرسمية ، فقد قطع المشروع شوطًا طويلاً ، وتجاوز بالفعل شعبية الحل من Crunchy Data مع أكثر من 1300 نجمة على GitHub وأقصى عدد من المساهمين (70+).
تحت غطاء هذا المشغل ، يتم استخدام الحلول التي تم اختبارها عبر الزمن:
هذه هي الطريقة التي يتم بها تقديم بنية مشغل Zalando:
تتم إدارة المشغل بالكامل من خلال Custom Resources ، ويقوم تلقائيًا بإنشاء مجموعة StatefulSet من الحاويات ، والتي يمكن تخصيصها بعد ذلك عن طريق إضافة العديد من العربات الجانبية إلى الكبسولات. كل هذا يعد إضافة مهمة بالمقارنة مع المشغل من Crunchy Data.
نظرًا لأنه كان الحل من Zalando الذي اخترناه من بين الخيارات الثلاثة قيد الدراسة ، فسيتم تقديم وصف إضافي لقدراته أدناه ، على الفور جنبًا إلى جنب مع ممارسة التطبيق.
تدرب مع مشغل Zalando Postgres
يعد نشر عامل أمرًا بسيطًا للغاية: ما عليك سوى تنزيل الإصدار الحالي من GitHub وتطبيق ملفات YAML من دليل manifests . بدلاً من ذلك ، يمكنك أيضًا استخدام OperatorHub .
بعد التثبيت ، يجب أن تقلق بشأن إعداد مخازن للسجلات والنسخ الاحتياطية . يتم ذلك عبر ConfigMap
postgres-operatorفي مساحة الاسم حيث قمت بتثبيت العبارة. مع تكوين المستودعات ، يمكنك نشر أول مجموعة PostgreSQL لك.
على سبيل المثال ، يبدو نشرنا القياسي كما يلي:
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: staging-db
spec:
numberOfInstances: 3
patroni:
synchronous_mode: true
postgresql:
version: "12"
resources:
limits:
cpu: 100m
memory: 1Gi
requests:
cpu: 100m
memory: 1Gi
sidecars:
- env:
- name: DATA_SOURCE_URI
value: 127.0.0.1:5432
- name: DATA_SOURCE_PASS
valueFrom:
secretKeyRef:
key: password
name: postgres.staging-db.credentials
- name: DATA_SOURCE_USER
value: postgres
image: wrouesnel/postgres_exporter
name: prometheus-exporter
resources:
limits:
cpu: 500m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
teamId: staging
volume:
size: 2Gi
ينشر هذا البيان مجموعة من 3 مثيلات مع جانب جانبي في شكل postgres_exporter ، نأخذ منه مقاييس التطبيق. كما ترى ، كل شيء بسيط للغاية ، وإذا كنت ترغب في ذلك ، يمكنك إنشاء عدد غير محدود من المجموعات.
يجدر الانتباه إلى لوحة إدارة الويب - postgres-Operator-ui . يأتي مع المشغل ويسمح لك بإنشاء مجموعات وحذفها ، وكذلك العمل مع النسخ الاحتياطية التي قام بها المشغل.
PostgreSQL
إدارة النسخ الاحتياطية لقائمة الكتلة
ميزة أخرى مثيرة للاهتمام هي دعم Teams API . تقوم هذه الآلية تلقائيًا بإنشاء أدوار في PostgreSQLبناءً على قائمة أسماء المستخدمين الناتجة. بعد ذلك ، تتيح لك واجهة برمجة التطبيقات (API) إعادة قائمة بالمستخدمين الذين تم إنشاء الأدوار لهم تلقائيًا.
المشاكل والحلول
ومع ذلك ، سرعان ما كشف استخدام المشغل عن عدة عيوب مهمة:
- عدم وجود دعم nodeSelector ؛
- عدم القدرة على تعطيل النسخ الاحتياطية ؛
- عند استخدام وظيفة إنشاء قاعدة البيانات ، لا تظهر الامتيازات الافتراضية ؛
- بشكل دوري لا توجد وثائق كافية أو أنها قديمة.
لحسن الحظ ، يمكن حل العديد منها. لنبدأ في النهاية - مشاكل التوثيق .
على الأرجح ستصادف حقيقة أنه ليس من الواضح دائمًا كيفية تسجيل نسخة احتياطية وكيفية توصيل دلو النسخ الاحتياطي بواجهة مستخدم المشغل. تتحدث الوثائق عن هذا بشكل عابر ، لكن الوصف الحقيقي موجود في العلاقات العامة :
- تحتاج إلى سر.
-
pod_environment_secret_nameCRD ConfigMap ( , ).
ومع ذلك ، كما اتضح ، فإن هذا مستحيل حاليًا. هذا هو السبب في أننا قمنا بتجميع نسختنا الخاصة من المشغل مع بعض التطورات الإضافية من طرف ثالث. انظر أدناه لمزيد من التفاصيل.
إذا قمت بتمرير معلمات النسخ الاحتياطي إلى المشغل ، أي
wal_s3_bucketمفاتيح الوصول في AWS S3 ، فسيقوم بنسخ كل شيء احتياطيًا : ليس فقط القواعد في الإنتاج ، ولكن أيضًا التدريج. لم يناسبنا.
في وصف المعلمات لـ Spilo ، وهو غلاف Docker الأساسي لـ PgSQL عند استخدام المشغل ، اتضح أنه يمكنك تمرير المعلمة
WAL_S3_BUCKETفارغة ، وبالتالي تعطيل النسخ الاحتياطية. علاوة على ذلك ، لفرحنا العظيم ، تم العثور على العلاقات العامة الجاهزة ، والتي قبلناها على الفور في مفترقنا. الآن يكفي ببساطة إضافة enableWALArchiving: falseكتلة PostgreSQL إلى المورد.
نعم ، كانت هناك فرصة للقيام بذلك بشكل مختلف عن طريق تشغيل مشغلين: أحدهما للتشغيل المرحلي (بدون نسخ احتياطية) ، والثاني للإنتاج. لكن تمكنا من الحصول على واحدة.
حسنًا ، لقد تعلمنا كيفية نقل الوصول لـ S3 إلى قواعد البيانات وبدأت النسخ الاحتياطية في الوصول إلى التخزين. كيف تجعل صفحات النسخ الاحتياطي تعمل في واجهة مستخدم المشغل؟
في واجهة مستخدم المشغل ، تحتاج إلى إضافة 3 متغيرات:
-
SPILO_S3_BACKUP_BUCKET -
AWS_ACCESS_KEY_ID -
AWS_SECRET_ACCESS_KEY
بعد ذلك ، ستصبح إدارة النسخ الاحتياطية متاحة ، والتي في حالتنا ستعمل على تبسيط العمل مع التدريج ، مما يسمح لك بتسليم شرائح من الإنتاج هناك دون برامج نصية إضافية.
ميزة أخرى كانت تسمى العمل مع Teams API والإمكانيات الواسعة لإنشاء قواعد البيانات والأدوار باستخدام أدوات المشغل. ومع ذلك ، فإن الأدوار التي تم إنشاؤها ليس لها حقوق افتراضية . وفقًا لذلك ، لا يمكن للمستخدم الذي يتمتع بحقوق القراءة قراءة الجداول الجديدة.
لماذا هذا؟ على الرغم من حقيقة أن الكود يحتوي على الرموز الضرورية
GRANT، إلا أنه لا يتم استخدامها دائمًا. هناك طريقتان: syncPreparedDatabasesو syncDatabases. ب- syncPreparedDatabasesبالرغم من preparedDatabases وجود شرط في المقطع defaultRolesوdefaultUsersلإنشاء الأدوار ، لا يتم تطبيق الحقوق الافتراضية. نحن بصدد إعداد التصحيح بحيث يتم تطبيق هذه الحقوق تلقائيًا.
واللحظة الأخيرة في التحسينات التي تهمنا هي التصحيح الذي يضيف Node Affinity إلى مجموعة StatefulSet التي تم إنشاؤها. غالبًا ما يفضل عملاؤنا خفض التكاليف باستخدام المثيلات الموضعية ، ومن الواضح أنه لا ينبغي لهم استضافة خدمات قاعدة البيانات. يمكن حل هذه المشكلة من خلال التسامح ، ولكن وجود تقارب العقدة يعطي الكثير من الثقة.
ماذا حدث؟
ونتيجة لحل المشاكل المذكورة أعلاه، ونحن متشعب مشغل بوستجرس من زالاندو إلى دينا مستودع ، حيث أنها بنيت مع هذه البقع مفيدة. ومن أجل الراحة ، قمنا أيضًا بتجميع صورة Docker .
قائمة العلاقات العامة المتشعبة:
- بناء في Docker صورة آمنة وخفيفة الوزن للمشغل ؛
- النسخ الاحتياطي تعطيل .
- تحديث إصدارات الموارد لإصدارات k8s الحالية ؛
- تنفيذ Node Affinity .
سيكون رائعًا إذا كان المجتمع يدعم هذه العلاقات العامة حتى يتمكنوا من الوصول إلى الإصدار التالي من المشغل (1.6).
علاوة! قصة نجاح هجرة الإنتاج
إذا كنت تستخدم Patroni ، فيمكن نقل الإنتاج المباشر إلى المشغل بأقل وقت توقف.
يتيح لك Spilo إنشاء مجموعات في وضع الاستعداد عبر مخازن S3 باستخدام Wal-E ، عندما يتم حفظ السجل الثنائي PgSQL لأول مرة في S3 ثم تنزيله بواسطة النسخة المتماثلة. ولكن ماذا لو لم يكن لديك Wal-E في بنيتك التحتية القديمة؟ لقد تم بالفعل اقتراح حل لهذه المشكلة على حبري.
يأتي النسخ المتماثل المنطقي لـ PostgreSQL للإنقاذ. ومع ذلك ، لن ندخل في تفاصيل كيفية إنشاء المنشورات والاشتراكات ، لأن ... خطتنا فشلت.
الحقيقة هي أن قاعدة البيانات تحتوي على عدة جداول محملة بملايين الصفوف ، والتي ، علاوة على ذلك ، تم تجديدها وحذفها باستمرار. اشتراك بسيط مع
copy_data، عندما تنسخ نسخة متماثلة جديدة كل المحتوى من النسخة الرئيسية ، فإنها ببساطة لا تواكب النسخة الرئيسية. نجح نسخ المحتوى لمدة أسبوع ، لكنه لم يلحق بالسيد. نتيجة لذلك ، ساعد مقال كتبه زملاء من Avito في التعامل مع المشكلة : يمكنك نقل البيانات باستخدام ملفات pg_dump. سوف أصف نسختنا (المعدلة قليلاً) من هذه الخوارزمية.
الفكرة هي أنه يمكنك جعل الاشتراك مغلقًا مرتبطًا بفتحة نسخ محددة ثم إصلاح رقم المعاملة. كانت هناك نسخ طبق الأصل لأعمال الإنتاج. هذا مهم لأن النسخة المتماثلة ستساعد في إنشاء تفريغ ثابت والاستمرار في تلقي التغييرات من الرئيسي.
في الأوامر اللاحقة التي تصف عملية الترحيل ، سيتم استخدام رموز المضيف التالية:
- خادم المصدر الرئيسي ؛
- replica1 - تدفق متماثلة على إنتاج القديم.
- النسخة المتماثلة 2 هي نسخة متماثلة منطقية جديدة.
خطة الهجرة
1. في المعالج ، قم بإنشاء اشتراك لجميع الجداول في مخطط
publicقاعدة البيانات dbname:
psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"
2. لنقم بإنشاء فتحة نسخ على الشريحة الرئيسية:
psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"
3. إيقاف النسخ المتماثل على النسخة المتماثلة القديمة:
psql -h replica1 -c "select pg_wal_replay_pause();"
4. احصل على رقم المعاملة من السيد:
psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"
5. تفريغ النسخة المتماثلة القديمة. سنفعل ذلك في عدة خيوط ، مما سيساعد في تسريع العملية:
pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname
6. تحميل التفريغ على الخادم الجديد:
pg_restore -h replica2 -F d -j 8 -d dbname dump/
7. بعد تنزيل ملف التفريغ ، يمكنك بدء النسخ المتماثل على النسخة المتماثلة المتدفقة:
psql -h replica1 -c "select pg_wal_replay_resume();"
7. لنقم بإنشاء اشتراك على نسخة منطقية جديدة:
psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"
8. الحصول على
oidاشتراكات:
psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"
9. لنفترض أنه تم استلامها
oid=1000. دعنا نطبق رقم المعاملة على الاشتراك:
psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"
10. لنبدأ النسخ المتماثل:
psql -h replica2 -d dbname -c "alter subscription oldprod enable;"
11. تحقق من حالة الاشتراك ، يجب أن يعمل النسخ:
psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"
psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"
12. بعد بدء النسخ المتماثل ومزامنة قواعد البيانات ، يمكنك التبديل.
13. بعد تعطيل النسخ المتماثل ، تحتاج إلى تصحيح التسلسلات. تم توثيق هذا جيدًا في مقال على wiki.postgresql.org .
بفضل هذه الخطة ، تمت عملية التحول بأقل قدر من التأخير.
خاتمة
يسمح لك مشغلو Kubernetes بتبسيط الأنشطة المختلفة عن طريق تقليلها إلى إنشاء موارد K8s. ومع ذلك ، بعد تحقيق أتمتة رائعة بمساعدتهم ، يجدر بنا أن نتذكر أنه يمكن أيضًا أن يجلب عددًا من الفروق الدقيقة غير المتوقعة ، لذا اختر المشغلين لديك بحكمة.
بعد مراجعة أشهر مشغلي Kubernetes الثلاثة لـ PostgreSQL ، اخترنا مشروعًا من Zalando. وكان علينا التغلب على بعض الصعوبات معه ، ولكن النتيجة كانت سعيدة حقًا ، لذلك نخطط لتوسيع هذه التجربة إلى بعض تركيبات PgSQL الأخرى. إذا كانت لديك خبرة في استخدام حلول مماثلة ، سنكون سعداء لرؤية التفاصيل في التعليقات!
ملاحظة
اقرأ أيضًا على مدونتنا: