لماذا تختار استضافة Elasticsearch ذاتيًا على خادم VPS
يتألق Elasticsearch حيث لا يعود البحث البسيط كافيًا: تسجيل BM25 قابل للضبط، والمرادفات، والمحلّلات اللغوية المخصّصة (الفرنسية والعربية ICU)، والاستعلامات الجغرافية، وحزمة ELK الكاملة لمركزة سجلات تطبيقاتك. تصبح عروض Elastic Cloud وOpenSearch Service باهظة بسرعة بمجرد أن يتجاوز الحجم المُفهرَس بضعة غيغابايتات، مع إضافة رسوم البيانات الصادرة. وعلى خادم VPS الخاص بك، أنت من يقرّر الإصدار المُنشَر والإضافات المُفعَّلة ومدة الاحتفاظ بالبيانات وسياسة اللقطات. وهو أيضًا السبيل الوحيد للاحتفاظ بالبيانات الحساسة داخل بنيتك التحتية الخاصة، دون أي تبعية لطرف سحابي خارجي.
على صعيد الترخيص، عاد Elasticsearch مفتوح المصدر في أغسطس 2024: منذ الإصدار 8.16، تُوزَّع الشفرة المصدرية بموجب ترخيص AGPLv3 (معتمد من OSI)، إلى جانب Elastic License وSSPL. الإصدارات الحالية الموصى بها هي 8.19.x (الفرع 8 ذو الصيانة الطويلة) و9.x (الفرع الرئيسي منذ 2025).
ما الذي تكسبه باستضافة Elasticsearch ذاتيًا
- بحث متقدّم بالنص الكامل: تسجيل BM25 والمرادفات ومحلّلات لغوية مخصّصة (الفرنسية والعربية ICU)
- تجميعات وأوجه (facets) معقّدة للتجارة الإلكترونية أو ذكاء الأعمال أو مركزة السجلات
- حزمة ELK كاملة (Logstash وBeats وKibana) دون رسوم برمجيات إضافية
- تحكّم كامل في الإصدار والإضافات وسياسات دورة حياة الفهارس (ILM)
- لا فوترة لكل حجم مُفهرَس ولا رسوم للبيانات الصادرة عبر الشبكة
- لقطات تلقائية إلى تخزينك الكائني المتوافق مع S3 عبر SLM
- البيانات الحساسة محفوظة داخل بنيتك التحتية الخاصة، تحت اختصاصك القضائي وحدك
المتطلبات بالأرقام قبل تشغيل أول حاوية
الحدّ الأدنى من ذاكرة RAM: 4 غيغابايت لبيئة اختبار، 8 غيغابايت (2-4 vCPU) لاستخدام إنتاجي خفيف، 16 غيغابايت بمجرد إضافة Kibana أو فهرسة عدة ملايين من المستندات. المعامل الرئيسي هو كومة JVM: اضبط -Xms و-Xmx على 50% من ذاكرة RAM المتاحة، دون تجاوز 31 غيغابايت (فوق ذلك، تنتقل JVM إلى وضع ضغط المؤشرات الأقل كفاءة؛ الحدّ الدقيق هو 31 غيغابايت مع G1GC، وليس 32). اضبط دائمًا -Xms مساوية لـ -Xmx: كومة مُخصَّصة بأقل من طاقتها عند الإقلاع ثم تمتد أثناء التشغيل تسبّب توقفات طويلة في GC.
على مستوى الشبكة، يستخدم Elasticsearch منفذين: 9200 (HTTP، واجهة API REST) و9300 (النقل بين العقد). لا تعرض المنفذ 9200 مباشرةً على الواجهة العامة — فهذا المصدر الأول للاختراق على الأنظمة غير المؤمَّنة. أما على مستوى التخزين، فـSSD NVMe موصى به: يُجري Elasticsearch عمليات قراءة عشوائية كثيرة على شرائح Lucene. خطّط أيضًا لتثبيت Docker وDocker Compose، ونطاق فرعي es.yourdomain.com يشير إلى الخادم.
النشر خطوة بخطوة
تجهيز نواة Linux
قبل تشغيل الحاوية، طبّق ضبطَين إلزاميَّين على مستوى النظام. أولًا، ارفع حدّ مناطق الذاكرة المُعيَّنة:
sysctl -w vm.max_map_count=262144. ثبّت هذا الإعداد بإضافةvm.max_map_count=262144إلى/etc/sysctl.conf. ثم عطّل التبديل (swap) على الخادم (swapoff -a)، أو اضبطbootstrap.memory_lock=trueفيelasticsearch.ymlلمنع JVM من الترحيل إلى القرص.كتابة ملف docker-compose.yml
أنشئ دليل عمل، ثم ملف
docker-compose.ymlيحتوي على خدمة Elasticsearch: الصورةdocker.elastic.co/elasticsearch/elasticsearch:8.19.4، ومتغير البيئةES_JAVA_OPTS=-Xms4g -Xmx4g، وحجم تخزين مُسمَّى مثبَّت على/usr/share/elasticsearch/data، والمنفذ 9200 مربوط بـ127.0.0.1فقط. أضف أيضًاdiscovery.type=single-nodeلنشر أحادي العقدة.تفعيل xpack.security وتشغيل الخدمة
في
elasticsearch.yml، تحقّق من أنxpack.security.enabled: trueوxpack.security.http.ssl.enabled: trueمُفعَّلان. منذ الإصدار 8.x، يكون الأمان مُفعَّلًا افتراضيًا. شغّل المجموعة:docker compose up -d. عند التشغيل الأول، انتظر من 2 إلى 3 دقائق. راجع السجلات:docker compose logs -f elasticsearch.إنشاء المستخدمين واسترجاع كلمة مرور elastic
بعد تشغيل الحاوية، أعد تعيين كلمة مرور المستخدم المتميّز
elastic:docker exec -it elasticsearch bin/elasticsearch-reset-password -u elastic. احتفظ بهذه الكلمة في مدير أسرار. ثم أنشئ مستخدم النظامkibana_systemإن أضفت Kibana. يجب ألّا يُستخدم هذا الحساب في استعلامات التطبيقات.التحقّق من المجموعة باستخدام curl
اختبر الاتصال من الخادم:
curl -u elastic:<كلمة_المرور> https://localhost:9200 --cacert /usr/share/elasticsearch/config/certs/http_ca.crt. استجابة JSON تحتوي علىcluster_nameوstatus: greenأوyellowتؤكّد أن المجموعة تعمل. الحالةyellowعلى مجموعة أحادية العقدة طبيعية.الكشف عبر وكيل عكسي HTTPS مع Nginx
ثبّت Nginx على الخادم وعيّن مضيفًا افتراضيًا لـ
es.yourdomain.com. يُعيد الوكيل العكسي توجيه الطلبات إلىhttps://127.0.0.1:9200ويُقدّم شهادة Let's Encrypt للعميل. أضف مصادقة أساسية Nginx كطبقة حماية إضافية.
أمان xpack: TLS والأدوار وعزل الشبكة
يغطّي أمان xpack في Elasticsearch ثلاث طبقات. TLS بين العقد (xpack.security.transport.ssl.enabled: true) يشفّر حركة البيانات بين العقد على المنفذ 9300. TLS على HTTP (xpack.security.http.ssl.enabled: true) يشفّر المنفذ 9200؛ بدونه تنتقل كلمات المرور بنصّ واضح. التحكّم في الأدوار: خصّص الدور الأدنى المطلوب لكل تطبيق. تجنّب استخدام حساب elastic في الإنتاج. معامل network.host الافتراضي هو _local_ (loopback فقط) — لا تُغيّره إلى 0.0.0.0 دون تهيئة الأمان.
تصليب الوصول إلى الشبكة باستخدام UFW
بعد التحقّق من أن Elasticsearch يستمع على 127.0.0.1 فقط، أغلق جدار الحماية: ufw deny 9200/tcp وufw deny 9300/tcp. يجب أن يكون الوكيل العكسي Nginx (المنفذ 443) هو الوحيد المتاح. إن تواصلت عدة عقد، اسمح صراحةً لعناوين IP العقد على المنفذ 9300. يمنحك الأمر ufw status بعد الضبط صورة دقيقة عمّا هو مفتوح.
إدارة دورة حياة الفهارس (ILM): التحكّم في عمر البيانات
تُؤتمت ILM دورة حياة فهارسك بحسب العمر أو الحجم، مانعةً إشباع القرص وحافظةً على سرعة الاستعلامات على البيانات الحديثة. تتضمّن سياسة ILM النموذجية أربع مراحل:
المرحلة الساخنة (hot): يستقبل الفهرس البيانات الجديدة. اضبط rollover تلقائيًا عند بلوغ حجم معيّن (max_size: 50gb) أو عمر معيّن (max_age: 7d). تعيش الفهارس الساخنة على أسرع أقراص NVMe لديك.
المرحلة الدافئة (warm): الفهرس للقراءة فقط. يُقلّص Elasticsearch النسخ المتماثلة ويُجري force-merge لشرائح Lucene — مما يقلّل الذاكرة ويُسرّع القراءات.
المرحلة الباردة (cold): بيانات نادرة الاستعلام. تنخفض النسخ إلى 0 ويمكن تركيب الفهرس من تخزين كائني (searchable snapshots).
مرحلة الحذف (delete): حذف تلقائي بعد فترة الاحتفاظ المحدّدة (مثال: 90 يومًا للسجلات).
PUT _ilm/policy/logs-policy
{
"policy": {
"phases": {
"hot": { "actions": { "rollover": { "max_age": "7d", "max_size": "50gb" } } },
"warm": { "min_age": "7d", "actions": { "forcemerge": { "max_num_segments": 1 }, "shrink": { "number_of_shards": 1 } } },
"cold": { "min_age": "30d", "actions": { "freeze": {} } },
"delete": { "min_age": "90d", "actions": { "delete": {} } }
}
}
}على خادم VPS تكون فيه مساحة القرص محدودة، هذا ما يمنع سجلاتك من إشباع قرص SSD ويُبقي الاستعلامات سريعة على البيانات الساخنة.
اللقطات إلى S3: النسخ الاحتياطي والتعافي من الكوارث
تتيح لك لقطات Elasticsearch نسخ الحالة الكاملة لفهارسك احتياطيًا نحو تخزين كائني متوافق مع S3. ادمجها مع سياسة دورة حياة اللقطات (SLM) لأتمتة النسخ الاحتياطية والاحتفاظ بها دون تدخّل يدوي.
1. تثبيت إضافة S3 وإعداد المستودع:
docker exec -it elasticsearch bin/elasticsearch-plugin install repository-s3أضف مفاتيح الوصول إلى keystore Elasticsearch (أبدًا في نصّ واضح):
docker exec -it elasticsearch bin/elasticsearch-keystore add s3.client.default.access_key
docker exec -it elasticsearch bin/elasticsearch-keystore add s3.client.default.secret_keyسجّل المستودع:
PUT _snapshot/s3-backup
{
"type": "s3",
"settings": {
"bucket": "my-elasticsearch-bucket",
"region": "eu-west-1",
"base_path": "snapshots/production"
}
}2. إنشاء سياسة دورة حياة اللقطات:
PUT _slm/policy/daily-snapshots
{
"schedule": "0 30 2 * * ?",
"name": "<daily-snap-{now/d}>",
"repository": "s3-backup",
"config": { "indices": ["*"], "ignore_unavailable": true },
"retention": { "expire_after": "30d", "min_count": 5, "max_count": 50 }
}تُطلق هذه السياسة لقطة يوميًا عند 2:30 صباحًا وتحذف ما هو أقدم من 30 يومًا مع الإبقاء على 5 نسخ كحدٍّ أدنى. اختبر الاستعادة من بيئة التطوير قبل أن تحتاجها.
مراقبة كومة JVM: اكتشاف OOM قبل وقوعه
على خادم VPS، يمكن لـ OOM Killer في نواة Linux إنهاء عملية Elasticsearch دون تحذير. المراقبة الاستباقية لكومة JVM تمنع 80% من حوادث الإنتاج.
المقاييس التي يجب مراقبتها عبر واجهة API _nodes/stats:
- jvm.mem.heap_used_percent: أطلق تنبيهًا فوق 75% في المتوسط، وتنبيهًا حرجًا فوق 85% على مدى 5 دقائق. الإشباع المتواصل عند 90%+ يشير إلى تسرّب ذاكرة أو كومة غير كافية الحجم.
- jvm.gc.collectors.old.collection_count وcollection_time_in_millis: ارتفاع سريع في عدد GC old-gen وأوقات تتجاوز 2 ثانية للمجموعة الواحدة يعني أن JVM تقضي وقتًا أطول في التجميع من وقتها في العمل.
القواعد التشغيلية:
1. إن تجاوز heap_used_percent نسبة 75% في الوضع المستقر، زِد الكومة (أو RAM الخادم) قبل مواجهة أول OOM.
2. لا تزد الكومة فوق 31 غيغابايت — بعد هذا الحدّ تُعطّل JVM ضغط المؤشرات (compressed oops) وتستهلك ذاكرة أكثر لكل كائن.
3. تحقّق بانتظام من أن bootstrap.memory_lock: true مُفعَّل: GET _nodes?filter_path=**.mlockall — قيمة false تعني أن التبديل (swap) لا يزال نشطًا.
Kibana: استكشاف الفهارس ولوحات المعلومات (اختياري)
Kibana هي الواجهة الرسومية الرسمية لـ Elasticsearch لاستكشاف الفهارس وبناء لوحات المعلومات وضبط التنبيهات. ليست إلزامية للاستخدام البرمجي، لكنها تُبسّط إدارة ILM وSLM.
أضف Kibana في ملف Compose نفسه:
kibana:
image: docker.elastic.co/kibana/kibana:8.19.4
environment:
- ELASTICSEARCH_HOSTS=https://elasticsearch:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=<كلمة_مرور_kibana_system>
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=/usr/share/kibana/config/certs/http_ca.crt
volumes:
- /مسار/إلى/http_ca.crt:/usr/share/kibana/config/certs/http_ca.crt:ro
depends_on:
- elasticsearchaعرض Kibana خلف وكيل Nginx على kibana.yourdomain.com مع مصادقة. لا تعرض Kibana مباشرةً على الإنترنت دون مصادقة: فهي تمنح وصولًا كاملًا لإدارة المجموعة. من Kibana، ادخل إلى Stack Management → Index Lifecycle Policies وSnapshot and Restore لإدارة ILM وSLM بشكل مرئي.
استكشاف الأخطاء: الأعطال الخمسة الأكثر شيوعًا
1. OOM Killer يوقف عملية Elasticsearch. العرَض: تتوقف الحاوية دون رسالة خطأ، ويكشف dmesg | grep -i killed عن Killed process. الحلّ: قلّص -Xmx إلى 50% من ذاكرة RAM المتاحة (بحدّ أقصى 31 غيغابايت)، وراقب الاستهلاك بـ docker stats.
2. max_map_count منخفض جدًا. العرَض: يرفض Elasticsearch الإقلاع برسالة max virtual memory areas vm.max_map_count [65530] is too low. الحلّ: sysctl -w vm.max_map_count=262144 ثم أضف vm.max_map_count=262144 إلى /etc/sysctl.conf.
3. Permission denied على /usr/share/elasticsearch/data. العرَض: رسالة AccessDeniedException في السجلات. السبب: دليل المضيف يملكه root لكن الحاوية تعمل بالمعرّف UID 1000. الحلّ: chown -R 1000:1000 <مسار_حجم_المضيف>.
4. رفض الاتصال على المنفذ 9200. العرَض: curl localhost:9200 يُعيد Connection refused. السبب الشائع: network.host مُضبوط بشكل خاطئ. اترك network.host بقيمته الافتراضية (_local_) وادخل عبر 127.0.0.1:9200. تحقّق أيضًا من أن الحاوية تعمل: docker ps.
5. بطء الإقلاع: طبيعي عند التهيئة الأولى. العرَض: تستغرق المجموعة من 2 إلى 3 دقائق للاستجابة. هذا ليس عطلًا. انتظر ظهور Cluster health status changed from [RED] to [GREEN] في السجلات.
هل تريد بديلًا مفتوح المصدر بالكامل؟
OpenSearch هو التفريع المجتمعي من Elasticsearch، وُلد عام 2021 حين غيّرت شركة Elastic ترخيصها إلى SSPL. يحافظ OpenSearch على ترخيص Apache 2.0 ويتضمّن ميزات أمان متقدّمة في توزيعته المجانية. منذ أن أعادت Elastic إدراج AGPLv3 في أغسطس 2024 مع الإصدار 8.16، كلا المشروعَين بات تحت ترخيص معتمد من OSI — يعتمد الاختيار الآن على النظام البيئي أكثر من اعتباره قيدًا على الترخيص. يتّبع نشر Docker نفس النمط باستخدام الصورة opensearchproject/opensearch.